@intentius/chant-lexicon-temporal 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/integrity.json +15 -0
- package/dist/manifest.json +8 -0
- package/dist/meta.json +26 -0
- package/dist/rules/tmp001.ts +53 -0
- package/dist/rules/tmp002.ts +45 -0
- package/dist/rules/tmp010-cron-syntax.ts +64 -0
- package/dist/rules/tmp011-namespace-reference.ts +49 -0
- package/dist/skills/chant-temporal-ops.md +184 -0
- package/dist/skills/chant-temporal.md +201 -0
- package/dist/types/index.d.ts +3 -0
- package/package.json +32 -0
- package/src/codegen/docs-cli.ts +7 -0
- package/src/codegen/docs.ts +23 -0
- package/src/codegen/generate-cli.ts +17 -0
- package/src/codegen/generate.ts +82 -0
- package/src/codegen/package-cli.ts +14 -0
- package/src/codegen/package.ts +55 -0
- package/src/composites/cloud-stack.ts +74 -0
- package/src/composites/composites.test.ts +131 -0
- package/src/composites/dev-stack.ts +81 -0
- package/src/config.ts +150 -0
- package/src/coverage.test.ts +9 -0
- package/src/coverage.ts +37 -0
- package/src/example.test.ts +59 -0
- package/src/generated/lexicon-temporal.json +26 -0
- package/src/index.ts +29 -0
- package/src/lint/post-synth/post-synth.test.ts +152 -0
- package/src/lint/post-synth/tmp010-cron-syntax.ts +64 -0
- package/src/lint/post-synth/tmp011-namespace-reference.ts +49 -0
- package/src/lint/rules/index.ts +2 -0
- package/src/lint/rules/lint-rules.test.ts +150 -0
- package/src/lint/rules/tmp001.ts +53 -0
- package/src/lint/rules/tmp002.ts +45 -0
- package/src/plugin.test.ts +97 -0
- package/src/plugin.ts +286 -0
- package/src/resources.ts +121 -0
- package/src/serializer.test.ts +292 -0
- package/src/serializer.ts +310 -0
- package/src/skills/chant-temporal-ops.md +184 -0
- package/src/skills/chant-temporal.md +201 -0
- package/src/validate-cli.ts +7 -0
- package/src/validate.test.ts +9 -0
- package/src/validate.ts +92 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Temporal plugin tests.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, expect, it } from "vitest";
|
|
6
|
+
import { temporalPlugin } from "./plugin";
|
|
7
|
+
import { isLexiconPlugin } from "@intentius/chant/lexicon";
|
|
8
|
+
|
|
9
|
+
describe("temporal plugin", () => {
|
|
10
|
+
it("is a valid LexiconPlugin", () => {
|
|
11
|
+
expect(isLexiconPlugin(temporalPlugin)).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("has the correct name", () => {
|
|
15
|
+
expect(temporalPlugin.name).toBe("temporal");
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("has a serializer with name 'temporal'", () => {
|
|
19
|
+
expect(temporalPlugin.serializer).toBeDefined();
|
|
20
|
+
expect(temporalPlugin.serializer.name).toBe("temporal");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("lintRules() returns 2 rules (TMP001, TMP002)", () => {
|
|
24
|
+
const rules = temporalPlugin.lintRules?.();
|
|
25
|
+
expect(Array.isArray(rules)).toBe(true);
|
|
26
|
+
expect(rules?.length).toBe(2);
|
|
27
|
+
const ids = rules?.map((r) => r.id).sort();
|
|
28
|
+
expect(ids).toEqual(["TMP001", "TMP002"]);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("mcpTools() returns 1 diff tool", () => {
|
|
32
|
+
const tools = temporalPlugin.mcpTools?.();
|
|
33
|
+
expect(Array.isArray(tools)).toBe(true);
|
|
34
|
+
expect(tools?.length).toBe(1);
|
|
35
|
+
expect(tools?.[0].name).toBe("diff");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("mcpResources() returns at least 2 resources including resource-catalog", () => {
|
|
39
|
+
const resources = temporalPlugin.mcpResources?.();
|
|
40
|
+
expect(Array.isArray(resources)).toBe(true);
|
|
41
|
+
expect((resources?.length ?? 0)).toBeGreaterThanOrEqual(2);
|
|
42
|
+
const uris = resources?.map((r) => r.uri);
|
|
43
|
+
expect(uris).toContain("resource-catalog");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("skills() returns 2 skill entries", () => {
|
|
47
|
+
const skills = temporalPlugin.skills?.();
|
|
48
|
+
expect(Array.isArray(skills)).toBe(true);
|
|
49
|
+
expect(skills?.length).toBe(2);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("skills include chant-temporal and chant-temporal-ops", () => {
|
|
53
|
+
const skills = temporalPlugin.skills?.() ?? [];
|
|
54
|
+
const names = skills.map((s) => s.name);
|
|
55
|
+
expect(names).toContain("chant-temporal");
|
|
56
|
+
expect(names).toContain("chant-temporal-ops");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe("initTemplates", () => {
|
|
60
|
+
it("default template returns src with temporal.ts", () => {
|
|
61
|
+
const result = temporalPlugin.initTemplates?.();
|
|
62
|
+
expect(result).toBeDefined();
|
|
63
|
+
expect(result?.src).toBeDefined();
|
|
64
|
+
expect(result?.src?.["temporal.ts"]).toBeDefined();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("default template includes TemporalServer and TemporalNamespace imports", () => {
|
|
68
|
+
const result = temporalPlugin.initTemplates?.();
|
|
69
|
+
const src = result?.src?.["temporal.ts"] as string;
|
|
70
|
+
expect(src).toContain("TemporalServer");
|
|
71
|
+
expect(src).toContain("TemporalNamespace");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("'cloud' template includes TemporalNamespace and SearchAttribute (no server)", () => {
|
|
75
|
+
const result = temporalPlugin.initTemplates?.("cloud");
|
|
76
|
+
const src = result?.src?.["temporal.ts"] as string;
|
|
77
|
+
expect(src).toContain("TemporalNamespace");
|
|
78
|
+
expect(src).toContain("SearchAttribute");
|
|
79
|
+
expect(src).not.toContain("TemporalServer");
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("'full' template includes all 4 resource types", () => {
|
|
83
|
+
const result = temporalPlugin.initTemplates?.("full");
|
|
84
|
+
const src = result?.src?.["temporal.ts"] as string;
|
|
85
|
+
expect(src).toContain("TemporalServer");
|
|
86
|
+
expect(src).toContain("TemporalNamespace");
|
|
87
|
+
expect(src).toContain("SearchAttribute");
|
|
88
|
+
expect(src).toContain("TemporalSchedule");
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("'full' template uses mode: \"full\"", () => {
|
|
92
|
+
const result = temporalPlugin.initTemplates?.("full");
|
|
93
|
+
const src = result?.src?.["temporal.ts"] as string;
|
|
94
|
+
expect(src).toContain('"full"');
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
package/src/plugin.ts
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Temporal lexicon plugin — implements the LexiconPlugin lifecycle.
|
|
3
|
+
*
|
|
4
|
+
* All resources are hand-written; there is no remote spec to generate from.
|
|
5
|
+
* The generate step is a no-op. The package step builds dist/manifest.json
|
|
6
|
+
* and copies skill markdown files.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { join, dirname } from "path";
|
|
10
|
+
import { fileURLToPath } from "url";
|
|
11
|
+
import type { LexiconPlugin } from "@intentius/chant/lexicon";
|
|
12
|
+
import { discoverLintRules, discoverPostSynthChecks } from "@intentius/chant/lint/discover";
|
|
13
|
+
import { createSkillsLoader, createDiffTool, createCatalogResource } from "@intentius/chant/lexicon-plugin-helpers";
|
|
14
|
+
import { temporalSerializer } from "./serializer";
|
|
15
|
+
|
|
16
|
+
const srcDir = dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
const rulesDir = join(srcDir, "lint/rules");
|
|
18
|
+
const postSynthDir = join(srcDir, "lint/post-synth");
|
|
19
|
+
|
|
20
|
+
export const temporalPlugin: LexiconPlugin = {
|
|
21
|
+
name: "temporal",
|
|
22
|
+
serializer: temporalSerializer,
|
|
23
|
+
|
|
24
|
+
// ── Required lifecycle methods ──────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
async generate(options?: { verbose?: boolean }): Promise<void> {
|
|
27
|
+
const { generate, writeGeneratedFiles } = await import("./codegen/generate");
|
|
28
|
+
const { dirname: pathDirname } = await import("path");
|
|
29
|
+
const { fileURLToPath: toPath } = await import("url");
|
|
30
|
+
const pkgDir = pathDirname(pathDirname(toPath(import.meta.url)));
|
|
31
|
+
const result = await generate(options);
|
|
32
|
+
writeGeneratedFiles(result, pkgDir);
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
async validate(options?: { verbose?: boolean }): Promise<void> {
|
|
36
|
+
const { validate } = await import("./validate");
|
|
37
|
+
const result = await validate(options);
|
|
38
|
+
if (result.failed > 0) {
|
|
39
|
+
throw new Error(`Temporal lexicon validation failed:\n${result.errors.join("\n")}`);
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
async coverage(options?: { verbose?: boolean }): Promise<void> {
|
|
44
|
+
const { analyze, printCoverageResult } = await import("./coverage");
|
|
45
|
+
const result = analyze();
|
|
46
|
+
printCoverageResult(result, options?.verbose ?? true);
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
async package(options?: { verbose?: boolean; force?: boolean }): Promise<void> {
|
|
50
|
+
const { packageLexicon } = await import("./codegen/package");
|
|
51
|
+
const { writeBundleSpec } = await import("@intentius/chant/codegen/package");
|
|
52
|
+
const { join: pathJoin, dirname: pathDirname } = await import("path");
|
|
53
|
+
const { fileURLToPath: toPath } = await import("url");
|
|
54
|
+
|
|
55
|
+
const { spec, stats } = await packageLexicon(options);
|
|
56
|
+
const pkgDir = pathDirname(pathDirname(toPath(import.meta.url)));
|
|
57
|
+
writeBundleSpec(spec, pathJoin(pkgDir, "dist"));
|
|
58
|
+
|
|
59
|
+
console.error(`Packaged ${stats.resources} resources, ${stats.ruleCount} rules, ${stats.skillCount} skills`);
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
// ── Optional extensions ─────────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
lintRules() {
|
|
65
|
+
return discoverLintRules(rulesDir, import.meta.url);
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
postSynthChecks() {
|
|
69
|
+
return discoverPostSynthChecks(postSynthDir, import.meta.url);
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
skills() {
|
|
73
|
+
return createSkillsLoader(import.meta.url, [
|
|
74
|
+
{
|
|
75
|
+
file: "chant-temporal.md",
|
|
76
|
+
name: "chant-temporal",
|
|
77
|
+
description: "Temporal server setup, namespace provisioning, and schedule registration",
|
|
78
|
+
triggers: [
|
|
79
|
+
{ type: "file-pattern", value: "**/*.ts" },
|
|
80
|
+
{ type: "context", value: "temporal" },
|
|
81
|
+
{ type: "context", value: "workflow" },
|
|
82
|
+
],
|
|
83
|
+
parameters: [],
|
|
84
|
+
examples: [],
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
file: "chant-temporal-ops.md",
|
|
88
|
+
name: "chant-temporal-ops",
|
|
89
|
+
description: "Signal workflows, diagnose stuck activities, reset checkpoints",
|
|
90
|
+
triggers: [
|
|
91
|
+
{ type: "context", value: "temporal workflow" },
|
|
92
|
+
{ type: "context", value: "stuck activity" },
|
|
93
|
+
{ type: "context", value: "chant run" },
|
|
94
|
+
],
|
|
95
|
+
parameters: [],
|
|
96
|
+
examples: [],
|
|
97
|
+
},
|
|
98
|
+
])();
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
mcpTools() {
|
|
102
|
+
return [
|
|
103
|
+
createDiffTool(
|
|
104
|
+
temporalSerializer,
|
|
105
|
+
"Compare current Temporal build output (docker-compose.yml, temporal-setup.sh, schedules/) against previous version",
|
|
106
|
+
),
|
|
107
|
+
];
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
mcpResources() {
|
|
111
|
+
return [
|
|
112
|
+
createCatalogResource(
|
|
113
|
+
import.meta.url,
|
|
114
|
+
"Temporal Resource Types",
|
|
115
|
+
"All supported Temporal resource types: TemporalServer, TemporalNamespace, SearchAttribute, TemporalSchedule",
|
|
116
|
+
"lexicon-temporal.json",
|
|
117
|
+
),
|
|
118
|
+
{
|
|
119
|
+
uri: "examples/dev-server",
|
|
120
|
+
name: "Local Dev Server Example",
|
|
121
|
+
description: "Minimal Temporal dev server with namespace for local development",
|
|
122
|
+
mimeType: "text/typescript",
|
|
123
|
+
async handler(): Promise<string> {
|
|
124
|
+
return [
|
|
125
|
+
'import { TemporalServer, TemporalNamespace } from "@intentius/chant-lexicon-temporal";',
|
|
126
|
+
"",
|
|
127
|
+
"// Local dev server — runs via `temporal server start-dev`",
|
|
128
|
+
'export const server = new TemporalServer({ mode: "dev" });',
|
|
129
|
+
"",
|
|
130
|
+
"export const ns = new TemporalNamespace({",
|
|
131
|
+
' name: "default",',
|
|
132
|
+
' retention: "7d",',
|
|
133
|
+
"});",
|
|
134
|
+
].join("\n");
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
uri: "examples/cloud-setup",
|
|
139
|
+
name: "Temporal Cloud Setup Example",
|
|
140
|
+
description: "Namespace and search attributes for Temporal Cloud (no local server)",
|
|
141
|
+
mimeType: "text/typescript",
|
|
142
|
+
async handler(): Promise<string> {
|
|
143
|
+
return [
|
|
144
|
+
'import { TemporalNamespace, SearchAttribute, TemporalSchedule } from "@intentius/chant-lexicon-temporal";',
|
|
145
|
+
"",
|
|
146
|
+
"export const ns = new TemporalNamespace({",
|
|
147
|
+
' name: "prod",',
|
|
148
|
+
' retention: "30d",',
|
|
149
|
+
' description: "Production workflow namespace",',
|
|
150
|
+
"});",
|
|
151
|
+
"",
|
|
152
|
+
"export const projectAttr = new SearchAttribute({",
|
|
153
|
+
' name: "Project",',
|
|
154
|
+
' type: "Keyword",',
|
|
155
|
+
' namespace: "prod",',
|
|
156
|
+
"});",
|
|
157
|
+
"",
|
|
158
|
+
"export const dailyReport = new TemporalSchedule({",
|
|
159
|
+
' scheduleId: "daily-report",',
|
|
160
|
+
" spec: {",
|
|
161
|
+
' cronExpressions: ["0 8 * * *"],',
|
|
162
|
+
" },",
|
|
163
|
+
" action: {",
|
|
164
|
+
' workflowType: "reportWorkflow",',
|
|
165
|
+
' taskQueue: "reports",',
|
|
166
|
+
" },",
|
|
167
|
+
" policies: {",
|
|
168
|
+
' overlap: "Skip",',
|
|
169
|
+
" },",
|
|
170
|
+
"});",
|
|
171
|
+
].join("\n");
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
];
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
// ── initTemplates ────────────────────────────────────────────────────
|
|
178
|
+
// 3 templates: "local" (default), "cloud", "full"
|
|
179
|
+
|
|
180
|
+
initTemplates(template?: string) {
|
|
181
|
+
if (template === "cloud") {
|
|
182
|
+
return {
|
|
183
|
+
src: {
|
|
184
|
+
"temporal.ts": [
|
|
185
|
+
'import { TemporalNamespace, SearchAttribute, TemporalSchedule } from "@intentius/chant-lexicon-temporal";',
|
|
186
|
+
"",
|
|
187
|
+
"// Namespace — provision once after connecting to Temporal Cloud",
|
|
188
|
+
"export const ns = new TemporalNamespace({",
|
|
189
|
+
' name: "my-namespace",',
|
|
190
|
+
' retention: "30d",',
|
|
191
|
+
' description: "Production deployment namespace",',
|
|
192
|
+
"});",
|
|
193
|
+
"",
|
|
194
|
+
"// Search attributes — register once per namespace",
|
|
195
|
+
"export const projectAttr = new SearchAttribute({",
|
|
196
|
+
' name: "Project",',
|
|
197
|
+
' type: "Keyword",',
|
|
198
|
+
' namespace: "my-namespace",',
|
|
199
|
+
"});",
|
|
200
|
+
"",
|
|
201
|
+
"// Schedule — daily maintenance run",
|
|
202
|
+
"export const maintenanceSchedule = new TemporalSchedule({",
|
|
203
|
+
' scheduleId: "daily-maintenance",',
|
|
204
|
+
" spec: {",
|
|
205
|
+
' cronExpressions: ["0 2 * * *"],',
|
|
206
|
+
" },",
|
|
207
|
+
" action: {",
|
|
208
|
+
' workflowType: "maintenanceWorkflow",',
|
|
209
|
+
' taskQueue: "maintenance-queue",',
|
|
210
|
+
" },",
|
|
211
|
+
" policies: {",
|
|
212
|
+
' overlap: "Skip",',
|
|
213
|
+
" },",
|
|
214
|
+
"});",
|
|
215
|
+
].join("\n"),
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (template === "full") {
|
|
221
|
+
return {
|
|
222
|
+
src: {
|
|
223
|
+
"temporal.ts": [
|
|
224
|
+
'import {',
|
|
225
|
+
' TemporalServer,',
|
|
226
|
+
' TemporalNamespace,',
|
|
227
|
+
' SearchAttribute,',
|
|
228
|
+
' TemporalSchedule,',
|
|
229
|
+
'} from "@intentius/chant-lexicon-temporal";',
|
|
230
|
+
"",
|
|
231
|
+
"// Full server stack (auto-setup + postgres + UI)",
|
|
232
|
+
"export const server = new TemporalServer({",
|
|
233
|
+
' version: "1.26.2",',
|
|
234
|
+
' mode: "full",',
|
|
235
|
+
" port: 7233,",
|
|
236
|
+
" uiPort: 8080,",
|
|
237
|
+
"});",
|
|
238
|
+
"",
|
|
239
|
+
"export const ns = new TemporalNamespace({",
|
|
240
|
+
' name: "default",',
|
|
241
|
+
' retention: "7d",',
|
|
242
|
+
"});",
|
|
243
|
+
"",
|
|
244
|
+
"export const projectAttr = new SearchAttribute({",
|
|
245
|
+
' name: "Project",',
|
|
246
|
+
' type: "Keyword",',
|
|
247
|
+
"});",
|
|
248
|
+
"",
|
|
249
|
+
"export const weeklyBackup = new TemporalSchedule({",
|
|
250
|
+
' scheduleId: "weekly-backup",',
|
|
251
|
+
" spec: {",
|
|
252
|
+
' cronExpressions: ["0 3 * * SUN"],',
|
|
253
|
+
" },",
|
|
254
|
+
" action: {",
|
|
255
|
+
' workflowType: "backupWorkflow",',
|
|
256
|
+
' taskQueue: "backup-queue",',
|
|
257
|
+
" },",
|
|
258
|
+
"});",
|
|
259
|
+
].join("\n"),
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// default = "local"
|
|
265
|
+
return {
|
|
266
|
+
src: {
|
|
267
|
+
"temporal.ts": [
|
|
268
|
+
'import { TemporalServer, TemporalNamespace } from "@intentius/chant-lexicon-temporal";',
|
|
269
|
+
"",
|
|
270
|
+
"// Local dev server — runs via `temporal server start-dev`",
|
|
271
|
+
"export const server = new TemporalServer({ mode: \"dev\" });",
|
|
272
|
+
"",
|
|
273
|
+
"export const ns = new TemporalNamespace({",
|
|
274
|
+
' name: "default",',
|
|
275
|
+
' retention: "7d",',
|
|
276
|
+
"});",
|
|
277
|
+
].join("\n"),
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
},
|
|
281
|
+
|
|
282
|
+
async docs(options?) {
|
|
283
|
+
const { generateDocs } = await import("./codegen/docs");
|
|
284
|
+
return generateDocs(options);
|
|
285
|
+
},
|
|
286
|
+
};
|
package/src/resources.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Temporal lexicon resources — hand-written Declarable constructors.
|
|
3
|
+
*
|
|
4
|
+
* These model the Temporal.io infrastructure concerns that chant serializes:
|
|
5
|
+
* server deployment configs, namespace provisioning scripts, search attribute
|
|
6
|
+
* registration, and SDK schedule creation code.
|
|
7
|
+
*
|
|
8
|
+
* All 4 resources are hand-written (no upstream spec to generate from).
|
|
9
|
+
*
|
|
10
|
+
* Reference: https://docs.temporal.io
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { createResource } from "@intentius/chant/runtime";
|
|
14
|
+
|
|
15
|
+
// ── TemporalServer ────────────────────────────────────────────────────
|
|
16
|
+
// Serializes to docker-compose.yml (primary) and temporal-helm-values.yaml.
|
|
17
|
+
// mode: "dev" emits a single-container dev server via `temporal server start-dev`.
|
|
18
|
+
// mode: "full" emits auto-setup + postgresql + UI services.
|
|
19
|
+
|
|
20
|
+
export const TemporalServer = createResource("Temporal::Server", "temporal", {});
|
|
21
|
+
|
|
22
|
+
export interface TemporalServerProps {
|
|
23
|
+
/** Temporal server version tag. Default: "1.26.2" */
|
|
24
|
+
version?: string;
|
|
25
|
+
/** Deployment mode. Default: "dev" */
|
|
26
|
+
mode?: "dev" | "full";
|
|
27
|
+
/** gRPC port. Default: 7233 */
|
|
28
|
+
port?: number;
|
|
29
|
+
/** Web UI port. Default: 8080 */
|
|
30
|
+
uiPort?: number;
|
|
31
|
+
/** PostgreSQL image tag for "full" mode. Default: "16-alpine" */
|
|
32
|
+
postgresVersion?: string;
|
|
33
|
+
/** Helm chart version hint — written as a comment in helm-values.yaml */
|
|
34
|
+
helmChartVersion?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ── TemporalNamespace ─────────────────────────────────────────────────
|
|
38
|
+
// Serializes to temporal-setup.sh as `temporal operator namespace create` commands.
|
|
39
|
+
|
|
40
|
+
export const TemporalNamespace = createResource("Temporal::Namespace", "temporal", {});
|
|
41
|
+
|
|
42
|
+
export interface TemporalNamespaceProps {
|
|
43
|
+
/** Namespace name */
|
|
44
|
+
name: string;
|
|
45
|
+
/** Workflow execution retention period. Default: "7d" */
|
|
46
|
+
retention?: string;
|
|
47
|
+
/** Human-readable description */
|
|
48
|
+
description?: string;
|
|
49
|
+
/** Whether this is a global (multi-cluster) namespace */
|
|
50
|
+
isGlobalNamespace?: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ── SearchAttribute ───────────────────────────────────────────────────
|
|
54
|
+
// Serializes to temporal-setup.sh as `temporal operator search-attribute create` commands.
|
|
55
|
+
|
|
56
|
+
export const SearchAttribute = createResource("Temporal::SearchAttribute", "temporal", {});
|
|
57
|
+
|
|
58
|
+
export interface SearchAttributeProps {
|
|
59
|
+
/** Attribute name (PascalCase recommended by Temporal) */
|
|
60
|
+
name: string;
|
|
61
|
+
/** Attribute value type */
|
|
62
|
+
type: "Text" | "Keyword" | "Int" | "Double" | "Bool" | "Datetime" | "KeywordList";
|
|
63
|
+
/** Namespace to register in. If omitted, --namespace flag is not emitted */
|
|
64
|
+
namespace?: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ── TemporalSchedule ──────────────────────────────────────────────────
|
|
68
|
+
// Serializes to schedules/<scheduleId>.ts — runnable TypeScript that creates
|
|
69
|
+
// the schedule via the Temporal SDK client.
|
|
70
|
+
|
|
71
|
+
export const TemporalSchedule = createResource("Temporal::Schedule", "temporal", {});
|
|
72
|
+
|
|
73
|
+
export interface TemporalScheduleProps {
|
|
74
|
+
/** Unique schedule identifier */
|
|
75
|
+
scheduleId: string;
|
|
76
|
+
/** Schedule timing specification */
|
|
77
|
+
spec: {
|
|
78
|
+
/** Cron expressions (e.g. "0 9 * * MON-FRI") */
|
|
79
|
+
cronExpressions?: string[];
|
|
80
|
+
/** Fixed intervals (e.g. { every: "1d" }) */
|
|
81
|
+
intervals?: Array<{ every: string; offset?: string }>;
|
|
82
|
+
};
|
|
83
|
+
/** What workflow to start */
|
|
84
|
+
action: {
|
|
85
|
+
workflowType: string;
|
|
86
|
+
taskQueue: string;
|
|
87
|
+
args?: unknown[];
|
|
88
|
+
workflowExecutionTimeout?: string;
|
|
89
|
+
workflowRunTimeout?: string;
|
|
90
|
+
memo?: Record<string, unknown>;
|
|
91
|
+
searchAttributes?: Record<string, unknown>;
|
|
92
|
+
/**
|
|
93
|
+
* Retry policy for the triggered workflow execution.
|
|
94
|
+
* When set, the generated schedule script includes `workflowStartOptions.retry`.
|
|
95
|
+
*/
|
|
96
|
+
workflowRetryPolicy?: {
|
|
97
|
+
/** Initial retry interval (e.g. "10s"). Default: Temporal server default (~1s). */
|
|
98
|
+
initialInterval?: string;
|
|
99
|
+
/** Backoff multiplier for each subsequent retry (e.g. 2). */
|
|
100
|
+
backoffCoefficient?: number;
|
|
101
|
+
/** 0 = unlimited retries; defaults to Temporal server default (unlimited). */
|
|
102
|
+
maximumAttempts?: number;
|
|
103
|
+
/** Cap on retry intervals (e.g. "5m"). */
|
|
104
|
+
maximumInterval?: string;
|
|
105
|
+
/** Error types that should NOT trigger a retry. */
|
|
106
|
+
nonRetryableErrorTypes?: string[];
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
policies?: {
|
|
110
|
+
overlap?: "Skip" | "BufferOne" | "BufferAll" | "CancelOther" | "TerminateOther" | "AllowAll";
|
|
111
|
+
catchupWindow?: string;
|
|
112
|
+
pauseOnFailure?: boolean;
|
|
113
|
+
};
|
|
114
|
+
/** Initial paused state */
|
|
115
|
+
state?: {
|
|
116
|
+
paused?: boolean;
|
|
117
|
+
note?: string;
|
|
118
|
+
};
|
|
119
|
+
/** Namespace to create schedule in. Default: process.env.TEMPORAL_NAMESPACE ?? "default" */
|
|
120
|
+
namespace?: string;
|
|
121
|
+
}
|