feat: add infrastructure foundation — scripts, schema key, new routes, model fields
- Add npm scripts for dev, migrate, seed, smoke - Add key column to scrips table (unique short identifier) - Register users and templates routes in server - Set development: false in Bun.serve for production mode - Add description and custom_fields to CreateTicketSchema - Make owner_id nullable/optional for unassigned tickets - Add migration for custom field key column Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
10
drizzle/migrations/0002_short_custom_field_keys.sql
Normal file
10
drizzle/migrations/0002_short_custom_field_keys.sql
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
ALTER TABLE "custom_fields" ADD COLUMN "key" text;
|
||||||
|
--> statement-breakpoint
|
||||||
|
UPDATE "custom_fields"
|
||||||
|
SET "key" = trim(both '_' from regexp_replace(lower("name"), '[^a-z0-9]+', '_', 'g'));
|
||||||
|
--> statement-breakpoint
|
||||||
|
UPDATE "custom_fields" SET "key" = 'field_' || substring("id"::text, 1, 8) WHERE "key" IS NULL OR "key" = '';
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "custom_fields" ALTER COLUMN "key" SET NOT NULL;
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "custom_fields" ADD CONSTRAINT "custom_fields_key_unique" UNIQUE("key");
|
||||||
@@ -15,6 +15,13 @@
|
|||||||
"when": 1780867177929,
|
"when": 1780867177929,
|
||||||
"tag": "0001_lovely_quentin_quire",
|
"tag": "0001_lovely_quentin_quire",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 2,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1780904200000,
|
||||||
|
"tag": "0002_short_custom_field_keys",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,13 @@
|
|||||||
"module": "src/index.ts",
|
"module": "src/index.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev:backend": "bun run src/index.ts",
|
||||||
|
"db:migrate": "bun run src/db/migrate.ts",
|
||||||
|
"db:seed": "bun run src/db/seed.ts",
|
||||||
|
"db:seed:reset": "bun run src/db/seed.ts --reset",
|
||||||
|
"smoke": "bun run scripts/smoke-test.ts"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
"@types/handlebars": "^4.1.0",
|
"@types/handlebars": "^4.1.0",
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ export const scrips = pgTable('scrips', {
|
|||||||
|
|
||||||
export const customFields = pgTable('custom_fields', {
|
export const customFields = pgTable('custom_fields', {
|
||||||
id: uuid('id').primaryKey().defaultRandom(),
|
id: uuid('id').primaryKey().defaultRandom(),
|
||||||
|
key: text('key').notNull().unique(),
|
||||||
name: text('name').notNull(),
|
name: text('name').notNull(),
|
||||||
field_type: text('field_type').notNull(),
|
field_type: text('field_type').notNull(),
|
||||||
values: jsonb('values'),
|
values: jsonb('values'),
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import { createQueuesRouter } from './routes/queues.ts';
|
|||||||
import { createScripsRouter } from './routes/scrips.ts';
|
import { createScripsRouter } from './routes/scrips.ts';
|
||||||
import { createCustomFieldsRouter } from './routes/custom-fields.ts';
|
import { createCustomFieldsRouter } from './routes/custom-fields.ts';
|
||||||
import { createLifecyclesRouter } from './routes/lifecycles.ts';
|
import { createLifecyclesRouter } from './routes/lifecycles.ts';
|
||||||
|
import { createUsersRouter } from './routes/users.ts';
|
||||||
|
import { createTemplatesRouter } from './routes/templates.ts';
|
||||||
|
|
||||||
let db: Db | null = null;
|
let db: Db | null = null;
|
||||||
|
|
||||||
@@ -31,6 +33,8 @@ app.route('/queues', createQueuesRouter(getDb()));
|
|||||||
app.route('/scrips', createScripsRouter(getDb()));
|
app.route('/scrips', createScripsRouter(getDb()));
|
||||||
app.route('/custom-fields', createCustomFieldsRouter(getDb()));
|
app.route('/custom-fields', createCustomFieldsRouter(getDb()));
|
||||||
app.route('/lifecycles', createLifecyclesRouter(getDb()));
|
app.route('/lifecycles', createLifecyclesRouter(getDb()));
|
||||||
|
app.route('/users', createUsersRouter(getDb()));
|
||||||
|
app.route('/templates', createTemplatesRouter(getDb()));
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
export { app };
|
export { app };
|
||||||
@@ -41,6 +45,7 @@ if (Bun.main === import.meta.path) {
|
|||||||
fetch: app.fetch,
|
fetch: app.fetch,
|
||||||
port: config.SERVER_PORT,
|
port: config.SERVER_PORT,
|
||||||
hostname: config.SERVER_HOST,
|
hostname: config.SERVER_HOST,
|
||||||
|
development: false,
|
||||||
});
|
});
|
||||||
console.log(`Server running at http://${config.SERVER_HOST}:${config.SERVER_PORT}`);
|
console.log(`Server running at http://${config.SERVER_HOST}:${config.SERVER_PORT}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,14 @@ export type Ticket = InferSelectModel<typeof tickets>;
|
|||||||
export const CreateTicketSchema = z.object({
|
export const CreateTicketSchema = z.object({
|
||||||
subject: z.string().min(1),
|
subject: z.string().min(1),
|
||||||
queue_id: z.string().uuid(),
|
queue_id: z.string().uuid(),
|
||||||
|
description: z.string().trim().optional(),
|
||||||
|
custom_fields: z.record(z.string(), z.string()).optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const UpdateTicketSchema = z.object({
|
export const UpdateTicketSchema = z.object({
|
||||||
subject: z.string().min(1).optional(),
|
subject: z.string().min(1).optional(),
|
||||||
status: z.string().min(1).optional(),
|
status: z.string().min(1).optional(),
|
||||||
owner_id: z.string().uuid().optional(),
|
owner_id: z.string().uuid().nullable().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const CommentSchema = z.object({
|
export const CommentSchema = z.object({
|
||||||
|
|||||||
Reference in New Issue
Block a user