@lunora/codegen 1.0.0-alpha.41 → 1.0.0-alpha.43
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/index.d.mts +142 -9
- package/dist/index.d.ts +142 -9
- package/dist/index.mjs +7 -6
- package/dist/packem_shared/AGENTS_FILENAME-BksnAJgx.mjs +116 -0
- package/dist/packem_shared/GENERATED_HEADER-B-FzJ297.mjs +4 -0
- package/dist/packem_shared/{OPENRPC_VERSION-DxbqafcJ.mjs → OPENRPC_VERSION-DqTYxQ22.mjs} +1 -1
- package/dist/packem_shared/{SCHEMA_SNAPSHOT_FILENAME-C1yHg38Z.mjs → SCHEMA_SNAPSHOT_FILENAME-BbF69nj9.mjs} +68 -9
- package/dist/packem_shared/{buildOpenApiDocument-_mwWOc2N.mjs → buildOpenApiDocument-BrN41JMl.mjs} +1 -1
- package/dist/packem_shared/{discoverCrons-D-jrpm97.mjs → discoverCrons-DJJ3ZE5F.mjs} +35 -20
- package/dist/packem_shared/{emit-CFz-9dcD.mjs → emit-DtherCpQ.mjs} +286 -32
- package/dist/packem_shared/{emitApp-D8rVuM__.mjs → emitApp-D7daY94X.mjs} +25 -2
- package/package.json +5 -4
- package/dist/packem_shared/GENERATED_HEADER-cUyu5VOU.mjs +0 -3
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { agentDefaultName, agentClassName, agentBindingName, voiceBindingName, voiceClassName } from '@lunora/agent/naming';
|
|
4
|
+
import { SyntaxKind, Node } from 'ts-morph';
|
|
5
|
+
import { diagnosticAt } from './CodegenDiagnosticError-DyQ5FwkM.mjs';
|
|
6
|
+
|
|
7
|
+
const AGENTS_FILENAME = "agents.ts";
|
|
8
|
+
const isDefineAgent = (identifier) => {
|
|
9
|
+
const symbol = identifier.getSymbol();
|
|
10
|
+
if (!symbol) {
|
|
11
|
+
return identifier.getText() === "defineAgent";
|
|
12
|
+
}
|
|
13
|
+
for (const declaration of symbol.getDeclarations()) {
|
|
14
|
+
if (!Node.isImportSpecifier(declaration)) {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (declaration.getImportDeclaration().getModuleSpecifierValue() !== "@lunora/agent") {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
return declaration.getNameNode().getText() === "defineAgent";
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
};
|
|
24
|
+
const stringProperty = (expression, exportName, property) => {
|
|
25
|
+
if (Node.isStringLiteral(expression) || Node.isNoSubstitutionTemplateLiteral(expression)) {
|
|
26
|
+
return expression.getLiteralValue();
|
|
27
|
+
}
|
|
28
|
+
throw diagnosticAt(
|
|
29
|
+
expression,
|
|
30
|
+
`agent "${exportName}": \`${property}\` must be a static string literal — it is deploy configuration codegen writes into wrangler.jsonc`
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
const booleanProperty = (expression, exportName, property) => {
|
|
34
|
+
if (expression.getKind() === SyntaxKind.TrueKeyword) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
if (expression.getKind() === SyntaxKind.FalseKeyword) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
throw diagnosticAt(
|
|
41
|
+
expression,
|
|
42
|
+
`agent "${exportName}": \`${property}\` must be a static boolean literal — it is deploy configuration codegen writes into the ctx.agents wiring spec`
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
const agentFromCall = (call, exportName) => {
|
|
46
|
+
const argument = call.getArguments()[0];
|
|
47
|
+
if (!argument || !Node.isObjectLiteralExpression(argument)) {
|
|
48
|
+
throw diagnosticAt(call, `agent "${exportName}": defineAgent must be passed an inline object literal`);
|
|
49
|
+
}
|
|
50
|
+
const ir = {
|
|
51
|
+
bindingName: agentBindingName(exportName),
|
|
52
|
+
className: agentClassName(exportName),
|
|
53
|
+
exportName,
|
|
54
|
+
name: agentDefaultName(exportName)
|
|
55
|
+
};
|
|
56
|
+
const nameProperty = argument.getProperty("name");
|
|
57
|
+
if (nameProperty && Node.isPropertyAssignment(nameProperty)) {
|
|
58
|
+
ir.name = stringProperty(nameProperty.getInitializerOrThrow(), exportName, "name");
|
|
59
|
+
}
|
|
60
|
+
const publicRunProperty = argument.getProperty("publicRun");
|
|
61
|
+
if (publicRunProperty && Node.isPropertyAssignment(publicRunProperty) && booleanProperty(publicRunProperty.getInitializerOrThrow(), exportName, "publicRun")) {
|
|
62
|
+
ir.publicRun = true;
|
|
63
|
+
}
|
|
64
|
+
const voiceProperty = argument.getProperty("voice");
|
|
65
|
+
if (voiceProperty && Node.isPropertyAssignment(voiceProperty)) {
|
|
66
|
+
const voiceInitializer = voiceProperty.getInitializerOrThrow();
|
|
67
|
+
if (!Node.isObjectLiteralExpression(voiceInitializer)) {
|
|
68
|
+
throw diagnosticAt(
|
|
69
|
+
voiceInitializer,
|
|
70
|
+
`agent "${exportName}": \`voice\` must be an inline object literal — its presence tells codegen to emit the voice-session Durable Object`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
ir.voice = true;
|
|
74
|
+
ir.voiceBindingName = voiceBindingName(exportName);
|
|
75
|
+
ir.voiceClassName = voiceClassName(exportName);
|
|
76
|
+
}
|
|
77
|
+
if (argument.getProperty("onEmail")) {
|
|
78
|
+
ir.onEmail = true;
|
|
79
|
+
}
|
|
80
|
+
return ir;
|
|
81
|
+
};
|
|
82
|
+
const agentsFromSource = (source) => {
|
|
83
|
+
const agents = [];
|
|
84
|
+
for (const declaration of source.getVariableDeclarations()) {
|
|
85
|
+
if (!declaration.isExported()) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const initializer = declaration.getInitializer();
|
|
89
|
+
if (initializer?.getKind() !== SyntaxKind.CallExpression) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const call = initializer;
|
|
93
|
+
const callee = call.getExpression();
|
|
94
|
+
if (!Node.isIdentifier(callee) || !isDefineAgent(callee)) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const nameNode = declaration.getNameNode();
|
|
98
|
+
if (!Node.isIdentifier(nameNode)) {
|
|
99
|
+
throw diagnosticAt(nameNode, "defineAgent exports must be plain named exports (no destructuring)");
|
|
100
|
+
}
|
|
101
|
+
agents.push(agentFromCall(call, nameNode.getText()));
|
|
102
|
+
}
|
|
103
|
+
return agents;
|
|
104
|
+
};
|
|
105
|
+
const discoverAgents = (project, lunoraDirectory) => {
|
|
106
|
+
const agentsPath = join(lunoraDirectory, AGENTS_FILENAME);
|
|
107
|
+
if (!existsSync(agentsPath)) {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
const source = project.getSourceFile(agentsPath) ?? project.addSourceFileAtPath(agentsPath);
|
|
111
|
+
const agents = agentsFromSource(source);
|
|
112
|
+
agents.sort((a, b) => a.exportName.localeCompare(b.exportName));
|
|
113
|
+
return agents;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export { AGENTS_FILENAME, discoverAgents };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import '@lunora/agent/component';
|
|
2
|
+
import '@lunora/errors';
|
|
3
|
+
export { G as GENERATED_HEADER, n as buildStorageColumns, e as emitAgents, a as emitApi, b as emitCollections, c as emitContainers, d as emitCrons, f as emitDataModel, g as emitDrizzleSchema, h as emitFunctions, o as emitQueues, p as emitSeed, i as emitServer, j as emitShard, k as emitVectors, l as emitWorkflows, m as emitWranglerCronTriggers } from './emit-DtherCpQ.mjs';
|
|
4
|
+
import './paths-BRd6JHuF.mjs';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as GENERATED_HEADER } from './emit-
|
|
1
|
+
import { G as GENERATED_HEADER } from './emit-DtherCpQ.mjs';
|
|
2
2
|
import { s as sanitizeNamespace } from './paths-BRd6JHuF.mjs';
|
|
3
3
|
import { argsObjectSchema, LUNORA_ERROR_CODES } from './LUNORA_ERROR_CODES-DvTLozCu.mjs';
|
|
4
4
|
|
|
@@ -5,11 +5,12 @@ import { LunoraError } from '@lunora/errors';
|
|
|
5
5
|
import { Node, SyntaxKind, Project } from 'ts-morph';
|
|
6
6
|
import { lintSchema } from './formatAdvisories-DRhEiJUz.mjs';
|
|
7
7
|
import { listLunoraSourceFiles, lunoraRelativePath, classifyProcedureCall, inlineHandler as inlineHandler$1, procedureHandler, chainUsesWrappedCall, isDatabaseAccessor, chainHasStep, discoverFunctions } from './discoverFunctions-CZ91aenA.mjs';
|
|
8
|
+
import { discoverAgents } from './AGENTS_FILENAME-BksnAJgx.mjs';
|
|
8
9
|
import discoverAuthApiCalls from './discoverAuthApiCalls-WMx8L2FG.mjs';
|
|
9
10
|
import { discoverContainers } from './CONTAINERS_FILENAME-DjpXMqhp.mjs';
|
|
10
|
-
import discoverCrons from './discoverCrons-
|
|
11
|
+
import discoverCrons from './discoverCrons-DJJ3ZE5F.mjs';
|
|
11
12
|
import { diagnosticAt } from './CodegenDiagnosticError-DyQ5FwkM.mjs';
|
|
12
|
-
import { C as CAPABILITIES,
|
|
13
|
+
import { C as CAPABILITIES, n as buildStorageColumns, f as emitDataModel, a as emitApi, i as emitServer, h as emitFunctions, j as emitShard, b as emitCollections, c as emitContainers, l as emitWorkflows, e as emitAgents, o as emitQueues, d as emitCrons, k as emitVectors, g as emitDrizzleSchema, p as emitSeed, m as emitWranglerCronTriggers } from './emit-DtherCpQ.mjs';
|
|
13
14
|
import { discoverFlagKeys } from './FLAGS_FILENAME-fEZtzWXi.mjs';
|
|
14
15
|
import discoverHttpRoutes from './discoverHttpRoutes-DNZLDCmm.mjs';
|
|
15
16
|
import discoverInserts from './discoverInserts-DFRJhmCv.mjs';
|
|
@@ -27,9 +28,9 @@ import { discoverShapes } from './SHAPES_FILENAME-DOhPGi-6.mjs';
|
|
|
27
28
|
import discoverStorageRulesMetadata from './discoverStorageRulesMetadata-nosjYcvN.mjs';
|
|
28
29
|
import { e as enclosingExportName$2 } from './discover-ast-CT6BgBr4.mjs';
|
|
29
30
|
import { discoverWorkflows } from './WORKFLOWS_FILENAME-B2By8S4s.mjs';
|
|
30
|
-
import { emitApp } from './emitApp-
|
|
31
|
-
import { buildOpenApiDocument, emitOpenApiModule } from './buildOpenApiDocument-
|
|
32
|
-
import { buildOpenRpcDocument, emitOpenRpcModule } from './OPENRPC_VERSION-
|
|
31
|
+
import { emitApp } from './emitApp-D7daY94X.mjs';
|
|
32
|
+
import { buildOpenApiDocument, emitOpenApiModule } from './buildOpenApiDocument-BrN41JMl.mjs';
|
|
33
|
+
import { buildOpenRpcDocument, emitOpenRpcModule } from './OPENRPC_VERSION-DqTYxQ22.mjs';
|
|
33
34
|
import { buildSchemaSnapshot, serializeSchemaSnapshot } from './SCHEMA_SNAPSHOT_VERSION-D0ARY6rL.mjs';
|
|
34
35
|
|
|
35
36
|
const HTTP_VERBS$1 = /* @__PURE__ */ new Set(["delete", "get", "head", "options", "patch", "post", "put"]);
|
|
@@ -2698,6 +2699,41 @@ const discoverRelationLoads = (project, lunoraDirectory) => {
|
|
|
2698
2699
|
return rows;
|
|
2699
2700
|
};
|
|
2700
2701
|
|
|
2702
|
+
const SANDBOX_MODULE_SPECIFIERS = /* @__PURE__ */ new Set(["@lunora/agent", "@lunora/agent/sandbox"]);
|
|
2703
|
+
const scanImportDeclaration = (declaration) => {
|
|
2704
|
+
const found = { usesSandboxBrowser: false, usesSandboxContainer: false };
|
|
2705
|
+
if (!SANDBOX_MODULE_SPECIFIERS.has(declaration.getModuleSpecifierValue()) || declaration.isTypeOnly()) {
|
|
2706
|
+
return found;
|
|
2707
|
+
}
|
|
2708
|
+
for (const named of declaration.getNamedImports()) {
|
|
2709
|
+
if (named.isTypeOnly()) {
|
|
2710
|
+
continue;
|
|
2711
|
+
}
|
|
2712
|
+
const name = named.getNameNode().getText();
|
|
2713
|
+
if (name === "browserTool") {
|
|
2714
|
+
found.usesSandboxBrowser = true;
|
|
2715
|
+
} else if (name === "containerTool") {
|
|
2716
|
+
found.usesSandboxContainer = true;
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
return found;
|
|
2720
|
+
};
|
|
2721
|
+
const discoverSandboxUsage = (project, lunoraDirectory) => {
|
|
2722
|
+
const usage = { usesSandboxBrowser: false, usesSandboxContainer: false };
|
|
2723
|
+
for (const filePath of listLunoraSourceFiles(lunoraDirectory)) {
|
|
2724
|
+
const sourceFile = project.getSourceFile(filePath) ?? project.addSourceFileAtPath(filePath);
|
|
2725
|
+
for (const declaration of sourceFile.getImportDeclarations()) {
|
|
2726
|
+
const found = scanImportDeclaration(declaration);
|
|
2727
|
+
usage.usesSandboxBrowser ||= found.usesSandboxBrowser;
|
|
2728
|
+
usage.usesSandboxContainer ||= found.usesSandboxContainer;
|
|
2729
|
+
}
|
|
2730
|
+
if (usage.usesSandboxBrowser && usage.usesSandboxContainer) {
|
|
2731
|
+
break;
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
return usage;
|
|
2735
|
+
};
|
|
2736
|
+
|
|
2701
2737
|
const literalValueOf = (node) => {
|
|
2702
2738
|
if (Node.isStringLiteral(node) || Node.isNoSubstitutionTemplateLiteral(node)) {
|
|
2703
2739
|
return node.getLiteralText();
|
|
@@ -3166,7 +3202,8 @@ const runCodegen = (options) => {
|
|
|
3166
3202
|
const env = discoverEnv(project, lunoraDirectory);
|
|
3167
3203
|
const workflows = discoverWorkflows(project, lunoraDirectory);
|
|
3168
3204
|
const queues = discoverQueues(project, lunoraDirectory);
|
|
3169
|
-
const
|
|
3205
|
+
const agents = discoverAgents(project, lunoraDirectory);
|
|
3206
|
+
const crons = discoverCrons(project, lunoraDirectory, workflows, agents);
|
|
3170
3207
|
const containers = discoverContainers(project, lunoraDirectory);
|
|
3171
3208
|
const advisories = options.lint === false ? [] : lintSchema({
|
|
3172
3209
|
adminRoutes: discoverAdminRoutes(project, lunoraDirectory),
|
|
@@ -3229,7 +3266,9 @@ const runCodegen = (options) => {
|
|
|
3229
3266
|
const hasFlags = existsSync(join(lunoraDirectory, "flags.ts"));
|
|
3230
3267
|
const flagKeys = hasFlags ? discoverFlagKeys(project, lunoraDirectory) : [];
|
|
3231
3268
|
const hasHyperdrive = featureUsage.hyperdrive;
|
|
3232
|
-
const
|
|
3269
|
+
const sandboxUsage = discoverSandboxUsage(project, lunoraDirectory);
|
|
3270
|
+
const usesSandbox = sandboxUsage.usesSandboxBrowser || sandboxUsage.usesSandboxContainer;
|
|
3271
|
+
const hasBrowser = featureUsage.browser || sandboxUsage.usesSandboxBrowser;
|
|
3233
3272
|
const hasImages = featureUsage.images;
|
|
3234
3273
|
const hasAnalytics = featureUsage.analytics;
|
|
3235
3274
|
const hasPipelines = featureUsage.pipelines;
|
|
@@ -3249,8 +3288,9 @@ const runCodegen = (options) => {
|
|
|
3249
3288
|
const useUmbrella = dependencies.has("lunorash");
|
|
3250
3289
|
const emitStartedAt = timingEnabled ? performance.now() : 0;
|
|
3251
3290
|
const dataModelContent = emitDataModel(schema, useUmbrella);
|
|
3252
|
-
const apiContent = emitApi(functions,
|
|
3291
|
+
const apiContent = emitApi({ agents, functions, useUmbrella, workflows });
|
|
3253
3292
|
const serverContent = emitServer({
|
|
3293
|
+
agents,
|
|
3254
3294
|
containers,
|
|
3255
3295
|
env,
|
|
3256
3296
|
hasAccessFacade,
|
|
@@ -3272,9 +3312,10 @@ const runCodegen = (options) => {
|
|
|
3272
3312
|
useUmbrella,
|
|
3273
3313
|
workflows
|
|
3274
3314
|
});
|
|
3275
|
-
const functionsContent = emitFunctions(functions, migrations,
|
|
3315
|
+
const functionsContent = emitFunctions({ agents, functions, migrations, mutators, shapes, useUmbrella, usesSandbox });
|
|
3276
3316
|
const shardContent = emitShard({
|
|
3277
3317
|
advisories,
|
|
3318
|
+
agents,
|
|
3278
3319
|
containers,
|
|
3279
3320
|
env,
|
|
3280
3321
|
flagKeys,
|
|
@@ -3304,6 +3345,7 @@ const runCodegen = (options) => {
|
|
|
3304
3345
|
const collectionsContent = emitCollections(shapes, dependencies.has("@lunora/db"), useUmbrella);
|
|
3305
3346
|
const containersContent = emitContainers(containers, schema.jurisdiction);
|
|
3306
3347
|
const workflowsContent = emitWorkflows(workflows);
|
|
3348
|
+
const agentsContent = emitAgents(agents);
|
|
3307
3349
|
const queuesContent = emitQueues(queues);
|
|
3308
3350
|
const cronsContent = emitCrons(crons);
|
|
3309
3351
|
const vectorsContent = emitVectors(schema.vectorIndexes);
|
|
@@ -3313,6 +3355,13 @@ const runCodegen = (options) => {
|
|
|
3313
3355
|
const wantsOpenApi = apiSpec === "openapi" || apiSpec === "both";
|
|
3314
3356
|
const wantsOpenRpc = apiSpec === "openrpc" || apiSpec === "both";
|
|
3315
3357
|
const appContent = emitApp({
|
|
3358
|
+
// Inbound-email agents (`defineAgent({ onEmail })`) → wire the worker's
|
|
3359
|
+
// top-level `email()` handler to each agent's `AGENT_*` Workflow binding so
|
|
3360
|
+
// received mail starts a durable run. Empty for email-free (and agent-free)
|
|
3361
|
+
// projects, so the emitted app.ts stays byte-identical.
|
|
3362
|
+
emailAgents: agents.filter((agent) => agent.onEmail === true).map((agent) => {
|
|
3363
|
+
return { bindingName: agent.bindingName, exportName: agent.exportName };
|
|
3364
|
+
}),
|
|
3316
3365
|
hasAccess: dependencies.has("@lunora/cloudflare-access"),
|
|
3317
3366
|
hasAi,
|
|
3318
3367
|
hasAnalytics,
|
|
@@ -3349,6 +3398,13 @@ const runCodegen = (options) => {
|
|
|
3349
3398
|
// Schema `.jurisdiction("…")` → pin the generated worker's DOs to the region.
|
|
3350
3399
|
jurisdiction: schema.jurisdiction,
|
|
3351
3400
|
useUmbrella,
|
|
3401
|
+
// Voice-enabled agents (`defineAgent({ voice: … })`) → wire the worker's
|
|
3402
|
+
// `/_lunora/voice/<exportName>` route to each agent's `VOICE_*` DO
|
|
3403
|
+
// namespace. Empty for voice-free (and agent-free) projects, so the
|
|
3404
|
+
// emitted app.ts stays byte-identical.
|
|
3405
|
+
voiceAgents: agents.filter((agent) => agent.voice === true && agent.voiceBindingName !== void 0).map((agent) => {
|
|
3406
|
+
return { bindingName: agent.voiceBindingName, exportName: agent.exportName };
|
|
3407
|
+
}),
|
|
3352
3408
|
wantsOpenApi,
|
|
3353
3409
|
wantsOpenRpc
|
|
3354
3410
|
});
|
|
@@ -3384,6 +3440,7 @@ const runCodegen = (options) => {
|
|
|
3384
3440
|
writeIfChanged(join(outputDirectory, "drizzle.shard.ts"), drizzleFiles.shard);
|
|
3385
3441
|
writeIfPresent(join(outputDirectory, "containers.ts"), containersContent);
|
|
3386
3442
|
writeIfPresent(join(outputDirectory, "workflows.ts"), workflowsContent);
|
|
3443
|
+
writeIfPresent(join(outputDirectory, "agents.ts"), agentsContent);
|
|
3387
3444
|
writeIfPresent(join(outputDirectory, "queues.ts"), queuesContent);
|
|
3388
3445
|
writeIfPresent(join(outputDirectory, "seed.ts"), seedContent);
|
|
3389
3446
|
writeIfPresent(join(outputDirectory, "collections.ts"), collectionsContent);
|
|
@@ -3404,9 +3461,11 @@ const runCodegen = (options) => {
|
|
|
3404
3461
|
}
|
|
3405
3462
|
return {
|
|
3406
3463
|
advisories,
|
|
3464
|
+
agents,
|
|
3407
3465
|
containers,
|
|
3408
3466
|
cronTriggers: emitWranglerCronTriggers(crons),
|
|
3409
3467
|
generated: {
|
|
3468
|
+
agents: agentsContent,
|
|
3410
3469
|
api: apiContent,
|
|
3411
3470
|
app: appContent,
|
|
3412
3471
|
collections: collectionsContent,
|
package/dist/packem_shared/{buildOpenApiDocument-_mwWOc2N.mjs → buildOpenApiDocument-BrN41JMl.mjs}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as GENERATED_HEADER } from './emit-
|
|
1
|
+
import { G as GENERATED_HEADER } from './emit-DtherCpQ.mjs';
|
|
2
2
|
import { s as sanitizeNamespace } from './paths-BRd6JHuF.mjs';
|
|
3
3
|
import { LUNORA_ERROR_CODES, objectSchema, argsObjectSchema, validatorIrToJsonSchema } from './LUNORA_ERROR_CODES-DvTLozCu.mjs';
|
|
4
4
|
|
|
@@ -128,24 +128,38 @@ const functionPathFromArgument = (call, index, jobName) => {
|
|
|
128
128
|
const workflowTarget = (workflow) => {
|
|
129
129
|
return { workflow: { binding: workflow.bindingName, exportName: workflow.exportName } };
|
|
130
130
|
};
|
|
131
|
-
const
|
|
131
|
+
const agentTarget = (agent) => {
|
|
132
|
+
return { workflow: { binding: agent.bindingName, exportName: agent.exportName } };
|
|
133
|
+
};
|
|
134
|
+
const resolveReferenceAccess = (argument, receiverName, byName, jobName, kind, build) => {
|
|
135
|
+
const receiver = argument.getExpression();
|
|
136
|
+
if (!Node.isIdentifier(receiver) || receiver.getText() !== receiverName) {
|
|
137
|
+
return void 0;
|
|
138
|
+
}
|
|
139
|
+
const definition = byName.get(argument.getName());
|
|
140
|
+
if (definition) {
|
|
141
|
+
return build(definition);
|
|
142
|
+
}
|
|
143
|
+
throw diagnosticAt(
|
|
144
|
+
argument,
|
|
145
|
+
`Cron job "${jobName}" targets ${receiverName}.${argument.getName()}, but no such ${kind} is declared in lunora/${kind}s.ts.`,
|
|
146
|
+
{
|
|
147
|
+
code: "CRON_NON_STATIC_FN",
|
|
148
|
+
name: "LunoraError",
|
|
149
|
+
status: 500
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
};
|
|
153
|
+
const resolveTarget = (call, index, jobName, workflowsByName, agentsByName) => {
|
|
132
154
|
const argument = call.getArguments()[index];
|
|
133
155
|
if (argument && Node.isPropertyAccessExpression(argument)) {
|
|
134
|
-
const
|
|
135
|
-
if (
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
argument,
|
|
142
|
-
`Cron job "${jobName}" targets workflows.${argument.getName()}, but no such workflow is declared in lunora/workflows.ts.`,
|
|
143
|
-
{
|
|
144
|
-
code: "CRON_NON_STATIC_FN",
|
|
145
|
-
name: "LunoraError",
|
|
146
|
-
status: 500
|
|
147
|
-
}
|
|
148
|
-
);
|
|
156
|
+
const workflowReference = resolveReferenceAccess(argument, "workflows", workflowsByName, jobName, "workflow", workflowTarget);
|
|
157
|
+
if (workflowReference) {
|
|
158
|
+
return workflowReference;
|
|
159
|
+
}
|
|
160
|
+
const agentReference = resolveReferenceAccess(argument, "agents", agentsByName, jobName, "agent", agentTarget);
|
|
161
|
+
if (agentReference) {
|
|
162
|
+
return agentReference;
|
|
149
163
|
}
|
|
150
164
|
return { functionPath: functionPathFromArgument(call, index, jobName) };
|
|
151
165
|
}
|
|
@@ -166,7 +180,7 @@ const resolveTarget = (call, index, jobName, workflowsByName) => {
|
|
|
166
180
|
}
|
|
167
181
|
return { functionPath: functionPathFromArgument(call, index, jobName) };
|
|
168
182
|
};
|
|
169
|
-
const cronFromCall = (call, callee, builderNames, workflowsByName) => {
|
|
183
|
+
const cronFromCall = (call, callee, builderNames, workflowsByName, agentsByName) => {
|
|
170
184
|
const method = callee.getName();
|
|
171
185
|
if (!CRON_METHODS.has(method)) {
|
|
172
186
|
return void 0;
|
|
@@ -211,7 +225,7 @@ const cronFromCall = (call, callee, builderNames, workflowsByName) => {
|
|
|
211
225
|
}
|
|
212
226
|
cron = compileCronSchedule(method, objectLiteralValue(scheduleArgument, name));
|
|
213
227
|
}
|
|
214
|
-
const target = resolveTarget(call, 2, name, workflowsByName);
|
|
228
|
+
const target = resolveTarget(call, 2, name, workflowsByName, agentsByName);
|
|
215
229
|
const argumentsNode = call.getArguments()[3];
|
|
216
230
|
const args = argumentsNode && Node.isObjectLiteralExpression(argumentsNode) ? objectLiteralValue(argumentsNode, name) : {};
|
|
217
231
|
return { args, cron, name, ...target };
|
|
@@ -227,10 +241,11 @@ const assertUniqueNames = (crons) => {
|
|
|
227
241
|
seen.add(cron.name);
|
|
228
242
|
}
|
|
229
243
|
};
|
|
230
|
-
const discoverCrons = (project, lunoraDirectory, workflows = []) => {
|
|
244
|
+
const discoverCrons = (project, lunoraDirectory, workflows = [], agents = []) => {
|
|
231
245
|
const filePaths = listLunoraSourceFiles(lunoraDirectory);
|
|
232
246
|
const crons = [];
|
|
233
247
|
const workflowsByName = new Map(workflows.map((workflow) => [workflow.exportName, workflow]));
|
|
248
|
+
const agentsByName = new Map(agents.map((agent) => [agent.exportName, agent]));
|
|
234
249
|
for (const filePath of filePaths) {
|
|
235
250
|
const source = project.getSourceFile(filePath) ?? project.addSourceFileAtPath(filePath);
|
|
236
251
|
const builderNames = collectCronBuilderNames(source);
|
|
@@ -242,7 +257,7 @@ const discoverCrons = (project, lunoraDirectory, workflows = []) => {
|
|
|
242
257
|
if (!Node.isPropertyAccessExpression(callee)) {
|
|
243
258
|
continue;
|
|
244
259
|
}
|
|
245
|
-
const cron = cronFromCall(call, callee, builderNames, workflowsByName);
|
|
260
|
+
const cron = cronFromCall(call, callee, builderNames, workflowsByName, agentsByName);
|
|
246
261
|
if (cron) {
|
|
247
262
|
crons.push(cron);
|
|
248
263
|
}
|