@lssm/module.contractspec-workspace 0.0.0-canary-20251217063201 → 0.0.0-canary-20251217073102

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.
@@ -1,69 +1,89 @@
1
- import{toPascalCase as e}from"./utils.js";function t(t){let i=e(t.name.split(`.`).pop()??`Telemetry`)+`Telemetry`,a=t.providers?.length?`providers: [
2
- ${t.providers.map(e=>` {
3
- type: '${e.type}',
4
- config: ${r(e.config)},
5
- }`).join(`,
6
- `)}
7
- ],`:``,o=t.events.map(e=>{let t=e.properties.map(e=>` '${e.name}': {
8
- type: '${e.type}',
9
- ${e.required?`required: true,`:``}
10
- ${e.pii?`pii: true,`:``}
11
- ${e.redact?`redact: true,`:``}
12
- ${e.description?`description: '${n(e.description)}',`:``}
13
- }`).join(`,
14
- `),r=e.anomalyRules?.length?` anomalyDetection: {
1
+ import { toPascalCase } from "./utils.js";
2
+
3
+ //#region src/templates/telemetry.ts
4
+ function generateTelemetrySpec(data) {
5
+ const specVar = toPascalCase(data.name.split(".").pop() ?? "Telemetry") + "Telemetry";
6
+ const providers = data.providers?.length ? `providers: [
7
+ ${data.providers.map((provider) => ` {
8
+ type: '${provider.type}',
9
+ config: ${formatConfigValue(provider.config)},
10
+ }`).join(",\n")}
11
+ ],` : "";
12
+ const events = data.events.map((event) => {
13
+ const properties = event.properties.map((prop) => ` '${prop.name}': {
14
+ type: '${prop.type}',
15
+ ${prop.required ? "required: true," : ""}
16
+ ${prop.pii ? "pii: true," : ""}
17
+ ${prop.redact ? "redact: true," : ""}
18
+ ${prop.description ? `description: '${escapeString(prop.description)}',` : ""}
19
+ }`).join(",\n");
20
+ const anomalyRules = event.anomalyRules?.length ? ` anomalyDetection: {
15
21
  enabled: true,
16
- ${typeof e.anomalyMinimumSample==`number`?`minimumSample: ${e.anomalyMinimumSample},`:``}
22
+ ${typeof event.anomalyMinimumSample === "number" ? `minimumSample: ${event.anomalyMinimumSample},` : ""}
17
23
  thresholds: [
18
- ${e.anomalyRules.map(e=>` {
19
- metric: '${n(e.metric)}',
20
- ${typeof e.min==`number`?`min: ${e.min},`:``}
21
- ${typeof e.max==`number`?`max: ${e.max},`:``}
22
- }`).join(`,
23
- `)}
24
+ ${event.anomalyRules.map((rule) => ` {
25
+ metric: '${escapeString(rule.metric)}',
26
+ ${typeof rule.min === "number" ? `min: ${rule.min},` : ""}
27
+ ${typeof rule.max === "number" ? `max: ${rule.max},` : ""}
28
+ }`).join(",\n")}
24
29
  ],
25
- actions: [${(e.anomalyActions??[]).map(e=>`'${e}'`).join(`, `)}],
26
- },`:e.anomalyEnabled?` anomalyDetection: {
30
+ actions: [${(event.anomalyActions ?? []).map((action) => `'${action}'`).join(", ")}],
31
+ },` : event.anomalyEnabled ? ` anomalyDetection: {
27
32
  enabled: true,
28
- ${typeof e.anomalyMinimumSample==`number`?`minimumSample: ${e.anomalyMinimumSample},`:``}
29
- },`:``;return` {
30
- name: '${n(e.name)}',
31
- version: ${e.version},
33
+ ${typeof event.anomalyMinimumSample === "number" ? `minimumSample: ${event.anomalyMinimumSample},` : ""}
34
+ },` : "";
35
+ return ` {
36
+ name: '${escapeString(event.name)}',
37
+ version: ${event.version},
32
38
  semantics: {
33
- what: '${n(e.what)}',
34
- ${e.who?`who: '${n(e.who)}',`:``}
35
- ${e.why?`why: '${n(e.why)}',`:``}
39
+ what: '${escapeString(event.what)}',
40
+ ${event.who ? `who: '${escapeString(event.who)}',` : ""}
41
+ ${event.why ? `why: '${escapeString(event.why)}',` : ""}
36
42
  },
37
- privacy: '${e.privacy}',
43
+ privacy: '${event.privacy}',
38
44
  properties: {
39
- ${t}
45
+ ${properties}
40
46
  },
41
- ${typeof e.retentionDays==`number`?`retention: { days: ${e.retentionDays}, ${e.retentionPolicy?`policy: '${e.retentionPolicy}'`:``} },`:``}
42
- ${typeof e.samplingRate==`number`?`sampling: { rate: ${e.samplingRate}${e.samplingConditions?`, conditions: ['${n(e.samplingConditions)}']`:``} },`:``}
43
- ${r}
44
- ${e.tags?.length?`tags: [${e.tags.map(e=>`'${n(e)}'`).join(`, `)}],`:``}
45
- }`}).join(`,
46
- `);return`import type { TelemetrySpec } from '@lssm/lib.contracts/telemetry';
47
+ ${typeof event.retentionDays === "number" ? `retention: { days: ${event.retentionDays}, ${event.retentionPolicy ? `policy: '${event.retentionPolicy}'` : ""} },` : ""}
48
+ ${typeof event.samplingRate === "number" ? `sampling: { rate: ${event.samplingRate}${event.samplingConditions ? `, conditions: ['${escapeString(event.samplingConditions)}']` : ""} },` : ""}
49
+ ${anomalyRules}
50
+ ${event.tags?.length ? `tags: [${event.tags.map((tag) => `'${escapeString(tag)}'`).join(", ")}],` : ""}
51
+ }`;
52
+ }).join(",\n");
53
+ return `import type { TelemetrySpec } from '@lssm/lib.contracts/telemetry';
47
54
 
48
- export const ${i}: TelemetrySpec = {
55
+ export const ${specVar}: TelemetrySpec = {
49
56
  meta: {
50
- name: '${n(t.name)}',
51
- version: ${t.version},
52
- title: '${n(t.name)} telemetry',
53
- description: '${n(t.description||`Describe the purpose of this telemetry spec.`)}',
54
- domain: '${n(t.domain)}',
55
- owners: [${t.owners.map(e=>`'${n(e)}'`).join(`, `)}],
56
- tags: [${t.tags.map(e=>`'${n(e)}'`).join(`, `)}],
57
- stability: '${t.stability}',
57
+ name: '${escapeString(data.name)}',
58
+ version: ${data.version},
59
+ title: '${escapeString(data.name)} telemetry',
60
+ description: '${escapeString(data.description || "Describe the purpose of this telemetry spec.")}',
61
+ domain: '${escapeString(data.domain)}',
62
+ owners: [${data.owners.map((owner) => `'${escapeString(owner)}'`).join(", ")}],
63
+ tags: [${data.tags.map((tag) => `'${escapeString(tag)}'`).join(", ")}],
64
+ stability: '${data.stability}',
58
65
  },
59
66
  config: {
60
- ${typeof t.defaultRetentionDays==`number`?`defaultRetentionDays: ${t.defaultRetentionDays},`:``}
61
- ${typeof t.defaultSamplingRate==`number`?`defaultSamplingRate: ${t.defaultSamplingRate},`:``}
62
- ${t.anomalyEnabled?`anomalyDetection: { enabled: true${typeof t.anomalyCheckIntervalMs==`number`?`, checkIntervalMs: ${t.anomalyCheckIntervalMs}`:``} },`:``}
63
- ${a}
67
+ ${typeof data.defaultRetentionDays === "number" ? `defaultRetentionDays: ${data.defaultRetentionDays},` : ""}
68
+ ${typeof data.defaultSamplingRate === "number" ? `defaultSamplingRate: ${data.defaultSamplingRate},` : ""}
69
+ ${data.anomalyEnabled ? `anomalyDetection: { enabled: true${typeof data.anomalyCheckIntervalMs === "number" ? `, checkIntervalMs: ${data.anomalyCheckIntervalMs}` : ""} },` : ""}
70
+ ${providers}
64
71
  },
65
72
  events: [
66
- ${o}
73
+ ${events}
67
74
  ],
68
75
  };
69
- `}function n(e){return e.replace(/\\/g,`\\\\`).replace(/'/g,`\\'`)}function r(e){let t=e.trim();return t?t.startsWith(`{`)&&t.endsWith(`}`)||t.startsWith(`[`)&&t.endsWith(`]`)?t:`'${n(t)}'`:`{}`}export{t as generateTelemetrySpec};
76
+ `;
77
+ }
78
+ function escapeString(value) {
79
+ return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
80
+ }
81
+ function formatConfigValue(value) {
82
+ const trimmed = value.trim();
83
+ if (!trimmed) return "{}";
84
+ if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]")) return trimmed;
85
+ return `'${escapeString(trimmed)}'`;
86
+ }
87
+
88
+ //#endregion
89
+ export { generateTelemetrySpec };
@@ -1 +1,38 @@
1
- function e(e){let n=t(e);return n.charAt(0).toLowerCase()+n.slice(1)}function t(e){return e.split(/[-_.]/).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``)}function n(e){return e.replace(/\./g,`-`).replace(/([a-z])([A-Z])/g,`$1-$2`).toLowerCase()}function r(e){return e.charAt(0).toUpperCase()+e.slice(1)}function i(e){return e.replace(/'/g,`\\'`)}export{r as capitalize,i as escapeString,e as toCamelCase,n as toKebabCase,t as toPascalCase};
1
+ //#region src/templates/utils.ts
2
+ /**
3
+ * Utility functions for template generation.
4
+ */
5
+ /**
6
+ * Convert string to camelCase.
7
+ */
8
+ function toCamelCase(str) {
9
+ const pascal = toPascalCase(str);
10
+ return pascal.charAt(0).toLowerCase() + pascal.slice(1);
11
+ }
12
+ /**
13
+ * Convert string to PascalCase.
14
+ */
15
+ function toPascalCase(str) {
16
+ return str.split(/[-_.]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
17
+ }
18
+ /**
19
+ * Convert string to kebab-case.
20
+ */
21
+ function toKebabCase(str) {
22
+ return str.replace(/\./g, "-").replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
23
+ }
24
+ /**
25
+ * Capitalize first letter.
26
+ */
27
+ function capitalize(str) {
28
+ return str.charAt(0).toUpperCase() + str.slice(1);
29
+ }
30
+ /**
31
+ * Escape single quotes in string.
32
+ */
33
+ function escapeString(value) {
34
+ return value.replace(/'/g, "\\'");
35
+ }
36
+
37
+ //#endregion
38
+ export { capitalize, escapeString, toCamelCase, toKebabCase, toPascalCase };
@@ -1,12 +1,14 @@
1
- function e({exportName:e,specImportPath:t,runnerName:n,workflowName:r}){return`import {
1
+ //#region src/templates/workflow-runner.ts
2
+ function generateWorkflowRunnerTemplate({ exportName, specImportPath, runnerName, workflowName }) {
3
+ return `import {
2
4
  InMemoryStateStore,
3
5
  WorkflowRegistry,
4
6
  WorkflowRunner,
5
7
  } from '@lssm/lib.contracts/workflow';
6
- import { ${e} } from '${t}';
8
+ import { ${exportName} } from '${specImportPath}';
7
9
 
8
10
  /**
9
- * Runner wiring for ${r}.
11
+ * Runner wiring for ${workflowName}.
10
12
  *
11
13
  * TODO:
12
14
  * - Replace the in-memory state store with a persistent adapter if needed.
@@ -14,11 +16,11 @@ import { ${e} } from '${t}';
14
16
  * - Wire eventEmitter to telemetry sinks.
15
17
  */
16
18
  const registry = new WorkflowRegistry();
17
- registry.register(${e});
19
+ registry.register(${exportName});
18
20
 
19
21
  const stateStore = new InMemoryStateStore();
20
22
 
21
- export const ${n} = new WorkflowRunner({
23
+ export const ${runnerName} = new WorkflowRunner({
22
24
  registry,
23
25
  stateStore,
24
26
  opExecutor: async (operation, input, ctx) => {
@@ -39,4 +41,8 @@ export const ${n} = new WorkflowRunner({
39
41
  // TODO: forward workflow events to telemetry or logging sinks
40
42
  },
41
43
  });
42
- `}export{e as generateWorkflowRunnerTemplate};
44
+ `;
45
+ }
46
+
47
+ //#endregion
48
+ export { generateWorkflowRunnerTemplate };
@@ -1,10 +1,18 @@
1
- import{escapeString as e,toPascalCase as t}from"./utils.js";function n(n){let i=t(n.name.split(`.`).pop()??`Workflow`)+`Workflow`,a=n.steps.map(e=>r(e)).join(`,
2
- `),o=n.transitions.map(t=>` {
3
- from: '${t.from}',
4
- to: '${t.to}',
5
- ${t.condition?` condition: '${e(t.condition)}',`:``}
6
- }`).join(`,
7
- `);return`import type { WorkflowSpec } from '@lssm/lib.contracts/workflow';
1
+ import { escapeString, toPascalCase } from "./utils.js";
2
+
3
+ //#region src/templates/workflow.ts
4
+ /**
5
+ * Generate workflow spec TypeScript code.
6
+ */
7
+ function generateWorkflowSpec(data) {
8
+ const specVarName = toPascalCase(data.name.split(".").pop() ?? "Workflow") + "Workflow";
9
+ const stepsCode = data.steps.map((step) => formatStep(step)).join(",\n");
10
+ const transitionsCode = data.transitions.map((transition) => ` {
11
+ from: '${transition.from}',
12
+ to: '${transition.to}',
13
+ ${transition.condition ? ` condition: '${escapeString(transition.condition)}',` : ""}
14
+ }`).join(",\n");
15
+ return `import type { WorkflowSpec } from '@lssm/lib.contracts/workflow';
8
16
 
9
17
  /**
10
18
  * Workflow generated via contractspec CLI.
@@ -14,28 +22,46 @@ ${t.condition?` condition: '${e(t.condition)}',`:``}
14
22
  * - Provide form renderers for human steps.
15
23
  * - Add guards/conditions as needed.
16
24
  */
17
- export const ${i}: WorkflowSpec = {
25
+ export const ${specVarName}: WorkflowSpec = {
18
26
  meta: {
19
- name: '${n.name}',
20
- version: ${n.version},
21
- title: '${e(n.title)}',
22
- description: '${e(n.description)}',
23
- domain: '${e(n.domain)}',
24
- stability: '${n.stability}',
25
- owners: [${n.owners.map(e=>`'${e}'`).join(`, `)}],
26
- tags: [${n.tags.map(e=>`'${e}'`).join(`, `)}],
27
+ name: '${data.name}',
28
+ version: ${data.version},
29
+ title: '${escapeString(data.title)}',
30
+ description: '${escapeString(data.description)}',
31
+ domain: '${escapeString(data.domain)}',
32
+ stability: '${data.stability}',
33
+ owners: [${data.owners.map((owner) => `'${owner}'`).join(", ")}],
34
+ tags: [${data.tags.map((tag) => `'${tag}'`).join(", ")}],
27
35
  },
28
36
  definition: {
29
- ${n.entryStepId?` entryStepId: '${n.entryStepId}',\n`:``} steps: [
30
- ${a}
37
+ ${data.entryStepId ? ` entryStepId: '${data.entryStepId}',\n` : ""} steps: [
38
+ ${stepsCode}
31
39
  ],
32
40
  transitions: [
33
- ${o}
41
+ ${transitionsCode}
34
42
  ],
35
43
  },
36
- ${n.policyFlags.length>0?`policy: {
37
- flags: [${n.policyFlags.map(e=>`'${e}'`).join(`, `)}],
38
- },`:`// policy: { flags: [] },`}
44
+ ${data.policyFlags.length > 0 ? `policy: {
45
+ flags: [${data.policyFlags.map((flag) => `'${flag}'`).join(", ")}],
46
+ },` : "// policy: { flags: [] },"}
39
47
  };
40
- `}function r(t){let n=[` {`,` id: '${t.id}',`,` type: '${t.type}',`,` label: '${e(t.label)}',`];t.description&&n.push(` description: '${e(t.description)}',`);let r=[];return t.operation&&r.push(`operation: { name: '${t.operation.name}', version: ${t.operation.version} }`),t.form&&r.push(`form: { key: '${t.form.key}', version: ${t.form.version} }`),r.length&&n.push(` action: { ${r.join(`, `)} },`),n.push(` }`),n.join(`
41
- `)}export{n as generateWorkflowSpec};
48
+ `;
49
+ }
50
+ function formatStep(step) {
51
+ const lines = [
52
+ ` {`,
53
+ ` id: '${step.id}',`,
54
+ ` type: '${step.type}',`,
55
+ ` label: '${escapeString(step.label)}',`
56
+ ];
57
+ if (step.description) lines.push(` description: '${escapeString(step.description)}',`);
58
+ const actionLines = [];
59
+ if (step.operation) actionLines.push(`operation: { name: '${step.operation.name}', version: ${step.operation.version} }`);
60
+ if (step.form) actionLines.push(`form: { key: '${step.form.key}', version: ${step.form.version} }`);
61
+ if (actionLines.length) lines.push(` action: { ${actionLines.join(", ")} },`);
62
+ lines.push(` }`);
63
+ return lines.join("\n");
64
+ }
65
+
66
+ //#endregion
67
+ export { generateWorkflowSpec };
@@ -1 +1,20 @@
1
- const e={aiProvider:`claude`,agentMode:`simple`,outputDir:`./src`,conventions:{operations:`interactions/commands|queries`,events:`events`,presentations:`presentations`,forms:`forms`},defaultOwners:[],defaultTags:[]};export{e as DEFAULT_WORKSPACE_CONFIG};
1
+ //#region src/types/generation-types.ts
2
+ /**
3
+ * Default workspace configuration.
4
+ */
5
+ const DEFAULT_WORKSPACE_CONFIG = {
6
+ aiProvider: "claude",
7
+ agentMode: "simple",
8
+ outputDir: "./src",
9
+ conventions: {
10
+ operations: "interactions/commands|queries",
11
+ events: "events",
12
+ presentations: "presentations",
13
+ forms: "forms"
14
+ },
15
+ defaultOwners: [],
16
+ defaultTags: []
17
+ };
18
+
19
+ //#endregion
20
+ export { DEFAULT_WORKSPACE_CONFIG };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lssm/module.contractspec-workspace",
3
- "version": "0.0.0-canary-20251217063201",
3
+ "version": "0.0.0-canary-20251217073102",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -23,13 +23,13 @@
23
23
  "test": "bun run"
24
24
  },
25
25
  "dependencies": {
26
- "@lssm/lib.contracts": "0.0.0-canary-20251217063201",
27
- "@lssm/lib.schema": "0.0.0-canary-20251217063201",
26
+ "@lssm/lib.contracts": "0.0.0-canary-20251217073102",
27
+ "@lssm/lib.schema": "0.0.0-canary-20251217073102",
28
28
  "zod": "^4.1.13"
29
29
  },
30
30
  "devDependencies": {
31
- "@lssm/tool.tsdown": "0.0.0-canary-20251217063201",
32
- "@lssm/tool.typescript": "0.0.0-canary-20251217063201",
31
+ "@lssm/tool.tsdown": "0.0.0-canary-20251217073102",
32
+ "@lssm/tool.typescript": "0.0.0-canary-20251217073102",
33
33
  "tsdown": "^0.17.4",
34
34
  "typescript": "^5.9.3"
35
35
  },