diff --git a/packages/cli/src/commands/database/seed/index.ts b/packages/cli/src/commands/database/seed/index.ts index 5ce0ce4f6..34ebbb014 100644 --- a/packages/cli/src/commands/database/seed/index.ts +++ b/packages/cli/src/commands/database/seed/index.ts @@ -11,6 +11,7 @@ import { createDemoAppApplication, defaultRole, } from '@logto/schemas'; +import { Hooks } from '@logto/schemas/models'; import chalk from 'chalk'; import type { DatabasePool, DatabaseTransactionConnection } from 'slonik'; import { sql } from 'slonik'; @@ -45,6 +46,11 @@ const createTables = async (connection: DatabaseTransactionConnection) => { // eslint-disable-next-line no-await-in-loop await connection.query(sql`${raw(query)}`); } + + for (const table of [Hooks]) { + // eslint-disable-next-line no-await-in-loop + await connection.query(sql`${raw(table.raw)}`); + } }; const seedTables = async (connection: DatabaseTransactionConnection) => { diff --git a/packages/core/package.json b/packages/core/package.json index 7e63f9064..0977e3ec4 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -35,7 +35,7 @@ "@logto/shared": "workspace:*", "@silverhand/essentials": "^1.3.0", "@withtyped/postgres": "^0.3.1", - "@withtyped/server": "^0.3.0", + "@withtyped/server": "^0.3.1", "chalk": "^5.0.0", "clean-deep": "^3.4.0", "date-fns": "^2.29.3", diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index a537a10a8..2814f5ef8 100644 --- a/packages/integration-tests/package.json +++ b/packages/integration-tests/package.json @@ -50,5 +50,8 @@ "eslintConfig": { "extends": "@silverhand" }, - "prettier": "@silverhand/eslint-config/.prettierrc" + "prettier": "@silverhand/eslint-config/.prettierrc", + "dependencies": { + "@withtyped/server": "^0.3.0" + } } diff --git a/packages/integration-tests/src/tests/api/hooks.test.ts b/packages/integration-tests/src/tests/api/hooks.test.ts new file mode 100644 index 000000000..01158d289 --- /dev/null +++ b/packages/integration-tests/src/tests/api/hooks.test.ts @@ -0,0 +1,31 @@ +import type { Hooks } from '@logto/schemas/models'; +import type { InferModelType } from '@withtyped/server'; + +import { authedAdminApi } from '#src/api/index.js'; + +describe('hooks', () => { + it('should be able to create, query, and delete a hook', async () => { + type Hook = InferModelType; + + const payload = { + event: 'PostRegister', + config: { + url: 'https://foo.bar', + headers: { foo: 'bar' }, + retries: 3, + }, + }; + const created = await authedAdminApi.post('hooks', { json: payload }).json(); + + expect(payload.event).toEqual(created.event); + expect(payload.config).toEqual(created.config); + + expect(await authedAdminApi.get('hooks').json()).toContainEqual(created); + expect(await authedAdminApi.get(`hooks/${created.id}`).json()).toEqual(created); + expect(await authedAdminApi.delete(`hooks/${created.id}`)).toHaveProperty('statusCode', 204); + await expect(authedAdminApi.get(`hooks/${created.id}`)).rejects.toHaveProperty( + 'response.statusCode', + 404 + ); + }); +}); diff --git a/packages/schemas/alterations/next-1671509870-hooks.ts b/packages/schemas/alterations/next-1671509870-hooks.ts new file mode 100644 index 000000000..90ff77047 --- /dev/null +++ b/packages/schemas/alterations/next-1671509870-hooks.ts @@ -0,0 +1,26 @@ +import { sql } from 'slonik'; + +import type { AlterationScript } from '../src/types/alteration.js'; + +const alteration: AlterationScript = { + up: async (pool) => { + await pool.query(sql` + create table hooks ( + id varchar(32) not null, + event varchar(128) not null, + config jsonb /* @use HookConfig */ not null, + created_at timestamptz not null default(now()), + primary key (id) + ); + + create index hooks__event on hooks (event); + `); + }, + down: async (pool) => { + await pool.query(sql` + drop table hooks; + `); + }, +}; + +export default alteration; diff --git a/packages/schemas/package.json b/packages/schemas/package.json index 374cf7a3f..395c03549 100644 --- a/packages/schemas/package.json +++ b/packages/schemas/package.json @@ -82,7 +82,7 @@ "@logto/language-kit": "workspace:*", "@logto/phrases": "workspace:*", "@logto/phrases-ui": "workspace:*", - "@withtyped/server": "^0.3.0", + "@withtyped/server": "^0.3.1", "zod": "^3.20.2" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 480150928..8b4f918c6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -280,7 +280,7 @@ importers: '@types/sinon': ^10.0.13 '@types/supertest': ^2.0.11 '@withtyped/postgres': ^0.3.1 - '@withtyped/server': ^0.3.0 + '@withtyped/server': ^0.3.1 chalk: ^5.0.0 clean-deep: ^3.4.0 copyfiles: ^2.4.1 @@ -337,8 +337,8 @@ importers: '@logto/schemas': link:../schemas '@logto/shared': link:../shared '@silverhand/essentials': 1.3.0 - '@withtyped/postgres': 0.3.1_@withtyped+server@0.3.0 - '@withtyped/server': 0.3.0 + '@withtyped/postgres': 0.3.1_@withtyped+server@0.3.1 + '@withtyped/server': 0.3.1 chalk: 5.1.2 clean-deep: 3.4.0 date-fns: 2.29.3 @@ -482,6 +482,7 @@ importers: '@types/jest': ^29.1.2 '@types/jest-environment-puppeteer': ^5.0.2 '@types/node': ^16.0.0 + '@withtyped/server': ^0.3.0 dotenv: ^16.0.0 eslint: ^8.21.0 got: ^12.5.3 @@ -494,6 +495,8 @@ importers: puppeteer: ^19.0.0 text-encoder: ^0.0.4 typescript: ^4.9.4 + dependencies: + '@withtyped/server': 0.3.0 devDependencies: '@jest/types': 29.1.2 '@logto/js': 1.0.0-beta.14 @@ -583,7 +586,7 @@ importers: '@types/lodash.uniq': ^4.5.6 '@types/node': ^16.0.0 '@types/pluralize': ^0.0.29 - '@withtyped/server': ^0.3.0 + '@withtyped/server': ^0.3.1 camelcase: ^7.0.0 eslint: ^8.21.0 jest: ^29.1.2 @@ -600,7 +603,7 @@ importers: '@logto/language-kit': link:../toolkit/language-kit '@logto/phrases': link:../phrases '@logto/phrases-ui': link:../phrases-ui - '@withtyped/server': 0.3.0 + '@withtyped/server': 0.3.1 zod: 3.20.2 devDependencies: '@silverhand/eslint-config': 1.3.0_eu7dlo3qq5moigliolva3udaxa @@ -4657,13 +4660,13 @@ packages: eslint-visitor-keys: 3.3.0 dev: true - /@withtyped/postgres/0.3.1_@withtyped+server@0.3.0: + /@withtyped/postgres/0.3.1_@withtyped+server@0.3.1: resolution: {integrity: sha512-+XP+kbmTKKpv/5Nf4KDVKfWp6kYGIyty3aUUnSrBY0KLdOUfesuPjFK6S7sNgbh+7pvk/iU48/3UDsjuy4m+SQ==} peerDependencies: '@withtyped/server': ^0.3.0 dependencies: '@types/pg': 8.6.5 - '@withtyped/server': 0.3.0 + '@withtyped/server': 0.3.1 '@withtyped/shared': 0.2.0 pg: 8.8.0 transitivePeerDependencies: @@ -4676,6 +4679,12 @@ packages: '@withtyped/shared': 0.2.0 dev: false + /@withtyped/server/0.3.1: + resolution: {integrity: sha512-AI4QDHVTgv5GWPomWCgP5vqgVWaiby1vm56LBbSqe6r1DTPOZrySoxNoaE5XTQzYX1Jd3pzq1CsOd5AxkgCfpg==} + dependencies: + '@withtyped/shared': 0.2.0 + dev: false + /@withtyped/shared/0.2.0: resolution: {integrity: sha512-SADIVEospfIWAVK0LxX7F1T04hsWMZ0NkfR3lNfvJqOktJ52GglI3FOTVYOM1NJYReDT6pR0XFlCfaF8TVPt8w==} dev: false