@contractspec/lib.runtime-sandbox 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/rolldown_runtime.js +18 -0
- package/dist/adapters/pglite/adapter.js +97 -0
- package/dist/adapters/pglite/adapter.js.map +1 -0
- package/dist/adapters/pglite/index.js +3 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/ports/database.port.d.ts +70 -0
- package/dist/ports/database.port.d.ts.map +1 -0
- package/dist/types/database.types.d.ts +47 -0
- package/dist/types/database.types.d.ts.map +1 -0
- package/dist/web/database/migrations.d.ts +12 -0
- package/dist/web/database/migrations.d.ts.map +1 -0
- package/dist/web/database/migrations.js +746 -0
- package/dist/web/database/migrations.js.map +1 -0
- package/dist/web/database/schema.d.ts +7349 -0
- package/dist/web/database/schema.d.ts.map +1 -0
- package/dist/web/database/schema.js +528 -0
- package/dist/web/database/schema.js.map +1 -0
- package/dist/web/events/local-pubsub.d.ts +10 -0
- package/dist/web/events/local-pubsub.d.ts.map +1 -0
- package/dist/web/events/local-pubsub.js +24 -0
- package/dist/web/events/local-pubsub.js.map +1 -0
- package/dist/web/graphql/local-client.d.ts +20 -0
- package/dist/web/graphql/local-client.d.ts.map +1 -0
- package/dist/web/graphql/local-client.js +536 -0
- package/dist/web/graphql/local-client.js.map +1 -0
- package/dist/web/index.d.ts +15 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +68 -0
- package/dist/web/index.js.map +1 -0
- package/dist/web/runtime/seeders/index.js +358 -0
- package/dist/web/runtime/seeders/index.js.map +1 -0
- package/dist/web/runtime/services.d.ts +60 -0
- package/dist/web/runtime/services.d.ts.map +1 -0
- package/dist/web/runtime/services.js +80 -0
- package/dist/web/runtime/services.js.map +1 -0
- package/dist/web/storage/indexeddb.d.ts +22 -0
- package/dist/web/storage/indexeddb.d.ts.map +1 -0
- package/dist/web/storage/indexeddb.js +85 -0
- package/dist/web/storage/indexeddb.js.map +1 -0
- package/dist/web/utils/id.d.ts +5 -0
- package/dist/web/utils/id.d.ts.map +1 -0
- package/dist/web/utils/id.js +9 -0
- package/dist/web/utils/id.js.map +1 -0
- package/package.json +70 -0
- package/src/adapters/pglite/adapter.ts +152 -0
- package/src/adapters/pglite/index.ts +1 -0
- package/src/index.ts +41 -0
- package/src/ports/database.port.ts +82 -0
- package/src/ports/index.ts +4 -0
- package/src/types/database.types.ts +55 -0
- package/src/types/index.ts +1 -0
- package/src/web/database/migrations.ts +760 -0
- package/src/web/database/schema.ts +596 -0
- package/src/web/events/local-pubsub.ts +28 -0
- package/src/web/graphql/local-client.ts +747 -0
- package/src/web/index.ts +21 -0
- package/src/web/runtime/seeders/index.ts +449 -0
- package/src/web/runtime/services.ts +132 -0
- package/src/web/storage/indexeddb.ts +116 -0
- package/src/web/utils/id.ts +7 -0
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drizzle schema for sandbox runtime database tables.
|
|
3
|
+
*
|
|
4
|
+
* This schema defines all tables used by the template examples:
|
|
5
|
+
* - Todos (tasks, categories)
|
|
6
|
+
* - Messaging (conversations, participants, messages)
|
|
7
|
+
* - Recipes (categories, recipes, ingredients, instructions)
|
|
8
|
+
* - CRM (pipelines, stages, deals, companies, contacts)
|
|
9
|
+
* - SaaS (projects, subscriptions, usage)
|
|
10
|
+
* - Agent Console (tools, definitions, runs, steps, logs)
|
|
11
|
+
* - Workflow System (definitions, steps, instances, approvals)
|
|
12
|
+
* - Marketplace (stores, products, orders, items, payouts, reviews)
|
|
13
|
+
* - Integration Hub (integrations, connections, syncs, mappings)
|
|
14
|
+
* - Analytics (dashboards, widgets, queries)
|
|
15
|
+
* - Policy-Safe Knowledge Assistant (contexts, rules, versions, snapshots, candidates, tasks)
|
|
16
|
+
*/
|
|
17
|
+
import { integer, pgTable, real, text, timestamp } from 'drizzle-orm/pg-core';
|
|
18
|
+
|
|
19
|
+
// ============ Todos Template ============
|
|
20
|
+
|
|
21
|
+
export const templateTaskCategory = pgTable('template_task_category', {
|
|
22
|
+
id: text('id').primaryKey(),
|
|
23
|
+
projectId: text('projectId').notNull(),
|
|
24
|
+
name: text('name').notNull(),
|
|
25
|
+
color: text('color'),
|
|
26
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
27
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export const templateTask = pgTable('template_task', {
|
|
31
|
+
id: text('id').primaryKey(),
|
|
32
|
+
projectId: text('projectId').notNull(),
|
|
33
|
+
categoryId: text('categoryId'),
|
|
34
|
+
title: text('title').notNull(),
|
|
35
|
+
description: text('description'),
|
|
36
|
+
completed: integer('completed').default(0),
|
|
37
|
+
priority: text('priority').default('MEDIUM'),
|
|
38
|
+
dueDate: text('dueDate'),
|
|
39
|
+
tags: text('tags'),
|
|
40
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
41
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// ============ Messaging Template ============
|
|
45
|
+
|
|
46
|
+
export const templateConversation = pgTable('template_conversation', {
|
|
47
|
+
id: text('id').primaryKey(),
|
|
48
|
+
projectId: text('projectId').notNull(),
|
|
49
|
+
name: text('name'),
|
|
50
|
+
isGroup: integer('isGroup').default(0),
|
|
51
|
+
avatarUrl: text('avatarUrl'),
|
|
52
|
+
lastMessageId: text('lastMessageId'),
|
|
53
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
54
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
export const templateConversationParticipant = pgTable(
|
|
58
|
+
'template_conversation_participant',
|
|
59
|
+
{
|
|
60
|
+
id: text('id').primaryKey(),
|
|
61
|
+
conversationId: text('conversationId').notNull(),
|
|
62
|
+
projectId: text('projectId').notNull(),
|
|
63
|
+
userId: text('userId').notNull(),
|
|
64
|
+
displayName: text('displayName'),
|
|
65
|
+
role: text('role'),
|
|
66
|
+
joinedAt: timestamp('joinedAt').defaultNow(),
|
|
67
|
+
lastReadAt: text('lastReadAt'),
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
export const templateMessage = pgTable('template_message', {
|
|
72
|
+
id: text('id').primaryKey(),
|
|
73
|
+
conversationId: text('conversationId').notNull(),
|
|
74
|
+
projectId: text('projectId').notNull(),
|
|
75
|
+
senderId: text('senderId').notNull(),
|
|
76
|
+
senderName: text('senderName'),
|
|
77
|
+
content: text('content').notNull(),
|
|
78
|
+
attachments: text('attachments'),
|
|
79
|
+
status: text('status').default('SENT'),
|
|
80
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
81
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// ============ Recipes Template ============
|
|
85
|
+
|
|
86
|
+
export const templateRecipeCategory = pgTable('template_recipe_category', {
|
|
87
|
+
id: text('id').primaryKey(),
|
|
88
|
+
nameEn: text('nameEn').notNull(),
|
|
89
|
+
nameFr: text('nameFr').notNull(),
|
|
90
|
+
icon: text('icon'),
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
export const templateRecipe = pgTable('template_recipe', {
|
|
94
|
+
id: text('id').primaryKey(),
|
|
95
|
+
projectId: text('projectId').notNull(),
|
|
96
|
+
categoryId: text('categoryId'),
|
|
97
|
+
slugEn: text('slugEn').notNull(),
|
|
98
|
+
slugFr: text('slugFr').notNull(),
|
|
99
|
+
nameEn: text('nameEn').notNull(),
|
|
100
|
+
nameFr: text('nameFr').notNull(),
|
|
101
|
+
descriptionEn: text('descriptionEn'),
|
|
102
|
+
descriptionFr: text('descriptionFr'),
|
|
103
|
+
heroImageUrl: text('heroImageUrl'),
|
|
104
|
+
prepTimeMinutes: integer('prepTimeMinutes'),
|
|
105
|
+
cookTimeMinutes: integer('cookTimeMinutes'),
|
|
106
|
+
servings: integer('servings'),
|
|
107
|
+
isFavorite: integer('isFavorite').default(0),
|
|
108
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
109
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
export const templateRecipeIngredient = pgTable('template_recipe_ingredient', {
|
|
113
|
+
id: text('id').primaryKey(),
|
|
114
|
+
recipeId: text('recipeId').notNull(),
|
|
115
|
+
nameEn: text('nameEn').notNull(),
|
|
116
|
+
nameFr: text('nameFr').notNull(),
|
|
117
|
+
quantity: text('quantity').notNull(),
|
|
118
|
+
ordering: integer('ordering').default(0),
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
export const templateRecipeInstruction = pgTable(
|
|
122
|
+
'template_recipe_instruction',
|
|
123
|
+
{
|
|
124
|
+
id: text('id').primaryKey(),
|
|
125
|
+
recipeId: text('recipeId').notNull(),
|
|
126
|
+
contentEn: text('contentEn').notNull(),
|
|
127
|
+
contentFr: text('contentFr').notNull(),
|
|
128
|
+
ordering: integer('ordering').default(0),
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
// ============ CRM Template ============
|
|
133
|
+
|
|
134
|
+
export const crmPipeline = pgTable('crm_pipeline', {
|
|
135
|
+
id: text('id').primaryKey(),
|
|
136
|
+
projectId: text('projectId').notNull(),
|
|
137
|
+
name: text('name').notNull(),
|
|
138
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
139
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
export const crmStage = pgTable('crm_stage', {
|
|
143
|
+
id: text('id').primaryKey(),
|
|
144
|
+
pipelineId: text('pipelineId').notNull(),
|
|
145
|
+
name: text('name').notNull(),
|
|
146
|
+
position: integer('position').notNull(),
|
|
147
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
export const crmDeal = pgTable('crm_deal', {
|
|
151
|
+
id: text('id').primaryKey(),
|
|
152
|
+
projectId: text('projectId').notNull(),
|
|
153
|
+
pipelineId: text('pipelineId').notNull(),
|
|
154
|
+
stageId: text('stageId').notNull(),
|
|
155
|
+
name: text('name').notNull(),
|
|
156
|
+
value: real('value').notNull().default(0),
|
|
157
|
+
currency: text('currency').default('USD'),
|
|
158
|
+
status: text('status').default('OPEN'),
|
|
159
|
+
contactId: text('contactId'),
|
|
160
|
+
companyId: text('companyId'),
|
|
161
|
+
ownerId: text('ownerId').notNull(),
|
|
162
|
+
expectedCloseDate: text('expectedCloseDate'),
|
|
163
|
+
wonSource: text('wonSource'),
|
|
164
|
+
lostReason: text('lostReason'),
|
|
165
|
+
notes: text('notes'),
|
|
166
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
167
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
export const crmCompany = pgTable('crm_company', {
|
|
171
|
+
id: text('id').primaryKey(),
|
|
172
|
+
projectId: text('projectId').notNull(),
|
|
173
|
+
name: text('name').notNull(),
|
|
174
|
+
domain: text('domain'),
|
|
175
|
+
industry: text('industry'),
|
|
176
|
+
size: text('size'),
|
|
177
|
+
website: text('website'),
|
|
178
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
179
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
export const crmContact = pgTable('crm_contact', {
|
|
183
|
+
id: text('id').primaryKey(),
|
|
184
|
+
projectId: text('projectId').notNull(),
|
|
185
|
+
companyId: text('companyId'),
|
|
186
|
+
firstName: text('firstName').notNull(),
|
|
187
|
+
lastName: text('lastName'),
|
|
188
|
+
email: text('email'),
|
|
189
|
+
phone: text('phone'),
|
|
190
|
+
title: text('title'),
|
|
191
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
192
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// ============ SaaS Template ============
|
|
196
|
+
|
|
197
|
+
export const saasProject = pgTable('saas_project', {
|
|
198
|
+
id: text('id').primaryKey(),
|
|
199
|
+
projectId: text('projectId').notNull(),
|
|
200
|
+
organizationId: text('organizationId').notNull(),
|
|
201
|
+
name: text('name').notNull(),
|
|
202
|
+
description: text('description'),
|
|
203
|
+
status: text('status').default('DRAFT'),
|
|
204
|
+
tier: text('tier').default('FREE'),
|
|
205
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
206
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
export const saasSubscription = pgTable('saas_subscription', {
|
|
210
|
+
id: text('id').primaryKey(),
|
|
211
|
+
projectId: text('projectId').notNull(),
|
|
212
|
+
organizationId: text('organizationId').notNull(),
|
|
213
|
+
plan: text('plan').notNull().default('FREE'),
|
|
214
|
+
status: text('status').default('ACTIVE'),
|
|
215
|
+
billingCycle: text('billingCycle').default('MONTHLY'),
|
|
216
|
+
currentPeriodStart: text('currentPeriodStart'),
|
|
217
|
+
currentPeriodEnd: text('currentPeriodEnd'),
|
|
218
|
+
cancelAtPeriodEnd: integer('cancelAtPeriodEnd').default(0),
|
|
219
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
220
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
export const saasUsage = pgTable('saas_usage', {
|
|
224
|
+
id: text('id').primaryKey(),
|
|
225
|
+
projectId: text('projectId').notNull(),
|
|
226
|
+
organizationId: text('organizationId').notNull(),
|
|
227
|
+
metricName: text('metricName').notNull(),
|
|
228
|
+
value: real('value').notNull().default(0),
|
|
229
|
+
periodStart: text('periodStart').notNull(),
|
|
230
|
+
periodEnd: text('periodEnd').notNull(),
|
|
231
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// ============ Agent Console Template ============
|
|
235
|
+
|
|
236
|
+
export const agentTool = pgTable('agent_tool', {
|
|
237
|
+
id: text('id').primaryKey(),
|
|
238
|
+
projectId: text('projectId').notNull(),
|
|
239
|
+
organizationId: text('organizationId').notNull(),
|
|
240
|
+
name: text('name').notNull(),
|
|
241
|
+
description: text('description'),
|
|
242
|
+
version: text('version').default('1.0.0'),
|
|
243
|
+
category: text('category').default('UTILITY'),
|
|
244
|
+
status: text('status').default('ACTIVE'),
|
|
245
|
+
inputSchema: text('inputSchema'),
|
|
246
|
+
outputSchema: text('outputSchema'),
|
|
247
|
+
endpoint: text('endpoint'),
|
|
248
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
249
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
export const agentDefinition = pgTable('agent_definition', {
|
|
253
|
+
id: text('id').primaryKey(),
|
|
254
|
+
projectId: text('projectId').notNull(),
|
|
255
|
+
organizationId: text('organizationId').notNull(),
|
|
256
|
+
name: text('name').notNull(),
|
|
257
|
+
description: text('description'),
|
|
258
|
+
modelProvider: text('modelProvider').default('openai'),
|
|
259
|
+
modelName: text('modelName').default('gpt-4'),
|
|
260
|
+
systemPrompt: text('systemPrompt'),
|
|
261
|
+
temperature: real('temperature').default(0.7),
|
|
262
|
+
maxTokens: integer('maxTokens').default(4096),
|
|
263
|
+
status: text('status').default('DRAFT'),
|
|
264
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
265
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
export const agentToolAssignment = pgTable('agent_tool_assignment', {
|
|
269
|
+
id: text('id').primaryKey(),
|
|
270
|
+
agentId: text('agentId').notNull(),
|
|
271
|
+
toolId: text('toolId').notNull(),
|
|
272
|
+
assignedAt: timestamp('assignedAt').defaultNow(),
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
export const agentRun = pgTable('agent_run', {
|
|
276
|
+
id: text('id').primaryKey(),
|
|
277
|
+
projectId: text('projectId').notNull(),
|
|
278
|
+
agentId: text('agentId').notNull(),
|
|
279
|
+
status: text('status').default('QUEUED'),
|
|
280
|
+
input: text('input'),
|
|
281
|
+
output: text('output'),
|
|
282
|
+
totalTokens: integer('totalTokens').default(0),
|
|
283
|
+
promptTokens: integer('promptTokens').default(0),
|
|
284
|
+
completionTokens: integer('completionTokens').default(0),
|
|
285
|
+
estimatedCostUsd: real('estimatedCostUsd').default(0),
|
|
286
|
+
durationMs: integer('durationMs'),
|
|
287
|
+
errorMessage: text('errorMessage'),
|
|
288
|
+
queuedAt: timestamp('queuedAt').defaultNow(),
|
|
289
|
+
startedAt: text('startedAt'),
|
|
290
|
+
completedAt: text('completedAt'),
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
export const agentRunStep = pgTable('agent_run_step', {
|
|
294
|
+
id: text('id').primaryKey(),
|
|
295
|
+
runId: text('runId').notNull(),
|
|
296
|
+
stepNumber: integer('stepNumber').notNull(),
|
|
297
|
+
type: text('type').notNull(),
|
|
298
|
+
toolId: text('toolId'),
|
|
299
|
+
toolInput: text('toolInput'),
|
|
300
|
+
toolOutput: text('toolOutput'),
|
|
301
|
+
reasoning: text('reasoning'),
|
|
302
|
+
tokensUsed: integer('tokensUsed').default(0),
|
|
303
|
+
durationMs: integer('durationMs'),
|
|
304
|
+
status: text('status').default('PENDING'),
|
|
305
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
export const agentRunLog = pgTable('agent_run_log', {
|
|
309
|
+
id: text('id').primaryKey(),
|
|
310
|
+
runId: text('runId').notNull(),
|
|
311
|
+
level: text('level').default('INFO'),
|
|
312
|
+
message: text('message').notNull(),
|
|
313
|
+
metadata: text('metadata'),
|
|
314
|
+
timestamp: timestamp('timestamp').defaultNow(),
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
// ============ Workflow Template ============
|
|
318
|
+
|
|
319
|
+
export const workflowDefinition = pgTable('workflow_definition', {
|
|
320
|
+
id: text('id').primaryKey(),
|
|
321
|
+
projectId: text('projectId').notNull(),
|
|
322
|
+
organizationId: text('organizationId').notNull(),
|
|
323
|
+
name: text('name').notNull(),
|
|
324
|
+
description: text('description'),
|
|
325
|
+
type: text('type').default('APPROVAL'),
|
|
326
|
+
status: text('status').default('DRAFT'),
|
|
327
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
328
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
export const workflowStep = pgTable('workflow_step', {
|
|
332
|
+
id: text('id').primaryKey(),
|
|
333
|
+
definitionId: text('definitionId').notNull(),
|
|
334
|
+
name: text('name').notNull(),
|
|
335
|
+
description: text('description'),
|
|
336
|
+
stepOrder: integer('stepOrder').notNull(),
|
|
337
|
+
type: text('type').default('APPROVAL'),
|
|
338
|
+
requiredRoles: text('requiredRoles'),
|
|
339
|
+
autoApproveCondition: text('autoApproveCondition'),
|
|
340
|
+
timeoutHours: integer('timeoutHours'),
|
|
341
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
export const workflowInstance = pgTable('workflow_instance', {
|
|
345
|
+
id: text('id').primaryKey(),
|
|
346
|
+
projectId: text('projectId').notNull(),
|
|
347
|
+
definitionId: text('definitionId').notNull(),
|
|
348
|
+
status: text('status').default('PENDING'),
|
|
349
|
+
currentStepId: text('currentStepId'),
|
|
350
|
+
data: text('data'),
|
|
351
|
+
requestedBy: text('requestedBy').notNull(),
|
|
352
|
+
startedAt: timestamp('startedAt').defaultNow(),
|
|
353
|
+
completedAt: text('completedAt'),
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
export const workflowApproval = pgTable('workflow_approval', {
|
|
357
|
+
id: text('id').primaryKey(),
|
|
358
|
+
instanceId: text('instanceId').notNull(),
|
|
359
|
+
stepId: text('stepId').notNull(),
|
|
360
|
+
status: text('status').default('PENDING'),
|
|
361
|
+
actorId: text('actorId'),
|
|
362
|
+
comment: text('comment'),
|
|
363
|
+
decidedAt: text('decidedAt'),
|
|
364
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
// ============ Marketplace Template ============
|
|
368
|
+
|
|
369
|
+
export const marketplaceStore = pgTable('marketplace_store', {
|
|
370
|
+
id: text('id').primaryKey(),
|
|
371
|
+
projectId: text('projectId').notNull(),
|
|
372
|
+
organizationId: text('organizationId').notNull(),
|
|
373
|
+
name: text('name').notNull(),
|
|
374
|
+
description: text('description'),
|
|
375
|
+
status: text('status').default('PENDING'),
|
|
376
|
+
rating: real('rating').default(0),
|
|
377
|
+
reviewCount: integer('reviewCount').default(0),
|
|
378
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
379
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
export const marketplaceProduct = pgTable('marketplace_product', {
|
|
383
|
+
id: text('id').primaryKey(),
|
|
384
|
+
storeId: text('storeId').notNull(),
|
|
385
|
+
name: text('name').notNull(),
|
|
386
|
+
description: text('description'),
|
|
387
|
+
price: real('price').notNull().default(0),
|
|
388
|
+
currency: text('currency').default('USD'),
|
|
389
|
+
status: text('status').default('DRAFT'),
|
|
390
|
+
stock: integer('stock').default(0),
|
|
391
|
+
category: text('category'),
|
|
392
|
+
imageUrl: text('imageUrl'),
|
|
393
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
394
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
export const marketplaceOrder = pgTable('marketplace_order', {
|
|
398
|
+
id: text('id').primaryKey(),
|
|
399
|
+
projectId: text('projectId').notNull(),
|
|
400
|
+
storeId: text('storeId').notNull(),
|
|
401
|
+
customerId: text('customerId').notNull(),
|
|
402
|
+
status: text('status').default('PENDING'),
|
|
403
|
+
total: real('total').notNull().default(0),
|
|
404
|
+
currency: text('currency').default('USD'),
|
|
405
|
+
shippingAddress: text('shippingAddress'),
|
|
406
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
407
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
export const marketplaceOrderItem = pgTable('marketplace_order_item', {
|
|
411
|
+
id: text('id').primaryKey(),
|
|
412
|
+
orderId: text('orderId').notNull(),
|
|
413
|
+
productId: text('productId').notNull(),
|
|
414
|
+
quantity: integer('quantity').notNull().default(1),
|
|
415
|
+
price: real('price').notNull().default(0),
|
|
416
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
export const marketplacePayout = pgTable('marketplace_payout', {
|
|
420
|
+
id: text('id').primaryKey(),
|
|
421
|
+
storeId: text('storeId').notNull(),
|
|
422
|
+
amount: real('amount').notNull().default(0),
|
|
423
|
+
currency: text('currency').default('USD'),
|
|
424
|
+
status: text('status').default('PENDING'),
|
|
425
|
+
processedAt: text('processedAt'),
|
|
426
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
export const marketplaceReview = pgTable('marketplace_review', {
|
|
430
|
+
id: text('id').primaryKey(),
|
|
431
|
+
productId: text('productId').notNull(),
|
|
432
|
+
customerId: text('customerId').notNull(),
|
|
433
|
+
orderId: text('orderId'),
|
|
434
|
+
rating: integer('rating').notNull(),
|
|
435
|
+
comment: text('comment'),
|
|
436
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
// ============ Integration Hub Template ============
|
|
440
|
+
|
|
441
|
+
export const integration = pgTable('integration', {
|
|
442
|
+
id: text('id').primaryKey(),
|
|
443
|
+
projectId: text('projectId').notNull(),
|
|
444
|
+
organizationId: text('organizationId').notNull(),
|
|
445
|
+
name: text('name').notNull(),
|
|
446
|
+
description: text('description'),
|
|
447
|
+
type: text('type').notNull(),
|
|
448
|
+
status: text('status').default('INACTIVE'),
|
|
449
|
+
iconUrl: text('iconUrl'),
|
|
450
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
451
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
export const integrationConnection = pgTable('integration_connection', {
|
|
455
|
+
id: text('id').primaryKey(),
|
|
456
|
+
integrationId: text('integrationId').notNull(),
|
|
457
|
+
name: text('name').notNull(),
|
|
458
|
+
status: text('status').default('DISCONNECTED'),
|
|
459
|
+
credentials: text('credentials'),
|
|
460
|
+
config: text('config'),
|
|
461
|
+
lastSyncAt: text('lastSyncAt'),
|
|
462
|
+
errorMessage: text('errorMessage'),
|
|
463
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
464
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
export const integrationSyncConfig = pgTable('integration_sync_config', {
|
|
468
|
+
id: text('id').primaryKey(),
|
|
469
|
+
connectionId: text('connectionId').notNull(),
|
|
470
|
+
name: text('name').notNull(),
|
|
471
|
+
sourceEntity: text('sourceEntity').notNull(),
|
|
472
|
+
targetEntity: text('targetEntity').notNull(),
|
|
473
|
+
frequency: text('frequency').default('DAILY'),
|
|
474
|
+
status: text('status').default('ACTIVE'),
|
|
475
|
+
lastRunAt: text('lastRunAt'),
|
|
476
|
+
lastRunStatus: text('lastRunStatus'),
|
|
477
|
+
recordsSynced: integer('recordsSynced').default(0),
|
|
478
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
479
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
export const integrationFieldMapping = pgTable('integration_field_mapping', {
|
|
483
|
+
id: text('id').primaryKey(),
|
|
484
|
+
syncConfigId: text('syncConfigId').notNull(),
|
|
485
|
+
sourceField: text('sourceField').notNull(),
|
|
486
|
+
targetField: text('targetField').notNull(),
|
|
487
|
+
transformType: text('transformType'),
|
|
488
|
+
transformConfig: text('transformConfig'),
|
|
489
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
// ============ Analytics Dashboard Template ============
|
|
493
|
+
|
|
494
|
+
export const analyticsDashboard = pgTable('analytics_dashboard', {
|
|
495
|
+
id: text('id').primaryKey(),
|
|
496
|
+
projectId: text('projectId').notNull(),
|
|
497
|
+
organizationId: text('organizationId').notNull(),
|
|
498
|
+
name: text('name').notNull(),
|
|
499
|
+
slug: text('slug').notNull(),
|
|
500
|
+
description: text('description'),
|
|
501
|
+
status: text('status').default('DRAFT'),
|
|
502
|
+
refreshInterval: text('refreshInterval').default('NONE'),
|
|
503
|
+
isPublic: integer('isPublic').default(0),
|
|
504
|
+
shareToken: text('shareToken'),
|
|
505
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
506
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
export const analyticsWidget = pgTable('analytics_widget', {
|
|
510
|
+
id: text('id').primaryKey(),
|
|
511
|
+
dashboardId: text('dashboardId').notNull(),
|
|
512
|
+
name: text('name').notNull(),
|
|
513
|
+
type: text('type').notNull(),
|
|
514
|
+
gridX: integer('gridX').default(0),
|
|
515
|
+
gridY: integer('gridY').default(0),
|
|
516
|
+
gridWidth: integer('gridWidth').default(6),
|
|
517
|
+
gridHeight: integer('gridHeight').default(4),
|
|
518
|
+
queryId: text('queryId'),
|
|
519
|
+
config: text('config'),
|
|
520
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
521
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
export const analyticsQuery = pgTable('analytics_query', {
|
|
525
|
+
id: text('id').primaryKey(),
|
|
526
|
+
projectId: text('projectId').notNull(),
|
|
527
|
+
organizationId: text('organizationId').notNull(),
|
|
528
|
+
name: text('name').notNull(),
|
|
529
|
+
description: text('description'),
|
|
530
|
+
type: text('type').notNull(),
|
|
531
|
+
definition: text('definition').notNull(),
|
|
532
|
+
sql: text('sql'),
|
|
533
|
+
cacheTtlSeconds: integer('cacheTtlSeconds').default(300),
|
|
534
|
+
isShared: integer('isShared').default(0),
|
|
535
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
536
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
// ============ Policy-Safe Knowledge Assistant Template ============
|
|
540
|
+
|
|
541
|
+
export const psaUserContext = pgTable('psa_user_context', {
|
|
542
|
+
projectId: text('projectId').primaryKey(),
|
|
543
|
+
locale: text('locale').notNull(),
|
|
544
|
+
jurisdiction: text('jurisdiction').notNull(),
|
|
545
|
+
allowedScope: text('allowedScope').notNull(),
|
|
546
|
+
kbSnapshotId: text('kbSnapshotId'),
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
export const psaRule = pgTable('psa_rule', {
|
|
550
|
+
id: text('id').primaryKey(),
|
|
551
|
+
projectId: text('projectId').notNull(),
|
|
552
|
+
jurisdiction: text('jurisdiction').notNull(),
|
|
553
|
+
topicKey: text('topicKey').notNull(),
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
export const psaRuleVersion = pgTable('psa_rule_version', {
|
|
557
|
+
id: text('id').primaryKey(),
|
|
558
|
+
ruleId: text('ruleId').notNull(),
|
|
559
|
+
jurisdiction: text('jurisdiction').notNull(),
|
|
560
|
+
topicKey: text('topicKey').notNull(),
|
|
561
|
+
version: integer('version').notNull(),
|
|
562
|
+
content: text('content').notNull(),
|
|
563
|
+
status: text('status').notNull(),
|
|
564
|
+
sourceRefsJson: text('sourceRefsJson').notNull(),
|
|
565
|
+
approvedBy: text('approvedBy'),
|
|
566
|
+
approvedAt: text('approvedAt'),
|
|
567
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
export const psaSnapshot = pgTable('psa_snapshot', {
|
|
571
|
+
id: text('id').primaryKey(),
|
|
572
|
+
jurisdiction: text('jurisdiction').notNull(),
|
|
573
|
+
asOfDate: text('asOfDate').notNull(),
|
|
574
|
+
includedRuleVersionIdsJson: text('includedRuleVersionIdsJson').notNull(),
|
|
575
|
+
publishedAt: text('publishedAt').notNull(),
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
export const psaChangeCandidate = pgTable('psa_change_candidate', {
|
|
579
|
+
id: text('id').primaryKey(),
|
|
580
|
+
projectId: text('projectId').notNull(),
|
|
581
|
+
jurisdiction: text('jurisdiction').notNull(),
|
|
582
|
+
detectedAt: text('detectedAt').notNull(),
|
|
583
|
+
diffSummary: text('diffSummary').notNull(),
|
|
584
|
+
riskLevel: text('riskLevel').notNull(),
|
|
585
|
+
proposedRuleVersionIdsJson: text('proposedRuleVersionIdsJson').notNull(),
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
export const psaReviewTask = pgTable('psa_review_task', {
|
|
589
|
+
id: text('id').primaryKey(),
|
|
590
|
+
changeCandidateId: text('changeCandidateId').notNull(),
|
|
591
|
+
status: text('status').notNull(),
|
|
592
|
+
assignedRole: text('assignedRole').notNull(),
|
|
593
|
+
decision: text('decision'),
|
|
594
|
+
decidedAt: text('decidedAt'),
|
|
595
|
+
decidedBy: text('decidedBy'),
|
|
596
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
type Listener<TPayload> = (payload: TPayload) => void;
|
|
2
|
+
|
|
3
|
+
export class LocalEventBus {
|
|
4
|
+
private listeners = new Map<string, Set<Listener<unknown>>>();
|
|
5
|
+
|
|
6
|
+
emit<TPayload = unknown>(event: string, payload: TPayload): void {
|
|
7
|
+
const listeners = this.listeners.get(event);
|
|
8
|
+
if (!listeners) return;
|
|
9
|
+
for (const listener of listeners) {
|
|
10
|
+
listener(payload);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
subscribe<TPayload = unknown>(
|
|
15
|
+
event: string,
|
|
16
|
+
listener: Listener<TPayload>
|
|
17
|
+
): () => void {
|
|
18
|
+
let listeners = this.listeners.get(event);
|
|
19
|
+
if (!listeners) {
|
|
20
|
+
listeners = new Set();
|
|
21
|
+
this.listeners.set(event, listeners);
|
|
22
|
+
}
|
|
23
|
+
listeners.add(listener as Listener<unknown>);
|
|
24
|
+
return () => {
|
|
25
|
+
listeners.delete(listener as Listener<unknown>);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|