@decocms/runtime 0.28.1 → 1.0.0-alpha.2

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.
Files changed (85) hide show
  1. package/package.json +15 -76
  2. package/scripts/generate-json-schema.ts +24 -0
  3. package/src/asset-server/dev-server-proxy.ts +16 -0
  4. package/src/asset-server/index.ts +44 -0
  5. package/src/bindings/README.md +1 -1
  6. package/src/bindings/binder.ts +1 -1
  7. package/src/bindings/channels.ts +1 -1
  8. package/src/bindings/deconfig/resources.ts +47 -17
  9. package/src/bindings/deconfig/types.ts +1 -1
  10. package/src/bindings/language-model/ai-sdk.ts +7 -4
  11. package/src/bindings/resources/bindings.ts +1 -1
  12. package/src/bindings/resources/schemas.ts +1 -1
  13. package/src/bindings/views.ts +1 -1
  14. package/src/bindings.ts +8 -7
  15. package/src/index.ts +5 -20
  16. package/src/mastra.ts +1 -229
  17. package/src/mcp.ts +7 -6
  18. package/src/proxy.ts +0 -8
  19. package/src/resources.ts +1 -1
  20. package/src/state.ts +1 -1
  21. package/src/views.ts +1 -1
  22. package/tsconfig.json +8 -0
  23. package/dist/admin.d.ts +0 -5
  24. package/dist/admin.js +0 -21
  25. package/dist/admin.js.map +0 -1
  26. package/dist/bindings/deconfig/index.d.ts +0 -12
  27. package/dist/bindings/deconfig/index.js +0 -10
  28. package/dist/bindings/deconfig/index.js.map +0 -1
  29. package/dist/bindings/index.d.ts +0 -2315
  30. package/dist/bindings/index.js +0 -156
  31. package/dist/bindings/index.js.map +0 -1
  32. package/dist/chunk-3AWMDSOH.js +0 -96
  33. package/dist/chunk-3AWMDSOH.js.map +0 -1
  34. package/dist/chunk-4XSQKJLU.js +0 -105
  35. package/dist/chunk-4XSQKJLU.js.map +0 -1
  36. package/dist/chunk-5EYZ2LVM.js +0 -158
  37. package/dist/chunk-5EYZ2LVM.js.map +0 -1
  38. package/dist/chunk-7ITSLORK.js +0 -128
  39. package/dist/chunk-7ITSLORK.js.map +0 -1
  40. package/dist/chunk-I7BWSAN6.js +0 -49
  41. package/dist/chunk-I7BWSAN6.js.map +0 -1
  42. package/dist/chunk-L4OT2YDO.js +0 -27
  43. package/dist/chunk-L4OT2YDO.js.map +0 -1
  44. package/dist/chunk-SHQSNOFL.js +0 -769
  45. package/dist/chunk-SHQSNOFL.js.map +0 -1
  46. package/dist/chunk-UHR3BLMF.js +0 -92
  47. package/dist/chunk-UHR3BLMF.js.map +0 -1
  48. package/dist/chunk-UIJGM3NV.js +0 -518
  49. package/dist/chunk-UIJGM3NV.js.map +0 -1
  50. package/dist/chunk-ZPUT6RN6.js +0 -32
  51. package/dist/chunk-ZPUT6RN6.js.map +0 -1
  52. package/dist/client.d.ts +0 -28
  53. package/dist/client.js +0 -5
  54. package/dist/client.js.map +0 -1
  55. package/dist/d1-store.d.ts +0 -9
  56. package/dist/d1-store.js +0 -4
  57. package/dist/d1-store.js.map +0 -1
  58. package/dist/drizzle.d.ts +0 -49
  59. package/dist/drizzle.js +0 -121
  60. package/dist/drizzle.js.map +0 -1
  61. package/dist/index-LOfgE9a_.d.ts +0 -471
  62. package/dist/index-xKtm7A7B.d.ts +0 -530
  63. package/dist/index.d.ts +0 -10
  64. package/dist/index.js +0 -637
  65. package/dist/index.js.map +0 -1
  66. package/dist/mastra.d.ts +0 -10
  67. package/dist/mastra.js +0 -6
  68. package/dist/mastra.js.map +0 -1
  69. package/dist/mcp-87iLaW9V.d.ts +0 -105
  70. package/dist/mcp-client.d.ts +0 -232
  71. package/dist/mcp-client.js +0 -4
  72. package/dist/mcp-client.js.map +0 -1
  73. package/dist/proxy.d.ts +0 -11
  74. package/dist/proxy.js +0 -5
  75. package/dist/proxy.js.map +0 -1
  76. package/dist/resources.d.ts +0 -362
  77. package/dist/resources.js +0 -4
  78. package/dist/resources.js.map +0 -1
  79. package/dist/views.d.ts +0 -72
  80. package/dist/views.js +0 -4
  81. package/dist/views.js.map +0 -1
  82. package/src/cf-imports.ts +0 -1
  83. package/src/d1-store.ts +0 -34
  84. package/src/deprecated.ts +0 -59
  85. package/src/workflow.ts +0 -193
@@ -1,769 +0,0 @@
1
- import { createMCPClientProxy, WELL_KNOWN_ORIGINS } from './chunk-5EYZ2LVM.js';
2
- import { normalizeDirectory, getMetadataString, ResourceUri, ResourcePath, toAsyncIterator } from './chunk-UHR3BLMF.js';
3
- import { createPrivateTool, createStreamableTool } from './chunk-UIJGM3NV.js';
4
- import { ViewsListOutputSchema } from './chunk-L4OT2YDO.js';
5
- import { env } from 'cloudflare:workers';
6
- import { z } from 'zod/v3';
7
-
8
- var Timings = z.object({
9
- sql_duration_ms: z.number().optional()
10
- });
11
- var Meta = z.object({
12
- changed_db: z.boolean().optional(),
13
- changes: z.number().optional(),
14
- duration: z.number().optional(),
15
- last_row_id: z.number().optional(),
16
- rows_read: z.number().optional(),
17
- rows_written: z.number().optional(),
18
- served_by_primary: z.boolean().optional(),
19
- served_by_region: z.enum(["WNAM", "ENAM", "WEUR", "EEUR", "APAC", "OC"]).optional(),
20
- size_after: z.number().optional(),
21
- timings: Timings.optional()
22
- });
23
- var QueryResult = z.object({
24
- meta: Meta.optional(),
25
- results: z.array(z.unknown()).optional(),
26
- success: z.boolean().optional()
27
- });
28
- [
29
- {
30
- name: "INTEGRATIONS_GET",
31
- inputSchema: z.object({
32
- id: z.string()
33
- }),
34
- outputSchema: z.object({
35
- connection: z.object({})
36
- })
37
- },
38
- {
39
- name: "DATABASES_RUN_SQL",
40
- inputSchema: z.object({
41
- sql: z.string().describe("The SQL query to run"),
42
- params: z.array(z.string()).describe("The parameters to pass to the SQL query")
43
- }),
44
- outputSchema: z.object({
45
- result: z.array(QueryResult)
46
- })
47
- }
48
- ];
49
- var global = createMCPFetchStub({});
50
- var MCPClient = new Proxy(
51
- {},
52
- {
53
- get(_, name) {
54
- if (name === "toJSON") {
55
- return null;
56
- }
57
- if (name === "forWorkspace") {
58
- return (workspace, token) => createMCPFetchStub({
59
- workspace,
60
- token,
61
- decoCmsApiUrl: env.DECO_API_URL
62
- });
63
- }
64
- if (name === "forConnection") {
65
- return (connection) => createMCPFetchStub({
66
- connection,
67
- decoCmsApiUrl: env.DECO_API_URL
68
- });
69
- }
70
- return global[name];
71
- }
72
- }
73
- );
74
- function createMCPFetchStub(options) {
75
- return createMCPClientProxy({
76
- ...options ?? {}
77
- });
78
- }
79
- var callbacksSchema = z.object({
80
- stream: z.string(),
81
- generate: z.string(),
82
- generateObject: z.string()
83
- });
84
- var channelIdSchema = z.object({
85
- workspace: z.string(),
86
- discriminator: z.string()
87
- });
88
- var channelBindingSchema = channelIdSchema.extend({
89
- agentId: z.string(),
90
- agentName: z.string(),
91
- agentLink: z.string()
92
- });
93
- var joinChannelSchema = channelBindingSchema.extend({
94
- callbacks: callbacksSchema
95
- });
96
- var listChannelsSchema = z.object({
97
- channels: z.array(
98
- z.object({
99
- label: z.string(),
100
- value: z.string()
101
- })
102
- )
103
- });
104
- var CHANNEL_BINDING = [
105
- {
106
- name: "DECO_CHAT_CHANNELS_JOIN",
107
- inputSchema: joinChannelSchema,
108
- outputSchema: z.any()
109
- },
110
- {
111
- name: "DECO_CHAT_CHANNELS_LEAVE",
112
- inputSchema: channelIdSchema,
113
- outputSchema: z.any()
114
- },
115
- {
116
- name: "DECO_CHAT_CHANNELS_LIST",
117
- inputSchema: z.any(),
118
- outputSchema: listChannelsSchema,
119
- opt: true
120
- }
121
- ];
122
- var VIEW_BINDING = [
123
- {
124
- name: "DECO_CHAT_VIEWS_LIST",
125
- inputSchema: z.any(),
126
- outputSchema: ViewsListOutputSchema
127
- }
128
- ];
129
- var listViewsSchema = ViewsListOutputSchema;
130
-
131
- // src/bindings/binder.ts
132
- var bindingClient = (binder) => {
133
- return {
134
- implements: (tools) => {
135
- return binder.every(
136
- (tool) => tool.opt === true || (tools ?? []).some((t) => t.name === tool.name)
137
- );
138
- },
139
- forConnection: (mcpConnection) => {
140
- return createMCPFetchStub({
141
- connection: mcpConnection,
142
- streamable: binder.reduce(
143
- (acc, tool) => {
144
- acc[tool.name] = tool.streamable === true;
145
- return acc;
146
- },
147
- {}
148
- )
149
- });
150
- }
151
- };
152
- };
153
- var ChannelBinding = bindingClient(CHANNEL_BINDING);
154
- var ViewBinding = bindingClient(VIEW_BINDING);
155
- var impl = (schema, implementation, createToolFn = createPrivateTool, createStreamableToolFn = createStreamableTool) => {
156
- const impl2 = [];
157
- for (const key in schema) {
158
- const toolSchema = schema[key];
159
- const toolImplementation = implementation[key];
160
- if (toolSchema.opt && !toolImplementation) {
161
- continue;
162
- }
163
- if (!toolImplementation) {
164
- throw new Error(`Implementation for ${key} is required`);
165
- }
166
- const { name, handler, streamable, ...toolLike } = {
167
- ...toolSchema,
168
- ...toolImplementation
169
- };
170
- if (streamable) {
171
- impl2.push(
172
- createStreamableToolFn({
173
- ...toolLike,
174
- streamable,
175
- id: name,
176
- execute: ({ context }) => Promise.resolve(handler(context))
177
- })
178
- );
179
- } else {
180
- impl2.push(
181
- createToolFn({
182
- ...toolLike,
183
- id: name,
184
- execute: ({ context }) => Promise.resolve(handler(context))
185
- })
186
- );
187
- }
188
- }
189
- return impl2;
190
- };
191
- var ResourceUriSchema = z.string().regex(
192
- /^rsc:\/\/[^/]+\/[^/]+\/.+$/,
193
- "Invalid resource URI format. Expected format: rsc://workspace/project/resource-id"
194
- );
195
- var DescribeInputSchema = z.object({});
196
- var DescribeOutputSchema = z.object({
197
- uriTemplate: ResourceUriSchema.describe("URI template for the resource"),
198
- features: z.object({
199
- watch: z.object({
200
- pathname: z.string().describe("Pathname to watch")
201
- })
202
- })
203
- });
204
- var SearchInputSchema = z.object({
205
- term: z.string().optional().describe("Search term to filter resources"),
206
- page: z.number().int().min(1).default(1).describe("Page number (1-based)"),
207
- pageSize: z.number().int().min(1).max(100).default(20).describe("Number of items per page"),
208
- filters: z.record(z.any()).optional().describe("Additional filters to apply"),
209
- sortBy: z.string().optional().describe("Field to sort by"),
210
- sortOrder: z.enum(["asc", "desc"]).optional().default("asc").describe("Sort order")
211
- });
212
- function createSearchOutputSchema(itemSchema) {
213
- return z.object({
214
- items: z.array(itemSchema).describe("Array of matching resources"),
215
- totalCount: z.number().int().min(0).describe("Total number of matching resources"),
216
- page: z.number().int().min(1).describe("Current page number"),
217
- pageSize: z.number().int().min(1).describe("Number of items per page"),
218
- totalPages: z.number().int().min(0).describe("Total number of pages"),
219
- hasNextPage: z.boolean().describe("Whether there are more pages available"),
220
- hasPreviousPage: z.boolean().describe("Whether there are previous pages available")
221
- });
222
- }
223
- var ReadInputSchema = z.object({
224
- uri: ResourceUriSchema.describe("URI of the resource to read")
225
- });
226
- function createReadOutputSchema(dataSchema) {
227
- return z.object({
228
- uri: ResourceUriSchema.describe("URI of the resource"),
229
- data: dataSchema.describe("Resource data"),
230
- created_at: z.string().datetime().optional().describe("Creation timestamp"),
231
- updated_at: z.string().datetime().optional().describe("Last update timestamp"),
232
- created_by: z.string().optional().describe("User who created the resource"),
233
- updated_by: z.string().optional().describe("User who last updated the resource")
234
- });
235
- }
236
- function createCreateInputSchema(dataSchema) {
237
- return z.object({
238
- data: dataSchema.describe("Resource data to create")
239
- });
240
- }
241
- function createCreateOutputSchema(dataSchema) {
242
- return z.object({
243
- uri: ResourceUriSchema.describe("URI of the created resource"),
244
- data: dataSchema.describe("Created resource data"),
245
- created_at: z.string().datetime().optional().describe("Creation timestamp"),
246
- updated_at: z.string().datetime().optional().describe("Last update timestamp"),
247
- created_by: z.string().optional().describe("User who created the resource")
248
- });
249
- }
250
- function createUpdateInputSchema(dataSchema) {
251
- return z.object({
252
- uri: ResourceUriSchema.describe("URI of the resource to update"),
253
- data: dataSchema.describe("Updated resource data")
254
- });
255
- }
256
- function createUpdateOutputSchema(dataSchema) {
257
- return z.object({
258
- uri: ResourceUriSchema.describe("URI of the updated resource"),
259
- data: dataSchema.describe("Updated resource data"),
260
- created_at: z.string().datetime().optional().describe("Original creation timestamp"),
261
- updated_at: z.string().datetime().optional().describe("Last update timestamp"),
262
- created_by: z.string().optional().describe("User who originally created the resource"),
263
- updated_by: z.string().optional().describe("User who last updated the resource")
264
- });
265
- }
266
- var DeleteInputSchema = z.object({
267
- uri: ResourceUriSchema.describe("URI of the resource to delete")
268
- });
269
- var DeleteOutputSchema = z.object({
270
- success: z.boolean().describe("Whether the deletion was successful"),
271
- uri: ResourceUriSchema.describe("URI of the deleted resource")
272
- });
273
- function createItemSchema(dataSchema) {
274
- return z.object({
275
- uri: ResourceUriSchema.describe("URI of the resource"),
276
- data: z.object({
277
- name: z.string().min(1, "Name is required"),
278
- description: z.string().optional().describe("Description of the resource"),
279
- icon: z.string().url().optional().describe("URL to the resource icon")
280
- }).and(dataSchema).describe("Resource data with required name"),
281
- created_at: z.string().datetime().optional().describe("Creation timestamp"),
282
- updated_at: z.string().datetime().optional().describe("Last update timestamp"),
283
- created_by: z.string().optional().describe("User who created the resource"),
284
- updated_by: z.string().optional().describe("User who last updated the resource")
285
- });
286
- }
287
-
288
- // src/bindings/resources/bindings.ts
289
- function createResourceBindings(resourceName, dataSchema) {
290
- const readOutputSchema = createReadOutputSchema(dataSchema);
291
- return [
292
- {
293
- name: `DECO_RESOURCE_${resourceName.toUpperCase()}_SEARCH`,
294
- inputSchema: SearchInputSchema,
295
- outputSchema: createSearchOutputSchema(
296
- createItemSchema(dataSchema.pick({ name: true, description: true }))
297
- )
298
- },
299
- {
300
- name: `DECO_RESOURCE_${resourceName.toUpperCase()}_READ`,
301
- inputSchema: ReadInputSchema,
302
- outputSchema: readOutputSchema
303
- },
304
- {
305
- name: `DECO_RESOURCE_${resourceName.toUpperCase()}_CREATE`,
306
- inputSchema: createCreateInputSchema(dataSchema),
307
- outputSchema: createCreateOutputSchema(dataSchema),
308
- opt: true
309
- },
310
- {
311
- name: `DECO_RESOURCE_${resourceName.toUpperCase()}_UPDATE`,
312
- inputSchema: createUpdateInputSchema(dataSchema),
313
- outputSchema: createUpdateOutputSchema(dataSchema),
314
- opt: true
315
- },
316
- {
317
- name: `DECO_RESOURCE_${resourceName.toUpperCase()}_DELETE`,
318
- inputSchema: DeleteInputSchema,
319
- outputSchema: DeleteOutputSchema,
320
- opt: true
321
- },
322
- {
323
- name: `DECO_RESOURCE_${resourceName.toUpperCase()}_DESCRIBE`,
324
- inputSchema: DescribeInputSchema,
325
- outputSchema: DescribeOutputSchema,
326
- opt: true
327
- }
328
- ];
329
- }
330
-
331
- // src/bindings/deconfig/resources.ts
332
- var NotFoundError = class extends Error {
333
- constructor(message) {
334
- super(message);
335
- this.name = "NotFoundError";
336
- }
337
- };
338
- var UserInputError = class extends Error {
339
- constructor(message) {
340
- super(message);
341
- this.name = "UserInputError";
342
- }
343
- };
344
- var dirOf = (options) => {
345
- return options.directory ? options.directory : `/resources/${options.resourceName}`;
346
- };
347
- var createDeconfigResource = (options) => {
348
- const {
349
- resourceName,
350
- dataSchema,
351
- enhancements,
352
- env: env2,
353
- validate: semanticValidate
354
- } = options;
355
- const deconfig = env2.DECONFIG;
356
- const directory = dirOf(options);
357
- const resourceBindings = createResourceBindings(resourceName, dataSchema);
358
- const tools = impl(resourceBindings, [
359
- // deco_resource_search
360
- {
361
- description: enhancements?.[`DECO_RESOURCE_${resourceName.toUpperCase()}_SEARCH`]?.description || `Search ${resourceName} resources in the DECONFIG directory ${directory}`,
362
- handler: async ({
363
- term,
364
- page = 1,
365
- pageSize = 10,
366
- filters,
367
- sortBy,
368
- sortOrder
369
- }) => {
370
- const normalizedDir = normalizeDirectory(directory);
371
- const offset = pageSize !== Infinity ? (page - 1) * pageSize : 0;
372
- const filesList = await deconfig.LIST_FILES({
373
- prefix: normalizedDir
374
- });
375
- const allFiles = Object.entries(filesList.files).filter(([path]) => path.endsWith(".json")).map(([path, metadata]) => ({
376
- path,
377
- resourceId: path.replace(`${normalizedDir}/`, "").replace(".json", ""),
378
- metadata
379
- }));
380
- let filteredFiles = allFiles;
381
- if (term) {
382
- filteredFiles = allFiles.filter(({ resourceId, path, metadata }) => {
383
- const searchTerm = term.toLowerCase();
384
- return resourceId.toLowerCase().includes(searchTerm) || path.toLowerCase().includes(searchTerm) || (getMetadataString(metadata, "name")?.toLowerCase() ?? "").includes(searchTerm) || (getMetadataString(metadata, "description")?.toLowerCase() ?? "").includes(searchTerm) || (getMetadataString(metadata, "createdBy")?.toLowerCase() ?? "").includes(searchTerm) || (getMetadataString(metadata, "updatedBy")?.toLowerCase() ?? "").includes(searchTerm);
385
- });
386
- }
387
- if (filters) {
388
- const createdByFilter = filters.created_by;
389
- const updatedByFilter = filters.updated_by;
390
- if (createdByFilter) {
391
- const createdBySet = new Set(
392
- Array.isArray(createdByFilter) ? createdByFilter.map((v) => String(v)) : [String(createdByFilter)]
393
- );
394
- filteredFiles = filteredFiles.filter(({ metadata }) => {
395
- const value = getMetadataString(metadata, "createdBy");
396
- return value ? createdBySet.has(value) : false;
397
- });
398
- }
399
- if (updatedByFilter) {
400
- const updatedBySet = new Set(
401
- Array.isArray(updatedByFilter) ? updatedByFilter.map((v) => String(v)) : [String(updatedByFilter)]
402
- );
403
- filteredFiles = filteredFiles.filter(({ metadata }) => {
404
- const value = getMetadataString(metadata, "updatedBy");
405
- return value ? updatedBySet.has(value) : false;
406
- });
407
- }
408
- }
409
- if (sortBy) {
410
- filteredFiles.sort((a, b) => {
411
- let aValue;
412
- let bValue;
413
- if (sortBy === "resourceId") {
414
- aValue = a.resourceId;
415
- bValue = b.resourceId;
416
- } else if (sortBy === "name") {
417
- aValue = getMetadataString(a.metadata, "name") || a.resourceId;
418
- bValue = getMetadataString(b.metadata, "name") || b.resourceId;
419
- } else if (sortBy === "description") {
420
- aValue = getMetadataString(a.metadata, "description") || "";
421
- bValue = getMetadataString(b.metadata, "description") || "";
422
- } else {
423
- aValue = a.metadata.mtime;
424
- bValue = b.metadata.mtime;
425
- }
426
- if (sortOrder === "desc") {
427
- return aValue < bValue ? 1 : aValue > bValue ? -1 : 0;
428
- } else {
429
- return aValue > bValue ? 1 : aValue < bValue ? -1 : 0;
430
- }
431
- });
432
- }
433
- const totalCount = filteredFiles.length;
434
- const totalPages = Math.ceil(totalCount / pageSize);
435
- const hasNextPage = offset + pageSize < totalCount;
436
- const hasPreviousPage = page > 1;
437
- const items = filteredFiles.slice(offset, offset + pageSize);
438
- return {
439
- items: items.map(({ resourceId, metadata }) => {
440
- const uri = ResourceUri.build(
441
- env2.DECO_REQUEST_CONTEXT.integrationId,
442
- resourceName,
443
- resourceId
444
- );
445
- const name = getMetadataString(metadata, "name") || resourceId;
446
- const description = getMetadataString(metadata, "description") || "";
447
- return {
448
- uri,
449
- data: { name, description },
450
- created_at: "ctime" in metadata && typeof metadata.ctime === "number" ? new Date(metadata.ctime).toISOString() : void 0,
451
- updated_at: "mtime" in metadata && typeof metadata.mtime === "number" ? new Date(metadata.mtime).toISOString() : void 0,
452
- created_by: getMetadataString(metadata, "createdBy"),
453
- updated_by: getMetadataString(metadata, "updatedBy") || getMetadataString(metadata, "createdBy")
454
- };
455
- }),
456
- totalCount,
457
- page,
458
- pageSize,
459
- totalPages,
460
- hasNextPage,
461
- hasPreviousPage
462
- };
463
- }
464
- },
465
- // deco_resource_read
466
- {
467
- description: enhancements?.[`DECO_RESOURCE_${resourceName.toUpperCase()}_READ`]?.description || `Read a ${resourceName} resource from the DECONFIG directory ${directory}`,
468
- handler: async ({ uri }) => {
469
- ResourceUriSchema.parse(uri);
470
- const resourceId = ResourceUri.unwind(uri).resourceId;
471
- const filePath = ResourcePath.build(directory, resourceId);
472
- try {
473
- const fileData = await deconfig.READ_FILE({
474
- path: filePath,
475
- format: "plainString"
476
- });
477
- const content = fileData.content;
478
- let parsedData = {};
479
- try {
480
- parsedData = JSON.parse(content);
481
- } catch {
482
- throw new UserInputError("Invalid JSON content in resource file");
483
- }
484
- const validatedData = dataSchema.parse(parsedData);
485
- return {
486
- uri,
487
- data: validatedData,
488
- created_at: new Date(fileData.ctime).toISOString(),
489
- updated_at: new Date(fileData.mtime).toISOString(),
490
- created_by: parsedData && "created_by" in parsedData && typeof parsedData.created_by === "string" ? parsedData.created_by : void 0,
491
- updated_by: parsedData && "updated_by" in parsedData && typeof parsedData.updated_by === "string" ? parsedData.updated_by : void 0
492
- };
493
- } catch (error) {
494
- if (error instanceof Error && error.message.includes("not found")) {
495
- throw new NotFoundError(`Resource not found: ${uri}`);
496
- }
497
- throw error;
498
- }
499
- }
500
- },
501
- // deco_resource_create (optional)
502
- {
503
- description: enhancements?.[`DECO_RESOURCE_${resourceName.toUpperCase()}_CREATE`]?.description || `Create a new ${resourceName} resource in the DECONFIG directory ${directory}`,
504
- handler: async ({ data }) => {
505
- const validatedData = dataSchema.parse(data);
506
- if (semanticValidate) {
507
- await semanticValidate(validatedData);
508
- }
509
- const resourceId = validatedData.name?.replace(/[^a-zA-Z0-9-_]/g, "-") || crypto.randomUUID();
510
- const uri = ResourceUri.build(
511
- env2.DECO_REQUEST_CONTEXT.integrationId,
512
- resourceName,
513
- resourceId
514
- );
515
- const filePath = ResourcePath.build(directory, resourceId);
516
- const user = env2.DECO_REQUEST_CONTEXT.ensureAuthenticated();
517
- const resourceData = {
518
- ...validatedData,
519
- id: resourceId,
520
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
521
- updated_at: (/* @__PURE__ */ new Date()).toISOString(),
522
- created_by: user?.id ? String(user.id) : void 0,
523
- updated_by: user?.id ? String(user.id) : void 0
524
- };
525
- const fileContent = JSON.stringify(resourceData, null, 2);
526
- const putResult = await deconfig.PUT_FILE({
527
- path: filePath,
528
- content: fileContent,
529
- metadata: {
530
- resourceType: resourceName,
531
- resourceId,
532
- createdBy: user?.id,
533
- name: validatedData.name || resourceId,
534
- description: validatedData.description || ""
535
- }
536
- });
537
- if (putResult.conflict) {
538
- throw new UserInputError(
539
- "Resource write conflicted. Please refresh and retry."
540
- );
541
- }
542
- return {
543
- uri,
544
- data: validatedData,
545
- created_at: resourceData.created_at,
546
- updated_at: resourceData.updated_at,
547
- created_by: user?.id ? String(user.id) : void 0,
548
- updated_by: user?.id ? String(user.id) : void 0
549
- };
550
- }
551
- },
552
- // deco_resource_update (optional)
553
- {
554
- description: enhancements?.[`DECO_RESOURCE_${resourceName.toUpperCase()}_UPDATE`]?.description || `Update a ${resourceName} resource in the DECONFIG directory ${directory}`,
555
- handler: async ({ uri, data }) => {
556
- ResourceUriSchema.parse(uri);
557
- const resourceId = ResourceUri.unwind(uri).resourceId;
558
- const filePath = ResourcePath.build(directory, resourceId);
559
- let existingData = {};
560
- try {
561
- const fileData = await deconfig.READ_FILE({
562
- path: filePath,
563
- format: "plainString"
564
- });
565
- existingData = JSON.parse(fileData.content);
566
- } catch {
567
- throw new NotFoundError(`Resource not found: ${uri}`);
568
- }
569
- const validatedData = dataSchema.parse(data);
570
- if (semanticValidate) {
571
- await semanticValidate(validatedData);
572
- }
573
- const user = env2.DECO_REQUEST_CONTEXT.ensureAuthenticated();
574
- const previousCreatedBy = typeof existingData["created_by"] === "string" ? existingData["created_by"] : void 0;
575
- const updatedData = {
576
- ...existingData,
577
- ...validatedData,
578
- id: resourceId,
579
- createdBy: previousCreatedBy,
580
- updated_at: (/* @__PURE__ */ new Date()).toISOString(),
581
- updated_by: user?.id ? String(user.id) : void 0
582
- };
583
- const fileContent = JSON.stringify(updatedData, null, 2);
584
- const putResult = await deconfig.PUT_FILE({
585
- path: filePath,
586
- content: fileContent,
587
- metadata: {
588
- resourceType: resourceName,
589
- resourceId,
590
- updatedBy: user?.id,
591
- name: validatedData.name || resourceId,
592
- description: validatedData.description || ""
593
- }
594
- });
595
- if (putResult.conflict) {
596
- throw new UserInputError(
597
- "Resource write conflicted. Please refresh and retry."
598
- );
599
- }
600
- return {
601
- uri,
602
- data: validatedData,
603
- created_at: existingData.created_at,
604
- updated_at: updatedData.updated_at,
605
- created_by: existingData.created_by,
606
- updated_by: user?.id ? String(user.id) : void 0
607
- };
608
- }
609
- },
610
- // deco_resource_delete (optional)
611
- {
612
- description: enhancements?.[`DECO_RESOURCE_${resourceName.toUpperCase()}_DELETE`]?.description || `Delete a ${resourceName} resource from the DECONFIG directory ${directory}`,
613
- handler: async ({ uri }) => {
614
- ResourceUriSchema.parse(uri);
615
- const resourceId = ResourceUri.unwind(uri).resourceId;
616
- const filePath = ResourcePath.build(directory, resourceId);
617
- try {
618
- await deconfig.DELETE_FILE({
619
- path: filePath
620
- });
621
- return {
622
- success: true,
623
- uri
624
- };
625
- } catch (error) {
626
- if (error instanceof Error && error.message.includes("not found")) {
627
- throw new NotFoundError(`Resource not found: ${uri}`);
628
- }
629
- throw error;
630
- }
631
- }
632
- },
633
- {
634
- description: enhancements?.[`DECO_RESOURCE_${resourceName.toUpperCase()}_DESCRIBE`]?.description || `Describe the ${resourceName} resource in the DECONFIG directory ${directory}`,
635
- handler: () => {
636
- return {
637
- uriTemplate: ResourceUri.build(
638
- env2.DECO_REQUEST_CONTEXT.integrationId,
639
- resourceName,
640
- "*"
641
- ),
642
- features: {
643
- watch: {
644
- pathname: `${RESOURCE_WATCH_BASE_PATHNAME}${directory}`
645
- }
646
- }
647
- };
648
- }
649
- }
650
- ]);
651
- return tools;
652
- };
653
- var removeLeadingSlash = (url) => {
654
- return url.startsWith("/") ? url.slice(1) : url;
655
- };
656
- var watcher = ({
657
- env: env2,
658
- pathFilter,
659
- resourceName,
660
- ...options
661
- }) => {
662
- const url = new URL(
663
- `/${removeLeadingSlash(env2.DECO_REQUEST_CONTEXT.workspace)}/deconfig/watch`,
664
- `${env2.DECO_API_URL ?? "https://api.decocms.com"}`
665
- );
666
- if (options.watcherId) {
667
- url.searchParams.set("watcher-id", options.watcherId);
668
- }
669
- url.searchParams.set("path-filter", pathFilter);
670
- url.searchParams.set("branch", env2.DECO_REQUEST_CONTEXT.branch ?? "main");
671
- url.searchParams.set("auth-token", env2.DECO_REQUEST_CONTEXT.token);
672
- url.searchParams.set("from-ctime", "1");
673
- const eventSource = new EventSource(url);
674
- const it = toAsyncIterator(eventSource, "change");
675
- const iterator = async function* () {
676
- for await (const event of it) {
677
- const { path } = event;
678
- try {
679
- const { resourceId } = ResourcePath.extract(path);
680
- const uri = ResourceUri.build(
681
- env2.DECO_REQUEST_CONTEXT.integrationId,
682
- resourceName,
683
- resourceId
684
- );
685
- yield { uri };
686
- } catch {
687
- }
688
- }
689
- };
690
- const mIterator = iterator();
691
- const retn = mIterator.return;
692
- mIterator.return = function(val) {
693
- eventSource.close();
694
- return retn?.call(mIterator, val) ?? val;
695
- };
696
- return mIterator;
697
- };
698
- var hasDeconfigBinding = (env2) => {
699
- return env2 !== void 0 && typeof env2 === "object" && env2 !== null && "DECONFIG" in env2;
700
- };
701
- var RESOURCE_WATCH_BASE_PATHNAME = "/resources/watch";
702
- var DeconfigResource = {
703
- WatchPathNameBase: RESOURCE_WATCH_BASE_PATHNAME,
704
- watchAPI: (req, env2) => {
705
- if (!hasDeconfigBinding(env2)) {
706
- return new Response("DECONFIG:@deco/deconfig binding is required", {
707
- status: 400
708
- });
709
- }
710
- const url = new URL(req.url);
711
- const uri = url.searchParams.get("uri");
712
- if (!uri) {
713
- return new Response("URI is required", { status: 400 });
714
- }
715
- const pathname = url.pathname;
716
- let pathFilter = pathname.slice(RESOURCE_WATCH_BASE_PATHNAME.length);
717
- const { resourceName, resourceId } = ResourceUri.unwind(uri);
718
- pathFilter = resourceId === "*" ? pathFilter : ResourcePath.build(pathFilter, resourceId);
719
- const watch = watcher({
720
- env: env2,
721
- resourceName,
722
- pathFilter
723
- });
724
- const sseStream = new ReadableStream({
725
- async start(controller) {
726
- const encoder = new TextEncoder();
727
- try {
728
- for await (const event of watch) {
729
- const sseData = `data: ${JSON.stringify(event)}
730
-
731
- `;
732
- controller.enqueue(encoder.encode(sseData));
733
- }
734
- controller.close();
735
- } catch (error) {
736
- controller.error(error);
737
- }
738
- },
739
- cancel() {
740
- watch.return?.();
741
- }
742
- });
743
- return new Response(sseStream, {
744
- status: 200,
745
- headers: {
746
- "Content-Type": "text/event-stream",
747
- "Cache-Control": "no-cache",
748
- Connection: "keep-alive",
749
- "Access-Control-Allow-Origin": WELL_KNOWN_ORIGINS.join(","),
750
- "Access-Control-Allow-Headers": "Cache-Control"
751
- }
752
- });
753
- },
754
- define: (options) => {
755
- return {
756
- watcher,
757
- create: (env2) => {
758
- return createDeconfigResource({
759
- env: env2,
760
- ...options
761
- });
762
- }
763
- };
764
- }
765
- };
766
-
767
- export { CHANNEL_BINDING, ChannelBinding, DeconfigResource, DeleteInputSchema, DeleteOutputSchema, DescribeInputSchema, DescribeOutputSchema, MCPClient, NotFoundError, RESOURCE_WATCH_BASE_PATHNAME, ReadInputSchema, ResourceUriSchema, SearchInputSchema, UserInputError, VIEW_BINDING, ViewBinding, bindingClient, createCreateInputSchema, createCreateOutputSchema, createDeconfigResource, createItemSchema, createMCPFetchStub, createReadOutputSchema, createResourceBindings, createSearchOutputSchema, createUpdateInputSchema, createUpdateOutputSchema, impl, listViewsSchema };
768
- //# sourceMappingURL=chunk-SHQSNOFL.js.map
769
- //# sourceMappingURL=chunk-SHQSNOFL.js.map