mirror of
https://github.com/logto-io/logto.git
synced 2025-01-20 21:32:31 -05:00
feat(core): allow jsonb partial update (#210)
* refactor(core): allow jsonb partial update allow jsonb partial update * fix(core): add comments add comments * fix(core): add non-nullable case add non-nullable case assertation * fix(core): use coalesce use coalesce * test(core): add ut add ut `
This commit is contained in:
parent
d14f1a8841
commit
3d550b74dd
3 changed files with 38 additions and 10 deletions
|
@ -1,4 +1,4 @@
|
|||
import { CreateUser, Users } from '@logto/schemas';
|
||||
import { CreateUser, Users, Applications } from '@logto/schemas';
|
||||
|
||||
import RequestError from '@/errors/RequestError';
|
||||
import { createTestPool } from '@/utils/test-utils';
|
||||
|
@ -35,6 +35,24 @@ describe('buildUpdateWhere()', () => {
|
|||
).resolves.toStrictEqual(user);
|
||||
});
|
||||
|
||||
it('return query with jsonb partial update if input data type is jsonb', async () => {
|
||||
const pool = createTestPool(
|
||||
'update "applications"\nset\n"custom_client_metadata"=\ncoalesce("custom_client_metadata",\'{}\'::jsonb)|| $1\nwhere "id"=$2\nreturning *',
|
||||
(_, [costumClientMetadata, id]) => ({
|
||||
id: String(id),
|
||||
costumClientMetadata: String(costumClientMetadata),
|
||||
})
|
||||
);
|
||||
const updateWhere = buildUpdateWhere(pool, Applications, true);
|
||||
|
||||
await expect(
|
||||
updateWhere({
|
||||
set: { customClientMetadata: { idTokenTtl: 3600 } },
|
||||
where: { id: 'foo' },
|
||||
})
|
||||
).resolves.toStrictEqual({ id: 'foo', costumClientMetadata: '{"idTokenTtl":3600}' });
|
||||
});
|
||||
|
||||
it('throws an error when `undefined` found in values', async () => {
|
||||
const pool = createTestPool(
|
||||
'update "users"\nset "username"=$1\nwhere "id"=$2 and "username"=$3'
|
||||
|
|
|
@ -38,10 +38,25 @@ export const buildUpdateWhere: BuildUpdateWhere = <
|
|||
const isKeyOfSchema = isKeyOf(schema);
|
||||
const connectKeyValueWithEqualSign = (data: Partial<Schema>) =>
|
||||
Object.entries(data)
|
||||
.map(
|
||||
([key, value]) =>
|
||||
isKeyOfSchema(key) && sql`${fields[key]}=${convertToPrimitiveOrSql(key, value)}`
|
||||
)
|
||||
.map(([key, value]) => {
|
||||
if (!isKeyOfSchema(key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
||||
/**
|
||||
* Jsonb || operator is used to shallow merge two jsonb types of data
|
||||
* all jsonb data field must be non-nullable
|
||||
* https://www.postgresql.org/docs/current/functions-json.html
|
||||
*/
|
||||
return sql`
|
||||
${fields[key]}=
|
||||
coalesce(${fields[key]},'{}'::jsonb)|| ${convertToPrimitiveOrSql(key, value)}
|
||||
`;
|
||||
}
|
||||
|
||||
return sql`${fields[key]}=${convertToPrimitiveOrSql(key, value)}`;
|
||||
})
|
||||
.filter((value): value is Truthy<typeof value> => notFalsy(value));
|
||||
|
||||
return async ({ set, where }: UpdateWhereData<Schema>) => {
|
||||
|
|
|
@ -84,14 +84,9 @@ export default function applicationRoutes<T extends AuthedRouter>(router: T) {
|
|||
params: { id },
|
||||
body,
|
||||
} = ctx.guard;
|
||||
const application = await findApplicationById(id);
|
||||
|
||||
ctx.body = await updateApplicationById(id, {
|
||||
...body,
|
||||
oidcClientMetadata: buildOidcClientMetadata({
|
||||
...application.oidcClientMetadata,
|
||||
...body.oidcClientMetadata,
|
||||
}),
|
||||
});
|
||||
|
||||
return next();
|
||||
|
|
Loading…
Add table
Reference in a new issue