@sap/joule-studio-dev-cli 0.1.20-alpha.3

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 (119) hide show
  1. package/LICENSE +38 -0
  2. package/README.md +53 -0
  3. package/dist/bin/commands/a2a.js +12 -0
  4. package/dist/bin/commands/a2a.js.map +1 -0
  5. package/dist/bin/commands/asset.js +20 -0
  6. package/dist/bin/commands/asset.js.map +1 -0
  7. package/dist/bin/commands/auth.js +16 -0
  8. package/dist/bin/commands/auth.js.map +1 -0
  9. package/dist/bin/commands/init.js +20 -0
  10. package/dist/bin/commands/init.js.map +1 -0
  11. package/dist/bin/commands/mcp.js +42 -0
  12. package/dist/bin/commands/mcp.js.map +1 -0
  13. package/dist/bin/commands/pro-code.js +12 -0
  14. package/dist/bin/commands/pro-code.js.map +1 -0
  15. package/dist/bin/commands/skills.js +27 -0
  16. package/dist/bin/commands/skills.js.map +1 -0
  17. package/dist/bin/commands/solution.js +52 -0
  18. package/dist/bin/commands/solution.js.map +1 -0
  19. package/dist/bin/help.js +42 -0
  20. package/dist/bin/help.js.map +1 -0
  21. package/dist/bin/jl.js +59 -0
  22. package/dist/bin/jl.js.map +1 -0
  23. package/dist/bin/login.js +60 -0
  24. package/dist/bin/login.js.map +1 -0
  25. package/dist/bin/logout.js +21 -0
  26. package/dist/bin/logout.js.map +1 -0
  27. package/dist/lib/a2a/message.js +74 -0
  28. package/dist/lib/a2a/message.js.map +1 -0
  29. package/dist/lib/asset/create.js +38 -0
  30. package/dist/lib/asset/create.js.map +1 -0
  31. package/dist/lib/asset/delete.js +57 -0
  32. package/dist/lib/asset/delete.js.map +1 -0
  33. package/dist/lib/asset/discover.js +46 -0
  34. package/dist/lib/asset/discover.js.map +1 -0
  35. package/dist/lib/auth-crypto.js +146 -0
  36. package/dist/lib/auth-crypto.js.map +1 -0
  37. package/dist/lib/auth.js +488 -0
  38. package/dist/lib/auth.js.map +1 -0
  39. package/dist/lib/context.js +35 -0
  40. package/dist/lib/context.js.map +1 -0
  41. package/dist/lib/errors.js +47 -0
  42. package/dist/lib/errors.js.map +1 -0
  43. package/dist/lib/fs-utils.js +34 -0
  44. package/dist/lib/fs-utils.js.map +1 -0
  45. package/dist/lib/init/agents.js +55 -0
  46. package/dist/lib/init/agents.js.map +1 -0
  47. package/dist/lib/init/shared.js +172 -0
  48. package/dist/lib/init/shared.js.map +1 -0
  49. package/dist/lib/mcp/call.js +158 -0
  50. package/dist/lib/mcp/call.js.map +1 -0
  51. package/dist/lib/mcp/client.js +100 -0
  52. package/dist/lib/mcp/client.js.map +1 -0
  53. package/dist/lib/mcp/list.js +20 -0
  54. package/dist/lib/mcp/list.js.map +1 -0
  55. package/dist/lib/mcp/start.js +120 -0
  56. package/dist/lib/mcp/start.js.map +1 -0
  57. package/dist/lib/mcp/tools.js +162 -0
  58. package/dist/lib/mcp/tools.js.map +1 -0
  59. package/dist/lib/plugin.js +77 -0
  60. package/dist/lib/plugin.js.map +1 -0
  61. package/dist/lib/plugins/agent/index.js +32 -0
  62. package/dist/lib/plugins/agent/index.js.map +1 -0
  63. package/dist/lib/plugins/agent/templates/asset.yaml.hbs +31 -0
  64. package/dist/lib/plugins/agent-extension/index.js +32 -0
  65. package/dist/lib/plugins/agent-extension/index.js.map +1 -0
  66. package/dist/lib/plugins/agent-extension/templates/asset.yaml.hbs +15 -0
  67. package/dist/lib/plugins/base-ui/index.js +32 -0
  68. package/dist/lib/plugins/base-ui/index.js.map +1 -0
  69. package/dist/lib/plugins/base-ui/templates/asset.yaml.hbs +8 -0
  70. package/dist/lib/plugins/cap-app/index.js +32 -0
  71. package/dist/lib/plugins/cap-app/index.js.map +1 -0
  72. package/dist/lib/plugins/cap-app/templates/asset.yaml.hbs +37 -0
  73. package/dist/lib/plugins/data-product/index.js +32 -0
  74. package/dist/lib/plugins/data-product/index.js.map +1 -0
  75. package/dist/lib/plugins/data-product/templates/asset.yaml.hbs +9 -0
  76. package/dist/lib/plugins/domain-model-extension/index.js +37 -0
  77. package/dist/lib/plugins/domain-model-extension/index.js.map +1 -0
  78. package/dist/lib/plugins/domain-model-extension/templates/asset.yaml.hbs +15 -0
  79. package/dist/lib/plugins/mcp-server/index.js +36 -0
  80. package/dist/lib/plugins/mcp-server/index.js.map +1 -0
  81. package/dist/lib/plugins/mcp-server/templates/asset.yaml.hbs +9 -0
  82. package/dist/lib/plugins/n8n-workflow/index.js +52 -0
  83. package/dist/lib/plugins/n8n-workflow/index.js.map +1 -0
  84. package/dist/lib/plugins/n8n-workflow/templates/asset.yaml.hbs +18 -0
  85. package/dist/lib/plugins/n8n-workflow/validation/asset-validator.js +62 -0
  86. package/dist/lib/plugins/n8n-workflow/validation/asset-validator.js.map +1 -0
  87. package/dist/lib/plugins/n8n-workflow/validation/yaml-validator.js +51 -0
  88. package/dist/lib/plugins/n8n-workflow/validation/yaml-validator.js.map +1 -0
  89. package/dist/lib/plugins/vercel-app/index.js +32 -0
  90. package/dist/lib/plugins/vercel-app/index.js.map +1 -0
  91. package/dist/lib/plugins/vercel-app/templates/asset.yaml.hbs +12 -0
  92. package/dist/lib/rule.js +2 -0
  93. package/dist/lib/rule.js.map +1 -0
  94. package/dist/lib/schemas/solution-schema.json +178 -0
  95. package/dist/lib/solution/build.js +186 -0
  96. package/dist/lib/solution/build.js.map +1 -0
  97. package/dist/lib/solution/create.js +42 -0
  98. package/dist/lib/solution/create.js.map +1 -0
  99. package/dist/lib/solution/deploy.js +66 -0
  100. package/dist/lib/solution/deploy.js.map +1 -0
  101. package/dist/lib/solution/list.js +21 -0
  102. package/dist/lib/solution/list.js.map +1 -0
  103. package/dist/lib/solution/logs.js +130 -0
  104. package/dist/lib/solution/logs.js.map +1 -0
  105. package/dist/lib/solution/status.js +161 -0
  106. package/dist/lib/solution/status.js.map +1 -0
  107. package/dist/lib/solution/templates/solution.yaml.hbs +9 -0
  108. package/dist/lib/solution/util/build-file.js +4 -0
  109. package/dist/lib/solution/util/build-file.js.map +1 -0
  110. package/dist/lib/template.js +74 -0
  111. package/dist/lib/template.js.map +1 -0
  112. package/dist/lib/term.js +16 -0
  113. package/dist/lib/term.js.map +1 -0
  114. package/dist/lib/validate.js +287 -0
  115. package/dist/lib/validate.js.map +1 -0
  116. package/dist/lib/yaml.js +33 -0
  117. package/dist/lib/yaml.js.map +1 -0
  118. package/dist/package.json +77 -0
  119. package/package.json +77 -0
@@ -0,0 +1,32 @@
1
+ import path from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ import Plugin from '../../plugin.js';
4
+ import { render } from '../../template.js';
5
+ import fsUtils from '../../fs-utils.js';
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+ class DataProductPlugin extends Plugin {
8
+ assetType() {
9
+ return 'data-product';
10
+ }
11
+ sourceRoot() {
12
+ return '.';
13
+ }
14
+ provides() {
15
+ return {};
16
+ }
17
+ templateDir() {
18
+ return path.join(__dirname, 'templates');
19
+ }
20
+ static help() {
21
+ return 'Data product asset — data consumption and production with governance configuration';
22
+ }
23
+ async run(name, _options, assetsDir) {
24
+ const assetDir = path.join(assetsDir, name);
25
+ fsUtils.mkdirp(assetDir);
26
+ const templatePath = path.join(this.templateDir(), 'asset.yaml.hbs');
27
+ const content = render(templatePath, { name });
28
+ fsUtils.writeFile(path.join(assetDir, 'asset.yaml'), content);
29
+ }
30
+ }
31
+ export default DataProductPlugin;
32
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../lib/plugins/data-product/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,MAAM,MAAM,iBAAiB,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC1C,OAAO,OAAO,MAAM,mBAAmB,CAAA;AAEvC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAE9D,MAAM,iBAAkB,SAAQ,MAAM;IAClC,SAAS;QACL,OAAO,cAAc,CAAA;IACzB,CAAC;IACD,UAAU;QACN,OAAO,GAAG,CAAA;IACd,CAAC;IACD,QAAQ;QACJ,OAAO,EAAE,CAAA;IACb,CAAC;IACD,WAAW;QACP,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;IAC5C,CAAC;IAED,MAAM,CAAC,IAAI;QACP,OAAO,oFAAoF,CAAA;IAC/F,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAY,EAAE,QAAiC,EAAE,SAAiB;QACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QAC3C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAExB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,gBAAgB,CAAC,CAAA;QACpE,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;QAC9C,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAA;IACjE,CAAC;CACJ;AAED,eAAe,iBAAiB,CAAA"}
@@ -0,0 +1,9 @@
1
+ apiVersion: asset.sap/v1
2
+ kind: Asset
3
+
4
+ metadata:
5
+ name: {{name}}
6
+
7
+ type: data-product
8
+
9
+ sourceRoot: "."
@@ -0,0 +1,37 @@
1
+ import path from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ import Plugin from '../../plugin.js';
4
+ import { render } from '../../template.js';
5
+ import fsUtils from '../../fs-utils.js';
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+ class DomainModelExtensionPlugin extends Plugin {
8
+ assetType() {
9
+ return 'domain-model-extension';
10
+ }
11
+ sourceRoot() {
12
+ return '.';
13
+ }
14
+ provides() {
15
+ return {
16
+ framework: 'cap',
17
+ service: { protocol: 'odata-v4', extensionType: 'entity-extension' },
18
+ appNamespace: '',
19
+ entities: [],
20
+ };
21
+ }
22
+ templateDir() {
23
+ return path.join(__dirname, 'templates');
24
+ }
25
+ static help() {
26
+ return 'Domain model extension asset — adds custom fields to existing CAP entities';
27
+ }
28
+ async run(name, _options, assetsDir) {
29
+ const assetDir = path.join(assetsDir, name);
30
+ fsUtils.mkdirp(assetDir);
31
+ const templatePath = path.join(this.templateDir(), 'asset.yaml.hbs');
32
+ const content = render(templatePath, { name });
33
+ fsUtils.writeFile(path.join(assetDir, 'asset.yaml'), content);
34
+ }
35
+ }
36
+ export default DomainModelExtensionPlugin;
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../lib/plugins/domain-model-extension/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,MAAM,MAAM,iBAAiB,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC1C,OAAO,OAAO,MAAM,mBAAmB,CAAA;AAEvC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAE9D,MAAM,0BAA2B,SAAQ,MAAM;IAC3C,SAAS;QACL,OAAO,wBAAwB,CAAA;IACnC,CAAC;IACD,UAAU;QACN,OAAO,GAAG,CAAA;IACd,CAAC;IACD,QAAQ;QACJ,OAAO;YACH,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,kBAAkB,EAAE;YACpE,YAAY,EAAE,EAAE;YAChB,QAAQ,EAAE,EAAE;SACf,CAAA;IACL,CAAC;IACD,WAAW;QACP,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;IAC5C,CAAC;IAED,MAAM,CAAC,IAAI;QACP,OAAO,4EAA4E,CAAA;IACvF,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAY,EAAE,QAAiC,EAAE,SAAiB;QACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QAC3C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAExB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,gBAAgB,CAAC,CAAA;QACpE,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;QAC9C,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAA;IACjE,CAAC;CACJ;AAED,eAAe,0BAA0B,CAAA"}
@@ -0,0 +1,15 @@
1
+ apiVersion: asset.sap/v1
2
+ kind: Asset
3
+
4
+ metadata:
5
+ name: {{name}}
6
+ version: 1.0.0
7
+
8
+ type: domain-model-extension
9
+
10
+ sourceRoot: "."
11
+
12
+ provides:
13
+ extensions:
14
+ - name: my-extension
15
+ descriptorFile: extension.yaml
@@ -0,0 +1,36 @@
1
+ import path from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ import Plugin from '../../plugin.js';
4
+ import { render } from '../../template.js';
5
+ import fsUtils from '../../fs-utils.js';
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+ class McpServerPlugin extends Plugin {
8
+ assetType() {
9
+ return 'mcp-server';
10
+ }
11
+ sourceRoot() {
12
+ return '.';
13
+ }
14
+ provides() {
15
+ return {};
16
+ }
17
+ templateDir() {
18
+ return path.join(__dirname, 'templates');
19
+ }
20
+ static help() {
21
+ return 'MCP server asset — API-to-MCP tool mapping (type: mcp-translation, asset.yaml + translation.json + api-spec.json)';
22
+ }
23
+ async run(name, _options, assetsDir) {
24
+ const assetDir = path.join(assetsDir, name);
25
+ fsUtils.mkdirp(assetDir);
26
+ const templatePath = path.join(this.templateDir(), 'asset.yaml.hbs');
27
+ const content = render(templatePath, { name });
28
+ fsUtils.writeFile(path.join(assetDir, 'asset.yaml'), content);
29
+ // Stub files populated by downstream tooling
30
+ fsUtils.mkdirp(path.join(assetDir, 'mcp-translation'));
31
+ fsUtils.writeFile(path.join(assetDir, 'mcp-translation', 'translation.json'), '{}\n');
32
+ fsUtils.writeFile(path.join(assetDir, 'api-spec.json'), '{}\n');
33
+ }
34
+ }
35
+ export default McpServerPlugin;
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../lib/plugins/mcp-server/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,MAAM,MAAM,iBAAiB,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC1C,OAAO,OAAO,MAAM,mBAAmB,CAAA;AAEvC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAE9D,MAAM,eAAgB,SAAQ,MAAM;IAChC,SAAS;QACL,OAAO,YAAY,CAAA;IACvB,CAAC;IACD,UAAU;QACN,OAAO,GAAG,CAAA;IACd,CAAC;IACD,QAAQ;QACJ,OAAO,EAAE,CAAA;IACb,CAAC;IACD,WAAW;QACP,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;IAC5C,CAAC;IAED,MAAM,CAAC,IAAI;QACP,OAAO,mHAAmH,CAAA;IAC9H,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAY,EAAE,QAAiC,EAAE,SAAiB;QACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QAC3C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAExB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,gBAAgB,CAAC,CAAA;QACpE,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;QAC9C,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAA;QAE7D,6CAA6C;QAC7C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAA;QACtD,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,CAAC,EAAE,MAAM,CAAC,CAAA;QACrF,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAA;IACnE,CAAC;CACJ;AAED,eAAe,eAAe,CAAA"}
@@ -0,0 +1,9 @@
1
+ apiVersion: asset.sap/v1
2
+ kind: Asset
3
+
4
+ type: mcp-translation
5
+
6
+ metadata:
7
+ name: {{name}}
8
+ version: 1.0.0
9
+ translation: mcp-translation/translation.json
@@ -0,0 +1,52 @@
1
+ import path from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ import Plugin from '../../plugin.js';
4
+ import { render } from '../../template.js';
5
+ import fsUtils from '../../fs-utils.js';
6
+ import { YamlValidator } from './validation/yaml-validator.js';
7
+ import { AssetValidator } from './validation/asset-validator.js';
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ class N8nWorkflowPlugin extends Plugin {
10
+ assetType() {
11
+ return 'n8n-workflow';
12
+ }
13
+ sourceRoot() {
14
+ return 'workflows';
15
+ }
16
+ provides() {
17
+ return { workflows: [] };
18
+ }
19
+ templateDir() {
20
+ return path.join(__dirname, 'templates');
21
+ }
22
+ static help() {
23
+ return 'n8n workflow asset — n8n automation workflow integration';
24
+ }
25
+ async run(name, options, assetsDir) {
26
+ const assetDir = path.join(assetsDir, name);
27
+ fsUtils.mkdirp(assetDir);
28
+ const workflowName = options.workflowName || name;
29
+ const rawFile = options.definitionFile;
30
+ let definitionFile = `${name}.n8n.json`;
31
+ if (rawFile) {
32
+ definitionFile = rawFile.endsWith('.n8n.json') ? rawFile : `${rawFile}.n8n.json`;
33
+ }
34
+ const templatePath = path.join(this.templateDir(), 'asset.yaml.hbs');
35
+ const content = render(templatePath, { name, workflowName, definitionFile });
36
+ fsUtils.writeFile(path.join(assetDir, 'asset.yaml'), content);
37
+ // Create stub workflow file so validation passes out of the box
38
+ const workflowsDir = path.join(assetDir, 'workflows');
39
+ fsUtils.mkdirp(workflowsDir);
40
+ fsUtils.writeFile(path.join(workflowsDir, definitionFile), '{"nodes":[],"connections":{}}');
41
+ }
42
+ yamlValidator = new YamlValidator();
43
+ assetValidator = new AssetValidator();
44
+ async checkAssetYamlExtra(assetYaml, assetDir) {
45
+ return this.yamlValidator.validate(assetYaml, assetDir);
46
+ }
47
+ async checkAsset(assetYaml, assetDir) {
48
+ return this.assetValidator.validate(assetYaml, assetDir);
49
+ }
50
+ }
51
+ export default N8nWorkflowPlugin;
52
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../lib/plugins/n8n-workflow/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,MAAM,MAAM,iBAAiB,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC1C,OAAO,OAAO,MAAM,mBAAmB,CAAA;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAA;AAEhE,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAE9D,MAAM,iBAAkB,SAAQ,MAAM;IAClC,SAAS;QACL,OAAO,cAAc,CAAA;IACzB,CAAC;IACD,UAAU;QACN,OAAO,WAAW,CAAA;IACtB,CAAC;IACD,QAAQ;QACJ,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,CAAA;IAC5B,CAAC;IACD,WAAW;QACP,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;IAC5C,CAAC;IAED,MAAM,CAAC,IAAI;QACP,OAAO,0DAA0D,CAAA;IACrE,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAY,EAAE,OAAgC,EAAE,SAAiB;QACvE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QAC3C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAExB,MAAM,YAAY,GAAI,OAAO,CAAC,YAAuB,IAAI,IAAI,CAAA;QAC7D,MAAM,OAAO,GAAG,OAAO,CAAC,cAAoC,CAAA;QAC5D,IAAI,cAAc,GAAG,GAAG,IAAI,WAAW,CAAA;QACvC,IAAI,OAAO,EAAE,CAAC;YACV,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,WAAW,CAAA;QACpF,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,gBAAgB,CAAC,CAAA;QACpE,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,cAAc,EAAE,CAAC,CAAA;QAE5E,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAA;QAE7D,gEAAgE;QAChE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAA;QACrD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;QAC5B,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,EAAE,+BAA+B,CAAC,CAAA;IAC/F,CAAC;IAEO,aAAa,GAAG,IAAI,aAAa,EAAE,CAAA;IACnC,cAAc,GAAG,IAAI,cAAc,EAAE,CAAA;IAEnC,KAAK,CAAC,mBAAmB,CAAC,SAAkC,EAAE,QAAiB;QACrF,OAAO,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IAC3D,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,SAAkC,EAAE,QAAgB;QACjE,OAAO,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IAC5D,CAAC;CACJ;AAED,eAAe,iBAAiB,CAAA"}
@@ -0,0 +1,18 @@
1
+ {{#hasPlaceholders}}
2
+ # TODO: replace <placeholder> values below with actual kebab-case names
3
+ {{/hasPlaceholders}}
4
+ apiVersion: asset.sap/v1
5
+ kind: Asset
6
+
7
+ metadata:
8
+ name: {{name}}
9
+ version: 1.0.0
10
+
11
+ type: n8n-workflow
12
+
13
+ sourceRoot: workflows
14
+
15
+ provides:
16
+ workflows:
17
+ - name: {{{workflowName}}} # kebab-case workflow name, e.g. order-processor
18
+ definitionFile: {{{definitionFile}}} # e.g. order-processor.n8n.json
@@ -0,0 +1,62 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fetchMcpServers, mcpInit, mcpRequest } from '../../../mcp/client.js';
4
+ import { getAuthHeaders } from '../../../auth.js';
5
+ export class AssetValidator {
6
+ async validate(assetYaml, assetDir) {
7
+ const issues = [];
8
+ const sourceRoot = assetYaml.sourceRoot || 'workflows';
9
+ const provides = assetYaml.provides;
10
+ const workflows = provides?.workflows;
11
+ if (!Array.isArray(workflows) || workflows.length === 0) {
12
+ return issues;
13
+ }
14
+ let cfg, headers;
15
+ try {
16
+ const store = await fetchMcpServers();
17
+ const serverName = Object.keys(store).find(n => n.includes('n8n'));
18
+ if (!serverName) {
19
+ issues.push('n8n MCP server not configured — cannot validate workflows');
20
+ return issues;
21
+ }
22
+ cfg = store[serverName];
23
+ headers = getAuthHeaders(cfg.backend);
24
+ await mcpInit(cfg.url, headers);
25
+ }
26
+ catch (e) {
27
+ issues.push(`n8n MCP server unreachable — cannot validate workflows (${e})`);
28
+ return issues;
29
+ }
30
+ for (const workflow of workflows) {
31
+ if (!workflow.definitionFile) {
32
+ continue;
33
+ }
34
+ const filePath = path.join(assetDir, sourceRoot, workflow.definitionFile);
35
+ if (!fs.existsSync(filePath)) {
36
+ continue; // covered by checkAssetYaml
37
+ }
38
+ const fileContent = fs.readFileSync(filePath, 'utf8');
39
+ try {
40
+ const result = (await mcpRequest(cfg.url, headers, 'tools/call', Date.now(), {
41
+ name: 'validate_n8n_workflow',
42
+ arguments: { workflow: fileContent },
43
+ }));
44
+ if (result?.isError) {
45
+ const text = result.content?.map(c => c.text).join(' ') || 'unknown error';
46
+ issues.push(`${workflow.definitionFile}: validation failed — ${text}`);
47
+ }
48
+ else {
49
+ const text = result?.content?.map(c => c.text).join(' ') || '';
50
+ if (text.includes('❌') || text.toLowerCase().includes('error')) {
51
+ issues.push(`${workflow.definitionFile}: ${text}`);
52
+ }
53
+ }
54
+ }
55
+ catch (e) {
56
+ issues.push(`${workflow.definitionFile}: MCP validation request failed — ${e}`);
57
+ }
58
+ }
59
+ return issues;
60
+ }
61
+ }
62
+ //# sourceMappingURL=asset-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-validator.js","sourceRoot":"","sources":["../../../../../lib/plugins/n8n-workflow/validation/asset-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { NAME_PATTERN } from '../../../plugin.js';
4
+ export class YamlValidator {
5
+ async validate(assetYaml, assetDir) {
6
+ const issues = [];
7
+ if (!assetYaml.sourceRoot) {
8
+ issues.push('sourceRoot is missing');
9
+ return issues;
10
+ }
11
+ const provides = assetYaml.provides;
12
+ if (!provides || typeof provides !== 'object') {
13
+ issues.push('provides is missing');
14
+ return issues;
15
+ }
16
+ const workflows = provides.workflows;
17
+ if (!Array.isArray(workflows)) {
18
+ issues.push('provides.workflows must be an array');
19
+ return issues;
20
+ }
21
+ if (workflows.length === 0) {
22
+ issues.push('provides.workflows must contain at least one entry');
23
+ return issues;
24
+ }
25
+ const sourceRoot = assetYaml.sourceRoot || 'workflows';
26
+ for (let i = 0; i < workflows.length; i++) {
27
+ const workflow = workflows[i];
28
+ const prefix = `provides.workflows[${i}]`;
29
+ if (!workflow.name) {
30
+ issues.push(`${prefix}.name is missing`);
31
+ }
32
+ else if (!NAME_PATTERN.test(workflow.name)) {
33
+ issues.push(`${prefix}.name '${workflow.name}' is not DNS-compatible (must be kebab-case)`);
34
+ }
35
+ if (!workflow.definitionFile) {
36
+ issues.push(`${prefix}.definitionFile is missing`);
37
+ }
38
+ else if (!workflow.definitionFile.endsWith('.n8n.json')) {
39
+ issues.push(`${prefix}.definitionFile '${workflow.definitionFile}' must end with .n8n.json`);
40
+ }
41
+ else if (assetDir) {
42
+ const filePath = path.join(assetDir, sourceRoot, workflow.definitionFile);
43
+ if (!fs.existsSync(filePath)) {
44
+ issues.push(`${prefix}.definitionFile '${workflow.definitionFile}' not found at ${filePath}`);
45
+ }
46
+ }
47
+ }
48
+ return issues;
49
+ }
50
+ }
51
+ //# sourceMappingURL=yaml-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yaml-validator.js","sourceRoot":"","sources":["../../../../../lib/plugins/n8n-workflow/validation/yaml-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD,MAAM,OAAO,aAAa;IACtB,KAAK,CAAC,QAAQ,CAAC,SAAkC,EAAE,QAAiB;QAChE,MAAM,MAAM,GAAa,EAAE,CAAA;QAE3B,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAA;YACpC,OAAO,MAAM,CAAA;QACjB,CAAC;QAED,MAAM,QAAQ,GAAG,SAAS,CAAC,QAA+C,CAAA;QAC1E,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC5C,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;YAClC,OAAO,MAAM,CAAA;QACjB,CAAC;QAED,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAkD,CAAA;QAC7E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5B,MAAM,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAA;YAClD,OAAO,MAAM,CAAA;QACjB,CAAC;QAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAA;YACjE,OAAO,MAAM,CAAA;QACjB,CAAC;QAED,MAAM,UAAU,GAAI,SAAS,CAAC,UAAqB,IAAI,WAAW,CAAA;QAElE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;YAC7B,MAAM,MAAM,GAAG,sBAAsB,CAAC,GAAG,CAAA;YAEzC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACjB,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,kBAAkB,CAAC,CAAA;YAC5C,CAAC;iBAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAc,CAAC,EAAE,CAAC;gBACrD,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,UAAU,QAAQ,CAAC,IAAI,8CAA8C,CAAC,CAAA;YAC/F,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC;gBAC3B,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,4BAA4B,CAAC,CAAA;YACtD,CAAC;iBAAM,IAAI,CAAE,QAAQ,CAAC,cAAyB,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBACpE,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,oBAAoB,QAAQ,CAAC,cAAc,2BAA2B,CAAC,CAAA;YAChG,CAAC;iBAAM,IAAI,QAAQ,EAAE,CAAC;gBAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,cAAwB,CAAC,CAAA;gBACnF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC3B,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,oBAAoB,QAAQ,CAAC,cAAc,kBAAkB,QAAQ,EAAE,CAAC,CAAA;gBACjG,CAAC;YACL,CAAC;QACL,CAAC;QAED,OAAO,MAAM,CAAA;IACjB,CAAC;CACJ"}
@@ -0,0 +1,32 @@
1
+ import path from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ import Plugin from '../../plugin.js';
4
+ import { render } from '../../template.js';
5
+ import fsUtils from '../../fs-utils.js';
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+ class VercelAppPlugin extends Plugin {
8
+ assetType() {
9
+ return 'vercel-app';
10
+ }
11
+ sourceRoot() {
12
+ return '.';
13
+ }
14
+ provides() {
15
+ return {};
16
+ }
17
+ templateDir() {
18
+ return path.join(__dirname, 'templates');
19
+ }
20
+ static help() {
21
+ return 'Vercel app asset — Vercel-deployed frontend application';
22
+ }
23
+ async run(name, _options, assetsDir) {
24
+ const assetDir = path.join(assetsDir, name);
25
+ fsUtils.mkdirp(assetDir);
26
+ const templatePath = path.join(this.templateDir(), 'asset.yaml.hbs');
27
+ const content = render(templatePath, { name });
28
+ fsUtils.writeFile(path.join(assetDir, 'asset.yaml'), content);
29
+ }
30
+ }
31
+ export default VercelAppPlugin;
32
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../lib/plugins/vercel-app/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,MAAM,MAAM,iBAAiB,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC1C,OAAO,OAAO,MAAM,mBAAmB,CAAA;AAEvC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAE9D,MAAM,eAAgB,SAAQ,MAAM;IAChC,SAAS;QACL,OAAO,YAAY,CAAA;IACvB,CAAC;IACD,UAAU;QACN,OAAO,GAAG,CAAA;IACd,CAAC;IACD,QAAQ;QACJ,OAAO,EAAE,CAAA;IACb,CAAC;IACD,WAAW;QACP,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;IAC5C,CAAC;IAED,MAAM,CAAC,IAAI;QACP,OAAO,yDAAyD,CAAA;IACpE,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAY,EAAE,QAAiC,EAAE,SAAiB;QACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QAC3C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAExB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,gBAAgB,CAAC,CAAA;QACpE,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;QAC9C,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAA;IACjE,CAAC;CACJ;AAED,eAAe,eAAe,CAAA"}
@@ -0,0 +1,12 @@
1
+ apiVersion: asset.sap/v1
2
+ kind: Asset
3
+
4
+ metadata:
5
+ name: {{name}}
6
+ version: 1.0.0
7
+
8
+ type: vercel-app
9
+
10
+ container:
11
+ buildPath: .
12
+ port: 3000
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule.js","sourceRoot":"","sources":["../../lib/rule.ts"],"names":[],"mappings":""}
@@ -0,0 +1,178 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Solution",
4
+ "description": "Schema for solution which contains multiple assets.",
5
+ "type": "object",
6
+ "properties": {
7
+ "metadata": {
8
+ "type": "object",
9
+ "properties": {
10
+ "name": {
11
+ "type": "string",
12
+ "description": "Identifying name of the solution (DNS-compatible)",
13
+ "pattern": "^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$"
14
+ },
15
+ "labels": {
16
+ "type": "object",
17
+ "description": "Key-value labels for the application",
18
+ "additionalProperties": {
19
+ "type": "string"
20
+ },
21
+ "properties": {}
22
+ },
23
+ "version": {
24
+ "type": "string",
25
+ "pattern": "^([0-9]+\\.[0-9]+\\.[0-9]+|DRAFT)$",
26
+ "description": "Semantic version or DRAFT"
27
+ },
28
+ "description": {
29
+ "type": "string"
30
+ }
31
+ },
32
+ "required": ["name", "version"]
33
+ },
34
+ "runtime": {
35
+ "type": "object",
36
+ "properties": {
37
+ "type": {
38
+ "type": "string",
39
+ "description": "Runtime type",
40
+ "default": "generic"
41
+ }
42
+ }
43
+ },
44
+ "overrides": {
45
+ "type": "object",
46
+ "description": "Solution-level configuration overrides",
47
+ "additionalProperties": true
48
+ },
49
+ "custom": {
50
+ "type": "object",
51
+ "description": "Opaque custom configuration for platform-specific properties.\n\nThis section is NOT validated by the type system and allows\nany structure. Use for:\n- Platform-specific deployment config (Vercel, CAP, Cloud Foundry)\n- Tool-specific extensions\n- Experimental features\n- Gradual migration paths\n\nCommon namespaces:\n- custom.vercel.* - Vercel deployment config\n- custom.cap.* - CAP framework config\n- custom.cf.* - Cloud Foundry config\n- custom.k8s.* - Kubernetes config\n- custom.tooling.* - Custom tooling\n",
52
+ "additionalProperties": true,
53
+ "properties": {}
54
+ },
55
+ "requires": {
56
+ "type": "array",
57
+ "description": "Solution-wide dependencies inherited by all assets",
58
+ "items": {
59
+ "oneOf": [
60
+ {
61
+ "type": "string"
62
+ },
63
+ {
64
+ "type": "object",
65
+ "required": ["name"],
66
+ "properties": {
67
+ "name": {
68
+ "type": "string"
69
+ },
70
+ "version": {
71
+ "type": "string"
72
+ },
73
+ "kind": {
74
+ "type": "string",
75
+ "enum": ["service", "platform-service", "asset"]
76
+ },
77
+ "plan": {
78
+ "type": "string",
79
+ "description": "Service plan (required for platform-service)"
80
+ }
81
+ }
82
+ }
83
+ ]
84
+ }
85
+ },
86
+ "assets": {
87
+ "type": "array",
88
+ "minItems": 1,
89
+ "description": "Array of assets composing this solution",
90
+ "items": {
91
+ "type": "object",
92
+ "oneOf": [
93
+ {
94
+ "required": ["ref"],
95
+ "properties": {
96
+ "ref": {
97
+ "type": "string",
98
+ "description": "Path or Git URI to asset.yaml"
99
+ },
100
+ "version": {
101
+ "type": "string",
102
+ "description": "Version constraint for referenced asset"
103
+ },
104
+ "alias": {
105
+ "type": "string",
106
+ "description": "Optional alias for the asset"
107
+ },
108
+ "spec": {
109
+ "type": "object",
110
+ "description": "Inline overrides (deep merged with ref)"
111
+ }
112
+ }
113
+ },
114
+ {
115
+ "required": ["name", "type"],
116
+ "properties": {
117
+ "name": {
118
+ "type": "string",
119
+ "pattern": "^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$",
120
+ "description": "Identifying name for the asset"
121
+ },
122
+ "type": {
123
+ "type": "string",
124
+ "description": "Asset type identifier (kind comes from type definition)"
125
+ },
126
+ "sourceRoot": {
127
+ "type": "string",
128
+ "description": "Source code root directory"
129
+ },
130
+ "requires": {
131
+ "type": "array",
132
+ "description": "Asset-specific dependencies"
133
+ },
134
+ "provides": {
135
+ "type": "object",
136
+ "description": "What this asset provides"
137
+ }
138
+ }
139
+ },
140
+ {
141
+ "required": ["name", "kind"],
142
+ "properties": {
143
+ "name": {
144
+ "type": "string",
145
+ "pattern": "^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$",
146
+ "description": "Identifying name for the asset"
147
+ },
148
+ "kind": {
149
+ "type": "string",
150
+ "enum": ["service", "ui", "process", "data-product", "sap-build"],
151
+ "description": "Asset category (explicit for inline assets)"
152
+ },
153
+ "type": {
154
+ "type": "string",
155
+ "description": "Asset type identifier"
156
+ },
157
+ "sourceRoot": {
158
+ "type": "string",
159
+ "description": "Source code root directory"
160
+ },
161
+ "requires": {
162
+ "type": "array",
163
+ "description": "Asset-specific dependencies (merged with solution requires)"
164
+ },
165
+ "provides": {
166
+ "type": "object",
167
+ "description": "What this asset provides"
168
+ }
169
+ }
170
+ }
171
+ ]
172
+ }
173
+ }
174
+ },
175
+ "required": ["assets"],
176
+ "x-spec-version": "v3.0.0",
177
+ "x-generated": "2026-03-12T20:42:06.286Z"
178
+ }