@contractspec/lib.example-shared-ui 0.0.0-canary-20260113170453

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.
@@ -0,0 +1,458 @@
1
+ import type { TemplateDefinition, TemplateId } from '../lib/types';
2
+
3
+ /**
4
+ * Generate TypeScript spec code from a template's definition.
5
+ * Converts FeatureModuleSpec contracts to TypeScript spec code.
6
+ */
7
+ export function generateSpecFromTemplate(
8
+ template: TemplateDefinition | null
9
+ ): string {
10
+ const templateId = template?.id ?? 'unknown';
11
+
12
+ if (!template) {
13
+ return generateDefaultSpec(templateId);
14
+ }
15
+
16
+ // Generate spec based on template type
17
+ switch (templateId) {
18
+ case 'crm-pipeline':
19
+ return generateCrmPipelineSpec(template.schema.contracts);
20
+ case 'saas-boilerplate':
21
+ return generateSaasBoilerplateSpec(template.schema.contracts);
22
+ case 'agent-console':
23
+ return generateAgentConsoleSpec(template.schema.contracts);
24
+ case 'todos-app':
25
+ return generateTodosSpec(template.schema.contracts);
26
+ case 'messaging-app':
27
+ return generateMessagingSpec(template.schema.contracts);
28
+ case 'recipe-app-i18n':
29
+ return generateRecipeSpec(template.schema.contracts);
30
+ default:
31
+ return generateDefaultSpec(templateId);
32
+ }
33
+ }
34
+
35
+ /**
36
+ * CRM Pipeline spec
37
+ */
38
+ function generateCrmPipelineSpec(contracts: string[]): string {
39
+ return `// CRM Pipeline Specs
40
+ // Contracts: ${contracts.join(', ')}
41
+
42
+ contractSpec("crm.deal.updateStage.v1", {
43
+ goal: "Move a deal to a different pipeline stage",
44
+ transport: { gql: { mutation: "updateDealStage" } },
45
+ io: {
46
+ input: {
47
+ dealId: "string",
48
+ stageId: "string",
49
+ notes: "string?"
50
+ },
51
+ output: {
52
+ deal: {
53
+ id: "string",
54
+ stage: "string",
55
+ probability: "number",
56
+ value: "number"
57
+ }
58
+ }
59
+ },
60
+ events: ["deal.stage.changed"],
61
+ policy: { auth: "user", rbac: "org:sales" }
62
+ });
63
+
64
+ contractSpec("crm.deal.create.v1", {
65
+ goal: "Create a new deal in the pipeline",
66
+ transport: { gql: { mutation: "createDeal" } },
67
+ io: {
68
+ input: {
69
+ title: "string",
70
+ value: "number",
71
+ contactId: "string",
72
+ stageId: "string",
73
+ ownerId: "string?"
74
+ },
75
+ output: {
76
+ deal: {
77
+ id: "string",
78
+ title: "string",
79
+ value: "number",
80
+ stage: "string",
81
+ createdAt: "ISO8601"
82
+ }
83
+ }
84
+ },
85
+ events: ["deal.created"]
86
+ });
87
+
88
+ contractSpec("crm.contact.list.v1", {
89
+ goal: "List contacts with filtering and pagination",
90
+ transport: { gql: { query: "listContacts" } },
91
+ io: {
92
+ input: {
93
+ filter: {
94
+ search: "string?",
95
+ companyId: "string?",
96
+ tags: "string[]?"
97
+ },
98
+ pagination: {
99
+ page: "number",
100
+ limit: "number"
101
+ }
102
+ },
103
+ output: {
104
+ contacts: "array<Contact>",
105
+ total: "number",
106
+ hasMore: "boolean"
107
+ }
108
+ }
109
+ });`;
110
+ }
111
+
112
+ /**
113
+ * SaaS Boilerplate spec
114
+ */
115
+ function generateSaasBoilerplateSpec(contracts: string[]): string {
116
+ return `// SaaS Boilerplate Specs
117
+ // Contracts: ${contracts.join(', ')}
118
+
119
+ contractSpec("saas.project.create.v1", {
120
+ goal: "Create a new project in an organization",
121
+ transport: { gql: { mutation: "createProject" } },
122
+ io: {
123
+ input: {
124
+ orgId: "string",
125
+ name: "string",
126
+ description: "string?"
127
+ },
128
+ output: {
129
+ project: {
130
+ id: "string",
131
+ name: "string",
132
+ description: "string?",
133
+ createdAt: "ISO8601"
134
+ }
135
+ }
136
+ },
137
+ policy: { auth: "user", rbac: "org:member" }
138
+ });
139
+
140
+ contractSpec("saas.billing.recordUsage.v1", {
141
+ goal: "Record usage for billing purposes",
142
+ transport: { gql: { mutation: "recordUsage" } },
143
+ io: {
144
+ input: {
145
+ orgId: "string",
146
+ metric: "enum<'api_calls'|'storage_gb'|'seats'>",
147
+ quantity: "number",
148
+ timestamp: "ISO8601?"
149
+ },
150
+ output: {
151
+ usage: {
152
+ id: "string",
153
+ metric: "string",
154
+ quantity: "number",
155
+ recordedAt: "ISO8601"
156
+ }
157
+ }
158
+ },
159
+ events: ["billing.usage.recorded"]
160
+ });
161
+
162
+ contractSpec("saas.settings.update.v1", {
163
+ goal: "Update organization or user settings",
164
+ transport: { gql: { mutation: "updateSettings" } },
165
+ io: {
166
+ input: {
167
+ scope: "enum<'org'|'user'>",
168
+ targetId: "string",
169
+ settings: "Record<string, unknown>"
170
+ },
171
+ output: {
172
+ settings: {
173
+ scope: "string",
174
+ values: "Record<string, unknown>",
175
+ updatedAt: "ISO8601"
176
+ }
177
+ }
178
+ },
179
+ events: ["settings.updated"]
180
+ });`;
181
+ }
182
+
183
+ /**
184
+ * Agent Console spec
185
+ */
186
+ function generateAgentConsoleSpec(contracts: string[]): string {
187
+ return `// Agent Console Specs
188
+ // Contracts: ${contracts.join(', ')}
189
+
190
+ contractSpec("agent.run.execute.v1", {
191
+ goal: "Execute an agent run with specified tools",
192
+ transport: { gql: { mutation: "executeAgentRun" } },
193
+ io: {
194
+ input: {
195
+ agentId: "string",
196
+ input: "string",
197
+ tools: "string[]?",
198
+ maxSteps: "number?"
199
+ },
200
+ output: {
201
+ runId: "string",
202
+ status: "enum<'running'|'completed'|'failed'>",
203
+ steps: "number"
204
+ }
205
+ },
206
+ events: ["run.started", "run.completed", "run.failed"]
207
+ });
208
+
209
+ contractSpec("agent.tool.create.v1", {
210
+ goal: "Register a new tool in the tool registry",
211
+ transport: { gql: { mutation: "createTool" } },
212
+ io: {
213
+ input: {
214
+ name: "string",
215
+ description: "string",
216
+ category: "enum<'code'|'data'|'api'|'file'|'custom'>",
217
+ schema: "JSONSchema",
218
+ handler: "string"
219
+ },
220
+ output: {
221
+ tool: {
222
+ id: "string",
223
+ name: "string",
224
+ category: "string",
225
+ createdAt: "ISO8601"
226
+ }
227
+ }
228
+ },
229
+ events: ["tool.created"]
230
+ });
231
+
232
+ contractSpec("agent.agent.create.v1", {
233
+ goal: "Create a new AI agent configuration",
234
+ transport: { gql: { mutation: "createAgent" } },
235
+ io: {
236
+ input: {
237
+ name: "string",
238
+ description: "string",
239
+ model: "string",
240
+ systemPrompt: "string?",
241
+ tools: "string[]?"
242
+ },
243
+ output: {
244
+ agent: {
245
+ id: "string",
246
+ name: "string",
247
+ model: "string",
248
+ toolCount: "number",
249
+ createdAt: "ISO8601"
250
+ }
251
+ }
252
+ },
253
+ events: ["agent.created"]
254
+ });`;
255
+ }
256
+
257
+ /**
258
+ * Todos App spec
259
+ */
260
+ function generateTodosSpec(contracts: string[]): string {
261
+ return `// To-dos App Specs
262
+ // Contracts: ${contracts.join(', ')}
263
+
264
+ contractSpec("tasks.board.v1", {
265
+ goal: "Assign and approve craft work",
266
+ transport: { gql: { field: "tasksBoard" } },
267
+ io: {
268
+ input: {
269
+ tenantId: "string",
270
+ assignee: "string?",
271
+ status: "enum<'pending'|'in_progress'|'completed'>?"
272
+ },
273
+ output: {
274
+ tasks: "array<Task>",
275
+ summary: {
276
+ total: "number",
277
+ completed: "number",
278
+ overdue: "number"
279
+ }
280
+ }
281
+ }
282
+ });
283
+
284
+ contractSpec("tasks.create.v1", {
285
+ goal: "Create a new task",
286
+ transport: { gql: { mutation: "createTask" } },
287
+ io: {
288
+ input: {
289
+ title: "string",
290
+ description: "string?",
291
+ assignee: "string?",
292
+ priority: "enum<'low'|'medium'|'high'>",
293
+ dueDate: "ISO8601?"
294
+ },
295
+ output: {
296
+ task: {
297
+ id: "string",
298
+ title: "string",
299
+ status: "string",
300
+ createdAt: "ISO8601"
301
+ }
302
+ }
303
+ },
304
+ events: ["task.created"]
305
+ });
306
+
307
+ contractSpec("tasks.complete.v1", {
308
+ goal: "Mark a task as completed",
309
+ transport: { gql: { mutation: "completeTask" } },
310
+ io: {
311
+ input: { taskId: "string" },
312
+ output: {
313
+ task: {
314
+ id: "string",
315
+ status: "string",
316
+ completedAt: "ISO8601"
317
+ }
318
+ }
319
+ },
320
+ events: ["task.completed"]
321
+ });`;
322
+ }
323
+
324
+ /**
325
+ * Messaging App spec
326
+ */
327
+ function generateMessagingSpec(contracts: string[]): string {
328
+ return `// Messaging App Specs
329
+ // Contracts: ${contracts.join(', ')}
330
+
331
+ contractSpec("messaging.send.v1", {
332
+ goal: "Deliver intent-rich updates",
333
+ io: {
334
+ input: {
335
+ conversationId: "string",
336
+ body: "richtext",
337
+ attachments: "array<Attachment>?"
338
+ },
339
+ output: {
340
+ messageId: "string",
341
+ deliveredAt: "ISO8601"
342
+ }
343
+ },
344
+ events: ["message.sent", "message.delivered"]
345
+ });
346
+
347
+ contractSpec("messaging.conversation.create.v1", {
348
+ goal: "Start a new conversation",
349
+ transport: { gql: { mutation: "createConversation" } },
350
+ io: {
351
+ input: {
352
+ participants: "string[]",
353
+ title: "string?",
354
+ type: "enum<'direct'|'group'>"
355
+ },
356
+ output: {
357
+ conversation: {
358
+ id: "string",
359
+ title: "string?",
360
+ participantCount: "number",
361
+ createdAt: "ISO8601"
362
+ }
363
+ }
364
+ },
365
+ events: ["conversation.created"]
366
+ });
367
+
368
+ contractSpec("messaging.read.v1", {
369
+ goal: "Mark messages as read",
370
+ transport: { gql: { mutation: "markRead" } },
371
+ io: {
372
+ input: {
373
+ conversationId: "string",
374
+ messageIds: "string[]"
375
+ },
376
+ output: {
377
+ readCount: "number",
378
+ readAt: "ISO8601"
379
+ }
380
+ },
381
+ events: ["message.read"]
382
+ });`;
383
+ }
384
+
385
+ /**
386
+ * Recipe App spec
387
+ */
388
+ function generateRecipeSpec(contracts: string[]): string {
389
+ return `// Recipe App (i18n) Specs
390
+ // Contracts: ${contracts.join(', ')}
391
+
392
+ contractSpec("recipes.lookup.v1", {
393
+ goal: "Serve bilingual rituals",
394
+ io: {
395
+ input: {
396
+ locale: "enum<'EN'|'FR'>",
397
+ slug: "string"
398
+ },
399
+ output: {
400
+ title: "string",
401
+ content: "markdown",
402
+ ingredients: "array<Ingredient>",
403
+ instructions: "array<Instruction>"
404
+ }
405
+ }
406
+ });
407
+
408
+ contractSpec("recipes.list.v1", {
409
+ goal: "Browse recipes with filtering",
410
+ transport: { gql: { query: "listRecipes" } },
411
+ io: {
412
+ input: {
413
+ locale: "enum<'EN'|'FR'>",
414
+ category: "string?",
415
+ search: "string?",
416
+ favorites: "boolean?"
417
+ },
418
+ output: {
419
+ recipes: "array<RecipeSummary>",
420
+ categories: "array<Category>",
421
+ total: "number"
422
+ }
423
+ }
424
+ });
425
+
426
+ contractSpec("recipes.favorite.toggle.v1", {
427
+ goal: "Toggle recipe favorite status",
428
+ transport: { gql: { mutation: "toggleFavorite" } },
429
+ io: {
430
+ input: { recipeId: "string" },
431
+ output: {
432
+ isFavorite: "boolean",
433
+ totalFavorites: "number"
434
+ }
435
+ },
436
+ events: ["recipe.favorited", "recipe.unfavorited"]
437
+ });`;
438
+ }
439
+
440
+ /**
441
+ * Default spec for unknown templates
442
+ */
443
+ function generateDefaultSpec(templateId: TemplateId): string {
444
+ return `// ${templateId} Specs
445
+
446
+ contractSpec("${templateId}.main.v1", {
447
+ goal: "Main operation for ${templateId}",
448
+ transport: { gql: { query: "main" } },
449
+ io: {
450
+ input: {
451
+ id: "string"
452
+ },
453
+ output: {
454
+ result: "unknown"
455
+ }
456
+ }
457
+ });`;
458
+ }
@@ -0,0 +1,2 @@
1
+ export * from './generateSpecFromTemplate';
2
+ export * from './fetchPresentationData';
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "@contractspec/tool.typescript/react-library.json",
3
+ "compilerOptions": {
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "jsx": "react-jsx",
7
+ "outDir": "dist"
8
+ },
9
+ "include": ["src/**/*"]
10
+ }