@pattern-stack/codegen 0.13.1 → 0.14.1
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/{job-orchestrator.protocol-CHOEqBDk.d.ts → job-orchestrator.protocol-CARhMLCO.d.ts} +1 -1
- package/dist/runtime/subsystems/analytics/analytics.module.js +6 -2
- package/dist/runtime/subsystems/analytics/analytics.module.js.map +1 -1
- package/dist/runtime/subsystems/analytics/analytics.tokens.d.ts +0 -11
- package/dist/runtime/subsystems/analytics/analytics.tokens.js +6 -2
- package/dist/runtime/subsystems/analytics/analytics.tokens.js.map +1 -1
- package/dist/runtime/subsystems/analytics/cube-backend.js +6 -2
- package/dist/runtime/subsystems/analytics/cube-backend.js.map +1 -1
- package/dist/runtime/subsystems/analytics/index.js +6 -2
- package/dist/runtime/subsystems/analytics/index.js.map +1 -1
- package/dist/runtime/subsystems/auth/auth.module.js +12 -6
- package/dist/runtime/subsystems/auth/auth.module.js.map +1 -1
- package/dist/runtime/subsystems/auth/auth.tokens.d.ts +0 -28
- package/dist/runtime/subsystems/auth/auth.tokens.js +12 -8
- package/dist/runtime/subsystems/auth/auth.tokens.js.map +1 -1
- package/dist/runtime/subsystems/auth/controllers/auth.controller.js +12 -5
- package/dist/runtime/subsystems/auth/controllers/auth.controller.js.map +1 -1
- package/dist/runtime/subsystems/auth/index.js +12 -8
- package/dist/runtime/subsystems/auth/index.js.map +1 -1
- package/dist/runtime/subsystems/auth/middleware/requester-context.js +12 -1
- package/dist/runtime/subsystems/auth/middleware/requester-context.js.map +1 -1
- package/dist/runtime/subsystems/bridge/bridge-delivery-handler.d.ts +1 -1
- package/dist/runtime/subsystems/bridge/bridge-delivery-handler.js +10 -2
- package/dist/runtime/subsystems/bridge/bridge-delivery-handler.js.map +1 -1
- package/dist/runtime/subsystems/bridge/bridge-delivery.memory-backend.d.ts +1 -1
- package/dist/runtime/subsystems/bridge/bridge-delivery.memory-backend.js +2 -2
- package/dist/runtime/subsystems/bridge/bridge-delivery.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/bridge/bridge-outbox-drain-hook.js +10 -2
- package/dist/runtime/subsystems/bridge/bridge-outbox-drain-hook.js.map +1 -1
- package/dist/runtime/subsystems/bridge/bridge.module.d.ts +1 -1
- package/dist/runtime/subsystems/bridge/bridge.module.js +186 -168
- package/dist/runtime/subsystems/bridge/bridge.module.js.map +1 -1
- package/dist/runtime/subsystems/bridge/bridge.protocol.d.ts +1 -1
- package/dist/runtime/subsystems/bridge/event-flow.service.d.ts +1 -1
- package/dist/runtime/subsystems/bridge/event-flow.service.js +9 -1
- package/dist/runtime/subsystems/bridge/event-flow.service.js.map +1 -1
- package/dist/runtime/subsystems/bridge/index.d.ts +1 -1
- package/dist/runtime/subsystems/bridge/index.js +168 -150
- package/dist/runtime/subsystems/bridge/index.js.map +1 -1
- package/dist/runtime/subsystems/cache/cache.drizzle-backend.js +6 -1
- package/dist/runtime/subsystems/cache/cache.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/cache/cache.memory-backend.js +6 -1
- package/dist/runtime/subsystems/cache/cache.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/cache/cache.module.js +6 -2
- package/dist/runtime/subsystems/cache/cache.module.js.map +1 -1
- package/dist/runtime/subsystems/cache/cache.tokens.d.ts +0 -10
- package/dist/runtime/subsystems/cache/cache.tokens.js +6 -2
- package/dist/runtime/subsystems/cache/cache.tokens.js.map +1 -1
- package/dist/runtime/subsystems/cache/index.js +6 -2
- package/dist/runtime/subsystems/cache/index.js.map +1 -1
- package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js +5 -0
- package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/events/event-bus.memory-backend.js +5 -0
- package/dist/runtime/subsystems/events/event-bus.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/events/event-bus.redis-backend.js +5 -1
- package/dist/runtime/subsystems/events/event-bus.redis-backend.js.map +1 -1
- package/dist/runtime/subsystems/events/events.module.js +5 -1
- package/dist/runtime/subsystems/events/events.module.js.map +1 -1
- package/dist/runtime/subsystems/events/events.tokens.d.ts +5 -11
- package/dist/runtime/subsystems/events/events.tokens.js +5 -1
- package/dist/runtime/subsystems/events/events.tokens.js.map +1 -1
- package/dist/runtime/subsystems/events/generated/bus.js +5 -0
- package/dist/runtime/subsystems/events/generated/bus.js.map +1 -1
- package/dist/runtime/subsystems/events/generated/index.js +5 -0
- package/dist/runtime/subsystems/events/generated/index.js.map +1 -1
- package/dist/runtime/subsystems/events/index.js +5 -1
- package/dist/runtime/subsystems/events/index.js.map +1 -1
- package/dist/runtime/subsystems/index.d.ts +2 -2
- package/dist/runtime/subsystems/index.js +186 -168
- package/dist/runtime/subsystems/index.js.map +1 -1
- package/dist/runtime/subsystems/jobs/bullmq.config.d.ts +0 -9
- package/dist/runtime/subsystems/jobs/bullmq.config.js +6 -2
- package/dist/runtime/subsystems/jobs/bullmq.config.js.map +1 -1
- package/dist/runtime/subsystems/jobs/index.d.ts +1 -1
- package/dist/runtime/subsystems/jobs/index.js +141 -124
- package/dist/runtime/subsystems/jobs/index.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-handler.base.d.ts +1 -1
- package/dist/runtime/subsystems/jobs/job-handler.base.js +5 -1
- package/dist/runtime/subsystems/jobs/job-handler.base.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.bullmq-backend.d.ts +1 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.bullmq-backend.js +10 -3
- package/dist/runtime/subsystems/jobs/job-orchestrator.bullmq-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.drizzle-backend.d.ts +1 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.drizzle-backend.js +8 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.d.ts +1 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.js +137 -7
- package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-orchestrator.protocol.d.ts +1 -1
- package/dist/runtime/subsystems/jobs/job-run-keyset-cursor.d.ts +1 -1
- package/dist/runtime/subsystems/jobs/job-run-service.drizzle-backend.d.ts +1 -1
- package/dist/runtime/subsystems/jobs/job-run-service.drizzle-backend.js +8 -2
- package/dist/runtime/subsystems/jobs/job-run-service.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-run-service.memory-backend.d.ts +1 -1
- package/dist/runtime/subsystems/jobs/job-run-service.memory-backend.js +25 -2
- package/dist/runtime/subsystems/jobs/job-run-service.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-run-service.protocol.d.ts +1 -1
- package/dist/runtime/subsystems/jobs/job-step-service.memory-backend.js +25 -2
- package/dist/runtime/subsystems/jobs/job-step-service.memory-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.d.ts +1 -1
- package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.js +5 -0
- package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-worker.d.ts +1 -1
- package/dist/runtime/subsystems/jobs/job-worker.js +10 -4
- package/dist/runtime/subsystems/jobs/job-worker.js.map +1 -1
- package/dist/runtime/subsystems/jobs/job-worker.module.d.ts +31 -3
- package/dist/runtime/subsystems/jobs/job-worker.module.js +163 -145
- package/dist/runtime/subsystems/jobs/job-worker.module.js.map +1 -1
- package/dist/runtime/subsystems/jobs/jobs-domain.module.js +144 -130
- package/dist/runtime/subsystems/jobs/jobs-domain.module.js.map +1 -1
- package/dist/runtime/subsystems/jobs/jobs-domain.tokens.d.ts +0 -11
- package/dist/runtime/subsystems/jobs/jobs-domain.tokens.js +8 -4
- package/dist/runtime/subsystems/jobs/jobs-domain.tokens.js.map +1 -1
- package/dist/runtime/subsystems/jobs/jobs-errors.d.ts +1 -1
- package/dist/runtime/subsystems/observability/index.d.ts +1 -1
- package/dist/runtime/subsystems/observability/index.js +9 -1
- package/dist/runtime/subsystems/observability/index.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.module.js +9 -1
- package/dist/runtime/subsystems/observability/observability.module.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.protocol.d.ts +1 -1
- package/dist/runtime/subsystems/observability/observability.service.d.ts +1 -1
- package/dist/runtime/subsystems/observability/observability.service.js +9 -1
- package/dist/runtime/subsystems/observability/observability.service.js.map +1 -1
- package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.d.ts +1 -1
- package/dist/runtime/subsystems/observability/reporters/index.d.ts +1 -1
- package/dist/runtime/subsystems/storage/index.js +5 -1
- package/dist/runtime/subsystems/storage/index.js.map +1 -1
- package/dist/runtime/subsystems/storage/storage.module.js +5 -1
- package/dist/runtime/subsystems/storage/storage.module.js.map +1 -1
- package/dist/runtime/subsystems/storage/storage.tokens.d.ts +0 -8
- package/dist/runtime/subsystems/storage/storage.tokens.js +5 -1
- package/dist/runtime/subsystems/storage/storage.tokens.js.map +1 -1
- package/dist/runtime/subsystems/token-key.d.ts +7 -0
- package/dist/runtime/subsystems/token-key.js +8 -0
- package/dist/runtime/subsystems/token-key.js.map +1 -0
- package/dist/src/cli/index.js +1160 -694
- package/dist/src/cli/index.js.map +1 -1
- package/package.json +5 -1
- package/runtime/subsystems/analytics/analytics.tokens.ts +6 -2
- package/runtime/subsystems/auth/auth.tokens.ts +15 -8
- package/runtime/subsystems/bridge/bridge-delivery.memory-backend.ts +8 -1
- package/runtime/subsystems/cache/cache.tokens.ts +7 -2
- package/runtime/subsystems/events/events.tokens.ts +8 -1
- package/runtime/subsystems/index.ts +5 -1
- package/runtime/subsystems/jobs/bullmq.config.ts +5 -2
- package/runtime/subsystems/jobs/job-handler.base.ts +6 -1
- package/runtime/subsystems/jobs/job-orchestrator.memory-backend.ts +8 -3
- package/runtime/subsystems/jobs/job-run-service.memory-backend.ts +4 -1
- package/runtime/subsystems/jobs/job-step-service.memory-backend.ts +7 -2
- package/runtime/subsystems/jobs/job-worker.module.ts +18 -2
- package/runtime/subsystems/jobs/job-worker.ts +4 -1
- package/runtime/subsystems/jobs/jobs-domain.tokens.ts +10 -7
- package/runtime/subsystems/storage/storage.tokens.ts +6 -1
- package/runtime/subsystems/token-key.ts +7 -0
- package/src/config/runtime-mode.mjs +82 -0
- package/templates/entity/new/backend/modules/core/integration-source.ejs.t +3 -2
- package/templates/entity/new/clean-lite-ps/controller.ejs.t +1 -1
- package/templates/entity/new/clean-lite-ps/module.ejs.t +1 -1
- package/templates/entity/new/clean-lite-ps/prompt-extension.js +8 -2
- package/templates/entity/new/clean-lite-ps/repository.ejs.t +4 -4
- package/templates/entity/new/clean-lite-ps/service.ejs.t +4 -4
- package/templates/entity/new/prompt.js +49 -10
package/dist/src/cli/index.js
CHANGED
|
@@ -1073,8 +1073,8 @@ var icons = {
|
|
|
1073
1073
|
};
|
|
1074
1074
|
|
|
1075
1075
|
// src/cli/commands/entity.ts
|
|
1076
|
-
import
|
|
1077
|
-
import
|
|
1076
|
+
import fs10 from "fs";
|
|
1077
|
+
import path14 from "path";
|
|
1078
1078
|
import { Command as Command2, Option as Option2 } from "clipanion";
|
|
1079
1079
|
|
|
1080
1080
|
// src/utils/yaml-loader.ts
|
|
@@ -3082,8 +3082,8 @@ function loadEntityFromYaml(filePath) {
|
|
|
3082
3082
|
}
|
|
3083
3083
|
function formatZodErrors(error) {
|
|
3084
3084
|
return error.errors.map((err) => {
|
|
3085
|
-
const
|
|
3086
|
-
const location =
|
|
3085
|
+
const path36 = err.path.join(".");
|
|
3086
|
+
const location = path36 ? `at '${path36}'` : "at root";
|
|
3087
3087
|
return `${err.message} ${location}`;
|
|
3088
3088
|
});
|
|
3089
3089
|
}
|
|
@@ -3684,8 +3684,8 @@ function collectEntitySurfaces(entities) {
|
|
|
3684
3684
|
return surfaces;
|
|
3685
3685
|
}
|
|
3686
3686
|
function resolveImportRef(ref, opts) {
|
|
3687
|
-
const { path:
|
|
3688
|
-
const file = resolveModuleFile(
|
|
3687
|
+
const { path: path36, exportName } = parseImportRef(ref);
|
|
3688
|
+
const file = resolveModuleFile(path36, opts);
|
|
3689
3689
|
if (!file) {
|
|
3690
3690
|
return { status: "module-not-found", resolvedFrom: opts.sourceRoot };
|
|
3691
3691
|
}
|
|
@@ -3905,19 +3905,19 @@ function findCircularDependencies(graph) {
|
|
|
3905
3905
|
const cycles = [];
|
|
3906
3906
|
const visited = /* @__PURE__ */ new Set();
|
|
3907
3907
|
const recursionStack = /* @__PURE__ */ new Set();
|
|
3908
|
-
function dfs(node,
|
|
3908
|
+
function dfs(node, path36) {
|
|
3909
3909
|
visited.add(node);
|
|
3910
3910
|
recursionStack.add(node);
|
|
3911
3911
|
const outgoingEdges = graph.edges.filter((e) => e.from === node);
|
|
3912
3912
|
for (const edge of outgoingEdges) {
|
|
3913
3913
|
if (!visited.has(edge.to)) {
|
|
3914
|
-
dfs(edge.to, [...
|
|
3914
|
+
dfs(edge.to, [...path36, edge.to]);
|
|
3915
3915
|
} else if (recursionStack.has(edge.to)) {
|
|
3916
|
-
const cycleStart =
|
|
3916
|
+
const cycleStart = path36.indexOf(edge.to);
|
|
3917
3917
|
if (cycleStart !== -1) {
|
|
3918
|
-
cycles.push([...
|
|
3918
|
+
cycles.push([...path36.slice(cycleStart), edge.to]);
|
|
3919
3919
|
} else {
|
|
3920
|
-
cycles.push([...
|
|
3920
|
+
cycles.push([...path36, edge.to]);
|
|
3921
3921
|
}
|
|
3922
3922
|
}
|
|
3923
3923
|
}
|
|
@@ -4514,8 +4514,8 @@ function suggestTransitiveRelationships(graph, options) {
|
|
|
4514
4514
|
for (const [entityName, entity] of graph.entities) {
|
|
4515
4515
|
if (shouldExcludeEntity(entityName, opts)) continue;
|
|
4516
4516
|
const paths = findTransitivePaths(graph, entityName, opts);
|
|
4517
|
-
for (const
|
|
4518
|
-
suggestions.push(createSuggestion(
|
|
4517
|
+
for (const path36 of paths) {
|
|
4518
|
+
suggestions.push(createSuggestion(path36));
|
|
4519
4519
|
}
|
|
4520
4520
|
}
|
|
4521
4521
|
return suggestions;
|
|
@@ -4546,7 +4546,7 @@ function findTransitivePaths(graph, sourceEntity, opts) {
|
|
|
4546
4546
|
while (queue.length > 0) {
|
|
4547
4547
|
const current = queue.shift();
|
|
4548
4548
|
if (!current) continue;
|
|
4549
|
-
const { entity, depth, path:
|
|
4549
|
+
const { entity, depth, path: path36, visited } = current;
|
|
4550
4550
|
if (depth >= opts.maxDepth) continue;
|
|
4551
4551
|
const currentEntity = graph.entities.get(entity);
|
|
4552
4552
|
if (!currentEntity) continue;
|
|
@@ -4557,7 +4557,7 @@ function findTransitivePaths(graph, sourceEntity, opts) {
|
|
|
4557
4557
|
if (shouldExcludeEntity(target, opts)) continue;
|
|
4558
4558
|
if (visited.has(target)) continue;
|
|
4559
4559
|
const newPath = [
|
|
4560
|
-
...
|
|
4560
|
+
...path36,
|
|
4561
4561
|
{
|
|
4562
4562
|
via: entity,
|
|
4563
4563
|
relationship: relName,
|
|
@@ -4625,15 +4625,15 @@ function generateYamlSnippet(name, target, throughPath) {
|
|
|
4625
4625
|
target: ${target}
|
|
4626
4626
|
through: "${throughPath}"`;
|
|
4627
4627
|
}
|
|
4628
|
-
function createSuggestion(
|
|
4629
|
-
const pathDescription = [
|
|
4628
|
+
function createSuggestion(path36) {
|
|
4629
|
+
const pathDescription = [path36.source, ...path36.hops.map((h) => h.via), path36.target].join(" -> ");
|
|
4630
4630
|
return {
|
|
4631
4631
|
severity: "info",
|
|
4632
4632
|
type: "transitive_suggestion",
|
|
4633
|
-
entity:
|
|
4633
|
+
entity: path36.source,
|
|
4634
4634
|
message: `Potential transitive relationship: ${pathDescription}`,
|
|
4635
|
-
suggestion: `Add "${
|
|
4636
|
-
path:
|
|
4635
|
+
suggestion: `Add "${path36.suggestedName}" relationship via "${path36.throughPath}"`,
|
|
4636
|
+
path: path36
|
|
4637
4637
|
};
|
|
4638
4638
|
}
|
|
4639
4639
|
|
|
@@ -6279,6 +6279,24 @@ import path8 from "path";
|
|
|
6279
6279
|
// src/cli/shared/subsystem-detect.ts
|
|
6280
6280
|
import fs4 from "fs";
|
|
6281
6281
|
import path6 from "path";
|
|
6282
|
+
|
|
6283
|
+
// src/cli/shared/runtime-import.ts
|
|
6284
|
+
var PACKAGE = "@pattern-stack/codegen";
|
|
6285
|
+
function resolveRuntimeMode(config) {
|
|
6286
|
+
return config?.runtime === "vendored" ? "vendored" : "package";
|
|
6287
|
+
}
|
|
6288
|
+
function subsystemsImport(mode, subsystem) {
|
|
6289
|
+
if (mode === "vendored") {
|
|
6290
|
+
return subsystem ? `@shared/subsystems/${subsystem}` : "@shared/subsystems";
|
|
6291
|
+
}
|
|
6292
|
+
return `${PACKAGE}/subsystems`;
|
|
6293
|
+
}
|
|
6294
|
+
function runtimeImport(mode, relpath) {
|
|
6295
|
+
const clean = relpath.replace(/^\/+/, "");
|
|
6296
|
+
return mode === "vendored" ? `@shared/${clean}` : `${PACKAGE}/runtime/${clean}`;
|
|
6297
|
+
}
|
|
6298
|
+
|
|
6299
|
+
// src/cli/shared/subsystem-detect.ts
|
|
6282
6300
|
var SUBSYSTEMS = [
|
|
6283
6301
|
{
|
|
6284
6302
|
name: "events",
|
|
@@ -6475,6 +6493,36 @@ async function detectInstalledSubsystems(ctx) {
|
|
|
6475
6493
|
const states = await detectSubsystemStatesImpl(ctx);
|
|
6476
6494
|
return states.filter((s) => s.status === "installed");
|
|
6477
6495
|
}
|
|
6496
|
+
function configuredSubsystemNames(config) {
|
|
6497
|
+
const subsystems = config?.subsystems;
|
|
6498
|
+
const raw = subsystems?.install;
|
|
6499
|
+
if (!Array.isArray(raw)) return [];
|
|
6500
|
+
const known = new Set(KNOWN_NAMES);
|
|
6501
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6502
|
+
const out = [];
|
|
6503
|
+
for (const entry of raw) {
|
|
6504
|
+
if (typeof entry !== "string") continue;
|
|
6505
|
+
if (!known.has(entry)) continue;
|
|
6506
|
+
const name = entry;
|
|
6507
|
+
if (seen.has(name)) continue;
|
|
6508
|
+
seen.add(name);
|
|
6509
|
+
out.push(name);
|
|
6510
|
+
}
|
|
6511
|
+
return out;
|
|
6512
|
+
}
|
|
6513
|
+
function configuredInstalledSubsystems(config) {
|
|
6514
|
+
return configuredSubsystemNames(config).map((name) => {
|
|
6515
|
+
const desc3 = SUBSYSTEMS.find((s) => s.name === name);
|
|
6516
|
+
const cfg = config?.[name];
|
|
6517
|
+
const backend = typeof cfg?.backend === "string" ? cfg.backend : desc3?.defaultBackend ?? "drizzle";
|
|
6518
|
+
return {
|
|
6519
|
+
name,
|
|
6520
|
+
path: `@pattern-stack/codegen/subsystems#${name}`,
|
|
6521
|
+
backend,
|
|
6522
|
+
status: "installed"
|
|
6523
|
+
};
|
|
6524
|
+
});
|
|
6525
|
+
}
|
|
6478
6526
|
|
|
6479
6527
|
// src/cli/shared/subsystems-path.ts
|
|
6480
6528
|
import path7 from "path";
|
|
@@ -6523,55 +6571,55 @@ function quoteBullmqDomainOpts(input) {
|
|
|
6523
6571
|
return `{ ${parts.join(", ")} }`;
|
|
6524
6572
|
}
|
|
6525
6573
|
var COMPOSERS = {
|
|
6526
|
-
events: ({
|
|
6574
|
+
events: ({ moduleImport, cfg }) => {
|
|
6527
6575
|
const backend = cfg?.backend ?? "drizzle";
|
|
6528
6576
|
const multiTenant = Boolean(cfg?.multi_tenant);
|
|
6529
6577
|
return {
|
|
6530
6578
|
imports: [
|
|
6531
|
-
`import { EventsModule } from '${
|
|
6579
|
+
`import { EventsModule } from '${moduleImport("events", "events.module")}';`
|
|
6532
6580
|
],
|
|
6533
6581
|
calls: [
|
|
6534
6582
|
` EventsModule.forRoot(${quoteOpts({ backend, multiTenant })}),`
|
|
6535
6583
|
]
|
|
6536
6584
|
};
|
|
6537
6585
|
},
|
|
6538
|
-
jobs: ({
|
|
6586
|
+
jobs: ({ moduleImport, cfg }) => {
|
|
6539
6587
|
const backend = cfg?.backend ?? "drizzle";
|
|
6540
6588
|
const multiTenant = Boolean(cfg?.multi_tenant);
|
|
6541
6589
|
const workerMode = (cfg?.worker_mode ?? "standalone").trim();
|
|
6542
6590
|
const imports = [
|
|
6543
|
-
`import { JobsDomainModule } from '${
|
|
6591
|
+
`import { JobsDomainModule } from '${moduleImport("jobs", "jobs-domain.module")}';`
|
|
6544
6592
|
];
|
|
6545
6593
|
const bullExt = backend === "bullmq" ? cfg?.extensions?.bullmq : void 0;
|
|
6546
6594
|
const domainOpts = quoteBullmqDomainOpts({ backend, multiTenant, bullExt });
|
|
6547
6595
|
const calls = [` JobsDomainModule.forRoot(${domainOpts}),`];
|
|
6548
6596
|
if (workerMode === "embedded") {
|
|
6549
6597
|
imports.push(
|
|
6550
|
-
`import { JobWorkerModule } from '${
|
|
6598
|
+
`import { JobWorkerModule } from '${moduleImport("jobs", "job-worker.module")}';`
|
|
6551
6599
|
);
|
|
6552
6600
|
const workerOpts = backend === "bullmq" ? `{ mode: 'embedded', backend: 'bullmq'${bullExt ? `, domainModuleExtensions: { bullmq: ${jsonToTs(bullExt)} }` : ""} }` : `{ mode: 'embedded' }`;
|
|
6553
6601
|
calls.push(` JobWorkerModule.forRoot(${workerOpts}),`);
|
|
6554
6602
|
}
|
|
6555
6603
|
return { imports, calls };
|
|
6556
6604
|
},
|
|
6557
|
-
bridge: ({
|
|
6605
|
+
bridge: ({ moduleImport, cfg }) => {
|
|
6558
6606
|
const backend = cfg?.backend ?? "drizzle";
|
|
6559
6607
|
const multiTenant = Boolean(cfg?.multi_tenant);
|
|
6560
6608
|
return {
|
|
6561
6609
|
imports: [
|
|
6562
|
-
`import { BridgeModule } from '${
|
|
6610
|
+
`import { BridgeModule } from '${moduleImport("bridge", "bridge.module")}';`
|
|
6563
6611
|
],
|
|
6564
6612
|
calls: [
|
|
6565
6613
|
` BridgeModule.forRoot(${quoteOpts({ backend, multiTenant })}),`
|
|
6566
6614
|
]
|
|
6567
6615
|
};
|
|
6568
6616
|
},
|
|
6569
|
-
integration: ({
|
|
6617
|
+
integration: ({ moduleImport, cfg }) => {
|
|
6570
6618
|
const backend = cfg?.backend ?? "drizzle";
|
|
6571
6619
|
const multiTenant = Boolean(cfg?.multi_tenant);
|
|
6572
6620
|
return {
|
|
6573
6621
|
imports: [
|
|
6574
|
-
`import { IntegrationModule } from '${
|
|
6622
|
+
`import { IntegrationModule } from '${moduleImport("integration", "integration.module")}';`
|
|
6575
6623
|
],
|
|
6576
6624
|
calls: [
|
|
6577
6625
|
` IntegrationModule.forRoot(${quoteOpts({ backend, multiTenant })}),`
|
|
@@ -6579,6 +6627,13 @@ var COMPOSERS = {
|
|
|
6579
6627
|
};
|
|
6580
6628
|
}
|
|
6581
6629
|
};
|
|
6630
|
+
var PACKAGE2 = "@pattern-stack/codegen";
|
|
6631
|
+
function makeModuleImport(mode, subsystemsRel) {
|
|
6632
|
+
if (mode === "vendored") {
|
|
6633
|
+
return (subsystem, moduleBasename) => `${subsystemsRel}/${subsystem}/${moduleBasename}`;
|
|
6634
|
+
}
|
|
6635
|
+
return (subsystem) => subsystem === "events" ? `${PACKAGE2}/subsystems` : `${PACKAGE2}/runtime/subsystems/${subsystem}/index`;
|
|
6636
|
+
}
|
|
6582
6637
|
var COMPOSABLE_ORDER = ["events", "jobs", "bridge", "integration"];
|
|
6583
6638
|
var HEADER3 = `// AUTO-GENERATED by @pattern-stack/codegen. DO NOT EDIT.
|
|
6584
6639
|
// Subsystem composition barrel \u2014 reflects \`subsystems.install\` in
|
|
@@ -6593,7 +6648,8 @@ var HEADER3 = `// AUTO-GENERATED by @pattern-stack/codegen. DO NOT EDIT.
|
|
|
6593
6648
|
// Regenerated by every \`codegen entity new\` / \`codegen subsystem install\`.
|
|
6594
6649
|
|
|
6595
6650
|
`;
|
|
6596
|
-
function buildSubsystemBarrel(installed, config, subsystemsRel) {
|
|
6651
|
+
function buildSubsystemBarrel(installed, config, subsystemsRel, mode = "vendored") {
|
|
6652
|
+
const moduleImport = makeModuleImport(mode, subsystemsRel);
|
|
6597
6653
|
const actable = installed.filter((i) => i.status !== "incomplete");
|
|
6598
6654
|
const installedNames = new Set(actable.map((i) => i.name));
|
|
6599
6655
|
const emitted = [];
|
|
@@ -6608,7 +6664,7 @@ function buildSubsystemBarrel(installed, config, subsystemsRel) {
|
|
|
6608
6664
|
continue;
|
|
6609
6665
|
}
|
|
6610
6666
|
const cfg = config?.[name] ?? void 0;
|
|
6611
|
-
const out = composer({
|
|
6667
|
+
const out = composer({ moduleImport, cfg });
|
|
6612
6668
|
allImports.push(...out.imports);
|
|
6613
6669
|
allCalls.push(...out.calls);
|
|
6614
6670
|
emitted.push(name);
|
|
@@ -6629,7 +6685,10 @@ ${allCalls.join("\n")}
|
|
|
6629
6685
|
async function regenerateSubsystemBarrel(opts) {
|
|
6630
6686
|
const { ctx, dryRun = false } = opts;
|
|
6631
6687
|
const generatedDir = opts.generatedDir ?? resolveGeneratedDir(ctx);
|
|
6632
|
-
const
|
|
6688
|
+
const mode = resolveRuntimeMode(ctx.config);
|
|
6689
|
+
const installed = mode === "package" ? configuredInstalledSubsystems(
|
|
6690
|
+
ctx.config
|
|
6691
|
+
) : await detectInstalledSubsystems(ctx);
|
|
6633
6692
|
const subsystemsAbs = resolveSubsystemsRoot(ctx);
|
|
6634
6693
|
const barrelAbs = path8.resolve(generatedDir, "subsystems.ts");
|
|
6635
6694
|
let subsystemsRel = path8.relative(path8.dirname(barrelAbs), subsystemsAbs).split(path8.sep).join("/");
|
|
@@ -6637,7 +6696,8 @@ async function regenerateSubsystemBarrel(opts) {
|
|
|
6637
6696
|
const { content, emitted, skipped } = buildSubsystemBarrel(
|
|
6638
6697
|
installed,
|
|
6639
6698
|
ctx.config,
|
|
6640
|
-
subsystemsRel
|
|
6699
|
+
subsystemsRel,
|
|
6700
|
+
mode
|
|
6641
6701
|
);
|
|
6642
6702
|
let written = false;
|
|
6643
6703
|
if (!dryRun) {
|
|
@@ -6654,11 +6714,101 @@ async function regenerateSubsystemBarrel(opts) {
|
|
|
6654
6714
|
};
|
|
6655
6715
|
}
|
|
6656
6716
|
|
|
6657
|
-
// src/cli/shared/
|
|
6717
|
+
// src/cli/shared/subsystem-schema-generator.ts
|
|
6658
6718
|
import fs6 from "fs";
|
|
6659
6719
|
import path9 from "path";
|
|
6660
|
-
|
|
6720
|
+
var PACKAGE3 = "@pattern-stack/codegen";
|
|
6721
|
+
var SCHEMA_SYMBOLS = {
|
|
6722
|
+
events: ["domainEvents"],
|
|
6723
|
+
jobs: [
|
|
6724
|
+
"jobs",
|
|
6725
|
+
"jobRuns",
|
|
6726
|
+
"jobSteps",
|
|
6727
|
+
"jobRunStatusEnum",
|
|
6728
|
+
"jobStepKindEnum",
|
|
6729
|
+
"jobStepStatusEnum",
|
|
6730
|
+
"collisionModeEnum",
|
|
6731
|
+
"replayFromEnum",
|
|
6732
|
+
"parentClosePolicyEnum",
|
|
6733
|
+
"waitKindEnum",
|
|
6734
|
+
"triggerSourceEnum"
|
|
6735
|
+
],
|
|
6736
|
+
bridge: ["bridgeDelivery", "bridgeDeliveryStatusEnum"],
|
|
6737
|
+
integration: [
|
|
6738
|
+
"integrationSubscriptions",
|
|
6739
|
+
"integrationRuns",
|
|
6740
|
+
"integrationRunItems",
|
|
6741
|
+
"integrationRunDirectionEnum",
|
|
6742
|
+
"integrationRunActionEnum",
|
|
6743
|
+
"integrationRunStatusEnum",
|
|
6744
|
+
"integrationRunItemOperationEnum",
|
|
6745
|
+
"integrationRunItemStatusEnum"
|
|
6746
|
+
]
|
|
6747
|
+
};
|
|
6748
|
+
var SCHEMA_ORDER = ["events", "jobs", "bridge", "integration"];
|
|
6661
6749
|
var HEADER4 = `// AUTO-GENERATED by @pattern-stack/codegen. Do not edit.
|
|
6750
|
+
// Subsystem Drizzle schema barrel \u2014 re-exports the tables + pgEnums of every
|
|
6751
|
+
// installed subsystem so drizzle-kit emits their CREATE TABLE / CREATE TYPE.
|
|
6752
|
+
//
|
|
6753
|
+
// Fold into your drizzle-kit schema entrypoint once, alongside the entity
|
|
6754
|
+
// schema barrel:
|
|
6755
|
+
//
|
|
6756
|
+
// // src/schema.ts
|
|
6757
|
+
// export * from './generated/schema'; // entity tables
|
|
6758
|
+
// export * from './generated/subsystems-schema'; // subsystem tables + enums
|
|
6759
|
+
//
|
|
6760
|
+
// Regenerated by every \`codegen entity new\` / \`codegen subsystem install\`.
|
|
6761
|
+
|
|
6762
|
+
`;
|
|
6763
|
+
function schemaImportFor(mode, subsystem, subsystemsRel) {
|
|
6764
|
+
return mode === "vendored" ? `${subsystemsRel}/${subsystem}` : `${PACKAGE3}/runtime/subsystems/${subsystem}/index`;
|
|
6765
|
+
}
|
|
6766
|
+
function buildSubsystemSchemaBarrel(installed, subsystemsRel, mode) {
|
|
6767
|
+
const actable = installed.filter((i) => i.status !== "incomplete");
|
|
6768
|
+
const installedNames = new Set(actable.map((i) => i.name));
|
|
6769
|
+
const emitted = [];
|
|
6770
|
+
const lines = [];
|
|
6771
|
+
for (const name of SCHEMA_ORDER) {
|
|
6772
|
+
if (!installedNames.has(name)) continue;
|
|
6773
|
+
const symbols = SCHEMA_SYMBOLS[name];
|
|
6774
|
+
if (!symbols || symbols.length === 0) continue;
|
|
6775
|
+
const importSpec = schemaImportFor(mode, name, subsystemsRel);
|
|
6776
|
+
lines.push(`export { ${symbols.join(", ")} } from '${importSpec}';`);
|
|
6777
|
+
emitted.push(name);
|
|
6778
|
+
}
|
|
6779
|
+
const body = lines.length === 0 ? "export {};\n" : lines.join("\n") + "\n";
|
|
6780
|
+
return { content: HEADER4 + body, emitted };
|
|
6781
|
+
}
|
|
6782
|
+
async function regenerateSubsystemSchemaBarrel(opts) {
|
|
6783
|
+
const { ctx, dryRun = false } = opts;
|
|
6784
|
+
const generatedDir = opts.generatedDir ?? resolveGeneratedDir(ctx);
|
|
6785
|
+
const mode = resolveRuntimeMode(ctx.config);
|
|
6786
|
+
const installed = mode === "package" ? configuredInstalledSubsystems(
|
|
6787
|
+
ctx.config
|
|
6788
|
+
) : await detectInstalledSubsystems(ctx);
|
|
6789
|
+
const subsystemsAbs = resolveSubsystemsRoot(ctx);
|
|
6790
|
+
const barrelAbs = path9.resolve(generatedDir, "subsystems-schema.ts");
|
|
6791
|
+
let subsystemsRel = path9.relative(path9.dirname(barrelAbs), subsystemsAbs).split(path9.sep).join("/");
|
|
6792
|
+
if (!subsystemsRel.startsWith(".")) subsystemsRel = "./" + subsystemsRel;
|
|
6793
|
+
const { content, emitted } = buildSubsystemSchemaBarrel(
|
|
6794
|
+
installed,
|
|
6795
|
+
subsystemsRel,
|
|
6796
|
+
mode
|
|
6797
|
+
);
|
|
6798
|
+
let written = false;
|
|
6799
|
+
if (!dryRun) {
|
|
6800
|
+
fs6.mkdirSync(path9.dirname(barrelAbs), { recursive: true });
|
|
6801
|
+
fs6.writeFileSync(barrelAbs, content);
|
|
6802
|
+
written = true;
|
|
6803
|
+
}
|
|
6804
|
+
return { schemaBarrel: barrelAbs, emitted, content, written };
|
|
6805
|
+
}
|
|
6806
|
+
|
|
6807
|
+
// src/cli/shared/bridge-registry-generator.ts
|
|
6808
|
+
import fs7 from "fs";
|
|
6809
|
+
import path10 from "path";
|
|
6810
|
+
import ts2 from "typescript";
|
|
6811
|
+
var HEADER5 = `// AUTO-GENERATED by @pattern-stack/codegen. Do not edit.
|
|
6662
6812
|
// Run \`codegen entity new --all\` to refresh.
|
|
6663
6813
|
`;
|
|
6664
6814
|
var DuplicateTriggerError = class extends Error {
|
|
@@ -6716,12 +6866,12 @@ var UnknownTriggerEventError = class extends Error {
|
|
|
6716
6866
|
name = "UnknownTriggerEventError";
|
|
6717
6867
|
};
|
|
6718
6868
|
function findHandlerFiles(dir) {
|
|
6719
|
-
if (!
|
|
6869
|
+
if (!fs7.existsSync(dir)) return [];
|
|
6720
6870
|
const out = [];
|
|
6721
|
-
for (const entry of
|
|
6871
|
+
for (const entry of fs7.readdirSync(dir, { withFileTypes: true })) {
|
|
6722
6872
|
if (entry.name.startsWith(".")) continue;
|
|
6723
6873
|
if (entry.name === "node_modules" || entry.name === "generated") continue;
|
|
6724
|
-
const full =
|
|
6874
|
+
const full = path10.join(dir, entry.name);
|
|
6725
6875
|
if (entry.isDirectory()) {
|
|
6726
6876
|
out.push(...findHandlerFiles(full));
|
|
6727
6877
|
} else if (entry.isFile() && entry.name.endsWith(".ts") && !entry.name.endsWith(".d.ts")) {
|
|
@@ -6784,7 +6934,7 @@ function scanHandlerFiles(handlersDir) {
|
|
|
6784
6934
|
const files = findHandlerFiles(handlersDir);
|
|
6785
6935
|
const out = [];
|
|
6786
6936
|
for (const filePath of files) {
|
|
6787
|
-
const text2 =
|
|
6937
|
+
const text2 = fs7.readFileSync(filePath, "utf8");
|
|
6788
6938
|
const sourceFile = ts2.createSourceFile(
|
|
6789
6939
|
filePath,
|
|
6790
6940
|
text2,
|
|
@@ -6799,9 +6949,9 @@ function scanHandlerFiles(handlersDir) {
|
|
|
6799
6949
|
}
|
|
6800
6950
|
function readKnownEventTypes(eventsGeneratedDir) {
|
|
6801
6951
|
if (!eventsGeneratedDir) return [];
|
|
6802
|
-
const registryPath =
|
|
6803
|
-
if (!
|
|
6804
|
-
const text2 =
|
|
6952
|
+
const registryPath = path10.join(eventsGeneratedDir, "registry.ts");
|
|
6953
|
+
if (!fs7.existsSync(registryPath)) return [];
|
|
6954
|
+
const text2 = fs7.readFileSync(registryPath, "utf8");
|
|
6805
6955
|
const out = /* @__PURE__ */ new Set();
|
|
6806
6956
|
const re = /^\s*'([a-zA-Z0-9_.-]+)':\s*\{/gm;
|
|
6807
6957
|
let m;
|
|
@@ -6813,9 +6963,9 @@ function readKnownEventTypes(eventsGeneratedDir) {
|
|
|
6813
6963
|
function readEventTiers(eventsGeneratedDir) {
|
|
6814
6964
|
const out = /* @__PURE__ */ new Map();
|
|
6815
6965
|
if (!eventsGeneratedDir) return out;
|
|
6816
|
-
const registryPath =
|
|
6817
|
-
if (!
|
|
6818
|
-
const text2 =
|
|
6966
|
+
const registryPath = path10.join(eventsGeneratedDir, "registry.ts");
|
|
6967
|
+
if (!fs7.existsSync(registryPath)) return out;
|
|
6968
|
+
const text2 = fs7.readFileSync(registryPath, "utf8");
|
|
6819
6969
|
const re = /'([a-zA-Z0-9_.-]+)':\s*\{[^}]*?tier:\s*'(domain|audit)'/g;
|
|
6820
6970
|
let m;
|
|
6821
6971
|
while ((m = re.exec(text2)) !== null) {
|
|
@@ -6872,7 +7022,7 @@ function validateAgainstEventRegistry(triggers, knownEventTypes) {
|
|
|
6872
7022
|
}
|
|
6873
7023
|
function buildBridgeRegistryContent(triggers) {
|
|
6874
7024
|
const chunks = [];
|
|
6875
|
-
chunks.push(
|
|
7025
|
+
chunks.push(HEADER5);
|
|
6876
7026
|
chunks.push("");
|
|
6877
7027
|
chunks.push(`import type { BridgeRegistry } from '../bridge.protocol';`);
|
|
6878
7028
|
chunks.push("");
|
|
@@ -6910,11 +7060,11 @@ function buildBridgeRegistryContent(triggers) {
|
|
|
6910
7060
|
var OUTPUT_FILE_NAME = "registry.ts";
|
|
6911
7061
|
async function generateBridgeRegistry(opts) {
|
|
6912
7062
|
const { handlersDir, eventsGeneratedDir, outputDir, dryRun = false } = opts;
|
|
6913
|
-
const bridgeProtocolPath =
|
|
6914
|
-
if (!
|
|
6915
|
-
const strayPath =
|
|
6916
|
-
if (!dryRun &&
|
|
6917
|
-
|
|
7063
|
+
const bridgeProtocolPath = path10.resolve(outputDir, "..", "bridge.protocol.ts");
|
|
7064
|
+
if (!fs7.existsSync(bridgeProtocolPath)) {
|
|
7065
|
+
const strayPath = path10.join(outputDir, OUTPUT_FILE_NAME);
|
|
7066
|
+
if (!dryRun && fs7.existsSync(strayPath)) {
|
|
7067
|
+
fs7.rmSync(strayPath);
|
|
6918
7068
|
}
|
|
6919
7069
|
return {
|
|
6920
7070
|
outputDir,
|
|
@@ -6935,13 +7085,13 @@ async function generateBridgeRegistry(opts) {
|
|
|
6935
7085
|
const content = buildBridgeRegistryContent(triggers);
|
|
6936
7086
|
const file = {
|
|
6937
7087
|
name: OUTPUT_FILE_NAME,
|
|
6938
|
-
outputPath:
|
|
7088
|
+
outputPath: path10.join(outputDir, OUTPUT_FILE_NAME),
|
|
6939
7089
|
content
|
|
6940
7090
|
};
|
|
6941
7091
|
let written = false;
|
|
6942
7092
|
if (!dryRun) {
|
|
6943
|
-
|
|
6944
|
-
|
|
7093
|
+
fs7.mkdirSync(outputDir, { recursive: true });
|
|
7094
|
+
fs7.writeFileSync(file.outputPath, file.content);
|
|
6945
7095
|
written = true;
|
|
6946
7096
|
}
|
|
6947
7097
|
const eventTypeCount = new Set(triggers.map((t) => t.event)).size;
|
|
@@ -6957,8 +7107,8 @@ async function generateBridgeRegistry(opts) {
|
|
|
6957
7107
|
}
|
|
6958
7108
|
|
|
6959
7109
|
// src/cli/shared/orchestration-generator.ts
|
|
6960
|
-
import
|
|
6961
|
-
import
|
|
7110
|
+
import fs8 from "fs";
|
|
7111
|
+
import path11 from "path";
|
|
6962
7112
|
var OrchestrationEmissionError = class extends Error {
|
|
6963
7113
|
constructor(issueType, patternName, message) {
|
|
6964
7114
|
super(`[${issueType}] ${patternName}: ${message}`);
|
|
@@ -6969,7 +7119,7 @@ var OrchestrationEmissionError = class extends Error {
|
|
|
6969
7119
|
patternName;
|
|
6970
7120
|
name = "OrchestrationEmissionError";
|
|
6971
7121
|
};
|
|
6972
|
-
var
|
|
7122
|
+
var HEADER6 = `// AUTO-GENERATED by @pattern-stack/codegen. Do not edit.
|
|
6973
7123
|
// See ADR-032 \u2014 Orchestration Patterns.
|
|
6974
7124
|
`;
|
|
6975
7125
|
function splitWords(str) {
|
|
@@ -7133,7 +7283,7 @@ function buildTokensTs(pattern) {
|
|
|
7133
7283
|
typeImports.push({ specifier: reg.valueTypeImport, name: reg.valueType });
|
|
7134
7284
|
}
|
|
7135
7285
|
const lines = [];
|
|
7136
|
-
lines.push(
|
|
7286
|
+
lines.push(HEADER6.trimEnd());
|
|
7137
7287
|
lines.push("");
|
|
7138
7288
|
for (const i of emitTypeImports(typeImports)) lines.push(i);
|
|
7139
7289
|
lines.push("");
|
|
@@ -7166,7 +7316,7 @@ function buildProvidersTs(pattern) {
|
|
|
7166
7316
|
}
|
|
7167
7317
|
const optsType = forRootOptionsTypeName(pattern);
|
|
7168
7318
|
const lines = [];
|
|
7169
|
-
lines.push(
|
|
7319
|
+
lines.push(HEADER6.trimEnd());
|
|
7170
7320
|
lines.push("");
|
|
7171
7321
|
lines.push(`import type { Provider } from '@nestjs/common';`);
|
|
7172
7322
|
for (const i of emitTypeImports(typeImports)) lines.push(i);
|
|
@@ -7233,7 +7383,7 @@ function buildDispatcherTs(pattern) {
|
|
|
7233
7383
|
const tokenValues = registries.map(({ names: names2 }) => names2.tokenConst);
|
|
7234
7384
|
const mapTypes = registries.map(({ names: names2 }) => names2.mapType);
|
|
7235
7385
|
const lines = [];
|
|
7236
|
-
lines.push(
|
|
7386
|
+
lines.push(HEADER6.trimEnd());
|
|
7237
7387
|
lines.push("");
|
|
7238
7388
|
lines.push(`import { Inject, Injectable } from '@nestjs/common';`);
|
|
7239
7389
|
for (const i of emitTypeImports(typeImports)) lines.push(i);
|
|
@@ -7307,7 +7457,7 @@ function buildModuleTs(pattern) {
|
|
|
7307
7457
|
}
|
|
7308
7458
|
const tokenValues = registries.map(({ names: names2 }) => names2.tokenConst);
|
|
7309
7459
|
const lines = [];
|
|
7310
|
-
lines.push(
|
|
7460
|
+
lines.push(HEADER6.trimEnd());
|
|
7311
7461
|
lines.push("");
|
|
7312
7462
|
lines.push(`import { type DynamicModule, Module } from '@nestjs/common';`);
|
|
7313
7463
|
for (const i of emitTypeImports(typeImports)) lines.push(i);
|
|
@@ -7341,7 +7491,7 @@ function buildModuleTs(pattern) {
|
|
|
7341
7491
|
}
|
|
7342
7492
|
function buildIndexTs(pattern) {
|
|
7343
7493
|
const lines = [];
|
|
7344
|
-
lines.push(
|
|
7494
|
+
lines.push(HEADER6.trimEnd());
|
|
7345
7495
|
lines.push("");
|
|
7346
7496
|
lines.push(`export * from './tokens.js';`);
|
|
7347
7497
|
lines.push(`export * from './dispatcher.js';`);
|
|
@@ -7352,7 +7502,7 @@ function buildIndexTs(pattern) {
|
|
|
7352
7502
|
}
|
|
7353
7503
|
function buildRootBarrelTs(patterns) {
|
|
7354
7504
|
const lines = [];
|
|
7355
|
-
lines.push(
|
|
7505
|
+
lines.push(HEADER6.trimEnd());
|
|
7356
7506
|
lines.push("");
|
|
7357
7507
|
if (patterns.length === 0) {
|
|
7358
7508
|
lines.push("// No orchestration patterns registered.");
|
|
@@ -7370,11 +7520,11 @@ function buildRootBarrelTs(patterns) {
|
|
|
7370
7520
|
function buildPatternFiles(pattern, outputRoot) {
|
|
7371
7521
|
assertEmittable(pattern);
|
|
7372
7522
|
const slug = toKebabCase2(pattern.name);
|
|
7373
|
-
const outputDir =
|
|
7523
|
+
const outputDir = path11.join(outputRoot, slug);
|
|
7374
7524
|
const make = (name, content) => ({
|
|
7375
7525
|
name,
|
|
7376
|
-
outputPath:
|
|
7377
|
-
relativePath:
|
|
7526
|
+
outputPath: path11.join(outputDir, name),
|
|
7527
|
+
relativePath: path11.join(slug, name),
|
|
7378
7528
|
content
|
|
7379
7529
|
});
|
|
7380
7530
|
const files = [
|
|
@@ -7402,21 +7552,21 @@ function generateOrchestrationModules(opts) {
|
|
|
7402
7552
|
}
|
|
7403
7553
|
const rootBarrel = {
|
|
7404
7554
|
name: "index.ts",
|
|
7405
|
-
outputPath:
|
|
7555
|
+
outputPath: path11.join(outputRoot, "index.ts"),
|
|
7406
7556
|
relativePath: "index.ts",
|
|
7407
7557
|
content: buildRootBarrelTs(patterns)
|
|
7408
7558
|
};
|
|
7409
7559
|
allFiles.push(rootBarrel);
|
|
7410
7560
|
let written = false;
|
|
7411
7561
|
if (!dryRun && patterns.length > 0) {
|
|
7412
|
-
|
|
7562
|
+
fs8.mkdirSync(outputRoot, { recursive: true });
|
|
7413
7563
|
for (const r of perPattern) {
|
|
7414
|
-
|
|
7564
|
+
fs8.mkdirSync(r.outputDir, { recursive: true });
|
|
7415
7565
|
for (const f of r.files) {
|
|
7416
|
-
|
|
7566
|
+
fs8.writeFileSync(f.outputPath, f.content);
|
|
7417
7567
|
}
|
|
7418
7568
|
}
|
|
7419
|
-
|
|
7569
|
+
fs8.writeFileSync(rootBarrel.outputPath, rootBarrel.content);
|
|
7420
7570
|
written = true;
|
|
7421
7571
|
}
|
|
7422
7572
|
return {
|
|
@@ -7428,8 +7578,8 @@ function generateOrchestrationModules(opts) {
|
|
|
7428
7578
|
}
|
|
7429
7579
|
|
|
7430
7580
|
// src/cli/shared/event-codegen-generator.ts
|
|
7431
|
-
import
|
|
7432
|
-
import
|
|
7581
|
+
import fs9 from "fs";
|
|
7582
|
+
import path12 from "path";
|
|
7433
7583
|
|
|
7434
7584
|
// src/parser/load-events.ts
|
|
7435
7585
|
import { basename as basename2, resolve as resolve4 } from "path";
|
|
@@ -7559,7 +7709,7 @@ function isEventFieldType(s) {
|
|
|
7559
7709
|
}
|
|
7560
7710
|
|
|
7561
7711
|
// src/cli/shared/event-codegen-generator.ts
|
|
7562
|
-
var
|
|
7712
|
+
var HEADER7 = `// AUTO-GENERATED by @pattern-stack/codegen. Do not edit.
|
|
7563
7713
|
// Run \`codegen entity new --all\` to refresh.
|
|
7564
7714
|
`;
|
|
7565
7715
|
function toCamelCase2(input) {
|
|
@@ -7613,7 +7763,7 @@ function aggregateTypeLiteral(ev) {
|
|
|
7613
7763
|
function collectEntityEvents(entitiesDir) {
|
|
7614
7764
|
const events = [];
|
|
7615
7765
|
const issues = [];
|
|
7616
|
-
if (!
|
|
7766
|
+
if (!fs9.existsSync(entitiesDir)) {
|
|
7617
7767
|
return { events, issues };
|
|
7618
7768
|
}
|
|
7619
7769
|
const files = findYamlFiles(entitiesDir);
|
|
@@ -7657,7 +7807,7 @@ function mergeEvents(topLevel, entitySugar) {
|
|
|
7657
7807
|
function collectMergedEvents(opts) {
|
|
7658
7808
|
const { entitiesDir, eventsDir } = opts;
|
|
7659
7809
|
const entityNames = [];
|
|
7660
|
-
if (
|
|
7810
|
+
if (fs9.existsSync(entitiesDir)) {
|
|
7661
7811
|
const entityFiles = findYamlFiles(entitiesDir);
|
|
7662
7812
|
for (const f of entityFiles) {
|
|
7663
7813
|
const result = loadEntityFromYaml(f);
|
|
@@ -7680,7 +7830,7 @@ function collectMergedEvents(opts) {
|
|
|
7680
7830
|
function buildTypesContent(events) {
|
|
7681
7831
|
const sorted = [...events].sort((a, b) => a.type.localeCompare(b.type));
|
|
7682
7832
|
if (sorted.length === 0) {
|
|
7683
|
-
return
|
|
7833
|
+
return HEADER7 + `
|
|
7684
7834
|
import type { DomainEvent } from '../event-bus.protocol';
|
|
7685
7835
|
|
|
7686
7836
|
export type AppDomainEvent = never;
|
|
@@ -7691,7 +7841,7 @@ export type PayloadOfType<T extends EventTypeName> = DomainEvent['payload'];
|
|
|
7691
7841
|
`;
|
|
7692
7842
|
}
|
|
7693
7843
|
const chunks = [];
|
|
7694
|
-
chunks.push(
|
|
7844
|
+
chunks.push(HEADER7);
|
|
7695
7845
|
chunks.push("");
|
|
7696
7846
|
chunks.push(`import type { DomainEvent } from '../event-bus.protocol';`);
|
|
7697
7847
|
chunks.push("");
|
|
@@ -7739,7 +7889,7 @@ export type PayloadOfType<T extends EventTypeName> = DomainEvent['payload'];
|
|
|
7739
7889
|
function buildSchemasContent(events) {
|
|
7740
7890
|
const sorted = [...events].sort((a, b) => a.type.localeCompare(b.type));
|
|
7741
7891
|
if (sorted.length === 0) {
|
|
7742
|
-
return
|
|
7892
|
+
return HEADER7 + `
|
|
7743
7893
|
import { z } from 'zod';
|
|
7744
7894
|
import type { EventTypeName } from './types';
|
|
7745
7895
|
|
|
@@ -7747,7 +7897,7 @@ export const eventPayloadSchemas = {} as Record<EventTypeName, z.ZodType>;
|
|
|
7747
7897
|
`;
|
|
7748
7898
|
}
|
|
7749
7899
|
const chunks = [];
|
|
7750
|
-
chunks.push(
|
|
7900
|
+
chunks.push(HEADER7);
|
|
7751
7901
|
chunks.push("");
|
|
7752
7902
|
chunks.push(`import { z } from 'zod';`);
|
|
7753
7903
|
chunks.push(`import type { EventTypeName } from './types';`);
|
|
@@ -7802,7 +7952,7 @@ var REGISTRY_GETTER = [
|
|
|
7802
7952
|
function buildRegistryContent(events) {
|
|
7803
7953
|
const sorted = [...events].sort((a, b) => a.type.localeCompare(b.type));
|
|
7804
7954
|
const chunks = [];
|
|
7805
|
-
chunks.push(
|
|
7955
|
+
chunks.push(HEADER7);
|
|
7806
7956
|
chunks.push("");
|
|
7807
7957
|
chunks.push(`import type { EventTypeName } from './types';`);
|
|
7808
7958
|
chunks.push("");
|
|
@@ -7982,10 +8132,10 @@ export class TypedEventBus {
|
|
|
7982
8132
|
}
|
|
7983
8133
|
`;
|
|
7984
8134
|
function buildBusContent(_events) {
|
|
7985
|
-
return
|
|
8135
|
+
return HEADER7 + "\n" + BUS_BODY;
|
|
7986
8136
|
}
|
|
7987
8137
|
function buildIndexContent(_events) {
|
|
7988
|
-
return
|
|
8138
|
+
return HEADER7 + `
|
|
7989
8139
|
export * from './types';
|
|
7990
8140
|
export * from './schemas';
|
|
7991
8141
|
export * from './registry';
|
|
@@ -8014,15 +8164,15 @@ async function generateEventCodegen(opts) {
|
|
|
8014
8164
|
};
|
|
8015
8165
|
const files = OUTPUT_FILE_NAMES.map((name) => ({
|
|
8016
8166
|
name,
|
|
8017
|
-
outputPath:
|
|
8167
|
+
outputPath: path12.join(outputDir, name),
|
|
8018
8168
|
content: builders[name](merged)
|
|
8019
8169
|
}));
|
|
8020
8170
|
const hasError = issues.some((i) => i.severity === "error");
|
|
8021
8171
|
let written = false;
|
|
8022
8172
|
if (!dryRun && !hasError) {
|
|
8023
|
-
|
|
8173
|
+
fs9.mkdirSync(outputDir, { recursive: true });
|
|
8024
8174
|
for (const file of files) {
|
|
8025
|
-
|
|
8175
|
+
fs9.writeFileSync(file.outputPath, file.content);
|
|
8026
8176
|
}
|
|
8027
8177
|
written = true;
|
|
8028
8178
|
}
|
|
@@ -8105,163 +8255,18 @@ function validateEntityEmits(entities, events) {
|
|
|
8105
8255
|
}
|
|
8106
8256
|
|
|
8107
8257
|
// src/cli/shared/provider-module-generator.ts
|
|
8108
|
-
import { existsSync as
|
|
8109
|
-
import { dirname, isAbsolute as isAbsolute2, join as
|
|
8110
|
-
function providerPascalCase(slug) {
|
|
8111
|
-
return slug.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
8112
|
-
}
|
|
8113
|
-
function providerConstantCase(slug) {
|
|
8114
|
-
return slug.replace(/-/g, "_").toUpperCase();
|
|
8115
|
-
}
|
|
8116
|
-
function providerModuleBanner(sourceYaml) {
|
|
8117
|
-
return `// @generated by @pattern-stack/codegen from ${sourceYaml} \u2014 DO NOT EDIT.
|
|
8118
|
-
// Hand edits are overwritten on re-emit. Regenerate with \`bun run codegen\`. To change this provider, edit its \`definitions/providers/*.yaml\`.`;
|
|
8119
|
-
}
|
|
8120
|
-
function generateProviderModule(def, sourceYaml) {
|
|
8121
|
-
const { slug } = def;
|
|
8122
|
-
const Pascal = providerPascalCase(slug);
|
|
8123
|
-
const CONST = providerConstantCase(slug);
|
|
8124
|
-
const strategy = parseImportRef(def.auth.strategy);
|
|
8125
|
-
const client = parseImportRef(def.client.class);
|
|
8126
|
-
const strategyToken = `${CONST}_AUTH_STRATEGY`;
|
|
8127
|
-
const clientToken = `${CONST}_CLIENT`;
|
|
8128
|
-
const surfaces = def.surfaces.join(", ");
|
|
8129
|
-
const title = def.display_name ? `${def.display_name} (\`${slug}\`)` : `\`${slug}\``;
|
|
8130
|
-
return `${providerModuleBanner(sourceYaml)}
|
|
8131
|
-
/**
|
|
8132
|
-
* Provider module for ${title}.
|
|
8133
|
-
*
|
|
8134
|
-
* Surfaces: ${surfaces}.
|
|
8135
|
-
*
|
|
8136
|
-
* Wires the declared auth strategy and API client under the provider-specific
|
|
8137
|
-
* DI tokens \`${strategyToken}\` and \`${clientToken}\`. Per the auth subsystem
|
|
8138
|
-
* contract, strategies are registered under provider-specific tokens rather
|
|
8139
|
-
* than a single \`AUTH_STRATEGY\`. Registry aggregation (RFC-0001 \xA73) is
|
|
8140
|
-
* emitted by a later codegen step.
|
|
8141
|
-
*/
|
|
8142
|
-
import { Module } from '@nestjs/common';
|
|
8143
|
-
import { ${strategy.exportName} } from '${strategy.path}';
|
|
8144
|
-
import { ${client.exportName} } from '${client.path}';
|
|
8145
|
-
|
|
8146
|
-
/** DI token for the \`${slug}\` provider's auth strategy. */
|
|
8147
|
-
export const ${strategyToken} = Symbol('${strategyToken}');
|
|
8148
|
-
/** DI token for the \`${slug}\` provider's API client. */
|
|
8149
|
-
export const ${clientToken} = Symbol('${clientToken}');
|
|
8150
|
-
|
|
8151
|
-
@Module({
|
|
8152
|
-
providers: [
|
|
8153
|
-
${strategy.exportName},
|
|
8154
|
-
${client.exportName},
|
|
8155
|
-
{ provide: ${strategyToken}, useExisting: ${strategy.exportName} },
|
|
8156
|
-
{ provide: ${clientToken}, useExisting: ${client.exportName} },
|
|
8157
|
-
],
|
|
8158
|
-
exports: [
|
|
8159
|
-
${strategy.exportName},
|
|
8160
|
-
${client.exportName},
|
|
8161
|
-
${strategyToken},
|
|
8162
|
-
${clientToken},
|
|
8163
|
-
],
|
|
8164
|
-
})
|
|
8165
|
-
export class ${Pascal}ProviderModule {}
|
|
8166
|
-
`;
|
|
8167
|
-
}
|
|
8168
|
-
function resolveTsconfigAliases(consumerRoot) {
|
|
8169
|
-
const tsconfigPath = join11(consumerRoot, "tsconfig.json");
|
|
8170
|
-
if (!existsSync9(tsconfigPath)) return null;
|
|
8171
|
-
let parsed;
|
|
8172
|
-
try {
|
|
8173
|
-
parsed = JSON.parse(stripJsonComments(readFileSync7(tsconfigPath, "utf-8")));
|
|
8174
|
-
} catch {
|
|
8175
|
-
return null;
|
|
8176
|
-
}
|
|
8177
|
-
const compilerOptions = parsed.compilerOptions ?? {};
|
|
8178
|
-
const baseUrl = compilerOptions.baseUrl ?? ".";
|
|
8179
|
-
const sourceRoot = isAbsolute2(baseUrl) ? baseUrl : resolve5(consumerRoot, baseUrl);
|
|
8180
|
-
const aliases = {};
|
|
8181
|
-
for (const [pattern, targets] of Object.entries(compilerOptions.paths ?? {})) {
|
|
8182
|
-
if (!Array.isArray(targets) || targets.length === 0) continue;
|
|
8183
|
-
const aliasKey = pattern.replace(/\/\*$/, "");
|
|
8184
|
-
const target = targets[0].replace(/\/\*$/, "");
|
|
8185
|
-
aliases[aliasKey] = isAbsolute2(target) ? target : resolve5(sourceRoot, target);
|
|
8186
|
-
}
|
|
8187
|
-
return { sourceRoot, aliases };
|
|
8188
|
-
}
|
|
8189
|
-
function stripJsonComments(input) {
|
|
8190
|
-
return input.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1");
|
|
8191
|
-
}
|
|
8192
|
-
function generateProviderModules(opts) {
|
|
8193
|
-
const base = {
|
|
8194
|
-
providersDir: opts.providersDir,
|
|
8195
|
-
skipped: false,
|
|
8196
|
-
written: [],
|
|
8197
|
-
loadFailures: [],
|
|
8198
|
-
issues: []
|
|
8199
|
-
};
|
|
8200
|
-
if (!existsSync9(opts.providersDir) || !statSync5(opts.providersDir).isDirectory()) {
|
|
8201
|
-
return { ...base, skipped: true };
|
|
8202
|
-
}
|
|
8203
|
-
const files = findYamlFiles(opts.providersDir);
|
|
8204
|
-
if (files.length === 0) return { ...base, skipped: true };
|
|
8205
|
-
const { successes, failures } = loadProvidersFromYaml(files);
|
|
8206
|
-
const loaded = successes.map((s) => ({
|
|
8207
|
-
definition: s.definition,
|
|
8208
|
-
filePath: s.filePath
|
|
8209
|
-
}));
|
|
8210
|
-
const issues = failures.map((f) => ({
|
|
8211
|
-
severity: "error",
|
|
8212
|
-
type: "provider_load_failed",
|
|
8213
|
-
message: `${f.error}${f.details?.length ? ` \u2014 ${f.details.join("; ")}` : ""}`,
|
|
8214
|
-
path: f.filePath
|
|
8215
|
-
}));
|
|
8216
|
-
issues.push(
|
|
8217
|
-
...validateProviders(loaded, {
|
|
8218
|
-
entitySurfaces: opts.entitySurfaces,
|
|
8219
|
-
sourceRoot: opts.sourceRoot,
|
|
8220
|
-
aliases: opts.aliases,
|
|
8221
|
-
skipImportCheck: opts.skipImportCheck
|
|
8222
|
-
})
|
|
8223
|
-
);
|
|
8224
|
-
if (issues.some((i) => i.severity === "error")) {
|
|
8225
|
-
return { ...base, loadFailures: failures, issues };
|
|
8226
|
-
}
|
|
8227
|
-
const written = [];
|
|
8228
|
-
for (const { definition, filePath } of loaded) {
|
|
8229
|
-
const sourceYaml = relativeSource(filePath);
|
|
8230
|
-
const content = generateProviderModule(definition, sourceYaml);
|
|
8231
|
-
const outPath = join11(
|
|
8232
|
-
opts.outputRoot,
|
|
8233
|
-
definition.slug,
|
|
8234
|
-
`${definition.slug}.provider.module.ts`
|
|
8235
|
-
);
|
|
8236
|
-
if (!opts.dryRun) {
|
|
8237
|
-
writeIfChanged(outPath, content);
|
|
8238
|
-
}
|
|
8239
|
-
written.push(outPath);
|
|
8240
|
-
}
|
|
8241
|
-
return { ...base, written, loadFailures: failures, issues };
|
|
8242
|
-
}
|
|
8243
|
-
function writeIfChanged(outPath, content) {
|
|
8244
|
-
if (existsSync9(outPath) && readFileSync7(outPath, "utf-8") === content) return;
|
|
8245
|
-
mkdirSync2(dirname(outPath), { recursive: true });
|
|
8246
|
-
writeFileSync2(outPath, content);
|
|
8247
|
-
}
|
|
8248
|
-
function relativeSource(filePath) {
|
|
8249
|
-
const marker = "definitions/providers/";
|
|
8250
|
-
const idx = filePath.lastIndexOf(marker);
|
|
8251
|
-
if (idx !== -1) return filePath.slice(idx);
|
|
8252
|
-
const slash = filePath.lastIndexOf("/");
|
|
8253
|
-
return slash === -1 ? filePath : `definitions/providers/${filePath.slice(slash + 1)}`;
|
|
8254
|
-
}
|
|
8258
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync8, statSync as statSync6, writeFileSync as writeFileSync3 } from "fs";
|
|
8259
|
+
import { dirname as dirname2, isAbsolute as isAbsolute2, join as join12, resolve as resolve6 } from "path";
|
|
8255
8260
|
|
|
8256
8261
|
// src/cli/shared/adapter-emission-generator.ts
|
|
8257
8262
|
import {
|
|
8258
|
-
existsSync as
|
|
8259
|
-
mkdirSync as
|
|
8260
|
-
readFileSync as
|
|
8261
|
-
statSync as
|
|
8262
|
-
writeFileSync as
|
|
8263
|
+
existsSync as existsSync9,
|
|
8264
|
+
mkdirSync as mkdirSync2,
|
|
8265
|
+
readFileSync as readFileSync7,
|
|
8266
|
+
statSync as statSync5,
|
|
8267
|
+
writeFileSync as writeFileSync2
|
|
8263
8268
|
} from "fs";
|
|
8264
|
-
import { dirname
|
|
8269
|
+
import { dirname, join as join11 } from "path";
|
|
8265
8270
|
|
|
8266
8271
|
// src/cli/shared/sink-emission-generator.ts
|
|
8267
8272
|
var SCAFFOLD_SENTINEL = "// <CODEGEN-SCAFFOLD-V1>";
|
|
@@ -8321,7 +8326,7 @@ function generateDefaultSink(input) {
|
|
|
8321
8326
|
// for entities with external FK join-keys, fill the marked TODO(s) below.
|
|
8322
8327
|
// Source: definitions entity '${input.entityName}' (surface: ${input.surface}).
|
|
8323
8328
|
import { Injectable } from '@nestjs/common';
|
|
8324
|
-
import type { IIntegrationSink } from '
|
|
8329
|
+
import type { IIntegrationSink } from '${subsystemsImport(input.mode ?? "package", "integration")}';
|
|
8325
8330
|
import {
|
|
8326
8331
|
${n.repoClass},
|
|
8327
8332
|
type ${n.projectionType},
|
|
@@ -8374,7 +8379,7 @@ function relationLabel(writeKey) {
|
|
|
8374
8379
|
}
|
|
8375
8380
|
|
|
8376
8381
|
// src/cli/shared/assembly-emission-generator.ts
|
|
8377
|
-
import { relative, resolve as
|
|
8382
|
+
import { relative, resolve as resolve5, sep } from "path";
|
|
8378
8383
|
function generatedBanner(sourceDesc) {
|
|
8379
8384
|
return `// @generated by @pattern-stack/codegen from ${sourceDesc} \u2014 DO NOT EDIT.
|
|
8380
8385
|
// Hand edits are overwritten on re-emit. Regenerate with \`bun run codegen\`.`;
|
|
@@ -8412,7 +8417,7 @@ import {
|
|
|
8412
8417
|
ExecuteIntegrationUseCase,
|
|
8413
8418
|
INTEGRATION_CHANGE_SOURCE,
|
|
8414
8419
|
INTEGRATION_SINK,
|
|
8415
|
-
} from '
|
|
8420
|
+
} from '${subsystemsImport(input.mode ?? "package", "integration")}';
|
|
8416
8421
|
import { ${adapterClass} } from '${adapterImport}';
|
|
8417
8422
|
import { ${adapterModuleClass} } from '${adapterModuleImport}';
|
|
8418
8423
|
import { ${sinkClass} } from '${sinkImport}';
|
|
@@ -8425,7 +8430,7 @@ import { ${token} } from '${tokensImport}';
|
|
|
8425
8430
|
* inbound-integration assembly (RFC-0002 \xA72, Option A).
|
|
8426
8431
|
*
|
|
8427
8432
|
* Binds this module's INTEGRATION_CHANGE_SOURCE from the adapter's
|
|
8428
|
-
* \`changeSources
|
|
8433
|
+
* \`changeSources.${input.entityName}\` and INTEGRATION_SINK from
|
|
8429
8434
|
* ${sinkClass}, provides a local ExecuteIntegrationUseCase, and aliases+exports
|
|
8430
8435
|
* it under ${token} (the bare class token is ambiguous at app root \u2014 every
|
|
8431
8436
|
* assembly provides it). The substrate (cursor store, run recorder, differ,
|
|
@@ -8437,7 +8442,7 @@ import { ${token} } from '${tokensImport}';
|
|
|
8437
8442
|
providers: [
|
|
8438
8443
|
{
|
|
8439
8444
|
provide: INTEGRATION_CHANGE_SOURCE,
|
|
8440
|
-
useFactory: (adapter: ${adapterClass}) => adapter.changeSources
|
|
8445
|
+
useFactory: (adapter: ${adapterClass}) => adapter.changeSources.${input.entityName},
|
|
8441
8446
|
inject: [${adapterClass}],
|
|
8442
8447
|
},
|
|
8443
8448
|
{
|
|
@@ -8486,8 +8491,8 @@ function generateIntegrationAggregator(surface, entries) {
|
|
|
8486
8491
|
);
|
|
8487
8492
|
const importLines = sorted.map((e) => {
|
|
8488
8493
|
const cls = assemblyModuleClass(e.entityName, e.provider);
|
|
8489
|
-
const
|
|
8490
|
-
return `import { ${cls} } from '${
|
|
8494
|
+
const path36 = `./modules/${e.provider}/${e.entityName}-integration.module`;
|
|
8495
|
+
return `import { ${cls} } from '${path36}';`;
|
|
8491
8496
|
}).join("\n");
|
|
8492
8497
|
const membersInline = moduleClasses.join(", ");
|
|
8493
8498
|
return `${generatedBanner(`surface: ${surface}`)}
|
|
@@ -8539,17 +8544,17 @@ function resolveEntityModuleImports(input) {
|
|
|
8539
8544
|
const repoClass = `${entityClass}Repository`;
|
|
8540
8545
|
const moduleClass = `${pluralPascalCase(input.entityPlural)}Module`;
|
|
8541
8546
|
const moduleGroupSegs = input.context ? ["modules", input.context, input.entityPlural] : ["modules", input.entityPlural];
|
|
8542
|
-
const repoFileAbs =
|
|
8547
|
+
const repoFileAbs = resolve5(
|
|
8543
8548
|
input.backendSrcAbs,
|
|
8544
8549
|
...moduleGroupSegs,
|
|
8545
8550
|
`${input.entityName}.repository.ts`
|
|
8546
8551
|
);
|
|
8547
|
-
const moduleFileAbs =
|
|
8552
|
+
const moduleFileAbs = resolve5(
|
|
8548
8553
|
input.backendSrcAbs,
|
|
8549
8554
|
...moduleGroupSegs,
|
|
8550
8555
|
`${input.entityPlural}.module.ts`
|
|
8551
8556
|
);
|
|
8552
|
-
const assemblyDirAbs =
|
|
8557
|
+
const assemblyDirAbs = resolve5(
|
|
8553
8558
|
input.backendSrcAbs,
|
|
8554
8559
|
"integrations",
|
|
8555
8560
|
input.surface,
|
|
@@ -8638,6 +8643,9 @@ var SURFACE_REGISTRY = {
|
|
|
8638
8643
|
readPrimitive: true
|
|
8639
8644
|
}
|
|
8640
8645
|
};
|
|
8646
|
+
function isClientlessProvider(surfaces) {
|
|
8647
|
+
return surfaces.length > 0 && surfaces.every((s) => SURFACE_REGISTRY[s]?.readPrimitive === true);
|
|
8648
|
+
}
|
|
8641
8649
|
var SCAFFOLD_SENTINEL2 = "// <CODEGEN-SCAFFOLD-V1>";
|
|
8642
8650
|
function generatedBanner2(sourceDesc) {
|
|
8643
8651
|
return `// @generated by @pattern-stack/codegen from ${sourceDesc} \u2014 DO NOT EDIT.
|
|
@@ -8692,7 +8700,7 @@ function serializeFilterArray(filters) {
|
|
|
8692
8700
|
${items.join("\n")}
|
|
8693
8701
|
]`;
|
|
8694
8702
|
}
|
|
8695
|
-
function buildReadPrimitiveEmission(providerSlug, providerPascal, surface, entities, entityDetection
|
|
8703
|
+
function buildReadPrimitiveEmission(providerSlug, providerPascal, surface, entities, entityDetection) {
|
|
8696
8704
|
const canonicalTypes = [];
|
|
8697
8705
|
const blocks = [];
|
|
8698
8706
|
const entries = [];
|
|
@@ -8724,24 +8732,32 @@ export class ${className} extends IncrementalReadBase<${canonical}, ResolvedFilt
|
|
|
8724
8732
|
// (e.g. Gmail \`q=\`); leave \`false\` to filter post-hydrate via \`matchesRecord\`.
|
|
8725
8733
|
protected override readonly filterPushdown = false;${cursorOverride}
|
|
8726
8734
|
|
|
8727
|
-
constructor(
|
|
8728
|
-
private readonly auth: IAuthStrategy,
|
|
8729
|
-
private readonly client: ${clientExportName},
|
|
8730
|
-
) {
|
|
8735
|
+
constructor(private readonly auth: IAuthStrategy) {
|
|
8731
8736
|
super();
|
|
8732
8737
|
}
|
|
8733
8738
|
|
|
8734
|
-
/**
|
|
8739
|
+
/**
|
|
8740
|
+
* TODO: walk the vendor list endpoint \u2192 pages of \`Ref\` (id + cursor + meta).
|
|
8741
|
+
* Per-connection (multi-account) adapters resolve credentials here from the
|
|
8742
|
+
* threaded subscription, e.g.
|
|
8743
|
+
* \`const client = <vendorClientFactory>({ accessToken: async () => (await this.auth.resolve(_ctx!.subscription!.externalRef)).accessToken });\`
|
|
8744
|
+
* \u2014 there is no provider-level singleton client. Provider-level-auth adapters
|
|
8745
|
+
* ignore \`_ctx\`.
|
|
8746
|
+
*/
|
|
8735
8747
|
protected async *enumerate(
|
|
8736
8748
|
_mode: ReadMode,
|
|
8737
8749
|
_filter?: ResolvedFilter[],
|
|
8738
8750
|
_pageSize?: number,
|
|
8751
|
+
_ctx?: ReadContext,
|
|
8739
8752
|
): AsyncIterable<Ref[]> {
|
|
8740
8753
|
throw new Error('not implemented: ${className}.enumerate');
|
|
8741
8754
|
}
|
|
8742
8755
|
|
|
8743
|
-
/**
|
|
8744
|
-
|
|
8756
|
+
/**
|
|
8757
|
+
* TODO: batched fetch-by-id \u2192 \`Map<id, raw>\` (\`mapConcurrent\`, or a vendor /batch).
|
|
8758
|
+
* Use \`_ctx?.subscription?.id\` to key raw-landing rows per connection.
|
|
8759
|
+
*/
|
|
8760
|
+
protected async hydrate(_ids: string[], _ctx?: ReadContext): Promise<Map<string, unknown>> {
|
|
8745
8761
|
throw new Error('not implemented: ${className}.hydrate');
|
|
8746
8762
|
}
|
|
8747
8763
|
|
|
@@ -8756,15 +8772,16 @@ export class ${className} extends IncrementalReadBase<${canonical}, ResolvedFilt
|
|
|
8756
8772
|
return ${constName};
|
|
8757
8773
|
}
|
|
8758
8774
|
}`);
|
|
8759
|
-
entries.push(` ${entity}: new ${className}(this.auth
|
|
8775
|
+
entries.push(` ${entity}: new ${className}(this.auth),`);
|
|
8760
8776
|
}
|
|
8761
8777
|
return { canonicalTypes, preamble: blocks.join("\n\n"), changeSourceEntries: entries };
|
|
8762
8778
|
}
|
|
8763
|
-
function generateAdapterScaffold(def, surface, entities, entityDetection) {
|
|
8779
|
+
function generateAdapterScaffold(def, surface, entities, entityDetection, mode = "package") {
|
|
8764
8780
|
const spec = SURFACE_REGISTRY[surface];
|
|
8765
8781
|
if (!spec) throw new Error(`no surface package for '${surface}'`);
|
|
8766
8782
|
const n = names(def.slug, surface);
|
|
8767
8783
|
const client = parseImportRef(def.client.class);
|
|
8784
|
+
const subsystemsSpec = subsystemsImport(mode, "integration");
|
|
8768
8785
|
const entitiesLiteral = entities.length ? `[${entities.map((e) => `'${e}'`).join(", ")}]` : "[]";
|
|
8769
8786
|
const readPrimitive = !!spec.readPrimitive && entities.length > 0;
|
|
8770
8787
|
const rp = readPrimitive ? buildReadPrimitiveEmission(
|
|
@@ -8772,21 +8789,26 @@ function generateAdapterScaffold(def, surface, entities, entityDetection) {
|
|
|
8772
8789
|
n.providerPascal,
|
|
8773
8790
|
surface,
|
|
8774
8791
|
entities,
|
|
8775
|
-
entityDetection
|
|
8776
|
-
client.exportName
|
|
8792
|
+
entityDetection
|
|
8777
8793
|
) : null;
|
|
8778
8794
|
const surfaceTypeImports = [
|
|
8779
8795
|
spec.portType,
|
|
8780
8796
|
...spec.l2Ports.map((p) => p.type),
|
|
8781
8797
|
spec.capabilitiesType,
|
|
8782
8798
|
...rp ? rp.canonicalTypes : []
|
|
8783
|
-
].map((t) => ` ${t},`).join("\n");
|
|
8784
|
-
const subsystemValueImport = rp ? `import { IncrementalReadBase } from '
|
|
8799
|
+
].sort().map((t) => ` ${t},`).join("\n");
|
|
8800
|
+
const subsystemValueImport = rp ? `import { IncrementalReadBase } from '${subsystemsSpec}';
|
|
8785
8801
|
` : "";
|
|
8786
8802
|
const subsystemTypeImports = [
|
|
8787
8803
|
"IAuthStrategy",
|
|
8788
8804
|
"IChangeSource",
|
|
8789
|
-
...rp ? [
|
|
8805
|
+
...rp ? [
|
|
8806
|
+
"IntegrationSubscriptionView",
|
|
8807
|
+
"ReadContext",
|
|
8808
|
+
"ReadMode",
|
|
8809
|
+
"Ref",
|
|
8810
|
+
"ResolvedFilter"
|
|
8811
|
+
] : []
|
|
8790
8812
|
].map((t) => ` ${t},`).join("\n");
|
|
8791
8813
|
const changeSourcesAssign = rp ? `
|
|
8792
8814
|
this.changeSources = {
|
|
@@ -8826,6 +8848,14 @@ ${rp.preamble}
|
|
|
8826
8848
|
const l2Section = l2Members ? `
|
|
8827
8849
|
${l2Members}
|
|
8828
8850
|
` : "";
|
|
8851
|
+
const clientTypeImport = rp ? "" : `import type { ${client.exportName} } from '${client.path}';
|
|
8852
|
+
`;
|
|
8853
|
+
const providerTokenImport = rp ? `import { ${n.strategyToken} } from '../../../providers/${def.slug}/${def.slug}.provider.module';` : `import { ${n.strategyToken}, ${n.clientToken} } from '../../../providers/${def.slug}/${def.slug}.provider.module';`;
|
|
8854
|
+
const ctorClientParam = rp ? "" : `
|
|
8855
|
+
@Inject(${n.clientToken}) private readonly client: ${client.exportName},`;
|
|
8856
|
+
const ctorOpen = rp ? ` constructor(@Inject(${n.strategyToken}) readonly auth: IAuthStrategy) {${changeSourcesAssign}}` : ` constructor(
|
|
8857
|
+
@Inject(${n.strategyToken}) readonly auth: IAuthStrategy,${ctorClientParam}
|
|
8858
|
+
) {${changeSourcesAssign}}`;
|
|
8829
8859
|
return `${SCAFFOLD_SENTINEL2}
|
|
8830
8860
|
// Scaffolded once by @pattern-stack/codegen, then author-owned. Re-running
|
|
8831
8861
|
// codegen detects the sentinel above and SKIPS this file \u2014 your edits are safe.
|
|
@@ -8837,9 +8867,8 @@ ${surfaceTypeImports}
|
|
|
8837
8867
|
import { ${spec.noCapsConst} } from '${spec.packageName}';
|
|
8838
8868
|
${subsystemValueImport}import type {
|
|
8839
8869
|
${subsystemTypeImports}
|
|
8840
|
-
} from '
|
|
8841
|
-
|
|
8842
|
-
import { ${n.strategyToken}, ${n.clientToken} } from '../../../providers/${def.slug}/${def.slug}.provider.module';
|
|
8870
|
+
} from '${subsystemsSpec}';
|
|
8871
|
+
${clientTypeImport}${providerTokenImport}
|
|
8843
8872
|
${preambleSection}
|
|
8844
8873
|
@Injectable()
|
|
8845
8874
|
export class ${n.adapterClass} implements ${spec.portType} {
|
|
@@ -8848,10 +8877,7 @@ export class ${n.adapterClass} implements ${spec.portType} {
|
|
|
8848
8877
|
${capabilityBody}
|
|
8849
8878
|
};
|
|
8850
8879
|
|
|
8851
|
-
|
|
8852
|
-
@Inject(${n.strategyToken}) readonly auth: IAuthStrategy,
|
|
8853
|
-
@Inject(${n.clientToken}) private readonly client: ${client.exportName},
|
|
8854
|
-
) {${changeSourcesAssign}}
|
|
8880
|
+
${ctorOpen}
|
|
8855
8881
|
${l2Section}
|
|
8856
8882
|
${changeSourcesDecl}
|
|
8857
8883
|
|
|
@@ -8883,10 +8909,10 @@ function generateAdaptersBarrel(surface, providerSlugs) {
|
|
|
8883
8909
|
${lines}
|
|
8884
8910
|
`;
|
|
8885
8911
|
}
|
|
8886
|
-
function generateSurfaceTokens(surface) {
|
|
8912
|
+
function generateSurfaceTokens(surface, mode = "package") {
|
|
8887
8913
|
const n = names("__placeholder__", surface);
|
|
8888
8914
|
return `${generatedBanner2(`surface: ${surface}`)}
|
|
8889
|
-
import type { IChangeSource } from '
|
|
8915
|
+
import type { IChangeSource } from '${subsystemsImport(mode, "integration")}';
|
|
8890
8916
|
|
|
8891
8917
|
/** The assembled list of every ${surface} adapter's contribution. */
|
|
8892
8918
|
export const ${n.contributionsToken} = Symbol.for('@app/integrations/${surface}.adapter-contributions');
|
|
@@ -8903,7 +8929,7 @@ export interface AdapterContribution {
|
|
|
8903
8929
|
}
|
|
8904
8930
|
`;
|
|
8905
8931
|
}
|
|
8906
|
-
function generateSurfaceAggregator(surface, providerSlugs) {
|
|
8932
|
+
function generateSurfaceAggregator(surface, providerSlugs, mode = "package") {
|
|
8907
8933
|
const n = names("__placeholder__", surface);
|
|
8908
8934
|
const slugs = [...providerSlugs].sort();
|
|
8909
8935
|
const per = slugs.map((slug) => names(slug, surface));
|
|
@@ -8930,7 +8956,7 @@ import {
|
|
|
8930
8956
|
MemoryEntityChangeSourceRegistry,
|
|
8931
8957
|
type IChangeSource,
|
|
8932
8958
|
type IEntityChangeSourceRegistry,
|
|
8933
|
-
} from '
|
|
8959
|
+
} from '${subsystemsImport(mode, "integration")}';
|
|
8934
8960
|
${moduleImport}
|
|
8935
8961
|
${adapterImports}
|
|
8936
8962
|
import {
|
|
@@ -9019,6 +9045,7 @@ function jsKey(key) {
|
|
|
9019
9045
|
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : `'${key}'`;
|
|
9020
9046
|
}
|
|
9021
9047
|
function emitAdapters(opts) {
|
|
9048
|
+
const mode = opts.mode ?? "package";
|
|
9022
9049
|
const result = {
|
|
9023
9050
|
written: [],
|
|
9024
9051
|
scaffoldsWritten: [],
|
|
@@ -9049,14 +9076,14 @@ function emitAdapters(opts) {
|
|
|
9049
9076
|
}
|
|
9050
9077
|
const defBySlug = new Map(opts.providers.map((p) => [p.definition.slug, p.definition]));
|
|
9051
9078
|
for (const [surface, slugs] of bySurface) {
|
|
9052
|
-
const surfaceDir =
|
|
9053
|
-
const adaptersDir =
|
|
9079
|
+
const surfaceDir = join11(opts.outputRoot, surface);
|
|
9080
|
+
const adaptersDir = join11(surfaceDir, "adapters");
|
|
9054
9081
|
for (const slug of slugs) {
|
|
9055
9082
|
const def = defBySlug.get(slug);
|
|
9056
|
-
const providerDir =
|
|
9057
|
-
const scaffoldPath =
|
|
9058
|
-
const modulePath =
|
|
9059
|
-
if (
|
|
9083
|
+
const providerDir = join11(adaptersDir, slug);
|
|
9084
|
+
const scaffoldPath = join11(providerDir, `${slug}-${surface}.adapter.ts`);
|
|
9085
|
+
const modulePath = join11(providerDir, `${slug}-${surface}.adapter.module.ts`);
|
|
9086
|
+
if (existsSync9(scaffoldPath)) {
|
|
9060
9087
|
result.scaffoldsSkipped.push(scaffoldPath);
|
|
9061
9088
|
} else {
|
|
9062
9089
|
const surfaceEntityNames = entitiesBySurface.get(surface) ?? [];
|
|
@@ -9069,36 +9096,37 @@ function emitAdapters(opts) {
|
|
|
9069
9096
|
def,
|
|
9070
9097
|
surface,
|
|
9071
9098
|
surfaceEntityNames,
|
|
9072
|
-
entityDetection
|
|
9099
|
+
entityDetection,
|
|
9100
|
+
mode
|
|
9073
9101
|
);
|
|
9074
9102
|
if (!opts.dryRun) writeFile(scaffoldPath, content);
|
|
9075
9103
|
result.scaffoldsWritten.push(scaffoldPath);
|
|
9076
9104
|
}
|
|
9077
9105
|
const moduleContent = generateAdapterModule(def, surface);
|
|
9078
|
-
if (!opts.dryRun)
|
|
9106
|
+
if (!opts.dryRun) writeIfChanged(modulePath, moduleContent);
|
|
9079
9107
|
result.written.push(modulePath);
|
|
9080
9108
|
}
|
|
9081
|
-
const barrelPath =
|
|
9082
|
-
const tokensPath =
|
|
9083
|
-
const aggregatorPath =
|
|
9084
|
-
const typedViewPath =
|
|
9109
|
+
const barrelPath = join11(adaptersDir, "index.ts");
|
|
9110
|
+
const tokensPath = join11(surfaceDir, `${surface}-adapters.tokens.ts`);
|
|
9111
|
+
const aggregatorPath = join11(surfaceDir, `${surface}-adapters.module.ts`);
|
|
9112
|
+
const typedViewPath = join11(surfaceDir, "types.generated.ts");
|
|
9085
9113
|
const files = [
|
|
9086
9114
|
[barrelPath, generateAdaptersBarrel(surface, slugs)],
|
|
9087
|
-
[tokensPath, generateSurfaceTokens(surface)],
|
|
9088
|
-
[aggregatorPath, generateSurfaceAggregator(surface, slugs)],
|
|
9115
|
+
[tokensPath, generateSurfaceTokens(surface, mode)],
|
|
9116
|
+
[aggregatorPath, generateSurfaceAggregator(surface, slugs, mode)],
|
|
9089
9117
|
[typedViewPath, generateTypedView(surface, slugs, entitiesBySurface.get(surface) ?? [])]
|
|
9090
9118
|
];
|
|
9091
|
-
for (const [
|
|
9092
|
-
if (!opts.dryRun)
|
|
9093
|
-
result.written.push(
|
|
9119
|
+
for (const [path36, content] of files) {
|
|
9120
|
+
if (!opts.dryRun) writeIfChanged(path36, content);
|
|
9121
|
+
result.written.push(path36);
|
|
9094
9122
|
}
|
|
9095
9123
|
if (opts.backendSrcAbs) {
|
|
9096
9124
|
const aliases = opts.aliases ?? {};
|
|
9097
9125
|
const surfaceEntities = entitiesBySurface.get(surface) ?? [];
|
|
9098
9126
|
const tokenEntries = [];
|
|
9099
9127
|
const assemblyEntries = [];
|
|
9100
|
-
const sinksDir =
|
|
9101
|
-
const modulesDir =
|
|
9128
|
+
const sinksDir = join11(surfaceDir, "sinks");
|
|
9129
|
+
const modulesDir = join11(surfaceDir, "modules");
|
|
9102
9130
|
for (const entityName of surfaceEntities) {
|
|
9103
9131
|
const def = entityByName.get(entityName);
|
|
9104
9132
|
const pattern = def?.entity.pattern ?? (Array.isArray(def?.entity.patterns) ? def?.entity.patterns?.[0] : void 0);
|
|
@@ -9123,17 +9151,17 @@ function emitAdapters(opts) {
|
|
|
9123
9151
|
backendSrcAbs: opts.backendSrcAbs,
|
|
9124
9152
|
aliases
|
|
9125
9153
|
});
|
|
9126
|
-
const sinkPath =
|
|
9127
|
-
if (
|
|
9154
|
+
const sinkPath = join11(sinksDir, `${entityName}.sink.ts`);
|
|
9155
|
+
if (existsSync9(sinkPath)) {
|
|
9128
9156
|
result.scaffoldsSkipped.push(sinkPath);
|
|
9129
9157
|
} else {
|
|
9130
9158
|
const sinkInput = buildSinkInput(def, surface, slugs[0], loc.repoImportSpecifier);
|
|
9131
|
-
const sinkContent = generateDefaultSink(sinkInput);
|
|
9159
|
+
const sinkContent = generateDefaultSink({ ...sinkInput, mode });
|
|
9132
9160
|
if (!opts.dryRun) writeFile(sinkPath, sinkContent);
|
|
9133
9161
|
result.scaffoldsWritten.push(sinkPath);
|
|
9134
9162
|
}
|
|
9135
9163
|
for (const slug of slugs) {
|
|
9136
|
-
const assemblyPath =
|
|
9164
|
+
const assemblyPath = join11(
|
|
9137
9165
|
modulesDir,
|
|
9138
9166
|
slug,
|
|
9139
9167
|
`${entityName}-integration.module.ts`
|
|
@@ -9147,23 +9175,24 @@ function emitAdapters(opts) {
|
|
|
9147
9175
|
moduleClass: loc.moduleClass,
|
|
9148
9176
|
repoImportSpecifier: loc.repoImportSpecifier,
|
|
9149
9177
|
repoClass: loc.repoClass,
|
|
9150
|
-
sourceDesc: `definitions/providers/${slug}.yaml
|
|
9178
|
+
sourceDesc: `definitions/providers/${slug}.yaml`,
|
|
9179
|
+
mode
|
|
9151
9180
|
});
|
|
9152
|
-
if (!opts.dryRun)
|
|
9181
|
+
if (!opts.dryRun) writeIfChanged(assemblyPath, assemblyContent);
|
|
9153
9182
|
result.assembliesWritten.push(assemblyPath);
|
|
9154
9183
|
tokenEntries.push({ entityName, entityClass: loc.entityClass, provider: slug });
|
|
9155
9184
|
assemblyEntries.push({ entityName, provider: slug });
|
|
9156
9185
|
}
|
|
9157
9186
|
}
|
|
9158
|
-
const integrationTokensPath =
|
|
9187
|
+
const integrationTokensPath = join11(
|
|
9159
9188
|
surfaceDir,
|
|
9160
9189
|
`${surface}-integration.tokens.ts`
|
|
9161
9190
|
);
|
|
9162
9191
|
const tokensContent = generateIntegrationTokens(surface, tokenEntries);
|
|
9163
|
-
if (!opts.dryRun)
|
|
9192
|
+
if (!opts.dryRun) writeIfChanged(integrationTokensPath, tokensContent);
|
|
9164
9193
|
result.tokensWritten.push(integrationTokensPath);
|
|
9165
9194
|
if (assemblyEntries.length > 0) {
|
|
9166
|
-
const integrationAggregatorPath =
|
|
9195
|
+
const integrationAggregatorPath = join11(
|
|
9167
9196
|
surfaceDir,
|
|
9168
9197
|
`${surface}-integration.module.ts`
|
|
9169
9198
|
);
|
|
@@ -9171,7 +9200,7 @@ function emitAdapters(opts) {
|
|
|
9171
9200
|
surface,
|
|
9172
9201
|
assemblyEntries
|
|
9173
9202
|
);
|
|
9174
|
-
if (!opts.dryRun)
|
|
9203
|
+
if (!opts.dryRun) writeIfChanged(integrationAggregatorPath, aggregatorContent);
|
|
9175
9204
|
result.integrationAggregatorsWritten.push(integrationAggregatorPath);
|
|
9176
9205
|
}
|
|
9177
9206
|
}
|
|
@@ -9228,44 +9257,240 @@ function pascalFromSnake(s) {
|
|
|
9228
9257
|
return camel.charAt(0).toUpperCase() + camel.slice(1);
|
|
9229
9258
|
}
|
|
9230
9259
|
function writeFile(outPath, content) {
|
|
9231
|
-
|
|
9232
|
-
|
|
9260
|
+
mkdirSync2(dirname(outPath), { recursive: true });
|
|
9261
|
+
writeFileSync2(outPath, content);
|
|
9233
9262
|
}
|
|
9234
|
-
function
|
|
9235
|
-
if (
|
|
9263
|
+
function writeIfChanged(outPath, content) {
|
|
9264
|
+
if (existsSync9(outPath) && statSync5(outPath).isFile() && readFileSync7(outPath, "utf-8") === content) {
|
|
9236
9265
|
return;
|
|
9237
9266
|
}
|
|
9238
9267
|
writeFile(outPath, content);
|
|
9239
9268
|
}
|
|
9240
9269
|
|
|
9241
|
-
// src/cli/shared/
|
|
9242
|
-
|
|
9243
|
-
|
|
9244
|
-
function resolveEventsDirFromConfig(cwd, config) {
|
|
9245
|
-
const configured = config?.paths?.events_dir;
|
|
9246
|
-
if (typeof configured === "string" && configured.length > 0) {
|
|
9247
|
-
return path12.resolve(cwd, configured);
|
|
9248
|
-
}
|
|
9249
|
-
return path12.resolve(cwd, FALLBACK);
|
|
9250
|
-
}
|
|
9251
|
-
function resolveEventsDir(ctx) {
|
|
9252
|
-
return resolveEventsDirFromConfig(ctx.cwd, ctx.config);
|
|
9253
|
-
}
|
|
9254
|
-
|
|
9255
|
-
// src/cli/ui/output.ts
|
|
9256
|
-
var MAX_ERROR_LEN = 500;
|
|
9257
|
-
function printSuccess(msg) {
|
|
9258
|
-
if (isJsonMode()) return;
|
|
9259
|
-
console.log(`${theme.success(icons.success)} ${msg}`);
|
|
9270
|
+
// src/cli/shared/provider-module-generator.ts
|
|
9271
|
+
function providerPascalCase(slug) {
|
|
9272
|
+
return slug.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
9260
9273
|
}
|
|
9261
|
-
function
|
|
9262
|
-
|
|
9263
|
-
const truncated = msg.length > MAX_ERROR_LEN ? msg.slice(0, MAX_ERROR_LEN) + "\u2026" : msg;
|
|
9264
|
-
console.error(`${theme.error(icons.error)} ${truncated}`);
|
|
9274
|
+
function providerConstantCase(slug) {
|
|
9275
|
+
return slug.replace(/-/g, "_").toUpperCase();
|
|
9265
9276
|
}
|
|
9266
|
-
function
|
|
9267
|
-
|
|
9268
|
-
|
|
9277
|
+
function providerModuleBanner(sourceYaml) {
|
|
9278
|
+
return `// @generated by @pattern-stack/codegen from ${sourceYaml} \u2014 DO NOT EDIT.
|
|
9279
|
+
// Hand edits are overwritten on re-emit. Regenerate with \`bun run codegen\`. To change this provider, edit its \`definitions/providers/*.yaml\`.`;
|
|
9280
|
+
}
|
|
9281
|
+
function generateProviderModule(def, sourceYaml, mode = "package") {
|
|
9282
|
+
const { slug } = def;
|
|
9283
|
+
const Pascal = providerPascalCase(slug);
|
|
9284
|
+
const CONST = providerConstantCase(slug);
|
|
9285
|
+
const strategy = parseImportRef(def.auth.strategy);
|
|
9286
|
+
const client = parseImportRef(def.client.class);
|
|
9287
|
+
const strategyToken = `${CONST}_AUTH_STRATEGY`;
|
|
9288
|
+
const clientToken = `${CONST}_CLIENT`;
|
|
9289
|
+
const surfaces = def.surfaces.join(", ");
|
|
9290
|
+
const title = def.display_name ? `${def.display_name} (\`${slug}\`)` : `\`${slug}\``;
|
|
9291
|
+
if (isClientlessProvider(def.surfaces)) {
|
|
9292
|
+
return `${providerModuleBanner(sourceYaml)}
|
|
9293
|
+
/**
|
|
9294
|
+
* Provider module for ${title}.
|
|
9295
|
+
*
|
|
9296
|
+
* Surfaces: ${surfaces}.
|
|
9297
|
+
*
|
|
9298
|
+
* Per-connection (read-primitive) provider \u2014 exposes \`${strategyToken}\`, the
|
|
9299
|
+
* per-connection credential resolver the interaction adapters use (RFC-0003 R5:
|
|
9300
|
+
* \`auth.resolve(ctx.subscription.externalRef)\`). There is NO provider-level
|
|
9301
|
+
* singleton client; adapters build a per-connection client inside their
|
|
9302
|
+
* \`enumerate\`/\`hydrate\`. \`${strategyToken}\` resolves the already-built
|
|
9303
|
+
* \`${slug}\` strategy from the @Global \`STRATEGY_REGISTRY\` (wired by the
|
|
9304
|
+
* consumer's AuthBindings module) \u2014 the strategy may need DI deps a bare class
|
|
9305
|
+
* can't satisfy, so it is registry-resolved, not provided directly.
|
|
9306
|
+
*/
|
|
9307
|
+
import { Module } from '@nestjs/common';
|
|
9308
|
+
import {
|
|
9309
|
+
type ProviderStrategyRegistry,
|
|
9310
|
+
STRATEGY_REGISTRY,
|
|
9311
|
+
} from '${subsystemsImport(mode, "auth")}';
|
|
9312
|
+
|
|
9313
|
+
/** DI token for the \`${slug}\` provider's auth strategy (resolved from STRATEGY_REGISTRY). */
|
|
9314
|
+
export const ${strategyToken} = Symbol('${strategyToken}');
|
|
9315
|
+
|
|
9316
|
+
const PROVIDER_SLUG = '${slug}';
|
|
9317
|
+
|
|
9318
|
+
@Module({
|
|
9319
|
+
providers: [
|
|
9320
|
+
{
|
|
9321
|
+
provide: ${strategyToken},
|
|
9322
|
+
useFactory: (registry: ProviderStrategyRegistry) => {
|
|
9323
|
+
const strategy = registry.get(PROVIDER_SLUG);
|
|
9324
|
+
if (!strategy) {
|
|
9325
|
+
throw new Error(
|
|
9326
|
+
\`${Pascal}ProviderModule: no '\${PROVIDER_SLUG}' strategy registered in STRATEGY_REGISTRY (wire it in your consumer AuthBindings module)\`,
|
|
9327
|
+
);
|
|
9328
|
+
}
|
|
9329
|
+
return strategy;
|
|
9330
|
+
},
|
|
9331
|
+
inject: [STRATEGY_REGISTRY],
|
|
9332
|
+
},
|
|
9333
|
+
],
|
|
9334
|
+
exports: [${strategyToken}],
|
|
9335
|
+
})
|
|
9336
|
+
export class ${Pascal}ProviderModule {}
|
|
9337
|
+
`;
|
|
9338
|
+
}
|
|
9339
|
+
return `${providerModuleBanner(sourceYaml)}
|
|
9340
|
+
/**
|
|
9341
|
+
* Provider module for ${title}.
|
|
9342
|
+
*
|
|
9343
|
+
* Surfaces: ${surfaces}.
|
|
9344
|
+
*
|
|
9345
|
+
* Wires the declared auth strategy and API client under the provider-specific
|
|
9346
|
+
* DI tokens \`${strategyToken}\` and \`${clientToken}\`. Per the auth subsystem
|
|
9347
|
+
* contract, strategies are registered under provider-specific tokens rather
|
|
9348
|
+
* than a single \`AUTH_STRATEGY\`. Registry aggregation (RFC-0001 \xA73) is
|
|
9349
|
+
* emitted by a later codegen step.
|
|
9350
|
+
*/
|
|
9351
|
+
import { Module } from '@nestjs/common';
|
|
9352
|
+
import { ${strategy.exportName} } from '${strategy.path}';
|
|
9353
|
+
import { ${client.exportName} } from '${client.path}';
|
|
9354
|
+
|
|
9355
|
+
/** DI token for the \`${slug}\` provider's auth strategy. */
|
|
9356
|
+
export const ${strategyToken} = Symbol('${strategyToken}');
|
|
9357
|
+
/** DI token for the \`${slug}\` provider's API client. */
|
|
9358
|
+
export const ${clientToken} = Symbol('${clientToken}');
|
|
9359
|
+
|
|
9360
|
+
@Module({
|
|
9361
|
+
providers: [
|
|
9362
|
+
${strategy.exportName},
|
|
9363
|
+
${client.exportName},
|
|
9364
|
+
{ provide: ${strategyToken}, useExisting: ${strategy.exportName} },
|
|
9365
|
+
{ provide: ${clientToken}, useExisting: ${client.exportName} },
|
|
9366
|
+
],
|
|
9367
|
+
exports: [
|
|
9368
|
+
${strategy.exportName},
|
|
9369
|
+
${client.exportName},
|
|
9370
|
+
${strategyToken},
|
|
9371
|
+
${clientToken},
|
|
9372
|
+
],
|
|
9373
|
+
})
|
|
9374
|
+
export class ${Pascal}ProviderModule {}
|
|
9375
|
+
`;
|
|
9376
|
+
}
|
|
9377
|
+
function resolveTsconfigAliases(consumerRoot) {
|
|
9378
|
+
const tsconfigPath = join12(consumerRoot, "tsconfig.json");
|
|
9379
|
+
if (!existsSync10(tsconfigPath)) return null;
|
|
9380
|
+
let parsed;
|
|
9381
|
+
try {
|
|
9382
|
+
parsed = JSON.parse(stripJsonComments(readFileSync8(tsconfigPath, "utf-8")));
|
|
9383
|
+
} catch {
|
|
9384
|
+
return null;
|
|
9385
|
+
}
|
|
9386
|
+
const compilerOptions = parsed.compilerOptions ?? {};
|
|
9387
|
+
const baseUrl = compilerOptions.baseUrl ?? ".";
|
|
9388
|
+
const sourceRoot = isAbsolute2(baseUrl) ? baseUrl : resolve6(consumerRoot, baseUrl);
|
|
9389
|
+
const aliases = {};
|
|
9390
|
+
for (const [pattern, targets] of Object.entries(compilerOptions.paths ?? {})) {
|
|
9391
|
+
if (!Array.isArray(targets) || targets.length === 0) continue;
|
|
9392
|
+
const aliasKey = pattern.replace(/\/\*$/, "");
|
|
9393
|
+
const target = targets[0].replace(/\/\*$/, "");
|
|
9394
|
+
aliases[aliasKey] = isAbsolute2(target) ? target : resolve6(sourceRoot, target);
|
|
9395
|
+
}
|
|
9396
|
+
return { sourceRoot, aliases };
|
|
9397
|
+
}
|
|
9398
|
+
function stripJsonComments(input) {
|
|
9399
|
+
return input.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1");
|
|
9400
|
+
}
|
|
9401
|
+
function generateProviderModules(opts) {
|
|
9402
|
+
const base = {
|
|
9403
|
+
providersDir: opts.providersDir,
|
|
9404
|
+
skipped: false,
|
|
9405
|
+
written: [],
|
|
9406
|
+
loadFailures: [],
|
|
9407
|
+
issues: []
|
|
9408
|
+
};
|
|
9409
|
+
if (!existsSync10(opts.providersDir) || !statSync6(opts.providersDir).isDirectory()) {
|
|
9410
|
+
return { ...base, skipped: true };
|
|
9411
|
+
}
|
|
9412
|
+
const files = findYamlFiles(opts.providersDir);
|
|
9413
|
+
if (files.length === 0) return { ...base, skipped: true };
|
|
9414
|
+
const { successes, failures } = loadProvidersFromYaml(files);
|
|
9415
|
+
const loaded = successes.map((s) => ({
|
|
9416
|
+
definition: s.definition,
|
|
9417
|
+
filePath: s.filePath
|
|
9418
|
+
}));
|
|
9419
|
+
const issues = failures.map((f) => ({
|
|
9420
|
+
severity: "error",
|
|
9421
|
+
type: "provider_load_failed",
|
|
9422
|
+
message: `${f.error}${f.details?.length ? ` \u2014 ${f.details.join("; ")}` : ""}`,
|
|
9423
|
+
path: f.filePath
|
|
9424
|
+
}));
|
|
9425
|
+
issues.push(
|
|
9426
|
+
...validateProviders(loaded, {
|
|
9427
|
+
entitySurfaces: opts.entitySurfaces,
|
|
9428
|
+
sourceRoot: opts.sourceRoot,
|
|
9429
|
+
aliases: opts.aliases,
|
|
9430
|
+
skipImportCheck: opts.skipImportCheck
|
|
9431
|
+
})
|
|
9432
|
+
);
|
|
9433
|
+
if (issues.some((i) => i.severity === "error")) {
|
|
9434
|
+
return { ...base, loadFailures: failures, issues };
|
|
9435
|
+
}
|
|
9436
|
+
const mode = opts.mode ?? "package";
|
|
9437
|
+
const written = [];
|
|
9438
|
+
for (const { definition, filePath } of loaded) {
|
|
9439
|
+
const sourceYaml = relativeSource(filePath);
|
|
9440
|
+
const content = generateProviderModule(definition, sourceYaml, mode);
|
|
9441
|
+
const outPath = join12(
|
|
9442
|
+
opts.outputRoot,
|
|
9443
|
+
definition.slug,
|
|
9444
|
+
`${definition.slug}.provider.module.ts`
|
|
9445
|
+
);
|
|
9446
|
+
if (!opts.dryRun) {
|
|
9447
|
+
writeIfChanged2(outPath, content);
|
|
9448
|
+
}
|
|
9449
|
+
written.push(outPath);
|
|
9450
|
+
}
|
|
9451
|
+
return { ...base, written, loadFailures: failures, issues };
|
|
9452
|
+
}
|
|
9453
|
+
function writeIfChanged2(outPath, content) {
|
|
9454
|
+
if (existsSync10(outPath) && readFileSync8(outPath, "utf-8") === content) return;
|
|
9455
|
+
mkdirSync3(dirname2(outPath), { recursive: true });
|
|
9456
|
+
writeFileSync3(outPath, content);
|
|
9457
|
+
}
|
|
9458
|
+
function relativeSource(filePath) {
|
|
9459
|
+
const marker = "definitions/providers/";
|
|
9460
|
+
const idx = filePath.lastIndexOf(marker);
|
|
9461
|
+
if (idx !== -1) return filePath.slice(idx);
|
|
9462
|
+
const slash = filePath.lastIndexOf("/");
|
|
9463
|
+
return slash === -1 ? filePath : `definitions/providers/${filePath.slice(slash + 1)}`;
|
|
9464
|
+
}
|
|
9465
|
+
|
|
9466
|
+
// src/cli/shared/events-path.ts
|
|
9467
|
+
import path13 from "path";
|
|
9468
|
+
var FALLBACK = "events";
|
|
9469
|
+
function resolveEventsDirFromConfig(cwd, config) {
|
|
9470
|
+
const configured = config?.paths?.events_dir;
|
|
9471
|
+
if (typeof configured === "string" && configured.length > 0) {
|
|
9472
|
+
return path13.resolve(cwd, configured);
|
|
9473
|
+
}
|
|
9474
|
+
return path13.resolve(cwd, FALLBACK);
|
|
9475
|
+
}
|
|
9476
|
+
function resolveEventsDir(ctx) {
|
|
9477
|
+
return resolveEventsDirFromConfig(ctx.cwd, ctx.config);
|
|
9478
|
+
}
|
|
9479
|
+
|
|
9480
|
+
// src/cli/ui/output.ts
|
|
9481
|
+
var MAX_ERROR_LEN = 500;
|
|
9482
|
+
function printSuccess(msg) {
|
|
9483
|
+
if (isJsonMode()) return;
|
|
9484
|
+
console.log(`${theme.success(icons.success)} ${msg}`);
|
|
9485
|
+
}
|
|
9486
|
+
function printError(msg) {
|
|
9487
|
+
if (isJsonMode()) return;
|
|
9488
|
+
const truncated = msg.length > MAX_ERROR_LEN ? msg.slice(0, MAX_ERROR_LEN) + "\u2026" : msg;
|
|
9489
|
+
console.error(`${theme.error(icons.error)} ${truncated}`);
|
|
9490
|
+
}
|
|
9491
|
+
function printWarning(msg) {
|
|
9492
|
+
if (isJsonMode()) return;
|
|
9493
|
+
console.warn(`${theme.warning(icons.warning)} ${msg}`);
|
|
9269
9494
|
}
|
|
9270
9495
|
function printInfo(msg) {
|
|
9271
9496
|
if (isJsonMode()) return;
|
|
@@ -9275,10 +9500,10 @@ function printInfo(msg) {
|
|
|
9275
9500
|
// src/cli/commands/entity.ts
|
|
9276
9501
|
function resolveProvidersDir(ctx) {
|
|
9277
9502
|
const fromConfig = ctx.config?.paths?.providers;
|
|
9278
|
-
return fromConfig != null ?
|
|
9503
|
+
return fromConfig != null ? path14.resolve(ctx.cwd, fromConfig) : path14.resolve(ctx.cwd, "definitions/providers");
|
|
9279
9504
|
}
|
|
9280
9505
|
function listEntityYamls2(dir, providersDir) {
|
|
9281
|
-
if (!
|
|
9506
|
+
if (!fs10.existsSync(dir)) return [];
|
|
9282
9507
|
return findYamlFiles(dir, {
|
|
9283
9508
|
excludeDirs: providersDir ? [providersDir] : []
|
|
9284
9509
|
});
|
|
@@ -9357,11 +9582,11 @@ async function hints(ctx) {
|
|
|
9357
9582
|
{ command: "codegen entity validate", description: "Validate YAML definitions" },
|
|
9358
9583
|
{ command: "codegen entity list", description: "List entities as a table" }
|
|
9359
9584
|
];
|
|
9360
|
-
const providersDir = ctx.config?.paths?.providers != null ?
|
|
9585
|
+
const providersDir = ctx.config?.paths?.providers != null ? path14.resolve(
|
|
9361
9586
|
ctx.cwd,
|
|
9362
9587
|
ctx.config.paths.providers
|
|
9363
|
-
) :
|
|
9364
|
-
if (
|
|
9588
|
+
) : path14.resolve(ctx.cwd, "definitions/providers");
|
|
9589
|
+
if (fs10.existsSync(providersDir)) {
|
|
9365
9590
|
baseHints.push({
|
|
9366
9591
|
command: "codegen entity new --all",
|
|
9367
9592
|
description: "Regenerate provider modules + adapter scaffolds (Track D)"
|
|
@@ -9416,14 +9641,14 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9416
9641
|
}
|
|
9417
9642
|
let targets = [];
|
|
9418
9643
|
if (this.all) {
|
|
9419
|
-
const dir = ctx.entitiesDir ??
|
|
9644
|
+
const dir = ctx.entitiesDir ?? path14.resolve(ctx.cwd, "entities");
|
|
9420
9645
|
targets = listEntityYamls2(dir, resolveProvidersDir(ctx));
|
|
9421
9646
|
if (targets.length === 0) {
|
|
9422
9647
|
printError(`No entity YAML files found in ${dir}`);
|
|
9423
9648
|
return 1;
|
|
9424
9649
|
}
|
|
9425
9650
|
} else if (this.yaml) {
|
|
9426
|
-
targets = [
|
|
9651
|
+
targets = [path14.resolve(ctx.cwd, this.yaml)];
|
|
9427
9652
|
} else {
|
|
9428
9653
|
printError("Missing YAML path. Pass a file or --all.");
|
|
9429
9654
|
return 2;
|
|
@@ -9440,7 +9665,7 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9440
9665
|
}
|
|
9441
9666
|
if (invalid.length > 0 && !this.continueOnError) {
|
|
9442
9667
|
for (const i of invalid) {
|
|
9443
|
-
printError(`${
|
|
9668
|
+
printError(`${path14.basename(i.file)} \u2014 ${i.message}`);
|
|
9444
9669
|
for (const detail of i.details ?? []) {
|
|
9445
9670
|
printError(` \u2022 ${detail}`);
|
|
9446
9671
|
}
|
|
@@ -9449,7 +9674,7 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9449
9674
|
return 1;
|
|
9450
9675
|
}
|
|
9451
9676
|
}
|
|
9452
|
-
const entitiesDirForEmits = ctx.entitiesDir ??
|
|
9677
|
+
const entitiesDirForEmits = ctx.entitiesDir ?? path14.resolve(ctx.cwd, "entities");
|
|
9453
9678
|
const eventsDirForEmits = resolveEventsDir(ctx);
|
|
9454
9679
|
const allEntitiesForEmits = loadEntities(entitiesDirForEmits, {
|
|
9455
9680
|
excludeDirs: [resolveProvidersDir(ctx)]
|
|
@@ -9498,34 +9723,35 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9498
9723
|
if (!isJsonMode()) return 1;
|
|
9499
9724
|
}
|
|
9500
9725
|
}
|
|
9501
|
-
const entitiesDir = ctx.entitiesDir ??
|
|
9502
|
-
const relationshipsDir =
|
|
9726
|
+
const entitiesDir = ctx.entitiesDir ?? path14.resolve(ctx.cwd, "entities");
|
|
9727
|
+
const relationshipsDir = path14.resolve(ctx.cwd, "relationships");
|
|
9503
9728
|
const generatedDir = resolveGeneratedDir(ctx);
|
|
9504
9729
|
const architecture = resolveArchitecture(ctx);
|
|
9505
9730
|
const subsystemsRoot = resolveSubsystemsRoot(ctx);
|
|
9506
|
-
const scopeEntityTypePath =
|
|
9731
|
+
const scopeEntityTypePath = path14.resolve(
|
|
9507
9732
|
subsystemsRoot,
|
|
9508
9733
|
"jobs/generated/scope-entity-type.ts"
|
|
9509
9734
|
);
|
|
9510
9735
|
const eventsDir = resolveEventsDir(ctx);
|
|
9511
|
-
const eventCodegenOutputDir =
|
|
9736
|
+
const eventCodegenOutputDir = path14.resolve(
|
|
9512
9737
|
subsystemsRoot,
|
|
9513
9738
|
"events/generated"
|
|
9514
9739
|
);
|
|
9515
|
-
const bridgeRegistryOutputDir =
|
|
9740
|
+
const bridgeRegistryOutputDir = path14.resolve(
|
|
9516
9741
|
subsystemsRoot,
|
|
9517
9742
|
"bridge/generated"
|
|
9518
9743
|
);
|
|
9519
9744
|
const backendSrcForHandlers = ctx.config?.paths?.backend_src ?? "src";
|
|
9520
|
-
const
|
|
9745
|
+
const runtimeMode = resolveRuntimeMode(ctx.config);
|
|
9746
|
+
const bridgeHandlersDir = path14.resolve(
|
|
9521
9747
|
ctx.cwd,
|
|
9522
9748
|
backendSrcForHandlers,
|
|
9523
9749
|
"jobs"
|
|
9524
9750
|
);
|
|
9525
9751
|
const orchestrationConfigured = ctx.config?.paths?.orchestration_src;
|
|
9526
|
-
const orchestrationOutputRoot =
|
|
9752
|
+
const orchestrationOutputRoot = path14.resolve(
|
|
9527
9753
|
ctx.cwd,
|
|
9528
|
-
typeof orchestrationConfigured === "string" && orchestrationConfigured.length > 0 ? orchestrationConfigured :
|
|
9754
|
+
typeof orchestrationConfigured === "string" && orchestrationConfigured.length > 0 ? orchestrationConfigured : path14.join(backendSrcForHandlers, "orchestration")
|
|
9529
9755
|
);
|
|
9530
9756
|
const orchestrationGlobs = (() => {
|
|
9531
9757
|
const fromCfg = ctx.config?.patterns;
|
|
@@ -9653,7 +9879,7 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9653
9879
|
}
|
|
9654
9880
|
if (invalid.length > 0) {
|
|
9655
9881
|
for (const i of invalid) {
|
|
9656
|
-
printWarning(`${
|
|
9882
|
+
printWarning(`${path14.basename(i.file)} \u2014 ${i.message}`);
|
|
9657
9883
|
}
|
|
9658
9884
|
}
|
|
9659
9885
|
console.log("");
|
|
@@ -9671,7 +9897,7 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9671
9897
|
}
|
|
9672
9898
|
const succeeded = [];
|
|
9673
9899
|
const failed = [
|
|
9674
|
-
...invalid.map((i) => ({ name:
|
|
9900
|
+
...invalid.map((i) => ({ name: path14.basename(i.file), file: i.file, message: i.message }))
|
|
9675
9901
|
];
|
|
9676
9902
|
for (const v of validated) {
|
|
9677
9903
|
if (!isJsonMode()) {
|
|
@@ -9714,6 +9940,14 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9714
9940
|
printWarning(`subsystem barrel regeneration failed \u2014 ${msg}`);
|
|
9715
9941
|
}
|
|
9716
9942
|
}
|
|
9943
|
+
try {
|
|
9944
|
+
await regenerateSubsystemSchemaBarrel({ ctx, generatedDir });
|
|
9945
|
+
} catch (err) {
|
|
9946
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
9947
|
+
if (!isJsonMode()) {
|
|
9948
|
+
printWarning(`subsystem schema barrel regeneration failed \u2014 ${msg}`);
|
|
9949
|
+
}
|
|
9950
|
+
}
|
|
9717
9951
|
let scopeResult = null;
|
|
9718
9952
|
try {
|
|
9719
9953
|
scopeResult = await generateScopeEntityType({
|
|
@@ -9786,12 +10020,12 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9786
10020
|
let providerResult = null;
|
|
9787
10021
|
try {
|
|
9788
10022
|
const providersDir = resolveProvidersDir(ctx);
|
|
9789
|
-
const providerOutputRoot =
|
|
10023
|
+
const providerOutputRoot = path14.resolve(
|
|
9790
10024
|
ctx.cwd,
|
|
9791
10025
|
backendSrcForHandlers,
|
|
9792
10026
|
"integrations/providers"
|
|
9793
10027
|
);
|
|
9794
|
-
const entitySurfaces =
|
|
10028
|
+
const entitySurfaces = fs10.existsSync(entitiesDir) ? collectEntitySurfaces(
|
|
9795
10029
|
loadEntitiesFromYaml(
|
|
9796
10030
|
findYamlFiles(entitiesDir, { excludeDirs: [providersDir] })
|
|
9797
10031
|
).successes.map((s) => s.definition)
|
|
@@ -9803,7 +10037,8 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9803
10037
|
entitySurfaces,
|
|
9804
10038
|
sourceRoot: tsAliases?.sourceRoot,
|
|
9805
10039
|
aliases: tsAliases?.aliases,
|
|
9806
|
-
skipImportCheck: tsAliases === null
|
|
10040
|
+
skipImportCheck: tsAliases === null,
|
|
10041
|
+
mode: runtimeMode
|
|
9807
10042
|
});
|
|
9808
10043
|
if (!providerResult.skipped && !isJsonMode()) {
|
|
9809
10044
|
for (const issue of providerResult.issues) {
|
|
@@ -9827,12 +10062,12 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9827
10062
|
try {
|
|
9828
10063
|
if (providerResult && !providerResult.skipped && providerResult.issues.length === 0) {
|
|
9829
10064
|
const providersDir = providerResult.providersDir;
|
|
9830
|
-
const adapterOutputRoot =
|
|
10065
|
+
const adapterOutputRoot = path14.resolve(
|
|
9831
10066
|
ctx.cwd,
|
|
9832
10067
|
backendSrcForHandlers,
|
|
9833
10068
|
"integrations"
|
|
9834
10069
|
);
|
|
9835
|
-
const entityDefs =
|
|
10070
|
+
const entityDefs = fs10.existsSync(entitiesDir) ? loadEntitiesFromYaml(
|
|
9836
10071
|
findYamlFiles(entitiesDir, { excludeDirs: [providersDir] })
|
|
9837
10072
|
).successes.map((s) => s.definition) : [];
|
|
9838
10073
|
const loadedProviders = loadProvidersFromYaml(
|
|
@@ -9846,8 +10081,9 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9846
10081
|
providers: loadedProviders,
|
|
9847
10082
|
entities: entityDefs,
|
|
9848
10083
|
outputRoot: adapterOutputRoot,
|
|
9849
|
-
backendSrcAbs:
|
|
9850
|
-
aliases: assemblyTsAliases?.aliases ?? {}
|
|
10084
|
+
backendSrcAbs: path14.resolve(ctx.cwd, backendSrcForHandlers),
|
|
10085
|
+
aliases: assemblyTsAliases?.aliases ?? {},
|
|
10086
|
+
mode: runtimeMode
|
|
9851
10087
|
});
|
|
9852
10088
|
if (!isJsonMode()) {
|
|
9853
10089
|
if (adapterResult.written.length || adapterResult.scaffoldsWritten.length) {
|
|
@@ -9947,22 +10183,22 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9947
10183
|
}
|
|
9948
10184
|
if (barrelResult) {
|
|
9949
10185
|
printInfo(
|
|
9950
|
-
`barrels regenerated (${barrelResult.entityCount} entities) \u2192 ${
|
|
10186
|
+
`barrels regenerated (${barrelResult.entityCount} entities) \u2192 ${path14.relative(ctx.cwd, barrelResult.modulesBarrel)}, ${path14.relative(ctx.cwd, barrelResult.schemaBarrel)}`
|
|
9951
10187
|
);
|
|
9952
10188
|
}
|
|
9953
10189
|
if (scopeResult) {
|
|
9954
10190
|
printInfo(
|
|
9955
|
-
`scope-entity-type regenerated (${scopeResult.scopeableNames.length} scopeable) \u2192 ${
|
|
10191
|
+
`scope-entity-type regenerated (${scopeResult.scopeableNames.length} scopeable) \u2192 ${path14.relative(ctx.cwd, scopeResult.outputPath)}`
|
|
9956
10192
|
);
|
|
9957
10193
|
}
|
|
9958
10194
|
if (eventCodegenResult) {
|
|
9959
10195
|
printInfo(
|
|
9960
|
-
`event codegen regenerated (${eventCodegenResult.eventCount} events) \u2192 ${
|
|
10196
|
+
`event codegen regenerated (${eventCodegenResult.eventCount} events) \u2192 ${path14.relative(ctx.cwd, eventCodegenResult.outputDir)}`
|
|
9961
10197
|
);
|
|
9962
10198
|
}
|
|
9963
10199
|
if (orchestrationResult && orchestrationResult.patterns.length > 0) {
|
|
9964
10200
|
printInfo(
|
|
9965
|
-
`orchestration regenerated (${orchestrationResult.patterns.length} patterns, ${orchestrationResult.files.length} files) \u2192 ${
|
|
10201
|
+
`orchestration regenerated (${orchestrationResult.patterns.length} patterns, ${orchestrationResult.files.length} files) \u2192 ${path14.relative(ctx.cwd, orchestrationResult.outputRoot)}`
|
|
9966
10202
|
);
|
|
9967
10203
|
}
|
|
9968
10204
|
}
|
|
@@ -10048,8 +10284,8 @@ var EntityValidateCommand = class extends Command2 {
|
|
|
10048
10284
|
json: this.json,
|
|
10049
10285
|
skipDetection: true
|
|
10050
10286
|
});
|
|
10051
|
-
const targetDir = this.dir ?
|
|
10052
|
-
if (!
|
|
10287
|
+
const targetDir = this.dir ? path14.resolve(ctx.cwd, this.dir) : ctx.entitiesDir ?? path14.resolve(ctx.cwd, "entities");
|
|
10288
|
+
if (!fs10.existsSync(targetDir)) {
|
|
10053
10289
|
printError(`Directory not found: ${targetDir}`);
|
|
10054
10290
|
return 1;
|
|
10055
10291
|
}
|
|
@@ -10100,8 +10336,8 @@ var entityNoun = {
|
|
|
10100
10336
|
var entity_default = entityNoun;
|
|
10101
10337
|
|
|
10102
10338
|
// src/cli/commands/subsystem.ts
|
|
10103
|
-
import
|
|
10104
|
-
import
|
|
10339
|
+
import fs13 from "fs";
|
|
10340
|
+
import path24 from "path";
|
|
10105
10341
|
import { Command as Command3, Option as Option3 } from "clipanion";
|
|
10106
10342
|
|
|
10107
10343
|
// src/cli/shared/config-block-detect.ts
|
|
@@ -10134,26 +10370,26 @@ function stripConfigBlock(yamlSource, subsystem) {
|
|
|
10134
10370
|
}
|
|
10135
10371
|
|
|
10136
10372
|
// src/cli/shared/events-scaffold-locals.ts
|
|
10137
|
-
import
|
|
10373
|
+
import path15 from "path";
|
|
10138
10374
|
function resolveEventsScaffoldLocals(input) {
|
|
10139
10375
|
const { cwd, config } = input;
|
|
10140
10376
|
void input.fileExists;
|
|
10141
10377
|
const eventsBlock = config?.events ?? {};
|
|
10142
10378
|
const subsystemsRoot = resolveSubsystemsRootFromConfig(cwd, config);
|
|
10143
|
-
const configPath =
|
|
10144
|
-
const schemaPath =
|
|
10379
|
+
const configPath = path15.resolve(cwd, "codegen.config.yaml");
|
|
10380
|
+
const schemaPath = path15.resolve(
|
|
10145
10381
|
subsystemsRoot,
|
|
10146
10382
|
"events",
|
|
10147
10383
|
"domain-events.schema.ts"
|
|
10148
10384
|
);
|
|
10149
|
-
const generatedKeepPath =
|
|
10385
|
+
const generatedKeepPath = path15.resolve(
|
|
10150
10386
|
subsystemsRoot,
|
|
10151
10387
|
"events",
|
|
10152
10388
|
"generated",
|
|
10153
10389
|
".gitkeep"
|
|
10154
10390
|
);
|
|
10155
10391
|
return {
|
|
10156
|
-
appName:
|
|
10392
|
+
appName: path15.basename(cwd),
|
|
10157
10393
|
multiTenant: normaliseMultiTenant(eventsBlock.multi_tenant),
|
|
10158
10394
|
configPath,
|
|
10159
10395
|
schemaPath,
|
|
@@ -10179,7 +10415,7 @@ function localsToHygenArgs(locals) {
|
|
|
10179
10415
|
}
|
|
10180
10416
|
|
|
10181
10417
|
// src/cli/shared/jobs-scaffold-locals.ts
|
|
10182
|
-
import
|
|
10418
|
+
import path16 from "path";
|
|
10183
10419
|
var MAIN_HOOK_SENTINEL = "JOBS \u2014 Embedded worker mode (optional)";
|
|
10184
10420
|
function workerSkipValue(exists) {
|
|
10185
10421
|
return exists ? "true" : "";
|
|
@@ -10188,10 +10424,10 @@ function resolveJobsScaffoldLocals(input) {
|
|
|
10188
10424
|
const { cwd, config, fileExists, readFile } = input;
|
|
10189
10425
|
const jobsBlock = config?.jobs ?? {};
|
|
10190
10426
|
const subsystemsRoot = resolveSubsystemsRootFromConfig(cwd, config);
|
|
10191
|
-
const workerPath =
|
|
10192
|
-
const mainTsPath =
|
|
10193
|
-
const configPath =
|
|
10194
|
-
const schemaPath =
|
|
10427
|
+
const workerPath = path16.resolve(cwd, "worker.ts");
|
|
10428
|
+
const mainTsPath = path16.resolve(cwd, "src/main.ts");
|
|
10429
|
+
const configPath = path16.resolve(cwd, "codegen.config.yaml");
|
|
10430
|
+
const schemaPath = path16.resolve(
|
|
10195
10431
|
subsystemsRoot,
|
|
10196
10432
|
"jobs",
|
|
10197
10433
|
"job-orchestration.schema.ts"
|
|
@@ -10199,7 +10435,7 @@ function resolveJobsScaffoldLocals(input) {
|
|
|
10199
10435
|
const mainContent = readFile(mainTsPath);
|
|
10200
10436
|
const mainHookInjected = mainContent !== null && mainContent.includes(MAIN_HOOK_SENTINEL);
|
|
10201
10437
|
return {
|
|
10202
|
-
appName:
|
|
10438
|
+
appName: path16.basename(cwd),
|
|
10203
10439
|
workerMode: normaliseWorkerMode(jobsBlock.worker_mode),
|
|
10204
10440
|
multiTenant: normaliseMultiTenant2(jobsBlock.multi_tenant),
|
|
10205
10441
|
mainTsPath,
|
|
@@ -10241,20 +10477,20 @@ function localsToHygenArgs2(locals) {
|
|
|
10241
10477
|
}
|
|
10242
10478
|
|
|
10243
10479
|
// src/cli/shared/integration-scaffold-locals.ts
|
|
10244
|
-
import
|
|
10480
|
+
import path17 from "path";
|
|
10245
10481
|
function resolveIntegrationScaffoldLocals(input) {
|
|
10246
10482
|
const { cwd, config } = input;
|
|
10247
10483
|
void input.fileExists;
|
|
10248
10484
|
const integrationBlock = config?.integration ?? {};
|
|
10249
10485
|
const subsystemsRoot = resolveSubsystemsRootFromConfig(cwd, config);
|
|
10250
|
-
const configPath =
|
|
10251
|
-
const schemaPath =
|
|
10486
|
+
const configPath = path17.resolve(cwd, "codegen.config.yaml");
|
|
10487
|
+
const schemaPath = path17.resolve(
|
|
10252
10488
|
subsystemsRoot,
|
|
10253
10489
|
"integration",
|
|
10254
10490
|
"integration-audit.schema.ts"
|
|
10255
10491
|
);
|
|
10256
10492
|
return {
|
|
10257
|
-
appName:
|
|
10493
|
+
appName: path17.basename(cwd),
|
|
10258
10494
|
multiTenant: normaliseMultiTenant3(integrationBlock.multi_tenant),
|
|
10259
10495
|
configPath,
|
|
10260
10496
|
schemaPath
|
|
@@ -10277,21 +10513,21 @@ function localsToHygenArgs3(locals) {
|
|
|
10277
10513
|
}
|
|
10278
10514
|
|
|
10279
10515
|
// src/cli/shared/bridge-scaffold-locals.ts
|
|
10280
|
-
import
|
|
10516
|
+
import path18 from "path";
|
|
10281
10517
|
function resolveBridgeScaffoldLocals(input) {
|
|
10282
10518
|
const { cwd, config } = input;
|
|
10283
10519
|
void input.fileExists;
|
|
10284
10520
|
const bridgeBlock = config?.bridge ?? {};
|
|
10285
10521
|
const subsystemsRoot = resolveSubsystemsRootFromConfig(cwd, config);
|
|
10286
|
-
const configPath =
|
|
10287
|
-
const generatedKeepPath =
|
|
10522
|
+
const configPath = path18.resolve(cwd, "codegen.config.yaml");
|
|
10523
|
+
const generatedKeepPath = path18.resolve(
|
|
10288
10524
|
subsystemsRoot,
|
|
10289
10525
|
"bridge",
|
|
10290
10526
|
"generated",
|
|
10291
10527
|
".gitkeep"
|
|
10292
10528
|
);
|
|
10293
10529
|
return {
|
|
10294
|
-
appName:
|
|
10530
|
+
appName: path18.basename(cwd),
|
|
10295
10531
|
multiTenant: normaliseMultiTenant4(bridgeBlock.multi_tenant),
|
|
10296
10532
|
configPath,
|
|
10297
10533
|
generatedKeepPath
|
|
@@ -10314,19 +10550,19 @@ function localsToHygenArgs4(locals) {
|
|
|
10314
10550
|
}
|
|
10315
10551
|
|
|
10316
10552
|
// src/cli/shared/observability-scaffold-locals.ts
|
|
10317
|
-
import
|
|
10553
|
+
import path19 from "path";
|
|
10318
10554
|
var FALLBACK_BACKEND_SRC2 = "src";
|
|
10319
10555
|
function resolveObservabilityScaffoldLocals(input) {
|
|
10320
10556
|
const { cwd, config } = input;
|
|
10321
10557
|
void input.fileExists;
|
|
10322
10558
|
const backendSrc = typeof config?.paths?.backend_src === "string" && config.paths.backend_src.length > 0 ? config.paths.backend_src : FALLBACK_BACKEND_SRC2;
|
|
10323
|
-
const appModulePath =
|
|
10324
|
-
const configPath =
|
|
10559
|
+
const appModulePath = path19.resolve(cwd, backendSrc, "app.module.ts");
|
|
10560
|
+
const configPath = path19.resolve(cwd, "codegen.config.yaml");
|
|
10325
10561
|
const obsBlock = config?.observability ?? {};
|
|
10326
10562
|
const reporters = obsBlock.reporters ?? {};
|
|
10327
10563
|
const bridgeMetrics = reporters.bridgeMetrics ?? {};
|
|
10328
10564
|
return {
|
|
10329
|
-
appName:
|
|
10565
|
+
appName: path19.basename(cwd),
|
|
10330
10566
|
appModulePath,
|
|
10331
10567
|
configPath,
|
|
10332
10568
|
bridgeMetricsEnabled: bridgeMetrics.enabled === true
|
|
@@ -10347,7 +10583,7 @@ function localsToHygenArgs5(locals) {
|
|
|
10347
10583
|
|
|
10348
10584
|
// src/cli/shared/auth-scaffold-locals.ts
|
|
10349
10585
|
import crypto2 from "crypto";
|
|
10350
|
-
import
|
|
10586
|
+
import path20 from "path";
|
|
10351
10587
|
var FALLBACK_BACKEND_SRC3 = "src";
|
|
10352
10588
|
var DEFAULT_REDIRECT_URI_BASE = "http://localhost:3000";
|
|
10353
10589
|
function resolveAuthScaffoldLocals(input) {
|
|
@@ -10359,15 +10595,15 @@ function resolveAuthScaffoldLocals(input) {
|
|
|
10359
10595
|
const redirectUriBase = typeof redirectRaw === "string" && redirectRaw.length > 0 ? redirectRaw : DEFAULT_REDIRECT_URI_BASE;
|
|
10360
10596
|
const tokenEncryptionKey = crypto2.randomBytes(32).toString("base64");
|
|
10361
10597
|
return {
|
|
10362
|
-
appName:
|
|
10363
|
-
configPath:
|
|
10364
|
-
schemaPath:
|
|
10598
|
+
appName: path20.basename(cwd),
|
|
10599
|
+
configPath: path20.resolve(cwd, "codegen.config.yaml"),
|
|
10600
|
+
schemaPath: path20.resolve(
|
|
10365
10601
|
subsystemsRoot,
|
|
10366
10602
|
"auth",
|
|
10367
10603
|
"auth-oauth-state.schema.ts"
|
|
10368
10604
|
),
|
|
10369
|
-
appModulePath:
|
|
10370
|
-
envConfigPath:
|
|
10605
|
+
appModulePath: path20.resolve(cwd, backendSrc, "app.module.ts"),
|
|
10606
|
+
envConfigPath: path20.resolve(cwd, ".env.config"),
|
|
10371
10607
|
redirectUriBase,
|
|
10372
10608
|
tokenEncryptionKey
|
|
10373
10609
|
};
|
|
@@ -10392,7 +10628,7 @@ function localsToHygenArgs6(locals) {
|
|
|
10392
10628
|
}
|
|
10393
10629
|
|
|
10394
10630
|
// src/cli/shared/auth-integrations-scaffold-locals.ts
|
|
10395
|
-
import
|
|
10631
|
+
import path21 from "path";
|
|
10396
10632
|
var FALLBACK_BACKEND_SRC4 = "src";
|
|
10397
10633
|
var DEFAULT_MODULES_DIR = "modules";
|
|
10398
10634
|
var DEFAULT_DEFINITIONS_DIR = "definitions/entities";
|
|
@@ -10401,17 +10637,17 @@ function resolveAuthIntegrationsScaffoldLocals(input) {
|
|
|
10401
10637
|
const backendSrc = typeof config?.paths?.backend_src === "string" && config.paths.backend_src.length > 0 ? config.paths.backend_src : FALLBACK_BACKEND_SRC4;
|
|
10402
10638
|
const pathsAny = config?.paths;
|
|
10403
10639
|
const modulesConfigured = pathsAny?.modules_dir;
|
|
10404
|
-
const vendorRoot = typeof modulesConfigured === "string" && modulesConfigured.length > 0 ?
|
|
10640
|
+
const vendorRoot = typeof modulesConfigured === "string" && modulesConfigured.length > 0 ? path21.resolve(cwd, modulesConfigured) : path21.resolve(cwd, backendSrc, DEFAULT_MODULES_DIR);
|
|
10405
10641
|
const entitiesConfigured = typeof pathsAny?.entities === "string" && pathsAny.entities.length > 0 ? pathsAny.entities : typeof pathsAny?.entities_dir === "string" && pathsAny.entities_dir.length > 0 ? pathsAny.entities_dir : null;
|
|
10406
|
-
const definitionsPath = entitiesConfigured !== null ?
|
|
10407
|
-
const appModulePath =
|
|
10642
|
+
const definitionsPath = entitiesConfigured !== null ? path21.resolve(cwd, entitiesConfigured, "connection.yaml") : path21.resolve(cwd, DEFAULT_DEFINITIONS_DIR, "connection.yaml");
|
|
10643
|
+
const appModulePath = path21.resolve(cwd, backendSrc, "app.module.ts");
|
|
10408
10644
|
let authModuleRegistered = false;
|
|
10409
10645
|
const appModuleSource = input.readFile(appModulePath);
|
|
10410
10646
|
if (appModuleSource && appModuleSource.includes("AuthModule.forRoot")) {
|
|
10411
10647
|
authModuleRegistered = true;
|
|
10412
10648
|
}
|
|
10413
10649
|
return {
|
|
10414
|
-
appName:
|
|
10650
|
+
appName: path21.basename(cwd),
|
|
10415
10651
|
appModulePath,
|
|
10416
10652
|
vendorRoot,
|
|
10417
10653
|
definitionsPath,
|
|
@@ -10428,11 +10664,11 @@ function localsToHygenArgs7(locals) {
|
|
|
10428
10664
|
}
|
|
10429
10665
|
|
|
10430
10666
|
// src/cli/shared/runtime-copier.ts
|
|
10431
|
-
import
|
|
10432
|
-
import
|
|
10667
|
+
import fs11 from "fs";
|
|
10668
|
+
import path22 from "path";
|
|
10433
10669
|
function readIfExists(p) {
|
|
10434
10670
|
try {
|
|
10435
|
-
return
|
|
10671
|
+
return fs11.readFileSync(p, "utf-8");
|
|
10436
10672
|
} catch {
|
|
10437
10673
|
return null;
|
|
10438
10674
|
}
|
|
@@ -10447,20 +10683,20 @@ function extractRelativeImports(source) {
|
|
|
10447
10683
|
return out;
|
|
10448
10684
|
}
|
|
10449
10685
|
function resolveSourceImport(sourceFile, specifier) {
|
|
10450
|
-
const base =
|
|
10451
|
-
const candidates = [base + ".ts", base + ".tsx",
|
|
10686
|
+
const base = path22.resolve(path22.dirname(sourceFile), specifier);
|
|
10687
|
+
const candidates = [base + ".ts", base + ".tsx", path22.join(base, "index.ts")];
|
|
10452
10688
|
for (const c of candidates) {
|
|
10453
|
-
if (
|
|
10689
|
+
if (fs11.existsSync(c)) return c;
|
|
10454
10690
|
}
|
|
10455
10691
|
return null;
|
|
10456
10692
|
}
|
|
10457
10693
|
async function copyRuntime(opts) {
|
|
10458
10694
|
const { sourceDir, targetDir, filter, resolveDeps, dryRun, onlyExisting } = opts;
|
|
10459
|
-
if (!
|
|
10695
|
+
if (!fs11.existsSync(sourceDir) || !fs11.statSync(sourceDir).isDirectory()) {
|
|
10460
10696
|
throw new Error(`runtime source directory not found: ${sourceDir}`);
|
|
10461
10697
|
}
|
|
10462
|
-
const runtimeRoot4 = opts.runtimeRoot ?
|
|
10463
|
-
const depsTargetRoot = opts.depsTargetRoot ??
|
|
10698
|
+
const runtimeRoot4 = opts.runtimeRoot ? path22.resolve(opts.runtimeRoot) : path22.resolve(sourceDir, "..", "..");
|
|
10699
|
+
const depsTargetRoot = opts.depsTargetRoot ?? path22.resolve(targetDir, "..");
|
|
10464
10700
|
const result = {
|
|
10465
10701
|
written: [],
|
|
10466
10702
|
updated: [],
|
|
@@ -10470,9 +10706,9 @@ async function copyRuntime(opts) {
|
|
|
10470
10706
|
};
|
|
10471
10707
|
const queue = [];
|
|
10472
10708
|
function walk(dir) {
|
|
10473
|
-
for (const entry of
|
|
10474
|
-
const src =
|
|
10475
|
-
const stat =
|
|
10709
|
+
for (const entry of fs11.readdirSync(dir)) {
|
|
10710
|
+
const src = path22.join(dir, entry);
|
|
10711
|
+
const stat = fs11.statSync(src);
|
|
10476
10712
|
if (stat.isDirectory()) {
|
|
10477
10713
|
if (entry === "generated") continue;
|
|
10478
10714
|
walk(src);
|
|
@@ -10480,9 +10716,9 @@ async function copyRuntime(opts) {
|
|
|
10480
10716
|
}
|
|
10481
10717
|
if (!stat.isFile()) continue;
|
|
10482
10718
|
if (!entry.endsWith(".ts") && !entry.endsWith(".tsx")) continue;
|
|
10483
|
-
const rel2 =
|
|
10719
|
+
const rel2 = path22.relative(sourceDir, src);
|
|
10484
10720
|
if (filter && !filter(rel2) && !filter(entry)) continue;
|
|
10485
|
-
queue.push({ src, dest:
|
|
10721
|
+
queue.push({ src, dest: path22.join(targetDir, rel2), isDep: false });
|
|
10486
10722
|
}
|
|
10487
10723
|
}
|
|
10488
10724
|
walk(sourceDir);
|
|
@@ -10491,10 +10727,10 @@ async function copyRuntime(opts) {
|
|
|
10491
10727
|
const next = queue.shift();
|
|
10492
10728
|
if (visited.has(next.src)) continue;
|
|
10493
10729
|
visited.add(next.src);
|
|
10494
|
-
if (onlyExisting && !
|
|
10730
|
+
if (onlyExisting && !fs11.existsSync(next.dest)) {
|
|
10495
10731
|
continue;
|
|
10496
10732
|
}
|
|
10497
|
-
const content =
|
|
10733
|
+
const content = fs11.readFileSync(next.src, "utf-8");
|
|
10498
10734
|
result.planned.push(next.dest);
|
|
10499
10735
|
const existing = readIfExists(next.dest);
|
|
10500
10736
|
const status = existing === content ? "unchanged" : existing === null ? "written" : "updated";
|
|
@@ -10503,18 +10739,18 @@ async function copyRuntime(opts) {
|
|
|
10503
10739
|
else result.unchanged.push(next.dest);
|
|
10504
10740
|
if (next.isDep) result.dependenciesCopied.push(next.dest);
|
|
10505
10741
|
if (!dryRun && status !== "unchanged") {
|
|
10506
|
-
|
|
10507
|
-
|
|
10742
|
+
fs11.mkdirSync(path22.dirname(next.dest), { recursive: true });
|
|
10743
|
+
fs11.writeFileSync(next.dest, content);
|
|
10508
10744
|
}
|
|
10509
10745
|
if (resolveDeps) {
|
|
10510
10746
|
for (const spec of extractRelativeImports(content)) {
|
|
10511
10747
|
const resolvedSrc = resolveSourceImport(next.src, spec);
|
|
10512
10748
|
if (!resolvedSrc) continue;
|
|
10513
|
-
const relToRuntime =
|
|
10514
|
-
if (relToRuntime.startsWith("..") ||
|
|
10515
|
-
const relToSource =
|
|
10516
|
-
if (!relToSource.startsWith("..") && !
|
|
10517
|
-
const depDest =
|
|
10749
|
+
const relToRuntime = path22.relative(runtimeRoot4, resolvedSrc);
|
|
10750
|
+
if (relToRuntime.startsWith("..") || path22.isAbsolute(relToRuntime)) continue;
|
|
10751
|
+
const relToSource = path22.relative(sourceDir, resolvedSrc);
|
|
10752
|
+
if (!relToSource.startsWith("..") && !path22.isAbsolute(relToSource)) continue;
|
|
10753
|
+
const depDest = path22.join(depsTargetRoot, relToRuntime);
|
|
10518
10754
|
queue.push({ src: resolvedSrc, dest: depDest, isDep: true });
|
|
10519
10755
|
}
|
|
10520
10756
|
}
|
|
@@ -10522,19 +10758,87 @@ async function copyRuntime(opts) {
|
|
|
10522
10758
|
return result;
|
|
10523
10759
|
}
|
|
10524
10760
|
|
|
10761
|
+
// src/cli/shared/subsystems-install-config.ts
|
|
10762
|
+
import fs12 from "fs";
|
|
10763
|
+
import path23 from "path";
|
|
10764
|
+
import yaml2 from "yaml";
|
|
10765
|
+
function readInstallList(config) {
|
|
10766
|
+
const raw = config?.subsystems?.install;
|
|
10767
|
+
if (!Array.isArray(raw)) return [];
|
|
10768
|
+
return raw.filter((e) => typeof e === "string");
|
|
10769
|
+
}
|
|
10770
|
+
function ensureSubsystemInstalled(configPath, name) {
|
|
10771
|
+
if (!fs12.existsSync(configPath)) {
|
|
10772
|
+
fs12.mkdirSync(path23.dirname(configPath), { recursive: true });
|
|
10773
|
+
fs12.writeFileSync(
|
|
10774
|
+
configPath,
|
|
10775
|
+
`subsystems:
|
|
10776
|
+
install:
|
|
10777
|
+
- ${name}
|
|
10778
|
+
`,
|
|
10779
|
+
"utf-8"
|
|
10780
|
+
);
|
|
10781
|
+
return { outcome: "added", install: [name] };
|
|
10782
|
+
}
|
|
10783
|
+
const source = fs12.readFileSync(configPath, "utf-8");
|
|
10784
|
+
let doc;
|
|
10785
|
+
try {
|
|
10786
|
+
doc = yaml2.parseDocument(source);
|
|
10787
|
+
if (doc.errors.length > 0) {
|
|
10788
|
+
return { outcome: "parse-error", install: [] };
|
|
10789
|
+
}
|
|
10790
|
+
} catch {
|
|
10791
|
+
return { outcome: "parse-error", install: [] };
|
|
10792
|
+
}
|
|
10793
|
+
const current = readInstallList(
|
|
10794
|
+
doc.toJS()
|
|
10795
|
+
);
|
|
10796
|
+
if (current.includes(name)) {
|
|
10797
|
+
return { outcome: "already", install: current };
|
|
10798
|
+
}
|
|
10799
|
+
const subsystemsNode = doc.get("subsystems", true);
|
|
10800
|
+
const installSeq = subsystemsNode && typeof subsystemsNode.get === "function" ? subsystemsNode.get("install", true) : void 0;
|
|
10801
|
+
if (installSeq && Array.isArray(installSeq.items) && installSeq.items.length > 0) {
|
|
10802
|
+
const lastItem = installSeq.items[installSeq.items.length - 1];
|
|
10803
|
+
const range = lastItem.range;
|
|
10804
|
+
if (range) {
|
|
10805
|
+
const insertAt = range[1];
|
|
10806
|
+
const lineStart = source.lastIndexOf("\n", range[0]) + 1;
|
|
10807
|
+
const indent = source.slice(lineStart, range[0]).match(/^\s*/)?.[0] ?? " ";
|
|
10808
|
+
const before = source.slice(0, insertAt);
|
|
10809
|
+
const after = source.slice(insertAt);
|
|
10810
|
+
const next = `${before}
|
|
10811
|
+
${indent}- ${name}${after}`;
|
|
10812
|
+
fs12.writeFileSync(configPath, next, "utf-8");
|
|
10813
|
+
return { outcome: "added", install: [...current, name] };
|
|
10814
|
+
}
|
|
10815
|
+
}
|
|
10816
|
+
doc.setIn(["subsystems", "install"], [...current, name]);
|
|
10817
|
+
fs12.writeFileSync(configPath, String(doc), "utf-8");
|
|
10818
|
+
return { outcome: "added", install: [...current, name] };
|
|
10819
|
+
}
|
|
10820
|
+
|
|
10525
10821
|
// src/cli/commands/subsystem.ts
|
|
10526
10822
|
function runtimeRoot() {
|
|
10527
|
-
const pkgRoot =
|
|
10528
|
-
const topLevel =
|
|
10529
|
-
if (
|
|
10530
|
-
return
|
|
10823
|
+
const pkgRoot = path24.resolve(import.meta.dirname, "..", "..", "..");
|
|
10824
|
+
const topLevel = path24.join(pkgRoot, "runtime");
|
|
10825
|
+
if (fs13.existsSync(topLevel)) return topLevel;
|
|
10826
|
+
return path24.join(pkgRoot, "dist", "runtime");
|
|
10531
10827
|
}
|
|
10532
10828
|
function subsystemSource(name) {
|
|
10533
|
-
return
|
|
10829
|
+
return path24.join(runtimeRoot(), "subsystems", name);
|
|
10534
10830
|
}
|
|
10535
10831
|
function describeSubsystem(name) {
|
|
10536
10832
|
return SUBSYSTEMS.find((s) => s.name === name) ?? null;
|
|
10537
10833
|
}
|
|
10834
|
+
var PACKAGE_CONFIG_BLOCK = {
|
|
10835
|
+
events: { detector: "events", actionFolder: "events-config" },
|
|
10836
|
+
jobs: { detector: "jobs", actionFolder: "jobs-config" },
|
|
10837
|
+
integration: { detector: "integration", actionFolder: "integration-config" },
|
|
10838
|
+
bridge: { detector: "bridge", actionFolder: "bridge-config" },
|
|
10839
|
+
observability: { detector: "observability", actionFolder: "observability-config" },
|
|
10840
|
+
auth: { detector: "auth", actionFolder: "auth-config" }
|
|
10841
|
+
};
|
|
10538
10842
|
async function summary2(ctx) {
|
|
10539
10843
|
const installed = await detectInstalledSubsystems(ctx);
|
|
10540
10844
|
const installedNames = new Set(installed.map((i) => i.name));
|
|
@@ -10557,7 +10861,7 @@ async function summary2(ctx) {
|
|
|
10557
10861
|
}
|
|
10558
10862
|
body.push(theme.muted("Installed:"));
|
|
10559
10863
|
for (const i of installed) {
|
|
10560
|
-
const rel2 =
|
|
10864
|
+
const rel2 = path24.relative(ctx.cwd, i.path) || i.path;
|
|
10561
10865
|
body.push(
|
|
10562
10866
|
` ${theme.success(icons.check)} ${i.name.padEnd(10)} ${theme.muted(
|
|
10563
10867
|
`${i.backend} backend`
|
|
@@ -10680,6 +10984,9 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
10680
10984
|
if (desc3.name === "auth-integrations") {
|
|
10681
10985
|
return this.executeAuthIntegrations(ctx);
|
|
10682
10986
|
}
|
|
10987
|
+
if (resolveRuntimeMode(ctx.config) === "package") {
|
|
10988
|
+
return this.executePackageMode(ctx, desc3, backend);
|
|
10989
|
+
}
|
|
10683
10990
|
const installed = await detectInstalledSubsystems(ctx);
|
|
10684
10991
|
const already = installed.find((i) => i.name === desc3.name);
|
|
10685
10992
|
if (already && !this.force) {
|
|
@@ -10697,14 +11004,14 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
10697
11004
|
return 0;
|
|
10698
11005
|
}
|
|
10699
11006
|
const targetRoot = resolveSubsystemsRoot(ctx, this.target);
|
|
10700
|
-
const subsystemTarget =
|
|
11007
|
+
const subsystemTarget = path24.join(targetRoot, desc3.name);
|
|
10701
11008
|
const source = subsystemSource(desc3.name);
|
|
10702
|
-
if (!
|
|
11009
|
+
if (!fs13.existsSync(source)) {
|
|
10703
11010
|
printError(`Runtime subsystem source missing: ${source}`);
|
|
10704
11011
|
return 1;
|
|
10705
11012
|
}
|
|
10706
11013
|
if (!this.force) {
|
|
10707
|
-
const gitCheck = checkGitSafety([
|
|
11014
|
+
const gitCheck = checkGitSafety([path24.relative(ctx.cwd, subsystemTarget) || subsystemTarget], ctx.cwd);
|
|
10708
11015
|
if (gitCheck.inRepo && !gitCheck.clean) {
|
|
10709
11016
|
printWarning(
|
|
10710
11017
|
`Uncommitted changes under ${subsystemTarget}. Pass --force to overwrite.`
|
|
@@ -10713,7 +11020,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
10713
11020
|
}
|
|
10714
11021
|
}
|
|
10715
11022
|
if (!isJsonMode()) {
|
|
10716
|
-
printInfo(`target = ${
|
|
11023
|
+
printInfo(`target = ${path24.relative(ctx.cwd, subsystemTarget) || subsystemTarget}`);
|
|
10717
11024
|
printInfo(`backend = ${backend}`);
|
|
10718
11025
|
}
|
|
10719
11026
|
const result = await copyRuntime({
|
|
@@ -10722,7 +11029,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
10722
11029
|
filter: backendFileFilter(backend, desc3.name),
|
|
10723
11030
|
resolveDeps: true,
|
|
10724
11031
|
runtimeRoot: runtimeRoot(),
|
|
10725
|
-
depsTargetRoot:
|
|
11032
|
+
depsTargetRoot: path24.resolve(targetRoot, ".."),
|
|
10726
11033
|
dryRun: this.dryRun
|
|
10727
11034
|
});
|
|
10728
11035
|
const jobsScaffold = desc3.name === "jobs" ? runJobsScaffold(ctx.cwd, ctx.config, {
|
|
@@ -10817,14 +11124,14 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
10817
11124
|
if (this.dryRun) {
|
|
10818
11125
|
printInfo(`Dry run \u2014 ${result.planned.length} files would be written`);
|
|
10819
11126
|
for (const p of result.planned) {
|
|
10820
|
-
console.log(` ${theme.muted(icons.arrow)} ${
|
|
11127
|
+
console.log(` ${theme.muted(icons.arrow)} ${path24.relative(ctx.cwd, p) || p}`);
|
|
10821
11128
|
}
|
|
10822
11129
|
if (jobsScaffold?.planned?.length) {
|
|
10823
11130
|
printInfo(
|
|
10824
11131
|
`Jobs scaffold \u2014 ${jobsScaffold.planned.length} template targets`
|
|
10825
11132
|
);
|
|
10826
11133
|
for (const p of jobsScaffold.planned) {
|
|
10827
|
-
console.log(` ${theme.muted(icons.arrow)} ${
|
|
11134
|
+
console.log(` ${theme.muted(icons.arrow)} ${path24.relative(ctx.cwd, p) || p}`);
|
|
10828
11135
|
}
|
|
10829
11136
|
}
|
|
10830
11137
|
if (eventsScaffold?.planned?.length) {
|
|
@@ -10832,7 +11139,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
10832
11139
|
`Events scaffold \u2014 ${eventsScaffold.planned.length} template targets`
|
|
10833
11140
|
);
|
|
10834
11141
|
for (const p of eventsScaffold.planned) {
|
|
10835
|
-
console.log(` ${theme.muted(icons.arrow)} ${
|
|
11142
|
+
console.log(` ${theme.muted(icons.arrow)} ${path24.relative(ctx.cwd, p) || p}`);
|
|
10836
11143
|
}
|
|
10837
11144
|
}
|
|
10838
11145
|
if (integrationScaffold?.planned?.length) {
|
|
@@ -10840,7 +11147,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
10840
11147
|
`Integration scaffold \u2014 ${integrationScaffold.planned.length} template targets`
|
|
10841
11148
|
);
|
|
10842
11149
|
for (const p of integrationScaffold.planned) {
|
|
10843
|
-
console.log(` ${theme.muted(icons.arrow)} ${
|
|
11150
|
+
console.log(` ${theme.muted(icons.arrow)} ${path24.relative(ctx.cwd, p) || p}`);
|
|
10844
11151
|
}
|
|
10845
11152
|
}
|
|
10846
11153
|
if (bridgeScaffold?.planned?.length) {
|
|
@@ -10848,7 +11155,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
10848
11155
|
`Bridge scaffold \u2014 ${bridgeScaffold.planned.length} template targets`
|
|
10849
11156
|
);
|
|
10850
11157
|
for (const p of bridgeScaffold.planned) {
|
|
10851
|
-
console.log(` ${theme.muted(icons.arrow)} ${
|
|
11158
|
+
console.log(` ${theme.muted(icons.arrow)} ${path24.relative(ctx.cwd, p) || p}`);
|
|
10852
11159
|
}
|
|
10853
11160
|
}
|
|
10854
11161
|
if (observabilityScaffold?.planned?.length) {
|
|
@@ -10856,7 +11163,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
10856
11163
|
`Observability scaffold \u2014 ${observabilityScaffold.planned.length} template targets`
|
|
10857
11164
|
);
|
|
10858
11165
|
for (const p of observabilityScaffold.planned) {
|
|
10859
|
-
console.log(` ${theme.muted(icons.arrow)} ${
|
|
11166
|
+
console.log(` ${theme.muted(icons.arrow)} ${path24.relative(ctx.cwd, p) || p}`);
|
|
10860
11167
|
}
|
|
10861
11168
|
}
|
|
10862
11169
|
if (authScaffold?.planned?.length) {
|
|
@@ -10864,7 +11171,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
10864
11171
|
`Auth scaffold \u2014 ${authScaffold.planned.length} template targets`
|
|
10865
11172
|
);
|
|
10866
11173
|
for (const p of authScaffold.planned) {
|
|
10867
|
-
console.log(` ${theme.muted(icons.arrow)} ${
|
|
11174
|
+
console.log(` ${theme.muted(icons.arrow)} ${path24.relative(ctx.cwd, p) || p}`);
|
|
10868
11175
|
}
|
|
10869
11176
|
}
|
|
10870
11177
|
return 0;
|
|
@@ -10973,6 +11280,143 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
10973
11280
|
}
|
|
10974
11281
|
return 0;
|
|
10975
11282
|
}
|
|
11283
|
+
/**
|
|
11284
|
+
* ADR-037: package-mode install. The subsystem runtime lives in the
|
|
11285
|
+
* published `@pattern-stack/codegen` package, so installing reduces to a
|
|
11286
|
+
* config + barrel operation with NO file vendoring:
|
|
11287
|
+
*
|
|
11288
|
+
* 1. record the name under `subsystems.install` (the package-mode
|
|
11289
|
+
* source of truth for "installed");
|
|
11290
|
+
* 2. inject the per-subsystem `<name>:` config block via the same Hygen
|
|
11291
|
+
* action vendored mode uses (the block is runtime-agnostic — it only
|
|
11292
|
+
* writes YAML, never code); cache/storage have no config block, so this
|
|
11293
|
+
* step is skipped for them;
|
|
11294
|
+
* 3. regenerate the composition barrel (`<generated>/subsystems.ts`) and
|
|
11295
|
+
* the schema barrel (`<generated>/subsystems-schema.ts`) so AppModule's
|
|
11296
|
+
* `...SUBSYSTEM_MODULES` and drizzle-kit's schema pick up the new
|
|
11297
|
+
* install.
|
|
11298
|
+
*
|
|
11299
|
+
* Idempotent: a name already in `subsystems.install` is a no-op unless
|
|
11300
|
+
* `--force` is passed (which still re-runs config-block injection under
|
|
11301
|
+
* `--force-config` and always regenerates the barrels).
|
|
11302
|
+
*/
|
|
11303
|
+
async executePackageMode(ctx, desc3, backend) {
|
|
11304
|
+
const configPath = path24.join(ctx.cwd, "codegen.config.yaml");
|
|
11305
|
+
const installed = configuredSubsystemNames(
|
|
11306
|
+
ctx.config
|
|
11307
|
+
);
|
|
11308
|
+
const already = installed.includes(desc3.name);
|
|
11309
|
+
if (already && !this.force) {
|
|
11310
|
+
if (isJsonMode()) {
|
|
11311
|
+
printJson({
|
|
11312
|
+
command: "subsystem install",
|
|
11313
|
+
subsystem: desc3.name,
|
|
11314
|
+
runtime: "package",
|
|
11315
|
+
status: "already-installed"
|
|
11316
|
+
});
|
|
11317
|
+
} else {
|
|
11318
|
+
printInfo(
|
|
11319
|
+
`${desc3.name} is already in subsystems.install (runtime: package \u2014 nothing to vendor). Pass --force to refresh the config block + barrels.`
|
|
11320
|
+
);
|
|
11321
|
+
}
|
|
11322
|
+
return 0;
|
|
11323
|
+
}
|
|
11324
|
+
const configSubsystem = PACKAGE_CONFIG_BLOCK[desc3.name];
|
|
11325
|
+
const configBlockOutcome = configSubsystem ? planConfigBlockAction(configPath, configSubsystem.detector, this.forceConfig) : null;
|
|
11326
|
+
if (configBlockOutcome === "parse-error") {
|
|
11327
|
+
printError(
|
|
11328
|
+
`codegen.config.yaml is not valid YAML: refusing to inject ${desc3.name} config block. Fix the YAML and re-run.`
|
|
11329
|
+
);
|
|
11330
|
+
return 1;
|
|
11331
|
+
}
|
|
11332
|
+
if (this.dryRun) {
|
|
11333
|
+
if (isJsonMode()) {
|
|
11334
|
+
printJson({
|
|
11335
|
+
command: "subsystem install",
|
|
11336
|
+
subsystem: desc3.name,
|
|
11337
|
+
runtime: "package",
|
|
11338
|
+
dryRun: true,
|
|
11339
|
+
installList: already ? installed : [...installed, desc3.name],
|
|
11340
|
+
configBlockOutcome
|
|
11341
|
+
});
|
|
11342
|
+
} else {
|
|
11343
|
+
printInfo(`Dry run \u2014 runtime: package (no files vendored).`);
|
|
11344
|
+
if (!already) printInfo(` would add '${desc3.name}' to subsystems.install`);
|
|
11345
|
+
if (configBlockOutcome) {
|
|
11346
|
+
printInfo(` ${desc3.name} config block would be ${configBlockOutcome}`);
|
|
11347
|
+
}
|
|
11348
|
+
printInfo(" would regenerate <generated>/subsystems.ts + subsystems-schema.ts");
|
|
11349
|
+
}
|
|
11350
|
+
return 0;
|
|
11351
|
+
}
|
|
11352
|
+
const installResult = ensureSubsystemInstalled(configPath, desc3.name);
|
|
11353
|
+
if (installResult.outcome === "parse-error") {
|
|
11354
|
+
printError(
|
|
11355
|
+
"codegen.config.yaml is not valid YAML: refusing to update subsystems.install. Fix the YAML and re-run."
|
|
11356
|
+
);
|
|
11357
|
+
return 1;
|
|
11358
|
+
}
|
|
11359
|
+
if (configSubsystem && configBlockOutcome) {
|
|
11360
|
+
const configResult = runConfigBlockAction({
|
|
11361
|
+
cwd: ctx.cwd,
|
|
11362
|
+
actionFolder: configSubsystem.actionFolder,
|
|
11363
|
+
configPath,
|
|
11364
|
+
subsystem: configSubsystem.detector,
|
|
11365
|
+
outcome: configBlockOutcome,
|
|
11366
|
+
json: isJsonMode()
|
|
11367
|
+
});
|
|
11368
|
+
if (!configResult.ok) {
|
|
11369
|
+
printError(
|
|
11370
|
+
`${desc3.name} config-block injection failed: ${configResult.error ?? "unknown error"}`
|
|
11371
|
+
);
|
|
11372
|
+
return 1;
|
|
11373
|
+
}
|
|
11374
|
+
}
|
|
11375
|
+
const refreshed = await loadContext({
|
|
11376
|
+
cwd: ctx.cwd,
|
|
11377
|
+
configPath: this.configPath,
|
|
11378
|
+
json: this.json,
|
|
11379
|
+
skipDetection: true
|
|
11380
|
+
});
|
|
11381
|
+
let barrelEmitted = [];
|
|
11382
|
+
let schemaEmitted = [];
|
|
11383
|
+
try {
|
|
11384
|
+
const generatedDir = resolveGeneratedDir(refreshed);
|
|
11385
|
+
const barrel = await regenerateSubsystemBarrel({ ctx: refreshed, generatedDir });
|
|
11386
|
+
barrelEmitted = barrel.emitted;
|
|
11387
|
+
const schema = await regenerateSubsystemSchemaBarrel({ ctx: refreshed, generatedDir });
|
|
11388
|
+
schemaEmitted = schema.emitted;
|
|
11389
|
+
} catch (err) {
|
|
11390
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
11391
|
+
printWarning(`barrel regeneration failed \u2014 ${msg}`);
|
|
11392
|
+
}
|
|
11393
|
+
if (isJsonMode()) {
|
|
11394
|
+
printJson({
|
|
11395
|
+
command: "subsystem install",
|
|
11396
|
+
subsystem: desc3.name,
|
|
11397
|
+
runtime: "package",
|
|
11398
|
+
backend,
|
|
11399
|
+
vendored: false,
|
|
11400
|
+
installList: installResult.install,
|
|
11401
|
+
installOutcome: installResult.outcome,
|
|
11402
|
+
configBlockOutcome,
|
|
11403
|
+
barrelEmitted,
|
|
11404
|
+
schemaEmitted
|
|
11405
|
+
});
|
|
11406
|
+
return 0;
|
|
11407
|
+
}
|
|
11408
|
+
printSuccess(`${desc3.name} installed (runtime: package \u2014 no files vendored).`);
|
|
11409
|
+
if (installResult.outcome === "added") {
|
|
11410
|
+
printInfo(`Added '${desc3.name}' to subsystems.install.`);
|
|
11411
|
+
}
|
|
11412
|
+
printInfo(
|
|
11413
|
+
`Regenerated <generated>/subsystems.ts (${barrelEmitted.join(", ") || "none"}) + subsystems-schema.ts (${schemaEmitted.join(", ") || "none"}).`
|
|
11414
|
+
);
|
|
11415
|
+
printInfo(
|
|
11416
|
+
"Wire once (if not already): `import { SUBSYSTEM_MODULES } from './generated/subsystems'` into AppModule, and `export * from './generated/subsystems-schema'` into your drizzle-kit schema entrypoint."
|
|
11417
|
+
);
|
|
11418
|
+
return 0;
|
|
11419
|
+
}
|
|
10976
11420
|
/**
|
|
10977
11421
|
* OPENAPI-4: install flow for the config-only `openapi-config`
|
|
10978
11422
|
* pseudo-subsystem.
|
|
@@ -10984,7 +11428,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
10984
11428
|
* semantics as jobs/events/integration/bridge.
|
|
10985
11429
|
*/
|
|
10986
11430
|
async executeOpenApiConfig(ctx) {
|
|
10987
|
-
const configPath =
|
|
11431
|
+
const configPath = path24.join(ctx.cwd, "codegen.config.yaml");
|
|
10988
11432
|
const outcome = planConfigBlockAction(configPath, "openapi", this.forceConfig);
|
|
10989
11433
|
if (outcome === "parse-error") {
|
|
10990
11434
|
printError(
|
|
@@ -11003,7 +11447,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
11003
11447
|
});
|
|
11004
11448
|
} else {
|
|
11005
11449
|
printInfo(`Dry run \u2014 openapi config block would be ${outcome}`);
|
|
11006
|
-
console.log(` ${theme.muted(icons.arrow)} ${
|
|
11450
|
+
console.log(` ${theme.muted(icons.arrow)} ${path24.relative(ctx.cwd, configPath) || configPath}`);
|
|
11007
11451
|
}
|
|
11008
11452
|
return 0;
|
|
11009
11453
|
}
|
|
@@ -11098,7 +11542,7 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
11098
11542
|
);
|
|
11099
11543
|
for (const p of scaffold.planned) {
|
|
11100
11544
|
console.log(
|
|
11101
|
-
` ${theme.muted(icons.arrow)} ${
|
|
11545
|
+
` ${theme.muted(icons.arrow)} ${path24.relative(ctx.cwd, p) || p}`
|
|
11102
11546
|
);
|
|
11103
11547
|
}
|
|
11104
11548
|
return 0;
|
|
@@ -11122,10 +11566,10 @@ var SubsystemInstallCommand = class extends Command3 {
|
|
|
11122
11566
|
}
|
|
11123
11567
|
};
|
|
11124
11568
|
function planConfigBlockAction(configPath, subsystem, forceConfig) {
|
|
11125
|
-
if (!
|
|
11569
|
+
if (!fs13.existsSync(configPath)) {
|
|
11126
11570
|
return "inject";
|
|
11127
11571
|
}
|
|
11128
|
-
const source =
|
|
11572
|
+
const source = fs13.readFileSync(configPath, "utf-8");
|
|
11129
11573
|
const state = detectConfigBlock(source, subsystem);
|
|
11130
11574
|
if (state === "parse-error") return "parse-error";
|
|
11131
11575
|
if (state === "missing") return "inject";
|
|
@@ -11148,9 +11592,9 @@ function runConfigBlockAction(input) {
|
|
|
11148
11592
|
);
|
|
11149
11593
|
}
|
|
11150
11594
|
try {
|
|
11151
|
-
const source =
|
|
11595
|
+
const source = fs13.readFileSync(input.configPath, "utf-8");
|
|
11152
11596
|
const stripped = stripConfigBlock(source, input.subsystem);
|
|
11153
|
-
|
|
11597
|
+
fs13.writeFileSync(input.configPath, stripped, "utf-8");
|
|
11154
11598
|
} catch (err) {
|
|
11155
11599
|
const message = err instanceof Error ? err.message : String(err);
|
|
11156
11600
|
return { ok: false, error: `strip failed: ${message}` };
|
|
@@ -11188,8 +11632,8 @@ function runJobsScaffold(cwd, config, opts) {
|
|
|
11188
11632
|
const locals = resolveJobsScaffoldLocals({
|
|
11189
11633
|
cwd,
|
|
11190
11634
|
config,
|
|
11191
|
-
fileExists: (p) =>
|
|
11192
|
-
readFile: (p) =>
|
|
11635
|
+
fileExists: (p) => fs13.existsSync(p),
|
|
11636
|
+
readFile: (p) => fs13.existsSync(p) ? fs13.readFileSync(p, "utf-8") : null
|
|
11193
11637
|
});
|
|
11194
11638
|
const planned = [
|
|
11195
11639
|
...!locals.workerExists ? [locals.workerPath] : [],
|
|
@@ -11246,7 +11690,7 @@ function runEventsScaffold(cwd, config, opts) {
|
|
|
11246
11690
|
const locals = resolveEventsScaffoldLocals({
|
|
11247
11691
|
cwd,
|
|
11248
11692
|
config,
|
|
11249
|
-
fileExists: (p) =>
|
|
11693
|
+
fileExists: (p) => fs13.existsSync(p)
|
|
11250
11694
|
});
|
|
11251
11695
|
const planned = [
|
|
11252
11696
|
locals.configPath,
|
|
@@ -11302,7 +11746,7 @@ function runIntegrationScaffold(cwd, config, opts) {
|
|
|
11302
11746
|
const locals = resolveIntegrationScaffoldLocals({
|
|
11303
11747
|
cwd,
|
|
11304
11748
|
config,
|
|
11305
|
-
fileExists: (p) =>
|
|
11749
|
+
fileExists: (p) => fs13.existsSync(p)
|
|
11306
11750
|
});
|
|
11307
11751
|
const planned = [
|
|
11308
11752
|
locals.configPath,
|
|
@@ -11357,7 +11801,7 @@ function runBridgeScaffold(cwd, config, opts) {
|
|
|
11357
11801
|
const locals = resolveBridgeScaffoldLocals({
|
|
11358
11802
|
cwd,
|
|
11359
11803
|
config,
|
|
11360
|
-
fileExists: (p) =>
|
|
11804
|
+
fileExists: (p) => fs13.existsSync(p)
|
|
11361
11805
|
});
|
|
11362
11806
|
const planned = [
|
|
11363
11807
|
locals.configPath,
|
|
@@ -11411,7 +11855,7 @@ function runObservabilityScaffold(cwd, config, opts) {
|
|
|
11411
11855
|
const locals = resolveObservabilityScaffoldLocals({
|
|
11412
11856
|
cwd,
|
|
11413
11857
|
config,
|
|
11414
|
-
fileExists: (p) =>
|
|
11858
|
+
fileExists: (p) => fs13.existsSync(p)
|
|
11415
11859
|
});
|
|
11416
11860
|
const planned = [locals.configPath, locals.appModulePath];
|
|
11417
11861
|
const configBlockOutcome = planConfigBlockAction(
|
|
@@ -11480,9 +11924,9 @@ function runAuthScaffold(cwd, config, opts) {
|
|
|
11480
11924
|
if (opts.dryRun) {
|
|
11481
11925
|
return { ok: true, planned, configBlockOutcome };
|
|
11482
11926
|
}
|
|
11483
|
-
if (!
|
|
11484
|
-
|
|
11485
|
-
|
|
11927
|
+
if (!fs13.existsSync(locals.envConfigPath)) {
|
|
11928
|
+
fs13.mkdirSync(path24.dirname(locals.envConfigPath), { recursive: true });
|
|
11929
|
+
fs13.writeFileSync(locals.envConfigPath, "", "utf-8");
|
|
11486
11930
|
}
|
|
11487
11931
|
const result = invokeHygen({
|
|
11488
11932
|
generator: "subsystem",
|
|
@@ -11518,57 +11962,57 @@ function runAuthScaffold(cwd, config, opts) {
|
|
|
11518
11962
|
return { ok: true, planned, configBlockOutcome };
|
|
11519
11963
|
}
|
|
11520
11964
|
function authIntegrationsExamplesRoot() {
|
|
11521
|
-
const pkgRoot =
|
|
11522
|
-
const topLevel =
|
|
11523
|
-
if (
|
|
11524
|
-
return
|
|
11965
|
+
const pkgRoot = path24.resolve(import.meta.dirname, "..", "..", "..");
|
|
11966
|
+
const topLevel = path24.join(pkgRoot, "examples", "auth-integrations");
|
|
11967
|
+
if (fs13.existsSync(topLevel)) return topLevel;
|
|
11968
|
+
return path24.join(pkgRoot, "dist", "examples", "auth-integrations");
|
|
11525
11969
|
}
|
|
11526
11970
|
function copyTreeIdempotent(srcDir, destDir, force, transform) {
|
|
11527
11971
|
const written = [];
|
|
11528
11972
|
const skipped = [];
|
|
11529
11973
|
const walk = (src, dest) => {
|
|
11530
|
-
const entries =
|
|
11974
|
+
const entries = fs13.readdirSync(src, { withFileTypes: true });
|
|
11531
11975
|
for (const entry of entries) {
|
|
11532
|
-
const srcPath =
|
|
11533
|
-
const destPath =
|
|
11976
|
+
const srcPath = path24.join(src, entry.name);
|
|
11977
|
+
const destPath = path24.join(dest, entry.name);
|
|
11534
11978
|
if (entry.isDirectory()) {
|
|
11535
|
-
|
|
11979
|
+
fs13.mkdirSync(destPath, { recursive: true });
|
|
11536
11980
|
walk(srcPath, destPath);
|
|
11537
11981
|
continue;
|
|
11538
11982
|
}
|
|
11539
11983
|
if (!entry.isFile()) continue;
|
|
11540
|
-
if (
|
|
11984
|
+
if (fs13.existsSync(destPath) && !force) {
|
|
11541
11985
|
skipped.push(destPath);
|
|
11542
11986
|
continue;
|
|
11543
11987
|
}
|
|
11544
|
-
|
|
11988
|
+
fs13.mkdirSync(path24.dirname(destPath), { recursive: true });
|
|
11545
11989
|
const isTextSource = transform && (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx"));
|
|
11546
11990
|
if (isTextSource && transform) {
|
|
11547
|
-
const raw =
|
|
11548
|
-
|
|
11991
|
+
const raw = fs13.readFileSync(srcPath, "utf-8");
|
|
11992
|
+
fs13.writeFileSync(destPath, transform(raw, destPath), "utf-8");
|
|
11549
11993
|
} else {
|
|
11550
|
-
|
|
11994
|
+
fs13.copyFileSync(srcPath, destPath);
|
|
11551
11995
|
}
|
|
11552
11996
|
written.push(destPath);
|
|
11553
11997
|
}
|
|
11554
11998
|
};
|
|
11555
|
-
if (!
|
|
11556
|
-
|
|
11999
|
+
if (!fs13.existsSync(srcDir)) return { written, skipped };
|
|
12000
|
+
fs13.mkdirSync(destDir, { recursive: true });
|
|
11557
12001
|
walk(srcDir, destDir);
|
|
11558
12002
|
return { written, skipped };
|
|
11559
12003
|
}
|
|
11560
12004
|
var AUTH_BARE_IMPORT_RE = /(['"])@pattern-stack\/codegen\/runtime\/subsystems\/auth\1/g;
|
|
11561
12005
|
function buildAuthImportRewriter(subsystemsRoot) {
|
|
11562
|
-
const authRoot =
|
|
12006
|
+
const authRoot = path24.join(subsystemsRoot, "auth");
|
|
11563
12007
|
return (content, destPath) => {
|
|
11564
12008
|
if (!AUTH_BARE_IMPORT_RE.test(content)) {
|
|
11565
12009
|
AUTH_BARE_IMPORT_RE.lastIndex = 0;
|
|
11566
12010
|
return content;
|
|
11567
12011
|
}
|
|
11568
12012
|
AUTH_BARE_IMPORT_RE.lastIndex = 0;
|
|
11569
|
-
let rel2 =
|
|
12013
|
+
let rel2 = path24.relative(path24.dirname(destPath), authRoot);
|
|
11570
12014
|
if (!rel2.startsWith(".")) rel2 = `./${rel2}`;
|
|
11571
|
-
const relPosix = rel2.split(
|
|
12015
|
+
const relPosix = rel2.split(path24.sep).join("/");
|
|
11572
12016
|
return content.replace(
|
|
11573
12017
|
AUTH_BARE_IMPORT_RE,
|
|
11574
12018
|
(_match, quote) => `${quote}${relPosix}${quote}`
|
|
@@ -11579,20 +12023,20 @@ function runAuthIntegrationsScaffold(cwd, config, opts) {
|
|
|
11579
12023
|
const locals = resolveAuthIntegrationsScaffoldLocals({
|
|
11580
12024
|
cwd,
|
|
11581
12025
|
config,
|
|
11582
|
-
fileExists: (p) =>
|
|
11583
|
-
readFile: (p) =>
|
|
12026
|
+
fileExists: (p) => fs13.existsSync(p),
|
|
12027
|
+
readFile: (p) => fs13.existsSync(p) ? fs13.readFileSync(p, "utf-8") : null
|
|
11584
12028
|
});
|
|
11585
12029
|
const examplesRoot = authIntegrationsExamplesRoot();
|
|
11586
|
-
if (!
|
|
12030
|
+
if (!fs13.existsSync(examplesRoot)) {
|
|
11587
12031
|
return {
|
|
11588
12032
|
ok: false,
|
|
11589
12033
|
planned: [],
|
|
11590
12034
|
error: `auth-integrations starter source missing: ${examplesRoot}`
|
|
11591
12035
|
};
|
|
11592
12036
|
}
|
|
11593
|
-
const adaptersSrc =
|
|
11594
|
-
const adaptersDest =
|
|
11595
|
-
const connectionYamlSrc =
|
|
12037
|
+
const adaptersSrc = path24.join(examplesRoot, "runtime", "connections");
|
|
12038
|
+
const adaptersDest = path24.join(locals.vendorRoot, "connections");
|
|
12039
|
+
const connectionYamlSrc = path24.join(
|
|
11596
12040
|
examplesRoot,
|
|
11597
12041
|
"definitions",
|
|
11598
12042
|
"entities",
|
|
@@ -11621,11 +12065,11 @@ function runAuthIntegrationsScaffold(cwd, config, opts) {
|
|
|
11621
12065
|
let yamlWritten = false;
|
|
11622
12066
|
let yamlSkipped = false;
|
|
11623
12067
|
try {
|
|
11624
|
-
if (
|
|
12068
|
+
if (fs13.existsSync(connectionYamlDest) && !opts.force) {
|
|
11625
12069
|
yamlSkipped = true;
|
|
11626
|
-
} else if (
|
|
11627
|
-
|
|
11628
|
-
|
|
12070
|
+
} else if (fs13.existsSync(connectionYamlSrc)) {
|
|
12071
|
+
fs13.mkdirSync(path24.dirname(connectionYamlDest), { recursive: true });
|
|
12072
|
+
fs13.copyFileSync(connectionYamlSrc, connectionYamlDest);
|
|
11629
12073
|
yamlWritten = true;
|
|
11630
12074
|
}
|
|
11631
12075
|
} catch (err) {
|
|
@@ -11690,7 +12134,7 @@ var SubsystemListCommand = class extends Command3 {
|
|
|
11690
12134
|
name: s.name,
|
|
11691
12135
|
status: inst ? inst.status : "available",
|
|
11692
12136
|
backend: inst ? inst.backend : null,
|
|
11693
|
-
path: inst ?
|
|
12137
|
+
path: inst ? path24.relative(ctx.cwd, inst.path) || inst.path : null
|
|
11694
12138
|
};
|
|
11695
12139
|
});
|
|
11696
12140
|
if (isJsonMode()) {
|
|
@@ -11779,14 +12223,14 @@ var SubsystemRemoveCommand = class extends Command3 {
|
|
|
11779
12223
|
return 1;
|
|
11780
12224
|
}
|
|
11781
12225
|
const subsystemDir = target.path;
|
|
11782
|
-
if (!
|
|
12226
|
+
if (!fs13.existsSync(subsystemDir)) {
|
|
11783
12227
|
printError(
|
|
11784
12228
|
`Detected install at ${subsystemDir} but the directory is gone \u2014 refusing to act.`
|
|
11785
12229
|
);
|
|
11786
12230
|
return 1;
|
|
11787
12231
|
}
|
|
11788
12232
|
if (!this.force) {
|
|
11789
|
-
const rel2 =
|
|
12233
|
+
const rel2 = path24.relative(ctx.cwd, subsystemDir) || subsystemDir;
|
|
11790
12234
|
const gitCheck = checkGitSafety([rel2], ctx.cwd);
|
|
11791
12235
|
if (gitCheck.inRepo && !gitCheck.clean) {
|
|
11792
12236
|
printWarning(
|
|
@@ -11796,7 +12240,7 @@ var SubsystemRemoveCommand = class extends Command3 {
|
|
|
11796
12240
|
}
|
|
11797
12241
|
}
|
|
11798
12242
|
try {
|
|
11799
|
-
|
|
12243
|
+
fs13.rmSync(subsystemDir, { recursive: true, force: true });
|
|
11800
12244
|
} catch (err) {
|
|
11801
12245
|
const message = err instanceof Error ? err.message : String(err);
|
|
11802
12246
|
printError(`Failed to remove ${subsystemDir}: ${message}`);
|
|
@@ -11822,7 +12266,7 @@ var SubsystemRemoveCommand = class extends Command3 {
|
|
|
11822
12266
|
return 0;
|
|
11823
12267
|
}
|
|
11824
12268
|
printSuccess(
|
|
11825
|
-
`${desc3.name} subsystem removed (${
|
|
12269
|
+
`${desc3.name} subsystem removed (${path24.relative(ctx.cwd, subsystemDir) || subsystemDir}).`
|
|
11826
12270
|
);
|
|
11827
12271
|
if (barrelRegenerated) {
|
|
11828
12272
|
printInfo("Regenerated <generated>/subsystems.ts barrel.");
|
|
@@ -11850,28 +12294,28 @@ var subsystemNoun = {
|
|
|
11850
12294
|
var subsystem_default = subsystemNoun;
|
|
11851
12295
|
|
|
11852
12296
|
// src/cli/commands/project.ts
|
|
11853
|
-
import
|
|
11854
|
-
import
|
|
12297
|
+
import fs19 from "fs";
|
|
12298
|
+
import path30 from "path";
|
|
11855
12299
|
import readline from "readline";
|
|
11856
12300
|
import { Command as Command7, Option as Option7 } from "clipanion";
|
|
11857
12301
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
11858
12302
|
|
|
11859
12303
|
// src/cli/shared/init-scaffold.ts
|
|
11860
|
-
import
|
|
11861
|
-
import
|
|
12304
|
+
import fs14 from "fs";
|
|
12305
|
+
import path25 from "path";
|
|
11862
12306
|
import { stringify as stringifyYaml } from "yaml";
|
|
11863
12307
|
function runtimeRoot2() {
|
|
11864
|
-
const pkgRoot =
|
|
11865
|
-
const topLevel =
|
|
11866
|
-
if (
|
|
11867
|
-
return
|
|
12308
|
+
const pkgRoot = path25.resolve(import.meta.dirname, "..", "..", "..");
|
|
12309
|
+
const topLevel = path25.join(pkgRoot, "runtime");
|
|
12310
|
+
if (fs14.existsSync(topLevel)) return topLevel;
|
|
12311
|
+
return path25.join(pkgRoot, "dist", "runtime");
|
|
11868
12312
|
}
|
|
11869
12313
|
function resolveRuntimePath(cwd) {
|
|
11870
|
-
const shimDir =
|
|
11871
|
-
return
|
|
12314
|
+
const shimDir = path25.join(cwd, "src", "shared", "base-classes");
|
|
12315
|
+
return path25.relative(shimDir, runtimeRoot2());
|
|
11872
12316
|
}
|
|
11873
12317
|
function loadRuntimeFile(relPath2) {
|
|
11874
|
-
return
|
|
12318
|
+
return fs14.readFileSync(path25.join(runtimeRoot2(), relPath2), "utf-8");
|
|
11875
12319
|
}
|
|
11876
12320
|
var VENDORED_RUNTIME_FILES = [
|
|
11877
12321
|
// base-classes — consumer-facing inheritance targets
|
|
@@ -11920,12 +12364,13 @@ var VENDORED_RUNTIME_FILES = [
|
|
|
11920
12364
|
},
|
|
11921
12365
|
{ runtime: "shared/openapi/index.ts", target: "src/shared/openapi/index.ts" }
|
|
11922
12366
|
];
|
|
11923
|
-
function databaseModuleContent() {
|
|
12367
|
+
function databaseModuleContent(mode) {
|
|
12368
|
+
const drizzleTokenImport = mode === "vendored" ? "../constants/tokens" : runtimeImport(mode, "constants/tokens");
|
|
11924
12369
|
return `import { Module, Global } from '@nestjs/common';
|
|
11925
12370
|
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
11926
12371
|
import { Pool } from 'pg';
|
|
11927
12372
|
import * as schema from '../../schema';
|
|
11928
|
-
import { DRIZZLE } from '
|
|
12373
|
+
import { DRIZZLE } from '${drizzleTokenImport}';
|
|
11929
12374
|
|
|
11930
12375
|
export { DRIZZLE };
|
|
11931
12376
|
export type DrizzleDB = ReturnType<typeof drizzle<typeof schema>>;
|
|
@@ -11952,11 +12397,12 @@ export type DrizzleDB = ReturnType<typeof drizzle<typeof schema>>;
|
|
|
11952
12397
|
export class DatabaseModule {}
|
|
11953
12398
|
`;
|
|
11954
12399
|
}
|
|
11955
|
-
function appModuleContent() {
|
|
12400
|
+
function appModuleContent(mode) {
|
|
12401
|
+
const openApiImport = mode === "vendored" ? "./shared/openapi" : runtimeImport(mode, "shared/openapi");
|
|
11956
12402
|
return `import { Global, Module } from '@nestjs/common';
|
|
11957
12403
|
import { DatabaseModule } from './shared/database/database.module';
|
|
11958
12404
|
import { GENERATED_MODULES } from './generated/modules';
|
|
11959
|
-
import { OPENAPI_REGISTRY, OpenApiRegistry } from '
|
|
12405
|
+
import { OPENAPI_REGISTRY, OpenApiRegistry } from '${openApiImport}';
|
|
11960
12406
|
|
|
11961
12407
|
/**
|
|
11962
12408
|
* OpenApiModule \u2014 @Global() wrapper around the OPENAPI_REGISTRY singleton.
|
|
@@ -11998,7 +12444,8 @@ class OpenApiModule {}
|
|
|
11998
12444
|
export class AppModule {}
|
|
11999
12445
|
`;
|
|
12000
12446
|
}
|
|
12001
|
-
function mainTsContent() {
|
|
12447
|
+
function mainTsContent(mode) {
|
|
12448
|
+
const openApiImport = mode === "vendored" ? "./shared/openapi" : runtimeImport(mode, "shared/openapi");
|
|
12002
12449
|
return `import 'reflect-metadata';
|
|
12003
12450
|
import fs from 'node:fs';
|
|
12004
12451
|
import path from 'node:path';
|
|
@@ -12006,7 +12453,7 @@ import { NestFactory } from '@nestjs/core';
|
|
|
12006
12453
|
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
|
12007
12454
|
import { parse as parseYaml } from 'yaml';
|
|
12008
12455
|
import { AppModule } from './app.module';
|
|
12009
|
-
import { OPENAPI_REGISTRY, OpenApiRegistry } from '
|
|
12456
|
+
import { OPENAPI_REGISTRY, OpenApiRegistry } from '${openApiImport}';
|
|
12010
12457
|
|
|
12011
12458
|
interface OpenApiConfig {
|
|
12012
12459
|
enabled?: boolean;
|
|
@@ -12285,10 +12732,10 @@ function mergeTsconfig(raw) {
|
|
|
12285
12732
|
};
|
|
12286
12733
|
}
|
|
12287
12734
|
function relOf(cwd, abs) {
|
|
12288
|
-
return
|
|
12735
|
+
return path25.relative(cwd, abs) || abs;
|
|
12289
12736
|
}
|
|
12290
12737
|
function fileEntry(cwd, absPath, content, opts) {
|
|
12291
|
-
const exists =
|
|
12738
|
+
const exists = fs14.existsSync(absPath);
|
|
12292
12739
|
let action;
|
|
12293
12740
|
let reason = opts.skipReason;
|
|
12294
12741
|
if (!exists) {
|
|
@@ -12303,7 +12750,7 @@ function fileEntry(cwd, absPath, content, opts) {
|
|
|
12303
12750
|
return { path: absPath, relPath: relOf(cwd, absPath), action, content, reason };
|
|
12304
12751
|
}
|
|
12305
12752
|
function dirEntry(cwd, absPath) {
|
|
12306
|
-
const exists =
|
|
12753
|
+
const exists = fs14.existsSync(absPath);
|
|
12307
12754
|
return {
|
|
12308
12755
|
path: absPath,
|
|
12309
12756
|
relPath: relOf(cwd, absPath),
|
|
@@ -12315,6 +12762,7 @@ function dirEntry(cwd, absPath) {
|
|
|
12315
12762
|
async function buildInitPlan(ctx, options) {
|
|
12316
12763
|
const cwd = options.cwd;
|
|
12317
12764
|
const force = Boolean(options.force);
|
|
12765
|
+
const runtimeMode = options.runtimeMode === "vendored" ? "vendored" : "package";
|
|
12318
12766
|
let framework = "nestjs";
|
|
12319
12767
|
let orm = "drizzle";
|
|
12320
12768
|
let architecture = "clean-lite-ps";
|
|
@@ -12335,8 +12783,13 @@ async function buildInitPlan(ctx, options) {
|
|
|
12335
12783
|
const runtimePath = options.runtimePath ?? resolveRuntimePath(cwd);
|
|
12336
12784
|
const entries = [];
|
|
12337
12785
|
{
|
|
12338
|
-
const configPath =
|
|
12786
|
+
const configPath = path25.join(cwd, "codegen.config.yaml");
|
|
12339
12787
|
const config = {
|
|
12788
|
+
// Runtime mode (ADR-037). `package` (default) imports the runtime from
|
|
12789
|
+
// `@pattern-stack/codegen/*`; `vendored` imports it via `@shared/*` and
|
|
12790
|
+
// vendors `src/shared/**`. Existing vendored projects MUST set this to
|
|
12791
|
+
// `vendored` explicitly — the default does not silently flip them.
|
|
12792
|
+
runtime: runtimeMode,
|
|
12340
12793
|
paths: {
|
|
12341
12794
|
backend_src: "src",
|
|
12342
12795
|
entities_dir: "entities",
|
|
@@ -12365,9 +12818,9 @@ async function buildInitPlan(ctx, options) {
|
|
|
12365
12818
|
entries.push(fileEntry(cwd, configPath, content, { force }));
|
|
12366
12819
|
}
|
|
12367
12820
|
{
|
|
12368
|
-
const tsconfigPath =
|
|
12369
|
-
if (
|
|
12370
|
-
const raw =
|
|
12821
|
+
const tsconfigPath = path25.join(cwd, "tsconfig.json");
|
|
12822
|
+
if (fs14.existsSync(tsconfigPath)) {
|
|
12823
|
+
const raw = fs14.readFileSync(tsconfigPath, "utf-8");
|
|
12371
12824
|
const merged = mergeTsconfig(raw);
|
|
12372
12825
|
if (merged.parseError) {
|
|
12373
12826
|
entries.push({
|
|
@@ -12412,20 +12865,22 @@ async function buildInitPlan(ctx, options) {
|
|
|
12412
12865
|
entries.push(
|
|
12413
12866
|
fileEntry(
|
|
12414
12867
|
cwd,
|
|
12415
|
-
|
|
12416
|
-
databaseModuleContent(),
|
|
12868
|
+
path25.join(cwd, "src", "shared", "database", "database.module.ts"),
|
|
12869
|
+
databaseModuleContent(runtimeMode),
|
|
12417
12870
|
{ force }
|
|
12418
12871
|
)
|
|
12419
12872
|
);
|
|
12420
|
-
|
|
12421
|
-
|
|
12422
|
-
|
|
12423
|
-
|
|
12873
|
+
if (runtimeMode === "vendored") {
|
|
12874
|
+
for (const v of VENDORED_RUNTIME_FILES) {
|
|
12875
|
+
entries.push(
|
|
12876
|
+
fileEntry(cwd, path25.join(cwd, v.target), loadRuntimeFile(v.runtime), { force })
|
|
12877
|
+
);
|
|
12878
|
+
}
|
|
12424
12879
|
}
|
|
12425
12880
|
entries.push(
|
|
12426
12881
|
fileEntry(
|
|
12427
12882
|
cwd,
|
|
12428
|
-
|
|
12883
|
+
path25.join(cwd, "src", "generated", "modules.ts"),
|
|
12429
12884
|
emptyModulesBarrel(),
|
|
12430
12885
|
{ force }
|
|
12431
12886
|
)
|
|
@@ -12433,19 +12888,19 @@ async function buildInitPlan(ctx, options) {
|
|
|
12433
12888
|
entries.push(
|
|
12434
12889
|
fileEntry(
|
|
12435
12890
|
cwd,
|
|
12436
|
-
|
|
12891
|
+
path25.join(cwd, "src", "generated", "schema.ts"),
|
|
12437
12892
|
emptySchemaBarrel(),
|
|
12438
12893
|
{ force }
|
|
12439
12894
|
)
|
|
12440
12895
|
);
|
|
12441
12896
|
{
|
|
12442
|
-
const appModulePath =
|
|
12443
|
-
if (!
|
|
12897
|
+
const appModulePath = path25.join(cwd, "src", "app.module.ts");
|
|
12898
|
+
if (!fs14.existsSync(appModulePath)) {
|
|
12444
12899
|
entries.push({
|
|
12445
12900
|
path: appModulePath,
|
|
12446
12901
|
relPath: relOf(cwd, appModulePath),
|
|
12447
12902
|
action: "create",
|
|
12448
|
-
content: appModuleContent()
|
|
12903
|
+
content: appModuleContent(runtimeMode)
|
|
12449
12904
|
});
|
|
12450
12905
|
} else {
|
|
12451
12906
|
entries.push({
|
|
@@ -12457,13 +12912,13 @@ async function buildInitPlan(ctx, options) {
|
|
|
12457
12912
|
}
|
|
12458
12913
|
}
|
|
12459
12914
|
{
|
|
12460
|
-
const mainPath =
|
|
12461
|
-
if (!
|
|
12915
|
+
const mainPath = path25.join(cwd, "src", "main.ts");
|
|
12916
|
+
if (!fs14.existsSync(mainPath)) {
|
|
12462
12917
|
entries.push({
|
|
12463
12918
|
path: mainPath,
|
|
12464
12919
|
relPath: relOf(cwd, mainPath),
|
|
12465
12920
|
action: "create",
|
|
12466
|
-
content: mainTsContent()
|
|
12921
|
+
content: mainTsContent(runtimeMode)
|
|
12467
12922
|
});
|
|
12468
12923
|
} else {
|
|
12469
12924
|
entries.push({
|
|
@@ -12475,8 +12930,8 @@ async function buildInitPlan(ctx, options) {
|
|
|
12475
12930
|
}
|
|
12476
12931
|
}
|
|
12477
12932
|
{
|
|
12478
|
-
const schemaPath =
|
|
12479
|
-
if (!
|
|
12933
|
+
const schemaPath = path25.join(cwd, "src", "schema.ts");
|
|
12934
|
+
if (!fs14.existsSync(schemaPath)) {
|
|
12480
12935
|
entries.push({
|
|
12481
12936
|
path: schemaPath,
|
|
12482
12937
|
relPath: relOf(cwd, schemaPath),
|
|
@@ -12492,14 +12947,14 @@ async function buildInitPlan(ctx, options) {
|
|
|
12492
12947
|
});
|
|
12493
12948
|
}
|
|
12494
12949
|
}
|
|
12495
|
-
entries.push(dirEntry(cwd,
|
|
12950
|
+
entries.push(dirEntry(cwd, path25.join(cwd, "entities")));
|
|
12496
12951
|
{
|
|
12497
|
-
const entitiesDir =
|
|
12498
|
-
const examplePath =
|
|
12499
|
-
const hasOtherYamls =
|
|
12500
|
-
(f) =>
|
|
12952
|
+
const entitiesDir = path25.join(cwd, "entities");
|
|
12953
|
+
const examplePath = path25.join(entitiesDir, "example.yaml");
|
|
12954
|
+
const hasOtherYamls = fs14.existsSync(entitiesDir) && findYamlFiles(entitiesDir).some(
|
|
12955
|
+
(f) => path25.basename(f) !== "example.yaml"
|
|
12501
12956
|
);
|
|
12502
|
-
if (
|
|
12957
|
+
if (fs14.existsSync(examplePath)) {
|
|
12503
12958
|
entries.push({
|
|
12504
12959
|
path: examplePath,
|
|
12505
12960
|
relPath: relOf(cwd, examplePath),
|
|
@@ -12545,7 +13000,7 @@ function writePlan(plan) {
|
|
|
12545
13000
|
continue;
|
|
12546
13001
|
}
|
|
12547
13002
|
if (e.directory) {
|
|
12548
|
-
|
|
13003
|
+
fs14.mkdirSync(e.path, { recursive: true });
|
|
12549
13004
|
created.push(e);
|
|
12550
13005
|
continue;
|
|
12551
13006
|
}
|
|
@@ -12553,8 +13008,8 @@ function writePlan(plan) {
|
|
|
12553
13008
|
skipped.push(e);
|
|
12554
13009
|
continue;
|
|
12555
13010
|
}
|
|
12556
|
-
|
|
12557
|
-
|
|
13011
|
+
fs14.mkdirSync(path25.dirname(e.path), { recursive: true });
|
|
13012
|
+
fs14.writeFileSync(e.path, e.content, "utf-8");
|
|
12558
13013
|
if (e.action === "create") created.push(e);
|
|
12559
13014
|
else if (e.action === "merge") merged.push(e);
|
|
12560
13015
|
else if (e.action === "overwrite") overwritten.push(e);
|
|
@@ -12563,8 +13018,8 @@ function writePlan(plan) {
|
|
|
12563
13018
|
}
|
|
12564
13019
|
|
|
12565
13020
|
// src/cli/commands/project-upgrade-openapi.ts
|
|
12566
|
-
import
|
|
12567
|
-
import
|
|
13021
|
+
import fs15 from "fs";
|
|
13022
|
+
import path26 from "path";
|
|
12568
13023
|
import { Command as Command4, Option as Option4 } from "clipanion";
|
|
12569
13024
|
import { Project, IndentationText, QuoteKind, NewLineKind } from "ts-morph";
|
|
12570
13025
|
|
|
@@ -12803,35 +13258,35 @@ var MAIN_SWAGGER_IMPORTS = [
|
|
|
12803
13258
|
"import { OPENAPI_REGISTRY, OpenApiRegistry } from './shared/openapi';"
|
|
12804
13259
|
];
|
|
12805
13260
|
function runtimeRoot3() {
|
|
12806
|
-
const pkgRoot =
|
|
12807
|
-
const topLevel =
|
|
12808
|
-
if (
|
|
12809
|
-
return
|
|
13261
|
+
const pkgRoot = path26.resolve(import.meta.dirname, "..", "..", "..");
|
|
13262
|
+
const topLevel = path26.join(pkgRoot, "runtime");
|
|
13263
|
+
if (fs15.existsSync(topLevel)) return topLevel;
|
|
13264
|
+
return path26.join(pkgRoot, "dist", "runtime");
|
|
12810
13265
|
}
|
|
12811
13266
|
function loadRuntimeFile2(rel2) {
|
|
12812
|
-
return
|
|
13267
|
+
return fs15.readFileSync(path26.join(runtimeRoot3(), rel2), "utf-8");
|
|
12813
13268
|
}
|
|
12814
13269
|
function resolveProjectRoot(startDir) {
|
|
12815
|
-
let dir =
|
|
13270
|
+
let dir = path26.resolve(startDir);
|
|
12816
13271
|
for (let i = 0; i < 16; i++) {
|
|
12817
|
-
if (
|
|
13272
|
+
if (fs15.existsSync(path26.join(dir, "codegen.config.yaml")) || fs15.existsSync(path26.join(dir, "package.json"))) {
|
|
12818
13273
|
return dir;
|
|
12819
13274
|
}
|
|
12820
|
-
const parent =
|
|
13275
|
+
const parent = path26.dirname(dir);
|
|
12821
13276
|
if (parent === dir) break;
|
|
12822
13277
|
dir = parent;
|
|
12823
13278
|
}
|
|
12824
|
-
return
|
|
13279
|
+
return path26.resolve(startDir);
|
|
12825
13280
|
}
|
|
12826
13281
|
async function runUpgradeOpenapi(opts) {
|
|
12827
13282
|
const { projectRoot, dryRun, force } = opts;
|
|
12828
13283
|
const changes = [];
|
|
12829
13284
|
for (const v of OPENAPI_VENDORED_FILES) {
|
|
12830
|
-
const target =
|
|
12831
|
-
const exists =
|
|
13285
|
+
const target = path26.join(projectRoot, v.target);
|
|
13286
|
+
const exists = fs15.existsSync(target);
|
|
12832
13287
|
const newContent = loadRuntimeFile2(v.runtime);
|
|
12833
13288
|
if (exists && !force) {
|
|
12834
|
-
const existing =
|
|
13289
|
+
const existing = fs15.readFileSync(target, "utf-8");
|
|
12835
13290
|
if (existing === newContent) {
|
|
12836
13291
|
changes.push({ path: v.target, action: "unchanged" });
|
|
12837
13292
|
} else {
|
|
@@ -12843,8 +13298,8 @@ async function runUpgradeOpenapi(opts) {
|
|
|
12843
13298
|
}
|
|
12844
13299
|
} else {
|
|
12845
13300
|
if (!dryRun) {
|
|
12846
|
-
|
|
12847
|
-
|
|
13301
|
+
fs15.mkdirSync(path26.dirname(target), { recursive: true });
|
|
13302
|
+
fs15.writeFileSync(target, newContent);
|
|
12848
13303
|
}
|
|
12849
13304
|
changes.push({
|
|
12850
13305
|
path: v.target,
|
|
@@ -12852,8 +13307,8 @@ async function runUpgradeOpenapi(opts) {
|
|
|
12852
13307
|
});
|
|
12853
13308
|
}
|
|
12854
13309
|
}
|
|
12855
|
-
const appModulePath =
|
|
12856
|
-
if (!
|
|
13310
|
+
const appModulePath = path26.join(projectRoot, "src", "app.module.ts");
|
|
13311
|
+
if (!fs15.existsSync(appModulePath)) {
|
|
12857
13312
|
return {
|
|
12858
13313
|
projectRoot,
|
|
12859
13314
|
changes,
|
|
@@ -12936,8 +13391,8 @@ async function runUpgradeOpenapi(opts) {
|
|
|
12936
13391
|
} else {
|
|
12937
13392
|
changes.push({ path: "src/app.module.ts", action: "unchanged" });
|
|
12938
13393
|
}
|
|
12939
|
-
const mainPath =
|
|
12940
|
-
if (
|
|
13394
|
+
const mainPath = path26.join(projectRoot, "src", "main.ts");
|
|
13395
|
+
if (fs15.existsSync(mainPath)) {
|
|
12941
13396
|
const mainSource = project.addSourceFileAtPath(mainPath);
|
|
12942
13397
|
const mainBefore = mainSource.getFullText();
|
|
12943
13398
|
const result = ensureMainSwaggerBlock(mainSource, {
|
|
@@ -13017,8 +13472,8 @@ var ProjectUpgradeOpenapiCommand = class extends Command4 {
|
|
|
13017
13472
|
json = Option4.Boolean("--json", false);
|
|
13018
13473
|
async execute() {
|
|
13019
13474
|
if (this.json) setJsonMode(true);
|
|
13020
|
-
const startDir = this.pathOpt ?
|
|
13021
|
-
if (!
|
|
13475
|
+
const startDir = this.pathOpt ? path26.resolve(this.pathOpt) : process.cwd();
|
|
13476
|
+
if (!fs15.existsSync(startDir)) {
|
|
13022
13477
|
printError(`Directory not found: ${startDir}`);
|
|
13023
13478
|
return 1;
|
|
13024
13479
|
}
|
|
@@ -13093,18 +13548,18 @@ ${CONSUMER_SETUP_POINTER}
|
|
|
13093
13548
|
};
|
|
13094
13549
|
|
|
13095
13550
|
// src/cli/commands/project-update.ts
|
|
13096
|
-
import
|
|
13097
|
-
import
|
|
13551
|
+
import fs18 from "fs";
|
|
13552
|
+
import path29 from "path";
|
|
13098
13553
|
import { Command as Command6, Option as Option6 } from "clipanion";
|
|
13099
13554
|
|
|
13100
13555
|
// src/cli/commands/skills.ts
|
|
13101
|
-
import
|
|
13102
|
-
import
|
|
13556
|
+
import fs17 from "fs";
|
|
13557
|
+
import path28 from "path";
|
|
13103
13558
|
import { Command as Command5, Option as Option5 } from "clipanion";
|
|
13104
13559
|
|
|
13105
13560
|
// src/cli/shared/tree-copier.ts
|
|
13106
|
-
import
|
|
13107
|
-
import
|
|
13561
|
+
import fs16 from "fs";
|
|
13562
|
+
import path27 from "path";
|
|
13108
13563
|
var TEXT_EXTENSIONS = [".ts", ".tsx", ".md", ".mdx", ".yaml", ".yml", ".json"];
|
|
13109
13564
|
function isTextFile(name) {
|
|
13110
13565
|
return TEXT_EXTENSIONS.some((ext) => name.endsWith(ext));
|
|
@@ -13117,26 +13572,26 @@ function copyTreeWithReport(opts) {
|
|
|
13117
13572
|
updated: [],
|
|
13118
13573
|
unchanged: []
|
|
13119
13574
|
};
|
|
13120
|
-
if (!
|
|
13575
|
+
if (!fs16.existsSync(srcDir) || !fs16.statSync(srcDir).isDirectory()) {
|
|
13121
13576
|
throw new Error(`tree-copier source directory not found: ${srcDir}`);
|
|
13122
13577
|
}
|
|
13123
13578
|
const walk = (relDir) => {
|
|
13124
|
-
const absSrcDir =
|
|
13125
|
-
for (const entry of
|
|
13126
|
-
const relPath2 = relDir ?
|
|
13127
|
-
const absSrc =
|
|
13579
|
+
const absSrcDir = path27.join(srcDir, relDir);
|
|
13580
|
+
for (const entry of fs16.readdirSync(absSrcDir, { withFileTypes: true })) {
|
|
13581
|
+
const relPath2 = relDir ? path27.posix.join(relDir, entry.name) : entry.name;
|
|
13582
|
+
const absSrc = path27.join(srcDir, relPath2);
|
|
13128
13583
|
if (entry.isDirectory()) {
|
|
13129
13584
|
walk(relPath2);
|
|
13130
13585
|
continue;
|
|
13131
13586
|
}
|
|
13132
13587
|
if (!entry.isFile()) continue;
|
|
13133
13588
|
if (include && !include(relPath2)) continue;
|
|
13134
|
-
const dest =
|
|
13135
|
-
let content =
|
|
13589
|
+
const dest = path27.join(destDir, relPath2);
|
|
13590
|
+
let content = fs16.readFileSync(absSrc, "utf-8");
|
|
13136
13591
|
if (transform && isTextFile(entry.name)) {
|
|
13137
13592
|
content = transform(content, dest);
|
|
13138
13593
|
}
|
|
13139
|
-
const existing =
|
|
13594
|
+
const existing = fs16.existsSync(dest) ? fs16.readFileSync(dest, "utf-8") : null;
|
|
13140
13595
|
let action;
|
|
13141
13596
|
if (existing === null) {
|
|
13142
13597
|
action = "created";
|
|
@@ -13146,8 +13601,8 @@ function copyTreeWithReport(opts) {
|
|
|
13146
13601
|
action = "updated";
|
|
13147
13602
|
}
|
|
13148
13603
|
if (!dryRun && action !== "unchanged") {
|
|
13149
|
-
|
|
13150
|
-
|
|
13604
|
+
fs16.mkdirSync(path27.dirname(dest), { recursive: true });
|
|
13605
|
+
fs16.writeFileSync(dest, content, "utf-8");
|
|
13151
13606
|
}
|
|
13152
13607
|
const record = { relPath: relPath2, dest, action };
|
|
13153
13608
|
report.entries.push(record);
|
|
@@ -13160,23 +13615,23 @@ function copyTreeWithReport(opts) {
|
|
|
13160
13615
|
|
|
13161
13616
|
// src/cli/commands/skills.ts
|
|
13162
13617
|
function consumerSkillsRoot() {
|
|
13163
|
-
const pkgRoot =
|
|
13164
|
-
const topLevel =
|
|
13165
|
-
if (
|
|
13166
|
-
return
|
|
13618
|
+
const pkgRoot = path28.resolve(import.meta.dirname, "..", "..", "..");
|
|
13619
|
+
const topLevel = path28.join(pkgRoot, "consumer-skills");
|
|
13620
|
+
if (fs17.existsSync(topLevel)) return topLevel;
|
|
13621
|
+
return path28.join(pkgRoot, "dist", "consumer-skills");
|
|
13167
13622
|
}
|
|
13168
13623
|
function skillsTargetDir(cwd) {
|
|
13169
|
-
return
|
|
13624
|
+
return path28.join(cwd, ".claude", "skills");
|
|
13170
13625
|
}
|
|
13171
13626
|
function availableSkills() {
|
|
13172
13627
|
const root = consumerSkillsRoot();
|
|
13173
|
-
if (!
|
|
13174
|
-
return
|
|
13628
|
+
if (!fs17.existsSync(root)) return [];
|
|
13629
|
+
return fs17.readdirSync(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
13175
13630
|
}
|
|
13176
13631
|
function runSkillsInstall(opts) {
|
|
13177
13632
|
const sourceRoot = consumerSkillsRoot();
|
|
13178
13633
|
const targetDir = skillsTargetDir(opts.cwd);
|
|
13179
|
-
if (!
|
|
13634
|
+
if (!fs17.existsSync(sourceRoot)) {
|
|
13180
13635
|
return {
|
|
13181
13636
|
ok: false,
|
|
13182
13637
|
sourceRoot,
|
|
@@ -13194,8 +13649,8 @@ function runSkillsInstall(opts) {
|
|
|
13194
13649
|
async function summary3(ctx) {
|
|
13195
13650
|
const skills = availableSkills();
|
|
13196
13651
|
const targetDir = skillsTargetDir(ctx.cwd);
|
|
13197
|
-
const installedDirs =
|
|
13198
|
-
|
|
13652
|
+
const installedDirs = fs17.existsSync(targetDir) ? new Set(
|
|
13653
|
+
fs17.readdirSync(targetDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name)
|
|
13199
13654
|
) : /* @__PURE__ */ new Set();
|
|
13200
13655
|
const body = [];
|
|
13201
13656
|
if (skills.length === 0) {
|
|
@@ -13213,13 +13668,13 @@ async function summary3(ctx) {
|
|
|
13213
13668
|
return {
|
|
13214
13669
|
title: "skills",
|
|
13215
13670
|
body,
|
|
13216
|
-
footer: `${installedCount} of ${skills.length} skills installed \u2192 ${
|
|
13671
|
+
footer: `${installedCount} of ${skills.length} skills installed \u2192 ${path28.relative(ctx.cwd, targetDir) || targetDir}`
|
|
13217
13672
|
};
|
|
13218
13673
|
}
|
|
13219
13674
|
async function hints3(ctx) {
|
|
13220
13675
|
const skills = availableSkills();
|
|
13221
13676
|
const targetDir = skillsTargetDir(ctx.cwd);
|
|
13222
|
-
const allPresent = skills.length > 0 &&
|
|
13677
|
+
const allPresent = skills.length > 0 && fs17.existsSync(targetDir) && skills.every((s) => fs17.existsSync(path28.join(targetDir, s)));
|
|
13223
13678
|
if (allPresent) {
|
|
13224
13679
|
return [
|
|
13225
13680
|
{ command: "codegen update", description: "Re-sync skills + runtime after a package bump" }
|
|
@@ -13294,7 +13749,7 @@ var SkillsInstallCommand = class extends Command5 {
|
|
|
13294
13749
|
});
|
|
13295
13750
|
return 0;
|
|
13296
13751
|
}
|
|
13297
|
-
printInfo(`target = ${
|
|
13752
|
+
printInfo(`target = ${path28.relative(ctx.cwd, result.targetDir) || result.targetDir}`);
|
|
13298
13753
|
console.log("");
|
|
13299
13754
|
renderTreeReport(report);
|
|
13300
13755
|
console.log("");
|
|
@@ -13322,8 +13777,8 @@ var SkillsListCommand = class extends Command5 {
|
|
|
13322
13777
|
const skills = availableSkills();
|
|
13323
13778
|
const targetDir = skillsTargetDir(ctx.cwd);
|
|
13324
13779
|
const rows = skills.map((name) => {
|
|
13325
|
-
const dir =
|
|
13326
|
-
return { name, status:
|
|
13780
|
+
const dir = path28.join(targetDir, name);
|
|
13781
|
+
return { name, status: fs17.existsSync(dir) ? "installed" : "available" };
|
|
13327
13782
|
});
|
|
13328
13783
|
if (isJsonMode()) {
|
|
13329
13784
|
printJson({ command: "skills list", target: targetDir, skills: rows });
|
|
@@ -13352,16 +13807,16 @@ var NON_RUNTIME_SUBSYSTEMS = /* @__PURE__ */ new Set(["openapi-config", "auth-in
|
|
|
13352
13807
|
function syncVendoredRuntime(cwd, write) {
|
|
13353
13808
|
const changes = [];
|
|
13354
13809
|
for (const v of VENDORED_RUNTIME_FILES) {
|
|
13355
|
-
const dest =
|
|
13810
|
+
const dest = path29.join(cwd, v.target);
|
|
13356
13811
|
const content = loadRuntimeFile(v.runtime);
|
|
13357
|
-
const existing =
|
|
13812
|
+
const existing = fs18.existsSync(dest) ? fs18.readFileSync(dest, "utf-8") : null;
|
|
13358
13813
|
let action;
|
|
13359
13814
|
if (existing === null) action = "created";
|
|
13360
13815
|
else if (existing === content) action = "unchanged";
|
|
13361
13816
|
else action = "updated";
|
|
13362
13817
|
if (write && action !== "unchanged") {
|
|
13363
|
-
|
|
13364
|
-
|
|
13818
|
+
fs18.mkdirSync(path29.dirname(dest), { recursive: true });
|
|
13819
|
+
fs18.writeFileSync(dest, content, "utf-8");
|
|
13365
13820
|
}
|
|
13366
13821
|
changes.push({ path: v.target, action });
|
|
13367
13822
|
}
|
|
@@ -13372,17 +13827,17 @@ async function syncSubsystemRuntime(cwd, inst, write) {
|
|
|
13372
13827
|
return { name: inst.name, changes: [], skippedReason: "config-only / vendored elsewhere" };
|
|
13373
13828
|
}
|
|
13374
13829
|
const source = subsystemSource(inst.name);
|
|
13375
|
-
if (!
|
|
13830
|
+
if (!fs18.existsSync(source)) {
|
|
13376
13831
|
return { name: inst.name, changes: [], skippedReason: "no runtime source in package" };
|
|
13377
13832
|
}
|
|
13378
|
-
const subsystemsRoot =
|
|
13833
|
+
const subsystemsRoot = path29.dirname(inst.path);
|
|
13379
13834
|
const result = await copyRuntime({
|
|
13380
13835
|
sourceDir: source,
|
|
13381
13836
|
targetDir: inst.path,
|
|
13382
13837
|
filter: backendFileFilter(inst.backend, inst.name),
|
|
13383
13838
|
resolveDeps: true,
|
|
13384
13839
|
runtimeRoot: runtimeRoot2(),
|
|
13385
|
-
depsTargetRoot:
|
|
13840
|
+
depsTargetRoot: path29.resolve(subsystemsRoot, ".."),
|
|
13386
13841
|
dryRun: !write,
|
|
13387
13842
|
// Refresh files already vendored for this subsystem; never install new
|
|
13388
13843
|
// ones (that's `subsystem install`). copyRuntime classifies accurately
|
|
@@ -13396,7 +13851,7 @@ async function syncSubsystemRuntime(cwd, inst, write) {
|
|
|
13396
13851
|
return { name: inst.name, changes };
|
|
13397
13852
|
}
|
|
13398
13853
|
function rel(cwd, abs) {
|
|
13399
|
-
return
|
|
13854
|
+
return path29.relative(cwd, abs) || abs;
|
|
13400
13855
|
}
|
|
13401
13856
|
var ProjectUpdateCommand = class extends Command6 {
|
|
13402
13857
|
static paths = [["project", "update"]];
|
|
@@ -13435,7 +13890,7 @@ var ProjectUpdateCommand = class extends Command6 {
|
|
|
13435
13890
|
const installed = this.skipSubsystems ? [] : await detectInstalledSubsystems(ctx);
|
|
13436
13891
|
if (!this.dryRun && !this.force) {
|
|
13437
13892
|
const vendoredDry = syncVendoredRuntime(ctx.cwd, false);
|
|
13438
|
-
const vendoredDirtyCandidates = vendoredDry.filter((c) => c.action === "updated").map((c) =>
|
|
13893
|
+
const vendoredDirtyCandidates = vendoredDry.filter((c) => c.action === "updated").map((c) => path29.join(ctx.cwd, c.path));
|
|
13439
13894
|
const skillDirtyCandidates = this.skipSkills ? [] : runSkillsInstall({ cwd: ctx.cwd, dryRun: true }).report?.updated.map((e) => e.dest) ?? [];
|
|
13440
13895
|
const subsystemDirs = installed.filter((i) => !NON_RUNTIME_SUBSYSTEMS.has(i.name)).map((i) => i.path);
|
|
13441
13896
|
const gate = checkGitSafety(
|
|
@@ -13606,7 +14061,8 @@ var ProjectInitCommand = class extends Command7 {
|
|
|
13606
14061
|
static usage = Command7.Usage({
|
|
13607
14062
|
description: "Scaffold a consumer project (config, shims, barrels, app.module)",
|
|
13608
14063
|
examples: [
|
|
13609
|
-
["Initialize with defaults", "codegen project init --yes"],
|
|
14064
|
+
["Initialize with defaults (package runtime)", "codegen project init --yes"],
|
|
14065
|
+
["Vendored runtime (legacy @shared/** model)", "codegen project init --yes --runtime vendored"],
|
|
13610
14066
|
["Preview without writing", "codegen project init --dry-run"],
|
|
13611
14067
|
["Create tsconfig if missing", "codegen project init --yes --with-tsconfig"],
|
|
13612
14068
|
["Overwrite existing shims", "codegen project init --force"]
|
|
@@ -13616,6 +14072,9 @@ var ProjectInitCommand = class extends Command7 {
|
|
|
13616
14072
|
dryRun = Option7.Boolean("--dry-run", false);
|
|
13617
14073
|
force = Option7.Boolean("--force", false);
|
|
13618
14074
|
withTsconfig = Option7.Boolean("--with-tsconfig", false);
|
|
14075
|
+
// Runtime mode (ADR-037). `package` (default) ⇒ depend on the npm package,
|
|
14076
|
+
// vendor nothing; `vendored` ⇒ vendor src/shared/** and import via @shared/*.
|
|
14077
|
+
runtime = Option7.String("--runtime", "package");
|
|
13619
14078
|
// Vendor consumer skills into .claude/skills by default; opt out with --no-skills.
|
|
13620
14079
|
skills = Option7.Boolean("--skills", true);
|
|
13621
14080
|
json = Option7.Boolean("--json", false);
|
|
@@ -13627,11 +14086,18 @@ var ProjectInitCommand = class extends Command7 {
|
|
|
13627
14086
|
json: this.json,
|
|
13628
14087
|
skipDetection: false
|
|
13629
14088
|
});
|
|
14089
|
+
const runtimeMode = this.runtime === "vendored" ? "vendored" : "package";
|
|
14090
|
+
if (this.runtime !== "package" && this.runtime !== "vendored" && !isJsonMode()) {
|
|
14091
|
+
printWarning(
|
|
14092
|
+
`--runtime '${this.runtime}' is not recognized (expected 'package' or 'vendored'); using 'package'.`
|
|
14093
|
+
);
|
|
14094
|
+
}
|
|
13630
14095
|
const plan = await buildInitPlan(ctx, {
|
|
13631
14096
|
cwd: ctx.cwd,
|
|
13632
14097
|
force: this.force,
|
|
13633
14098
|
withTsconfig: this.withTsconfig,
|
|
13634
|
-
skipScan: false
|
|
14099
|
+
skipScan: false,
|
|
14100
|
+
runtimeMode
|
|
13635
14101
|
});
|
|
13636
14102
|
if (this.force && !isJsonMode()) {
|
|
13637
14103
|
printWarning("--force: existing scaffold files will be overwritten.");
|
|
@@ -13775,9 +14241,9 @@ var ProjectScanCommand = class extends Command7 {
|
|
|
13775
14241
|
cwd = Option7.String("--cwd", { required: false });
|
|
13776
14242
|
async execute() {
|
|
13777
14243
|
if (this.json) setJsonMode(true);
|
|
13778
|
-
const baseCwd = this.cwd ?
|
|
13779
|
-
const target = this.directory ?
|
|
13780
|
-
if (!
|
|
14244
|
+
const baseCwd = this.cwd ? path30.resolve(this.cwd) : process.cwd();
|
|
14245
|
+
const target = this.directory ? path30.resolve(baseCwd, this.directory) : baseCwd;
|
|
14246
|
+
if (!fs19.existsSync(target)) {
|
|
13781
14247
|
printError(`Directory not found: ${target}`);
|
|
13782
14248
|
return 1;
|
|
13783
14249
|
}
|
|
@@ -13827,8 +14293,8 @@ var ProjectScanCommand = class extends Command7 {
|
|
|
13827
14293
|
`architecture: ${profile.architecture.evidence.join(", ") || "\u2014"}`
|
|
13828
14294
|
]);
|
|
13829
14295
|
}
|
|
13830
|
-
const outPath =
|
|
13831
|
-
const existsNow =
|
|
14296
|
+
const outPath = path30.join(target, "codegen.config.yaml");
|
|
14297
|
+
const existsNow = fs19.existsSync(outPath);
|
|
13832
14298
|
if (this.dryRun) {
|
|
13833
14299
|
console.log("");
|
|
13834
14300
|
printInfo("Dry run \u2014 proposed codegen.config.yaml:");
|
|
@@ -13841,7 +14307,7 @@ var ProjectScanCommand = class extends Command7 {
|
|
|
13841
14307
|
printWarning(`${outPath} already exists \u2014 pass --force via edit; skipping.`);
|
|
13842
14308
|
return 0;
|
|
13843
14309
|
}
|
|
13844
|
-
|
|
14310
|
+
fs19.writeFileSync(outPath, yamlText);
|
|
13845
14311
|
printSuccess(`wrote ${outPath}`);
|
|
13846
14312
|
return 0;
|
|
13847
14313
|
}
|
|
@@ -13948,12 +14414,12 @@ var ProjectInspectCommand = class extends Command7 {
|
|
|
13948
14414
|
return 2;
|
|
13949
14415
|
}
|
|
13950
14416
|
resolveEntitiesDir(ctx) {
|
|
13951
|
-
if (this.dir) return
|
|
13952
|
-
return ctx.entitiesDir ??
|
|
14417
|
+
if (this.dir) return path30.resolve(ctx.cwd, this.dir);
|
|
14418
|
+
return ctx.entitiesDir ?? path30.resolve(ctx.cwd, "entities");
|
|
13953
14419
|
}
|
|
13954
14420
|
async runAnalysis(ctx, kind) {
|
|
13955
14421
|
const entitiesDir = this.resolveEntitiesDir(ctx);
|
|
13956
|
-
if (!entitiesDir || !
|
|
14422
|
+
if (!entitiesDir || !fs19.existsSync(entitiesDir)) {
|
|
13957
14423
|
printError(`Directory not found: ${entitiesDir ?? "(no entities/ dir)"}`);
|
|
13958
14424
|
return 1;
|
|
13959
14425
|
}
|
|
@@ -13983,7 +14449,7 @@ var ProjectInspectCommand = class extends Command7 {
|
|
|
13983
14449
|
out = formatConsole(filtered);
|
|
13984
14450
|
}
|
|
13985
14451
|
if (this.output) {
|
|
13986
|
-
|
|
14452
|
+
fs19.writeFileSync(this.output, out);
|
|
13987
14453
|
if (!isJsonMode()) printSuccess(`wrote ${this.output}`);
|
|
13988
14454
|
} else {
|
|
13989
14455
|
console.log(out);
|
|
@@ -13996,7 +14462,7 @@ var ProjectInspectCommand = class extends Command7 {
|
|
|
13996
14462
|
}
|
|
13997
14463
|
async runManifest(ctx) {
|
|
13998
14464
|
const entitiesDir = this.resolveEntitiesDir(ctx);
|
|
13999
|
-
if (!entitiesDir || !
|
|
14465
|
+
if (!entitiesDir || !fs19.existsSync(entitiesDir)) {
|
|
14000
14466
|
printError(`Directory not found: ${entitiesDir ?? "(no entities/ dir)"}`);
|
|
14001
14467
|
return 1;
|
|
14002
14468
|
}
|
|
@@ -14152,17 +14618,17 @@ var ProjectGraphCommand = class extends Command7 {
|
|
|
14152
14618
|
json: this.json,
|
|
14153
14619
|
skipDetection: true
|
|
14154
14620
|
});
|
|
14155
|
-
const entitiesDir = this.dir ?
|
|
14156
|
-
if (!
|
|
14621
|
+
const entitiesDir = this.dir ? path30.resolve(ctx.cwd, this.dir) : ctx.entitiesDir ?? path30.resolve(ctx.cwd, "entities");
|
|
14622
|
+
if (!fs19.existsSync(entitiesDir)) {
|
|
14157
14623
|
printError(`Entity directory not found: ${entitiesDir}`);
|
|
14158
14624
|
return 1;
|
|
14159
14625
|
}
|
|
14160
14626
|
const relCandidates = [
|
|
14161
|
-
|
|
14162
|
-
|
|
14163
|
-
|
|
14627
|
+
path30.resolve(path30.dirname(entitiesDir), "relationships"),
|
|
14628
|
+
path30.resolve(entitiesDir, "relationships"),
|
|
14629
|
+
path30.resolve(ctx.cwd, "relationships")
|
|
14164
14630
|
];
|
|
14165
|
-
const relationshipsDir = relCandidates.find((d) =>
|
|
14631
|
+
const relationshipsDir = relCandidates.find((d) => fs19.existsSync(d));
|
|
14166
14632
|
const result = await analyzeDomain(entitiesDir, relationshipsDir);
|
|
14167
14633
|
const serialized = serializeDomainGraph(result.graph);
|
|
14168
14634
|
if (isJsonMode()) {
|
|
@@ -14176,20 +14642,20 @@ var ProjectGraphCommand = class extends Command7 {
|
|
|
14176
14642
|
return 0;
|
|
14177
14643
|
}
|
|
14178
14644
|
if (this.output) {
|
|
14179
|
-
const outPath =
|
|
14180
|
-
|
|
14645
|
+
const outPath = path30.resolve(ctx.cwd, this.output);
|
|
14646
|
+
fs19.writeFileSync(outPath, JSON.stringify(serialized, null, 2));
|
|
14181
14647
|
printSuccess(`Graph written to ${outPath}`);
|
|
14182
14648
|
printInfo(`${result.entities.length} entities, ${result.relationshipDefinitions.length} relationships, ${result.graph.edges.length} edges`);
|
|
14183
14649
|
return 0;
|
|
14184
14650
|
}
|
|
14185
14651
|
const os = await import("os");
|
|
14186
|
-
const tmpDir =
|
|
14187
|
-
const graphPath =
|
|
14188
|
-
|
|
14189
|
-
const viewerDir =
|
|
14190
|
-
const viewerDist =
|
|
14191
|
-
if (
|
|
14192
|
-
|
|
14652
|
+
const tmpDir = fs19.mkdtempSync(path30.join(os.default.tmpdir(), "codegen-graph-"));
|
|
14653
|
+
const graphPath = path30.join(tmpDir, "graph.json");
|
|
14654
|
+
fs19.writeFileSync(graphPath, JSON.stringify(serialized, null, 2));
|
|
14655
|
+
const viewerDir = path30.resolve(import.meta.dirname, "..", "..", "..", "tools", "schema-graph-viewer");
|
|
14656
|
+
const viewerDist = path30.join(viewerDir, "dist", "index.html");
|
|
14657
|
+
if (fs19.existsSync(viewerDist)) {
|
|
14658
|
+
fs19.copyFileSync(graphPath, path30.join(viewerDir, "dist", "graph.json"));
|
|
14193
14659
|
printSuccess("Graph exported");
|
|
14194
14660
|
printInfo(`${result.entities.length} entities, ${result.relationshipDefinitions.length} relationships, ${result.graph.edges.length} edges`);
|
|
14195
14661
|
printInfo(`Graph JSON: ${graphPath}`);
|
|
@@ -14220,8 +14686,8 @@ var projectNoun = {
|
|
|
14220
14686
|
var project_default = projectNoun;
|
|
14221
14687
|
|
|
14222
14688
|
// src/cli/commands/dev.ts
|
|
14223
|
-
import
|
|
14224
|
-
import
|
|
14689
|
+
import fs20 from "fs";
|
|
14690
|
+
import path31 from "path";
|
|
14225
14691
|
import { execSync as execSync3, spawn, spawnSync } from "child_process";
|
|
14226
14692
|
import { Command as Command8, Option as Option8 } from "clipanion";
|
|
14227
14693
|
var DEFAULT_APP_PORT = 3e3;
|
|
@@ -14254,33 +14720,33 @@ function getRedisPort(_ctx) {
|
|
|
14254
14720
|
return Number(process.env.DEV_REDIS_PORT ?? DEFAULT_REDIS_PORT);
|
|
14255
14721
|
}
|
|
14256
14722
|
function composeFilePath(cwd) {
|
|
14257
|
-
const devPath =
|
|
14258
|
-
if (
|
|
14259
|
-
const rootPath =
|
|
14260
|
-
if (
|
|
14723
|
+
const devPath = path31.join(cwd, COMPOSE_FILE);
|
|
14724
|
+
if (fs20.existsSync(devPath)) return devPath;
|
|
14725
|
+
const rootPath = path31.join(cwd, "docker-compose.yml");
|
|
14726
|
+
if (fs20.existsSync(rootPath)) return rootPath;
|
|
14261
14727
|
return devPath;
|
|
14262
14728
|
}
|
|
14263
14729
|
function pidFilePath(cwd) {
|
|
14264
|
-
return
|
|
14730
|
+
return path31.join(cwd, PID_FILE);
|
|
14265
14731
|
}
|
|
14266
14732
|
function readAppPid(cwd) {
|
|
14267
14733
|
const p = pidFilePath(cwd);
|
|
14268
|
-
if (!
|
|
14269
|
-
const pid = parseInt(
|
|
14734
|
+
if (!fs20.existsSync(p)) return null;
|
|
14735
|
+
const pid = parseInt(fs20.readFileSync(p, "utf-8").trim(), 10);
|
|
14270
14736
|
if (isNaN(pid)) return null;
|
|
14271
14737
|
try {
|
|
14272
14738
|
process.kill(pid, 0);
|
|
14273
14739
|
return pid;
|
|
14274
14740
|
} catch {
|
|
14275
|
-
|
|
14741
|
+
fs20.rmSync(p, { force: true });
|
|
14276
14742
|
return null;
|
|
14277
14743
|
}
|
|
14278
14744
|
}
|
|
14279
14745
|
function writeAppPid(cwd, pid) {
|
|
14280
|
-
|
|
14746
|
+
fs20.writeFileSync(pidFilePath(cwd), String(pid));
|
|
14281
14747
|
}
|
|
14282
14748
|
function clearAppPid(cwd) {
|
|
14283
|
-
|
|
14749
|
+
fs20.rmSync(pidFilePath(cwd), { force: true });
|
|
14284
14750
|
}
|
|
14285
14751
|
function checkPostgres(cwd, port) {
|
|
14286
14752
|
const r = runCmd(`docker exec codegen-dev-postgres pg_isready -U postgres`, cwd, {
|
|
@@ -14320,9 +14786,9 @@ function checkApp(cwd, port) {
|
|
|
14320
14786
|
};
|
|
14321
14787
|
}
|
|
14322
14788
|
function listEntityNames(ctx) {
|
|
14323
|
-
if (!ctx.entitiesDir || !
|
|
14789
|
+
if (!ctx.entitiesDir || !fs20.existsSync(ctx.entitiesDir)) return [];
|
|
14324
14790
|
return findYamlFiles(ctx.entitiesDir).map(
|
|
14325
|
-
(f) =>
|
|
14791
|
+
(f) => path31.basename(f).replace(/\.ya?ml$/, "")
|
|
14326
14792
|
);
|
|
14327
14793
|
}
|
|
14328
14794
|
function formatServiceLine(svc) {
|
|
@@ -14332,8 +14798,8 @@ function formatServiceLine(svc) {
|
|
|
14332
14798
|
return `${icon} ${svc.name.padEnd(12)} ${theme.muted(`${svc.host}:${svc.port}`)} ${status}${pidStr}`;
|
|
14333
14799
|
}
|
|
14334
14800
|
function ensureComposeFile(cwd, pgPort, redisPort) {
|
|
14335
|
-
const composePath =
|
|
14336
|
-
if (
|
|
14801
|
+
const composePath = path31.join(cwd, COMPOSE_FILE);
|
|
14802
|
+
if (fs20.existsSync(composePath)) return composePath;
|
|
14337
14803
|
const content = `# Auto-generated by codegen dev
|
|
14338
14804
|
# Ports offset from defaults to avoid conflicts with other local services.
|
|
14339
14805
|
services:
|
|
@@ -14368,7 +14834,7 @@ services:
|
|
|
14368
14834
|
volumes:
|
|
14369
14835
|
codegen-dev-pgdata:
|
|
14370
14836
|
`;
|
|
14371
|
-
|
|
14837
|
+
fs20.writeFileSync(composePath, content);
|
|
14372
14838
|
return composePath;
|
|
14373
14839
|
}
|
|
14374
14840
|
var DevUpCommand = class extends Command8 {
|
|
@@ -14417,7 +14883,7 @@ var DevUpCommand = class extends Command8 {
|
|
|
14417
14883
|
if (!pgReady) printWarning("postgres did not become healthy in time");
|
|
14418
14884
|
if (!redisReady) printWarning("redis did not become healthy in time");
|
|
14419
14885
|
const drizzleConfig = ["drizzle.config.ts", "drizzle.config.js"].find(
|
|
14420
|
-
(f) =>
|
|
14886
|
+
(f) => fs20.existsSync(path31.join(ctx.cwd, f))
|
|
14421
14887
|
);
|
|
14422
14888
|
if (drizzleConfig) {
|
|
14423
14889
|
if (!isJsonMode()) printInfo("pushing database schema...");
|
|
@@ -14437,8 +14903,8 @@ var DevUpCommand = class extends Command8 {
|
|
|
14437
14903
|
if (!isJsonMode()) printInfo("starting NestJS app...");
|
|
14438
14904
|
const dbUrl = `postgres://postgres:postgres@localhost:${pgPort}/codegen_dev`;
|
|
14439
14905
|
const redisUrl = `redis://localhost:${redisPort}`;
|
|
14440
|
-
const logFile =
|
|
14441
|
-
const logFd =
|
|
14906
|
+
const logFile = path31.join(ctx.cwd, ".dev-app.log");
|
|
14907
|
+
const logFd = fs20.openSync(logFile, "a");
|
|
14442
14908
|
const child = spawn("bun", ["src/main.ts"], {
|
|
14443
14909
|
cwd: ctx.cwd,
|
|
14444
14910
|
detached: true,
|
|
@@ -14451,7 +14917,7 @@ var DevUpCommand = class extends Command8 {
|
|
|
14451
14917
|
}
|
|
14452
14918
|
});
|
|
14453
14919
|
child.unref();
|
|
14454
|
-
|
|
14920
|
+
fs20.closeSync(logFd);
|
|
14455
14921
|
if (child.pid) {
|
|
14456
14922
|
writeAppPid(ctx.cwd, child.pid);
|
|
14457
14923
|
spawnSync("sleep", ["2"]);
|
|
@@ -14595,8 +15061,8 @@ var DevLogsCommand = class extends Command8 {
|
|
|
14595
15061
|
}
|
|
14596
15062
|
return 0;
|
|
14597
15063
|
}
|
|
14598
|
-
const logFile =
|
|
14599
|
-
if (!
|
|
15064
|
+
const logFile = path31.join(ctx.cwd, ".dev-app.log");
|
|
15065
|
+
if (!fs20.existsSync(logFile)) {
|
|
14600
15066
|
printInfo("no app logs found \u2014 is the app running?");
|
|
14601
15067
|
return 0;
|
|
14602
15068
|
}
|
|
@@ -14639,8 +15105,8 @@ var DevRestartCommand = class extends Command8 {
|
|
|
14639
15105
|
spawnSync("sleep", ["1"]);
|
|
14640
15106
|
const dbUrl = `postgres://postgres:postgres@localhost:${pgPort}/codegen_dev`;
|
|
14641
15107
|
const redisUrl = `redis://localhost:${redisPort}`;
|
|
14642
|
-
const logFile =
|
|
14643
|
-
const logFd =
|
|
15108
|
+
const logFile = path31.join(ctx.cwd, ".dev-app.log");
|
|
15109
|
+
const logFd = fs20.openSync(logFile, "a");
|
|
14644
15110
|
const child = spawn("bun", ["src/main.ts"], {
|
|
14645
15111
|
cwd: ctx.cwd,
|
|
14646
15112
|
detached: true,
|
|
@@ -14653,7 +15119,7 @@ var DevRestartCommand = class extends Command8 {
|
|
|
14653
15119
|
}
|
|
14654
15120
|
});
|
|
14655
15121
|
child.unref();
|
|
14656
|
-
|
|
15122
|
+
fs20.closeSync(logFd);
|
|
14657
15123
|
if (child.pid) {
|
|
14658
15124
|
writeAppPid(ctx.cwd, child.pid);
|
|
14659
15125
|
spawnSync("sleep", ["2"]);
|
|
@@ -14768,11 +15234,11 @@ var devNoun = {
|
|
|
14768
15234
|
var dev_default = devNoun;
|
|
14769
15235
|
|
|
14770
15236
|
// src/cli/commands/relationship.ts
|
|
14771
|
-
import
|
|
14772
|
-
import
|
|
15237
|
+
import fs21 from "fs";
|
|
15238
|
+
import path32 from "path";
|
|
14773
15239
|
import { Command as Command9, Option as Option9 } from "clipanion";
|
|
14774
15240
|
function listRelationshipYamls2(dir) {
|
|
14775
|
-
if (!
|
|
15241
|
+
if (!fs21.existsSync(dir)) return [];
|
|
14776
15242
|
return findYamlFiles(dir).filter(
|
|
14777
15243
|
(full) => detectYamlType(full) === "relationship"
|
|
14778
15244
|
);
|
|
@@ -14796,7 +15262,7 @@ function padRight2(s, n) {
|
|
|
14796
15262
|
return s.length >= n ? s : s + " ".repeat(n - s.length);
|
|
14797
15263
|
}
|
|
14798
15264
|
async function summary6(ctx) {
|
|
14799
|
-
const relDir =
|
|
15265
|
+
const relDir = path32.resolve(ctx.cwd, "relationships");
|
|
14800
15266
|
const files = listRelationshipYamls2(relDir);
|
|
14801
15267
|
if (files.length === 0) {
|
|
14802
15268
|
return {
|
|
@@ -14866,14 +15332,14 @@ var RelationshipNewCommand = class extends Command9 {
|
|
|
14866
15332
|
}
|
|
14867
15333
|
let targets = [];
|
|
14868
15334
|
if (this.all) {
|
|
14869
|
-
const dir =
|
|
15335
|
+
const dir = path32.resolve(ctx.cwd, "relationships");
|
|
14870
15336
|
targets = listRelationshipYamls2(dir);
|
|
14871
15337
|
if (targets.length === 0) {
|
|
14872
15338
|
printError(`No relationship YAML files found in ${dir}`);
|
|
14873
15339
|
return 1;
|
|
14874
15340
|
}
|
|
14875
15341
|
} else if (this.yaml) {
|
|
14876
|
-
targets = [
|
|
15342
|
+
targets = [path32.resolve(ctx.cwd, this.yaml)];
|
|
14877
15343
|
} else {
|
|
14878
15344
|
printError("Missing YAML path. Pass a file or --all.");
|
|
14879
15345
|
return 2;
|
|
@@ -14890,7 +15356,7 @@ var RelationshipNewCommand = class extends Command9 {
|
|
|
14890
15356
|
}
|
|
14891
15357
|
if (invalid.length > 0) {
|
|
14892
15358
|
for (const i of invalid) {
|
|
14893
|
-
printError(`${
|
|
15359
|
+
printError(`${path32.basename(i.file)} \u2014 ${i.message}`);
|
|
14894
15360
|
}
|
|
14895
15361
|
if (!isJsonMode()) return 1;
|
|
14896
15362
|
}
|
|
@@ -14921,7 +15387,7 @@ var RelationshipNewCommand = class extends Command9 {
|
|
|
14921
15387
|
}
|
|
14922
15388
|
const succeeded = [];
|
|
14923
15389
|
const failed = [
|
|
14924
|
-
...invalid.map((i) => ({ name:
|
|
15390
|
+
...invalid.map((i) => ({ name: path32.basename(i.file), file: i.file, message: i.message }))
|
|
14925
15391
|
];
|
|
14926
15392
|
for (const v of validated) {
|
|
14927
15393
|
if (!isJsonMode()) {
|
|
@@ -14940,8 +15406,8 @@ var RelationshipNewCommand = class extends Command9 {
|
|
|
14940
15406
|
if (!isJsonMode()) printError(`${v.name} \u2014 ${res.stderr ?? "failed"}`);
|
|
14941
15407
|
}
|
|
14942
15408
|
}
|
|
14943
|
-
const entitiesDir = ctx.entitiesDir ??
|
|
14944
|
-
const relationshipsDir =
|
|
15409
|
+
const entitiesDir = ctx.entitiesDir ?? path32.resolve(ctx.cwd, "entities");
|
|
15410
|
+
const relationshipsDir = path32.resolve(ctx.cwd, "relationships");
|
|
14945
15411
|
const generatedDir = resolveGeneratedDir(ctx);
|
|
14946
15412
|
const architecture = resolveArchitecture(ctx);
|
|
14947
15413
|
let barrelResult = null;
|
|
@@ -14986,7 +15452,7 @@ var RelationshipNewCommand = class extends Command9 {
|
|
|
14986
15452
|
}
|
|
14987
15453
|
if (barrelResult) {
|
|
14988
15454
|
printInfo(
|
|
14989
|
-
`barrels regenerated (${barrelResult.entityCount} modules) \u2192 ${
|
|
15455
|
+
`barrels regenerated (${barrelResult.entityCount} modules) \u2192 ${path32.relative(ctx.cwd, barrelResult.modulesBarrel)}, ${path32.relative(ctx.cwd, barrelResult.schemaBarrel)}`
|
|
14990
15456
|
);
|
|
14991
15457
|
}
|
|
14992
15458
|
}
|
|
@@ -15009,7 +15475,7 @@ var RelationshipListCommand = class extends Command9 {
|
|
|
15009
15475
|
json: this.json,
|
|
15010
15476
|
skipDetection: true
|
|
15011
15477
|
});
|
|
15012
|
-
const relDir =
|
|
15478
|
+
const relDir = path32.resolve(ctx.cwd, "relationships");
|
|
15013
15479
|
const files = listRelationshipYamls2(relDir);
|
|
15014
15480
|
if (files.length === 0) {
|
|
15015
15481
|
printInfo("No relationship definitions found.");
|
|
@@ -15049,7 +15515,7 @@ var relationshipNoun = {
|
|
|
15049
15515
|
var relationship_default = relationshipNoun;
|
|
15050
15516
|
|
|
15051
15517
|
// src/cli/commands/junction.ts
|
|
15052
|
-
import
|
|
15518
|
+
import path33 from "path";
|
|
15053
15519
|
import { Command as Command10, Option as Option10 } from "clipanion";
|
|
15054
15520
|
function summarizeJunctionFile(filePath) {
|
|
15055
15521
|
const result = loadJunctionFromYaml(filePath);
|
|
@@ -15072,7 +15538,7 @@ function padRight3(s, n) {
|
|
|
15072
15538
|
return s.length >= n ? s : s + " ".repeat(n - s.length);
|
|
15073
15539
|
}
|
|
15074
15540
|
async function summary7(ctx) {
|
|
15075
|
-
const junctionDir =
|
|
15541
|
+
const junctionDir = path33.resolve(ctx.cwd, "junctions");
|
|
15076
15542
|
const files = listJunctionYamls(junctionDir);
|
|
15077
15543
|
if (files.length === 0) {
|
|
15078
15544
|
return {
|
|
@@ -15142,14 +15608,14 @@ var JunctionNewCommand = class extends Command10 {
|
|
|
15142
15608
|
}
|
|
15143
15609
|
let targets = [];
|
|
15144
15610
|
if (this.all) {
|
|
15145
|
-
const dir =
|
|
15611
|
+
const dir = path33.resolve(ctx.cwd, "junctions");
|
|
15146
15612
|
targets = listJunctionYamls(dir);
|
|
15147
15613
|
if (targets.length === 0) {
|
|
15148
15614
|
printError(`No junction YAML files found in ${dir}`);
|
|
15149
15615
|
return 1;
|
|
15150
15616
|
}
|
|
15151
15617
|
} else if (this.yaml) {
|
|
15152
|
-
targets = [
|
|
15618
|
+
targets = [path33.resolve(ctx.cwd, this.yaml)];
|
|
15153
15619
|
} else {
|
|
15154
15620
|
printError("Missing YAML path. Pass a file or --all.");
|
|
15155
15621
|
return 2;
|
|
@@ -15168,7 +15634,7 @@ var JunctionNewCommand = class extends Command10 {
|
|
|
15168
15634
|
}
|
|
15169
15635
|
if (invalid.length > 0) {
|
|
15170
15636
|
for (const i of invalid) {
|
|
15171
|
-
printError(`${
|
|
15637
|
+
printError(`${path33.basename(i.file)} \u2014 ${i.message}`);
|
|
15172
15638
|
}
|
|
15173
15639
|
if (!isJsonMode()) return 1;
|
|
15174
15640
|
}
|
|
@@ -15199,7 +15665,7 @@ var JunctionNewCommand = class extends Command10 {
|
|
|
15199
15665
|
}
|
|
15200
15666
|
const succeeded = [];
|
|
15201
15667
|
const failed = [
|
|
15202
|
-
...invalid.map((i) => ({ name:
|
|
15668
|
+
...invalid.map((i) => ({ name: path33.basename(i.file), file: i.file, message: i.message }))
|
|
15203
15669
|
];
|
|
15204
15670
|
for (const v of validated) {
|
|
15205
15671
|
if (!isJsonMode()) {
|
|
@@ -15218,9 +15684,9 @@ var JunctionNewCommand = class extends Command10 {
|
|
|
15218
15684
|
if (!isJsonMode()) printError(`${v.name} \u2014 ${res.stderr ?? "failed"}`);
|
|
15219
15685
|
}
|
|
15220
15686
|
}
|
|
15221
|
-
const entitiesDir = ctx.entitiesDir ??
|
|
15222
|
-
const relationshipsDir =
|
|
15223
|
-
const junctionsDir =
|
|
15687
|
+
const entitiesDir = ctx.entitiesDir ?? path33.resolve(ctx.cwd, "entities");
|
|
15688
|
+
const relationshipsDir = path33.resolve(ctx.cwd, "relationships");
|
|
15689
|
+
const junctionsDir = path33.resolve(ctx.cwd, "junctions");
|
|
15224
15690
|
const generatedDir = resolveGeneratedDir(ctx);
|
|
15225
15691
|
const architecture = resolveArchitecture(ctx);
|
|
15226
15692
|
let barrelResult = null;
|
|
@@ -15266,7 +15732,7 @@ var JunctionNewCommand = class extends Command10 {
|
|
|
15266
15732
|
}
|
|
15267
15733
|
if (barrelResult) {
|
|
15268
15734
|
printInfo(
|
|
15269
|
-
`barrels regenerated (${barrelResult.entityCount} modules) \u2192 ${
|
|
15735
|
+
`barrels regenerated (${barrelResult.entityCount} modules) \u2192 ${path33.relative(ctx.cwd, barrelResult.modulesBarrel)}, ${path33.relative(ctx.cwd, barrelResult.schemaBarrel)}`
|
|
15270
15736
|
);
|
|
15271
15737
|
}
|
|
15272
15738
|
}
|
|
@@ -15289,7 +15755,7 @@ var JunctionListCommand = class extends Command10 {
|
|
|
15289
15755
|
json: this.json,
|
|
15290
15756
|
skipDetection: true
|
|
15291
15757
|
});
|
|
15292
|
-
const junctionDir =
|
|
15758
|
+
const junctionDir = path33.resolve(ctx.cwd, "junctions");
|
|
15293
15759
|
const files = listJunctionYamls(junctionDir);
|
|
15294
15760
|
if (files.length === 0) {
|
|
15295
15761
|
printInfo("No junction definitions found.");
|
|
@@ -15329,8 +15795,8 @@ var junctionNoun = {
|
|
|
15329
15795
|
var junction_default = junctionNoun;
|
|
15330
15796
|
|
|
15331
15797
|
// src/cli/commands/events.ts
|
|
15332
|
-
import
|
|
15333
|
-
import
|
|
15798
|
+
import fs22 from "fs";
|
|
15799
|
+
import path34 from "path";
|
|
15334
15800
|
import ts3 from "typescript";
|
|
15335
15801
|
import { Command as Command11, Option as Option11 } from "clipanion";
|
|
15336
15802
|
function scanSourceFileForConsumers(sourceFile, filePath, eventType) {
|
|
@@ -15429,7 +15895,7 @@ function scanDirectoryForConsumers(rootDir, eventType) {
|
|
|
15429
15895
|
const tier1 = [];
|
|
15430
15896
|
let hasEventFlowImport = false;
|
|
15431
15897
|
for (const filePath of files) {
|
|
15432
|
-
const text2 =
|
|
15898
|
+
const text2 = fs22.readFileSync(filePath, "utf8");
|
|
15433
15899
|
const sourceFile = ts3.createSourceFile(
|
|
15434
15900
|
filePath,
|
|
15435
15901
|
text2,
|
|
@@ -15466,7 +15932,7 @@ function suggestEventTypes(target, known, limit = 3) {
|
|
|
15466
15932
|
return known.map((t) => ({ t, d: levenshtein(target, t) })).sort((a, b) => a.d - b.d).slice(0, limit).map((x) => x.t);
|
|
15467
15933
|
}
|
|
15468
15934
|
function renderConsumerReport(result, cwd) {
|
|
15469
|
-
const rel2 = (p) =>
|
|
15935
|
+
const rel2 = (p) => path34.relative(cwd, p) || p;
|
|
15470
15936
|
const lines = [];
|
|
15471
15937
|
const total = result.tier3.length + result.tier2.length + result.tier1.length;
|
|
15472
15938
|
lines.push(`Event: ${result.eventType}`);
|
|
@@ -15502,7 +15968,7 @@ function renderConsumerReport(result, cwd) {
|
|
|
15502
15968
|
return lines;
|
|
15503
15969
|
}
|
|
15504
15970
|
function runConsumersScan(opts) {
|
|
15505
|
-
const scanRoot = opts.scanRoot ??
|
|
15971
|
+
const scanRoot = opts.scanRoot ?? path34.join(opts.cwd, "src");
|
|
15506
15972
|
const handlersDir = opts.handlersDir ?? scanRoot;
|
|
15507
15973
|
const allTriggers = scanHandlerFiles(handlersDir);
|
|
15508
15974
|
const tier3 = allTriggers.filter((t) => t.event === opts.eventType).map((t) => ({
|
|
@@ -15511,8 +15977,8 @@ function runConsumersScan(opts) {
|
|
|
15511
15977
|
sourceFile: t.sourceFile,
|
|
15512
15978
|
sourceLine: t.sourceLine
|
|
15513
15979
|
}));
|
|
15514
|
-
const tier21 =
|
|
15515
|
-
const eventsGeneratedDir = opts.eventsGeneratedDir ??
|
|
15980
|
+
const tier21 = fs22.existsSync(scanRoot) ? scanDirectoryForConsumers(scanRoot, opts.eventType) : { tier2: [], tier1: [], hasEventFlowImport: false };
|
|
15981
|
+
const eventsGeneratedDir = opts.eventsGeneratedDir ?? path34.join(
|
|
15516
15982
|
resolveSubsystemsRootFromContext(opts.cwd, opts.config),
|
|
15517
15983
|
"events",
|
|
15518
15984
|
"generated"
|
|
@@ -15533,11 +15999,11 @@ function runConsumersScan(opts) {
|
|
|
15533
15999
|
function resolveSubsystemsRootFromContext(cwd, config) {
|
|
15534
16000
|
const configured = config?.paths?.subsystems;
|
|
15535
16001
|
if (typeof configured === "string" && configured.length > 0) {
|
|
15536
|
-
return
|
|
16002
|
+
return path34.resolve(cwd, configured);
|
|
15537
16003
|
}
|
|
15538
16004
|
const backendSrc = config?.paths?.backend_src;
|
|
15539
16005
|
const base = typeof backendSrc === "string" && backendSrc.length > 0 ? backendSrc : "src";
|
|
15540
|
-
return
|
|
16006
|
+
return path34.resolve(cwd, base, "shared", "subsystems");
|
|
15541
16007
|
}
|
|
15542
16008
|
var EventsConsumersCommand = class extends Command11 {
|
|
15543
16009
|
static paths = [["events", "consumers"]];
|
|
@@ -15626,7 +16092,7 @@ var eventsNoun = {
|
|
|
15626
16092
|
var events_default = eventsNoun;
|
|
15627
16093
|
|
|
15628
16094
|
// src/cli/commands/orchestration.ts
|
|
15629
|
-
import
|
|
16095
|
+
import path35 from "path";
|
|
15630
16096
|
import { Command as Command12, Option as Option12 } from "clipanion";
|
|
15631
16097
|
var DEFAULT_PATTERN_GLOBS = ["src/patterns/*.pattern.ts"];
|
|
15632
16098
|
function resolvePatternGlobs(ctx) {
|
|
@@ -15640,10 +16106,10 @@ function resolveOrchestrationOutputRoot(ctx) {
|
|
|
15640
16106
|
const paths = ctx.config?.paths;
|
|
15641
16107
|
const explicit = paths?.orchestration_src;
|
|
15642
16108
|
if (typeof explicit === "string" && explicit.length > 0) {
|
|
15643
|
-
return
|
|
16109
|
+
return path35.resolve(ctx.cwd, explicit);
|
|
15644
16110
|
}
|
|
15645
16111
|
const backendSrc = typeof paths?.backend_src === "string" && paths.backend_src.length > 0 ? paths.backend_src : "app/backend/src";
|
|
15646
|
-
return
|
|
16112
|
+
return path35.resolve(ctx.cwd, backendSrc, "orchestration");
|
|
15647
16113
|
}
|
|
15648
16114
|
async function reloadRegistry(ctx) {
|
|
15649
16115
|
_resetRegistryForTests({ includeLibrary: false });
|
|
@@ -15732,12 +16198,12 @@ var OrchestrationGenCommand = class extends Command12 {
|
|
|
15732
16198
|
);
|
|
15733
16199
|
for (const f of result.files) {
|
|
15734
16200
|
console.log(
|
|
15735
|
-
` ${theme.muted(icons.arrow)} ${
|
|
16201
|
+
` ${theme.muted(icons.arrow)} ${path35.relative(ctx.cwd, f.outputPath)}`
|
|
15736
16202
|
);
|
|
15737
16203
|
}
|
|
15738
16204
|
} else {
|
|
15739
16205
|
printSuccess(
|
|
15740
|
-
`Emitted ${result.files.length} file(s) across ${targets.length} pattern(s) \u2192 ${
|
|
16206
|
+
`Emitted ${result.files.length} file(s) across ${targets.length} pattern(s) \u2192 ${path35.relative(ctx.cwd, outputRoot)}`
|
|
15741
16207
|
);
|
|
15742
16208
|
}
|
|
15743
16209
|
return 0;
|