@pattern-stack/codegen 0.13.0 → 0.14.0
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-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 +14 -9
- 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 +14 -9
- 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 +3 -3
- package/dist/runtime/subsystems/index.js +34 -26
- package/dist/runtime/subsystems/index.js.map +1 -1
- package/dist/runtime/subsystems/integration/incremental-read.d.ts +35 -8
- package/dist/runtime/subsystems/integration/incremental-read.js +9 -6
- package/dist/runtime/subsystems/integration/incremental-read.js.map +1 -1
- package/dist/runtime/subsystems/integration/index.d.ts +1 -1
- package/dist/runtime/subsystems/integration/index.js +9 -6
- package/dist/runtime/subsystems/integration/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 +13 -9
- 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 +9 -1
- 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 +8 -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-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 +5 -2
- package/dist/runtime/subsystems/jobs/job-worker.module.js +13 -8
- package/dist/runtime/subsystems/jobs/job-worker.module.js.map +1 -1
- package/dist/runtime/subsystems/jobs/jobs-domain.module.js +11 -6
- 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 +362 -233
- 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/cache/cache.tokens.ts +7 -2
- package/runtime/subsystems/events/events.tokens.ts +8 -1
- package/runtime/subsystems/index.ts +6 -1
- package/runtime/subsystems/integration/incremental-read.ts +43 -9
- package/runtime/subsystems/integration/index.ts +1 -0
- package/runtime/subsystems/jobs/bullmq.config.ts +5 -2
- package/runtime/subsystems/jobs/job-handler.base.ts +6 -1
- package/runtime/subsystems/jobs/job-worker.module.ts +5 -1
- 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
|
@@ -8105,164 +8105,35 @@ function validateEntityEmits(entities, events) {
|
|
|
8105
8105
|
}
|
|
8106
8106
|
|
|
8107
8107
|
// 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}';
|
|
8108
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync8, statSync as statSync6, writeFileSync as writeFileSync3 } from "fs";
|
|
8109
|
+
import { dirname as dirname2, isAbsolute as isAbsolute2, join as join12, resolve as resolve6 } from "path";
|
|
8145
8110
|
|
|
8146
|
-
|
|
8147
|
-
|
|
8148
|
-
|
|
8149
|
-
|
|
8111
|
+
// src/cli/shared/adapter-emission-generator.ts
|
|
8112
|
+
import {
|
|
8113
|
+
existsSync as existsSync9,
|
|
8114
|
+
mkdirSync as mkdirSync2,
|
|
8115
|
+
readFileSync as readFileSync7,
|
|
8116
|
+
statSync as statSync5,
|
|
8117
|
+
writeFileSync as writeFileSync2
|
|
8118
|
+
} from "fs";
|
|
8119
|
+
import { dirname, join as join11 } from "path";
|
|
8150
8120
|
|
|
8151
|
-
|
|
8152
|
-
|
|
8153
|
-
|
|
8154
|
-
|
|
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");
|
|
8121
|
+
// src/cli/shared/runtime-import.ts
|
|
8122
|
+
var PACKAGE = "@pattern-stack/codegen";
|
|
8123
|
+
function resolveRuntimeMode(config) {
|
|
8124
|
+
return config?.runtime === "vendored" ? "vendored" : "package";
|
|
8191
8125
|
}
|
|
8192
|
-
function
|
|
8193
|
-
|
|
8194
|
-
|
|
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);
|
|
8126
|
+
function subsystemsImport(mode, subsystem) {
|
|
8127
|
+
if (mode === "vendored") {
|
|
8128
|
+
return subsystem ? `@shared/subsystems/${subsystem}` : "@shared/subsystems";
|
|
8240
8129
|
}
|
|
8241
|
-
return {
|
|
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);
|
|
8130
|
+
return `${PACKAGE}/subsystems`;
|
|
8247
8131
|
}
|
|
8248
|
-
function
|
|
8249
|
-
const
|
|
8250
|
-
|
|
8251
|
-
if (idx !== -1) return filePath.slice(idx);
|
|
8252
|
-
const slash = filePath.lastIndexOf("/");
|
|
8253
|
-
return slash === -1 ? filePath : `definitions/providers/${filePath.slice(slash + 1)}`;
|
|
8132
|
+
function runtimeImport(mode, relpath) {
|
|
8133
|
+
const clean = relpath.replace(/^\/+/, "");
|
|
8134
|
+
return mode === "vendored" ? `@shared/${clean}` : `${PACKAGE}/runtime/${clean}`;
|
|
8254
8135
|
}
|
|
8255
8136
|
|
|
8256
|
-
// src/cli/shared/adapter-emission-generator.ts
|
|
8257
|
-
import {
|
|
8258
|
-
existsSync as existsSync10,
|
|
8259
|
-
mkdirSync as mkdirSync3,
|
|
8260
|
-
readFileSync as readFileSync8,
|
|
8261
|
-
statSync as statSync6,
|
|
8262
|
-
writeFileSync as writeFileSync3
|
|
8263
|
-
} from "fs";
|
|
8264
|
-
import { dirname as dirname2, join as join12 } from "path";
|
|
8265
|
-
|
|
8266
8137
|
// src/cli/shared/sink-emission-generator.ts
|
|
8267
8138
|
var SCAFFOLD_SENTINEL = "// <CODEGEN-SCAFFOLD-V1>";
|
|
8268
8139
|
var USER_ID_FIELD = "userId";
|
|
@@ -8321,7 +8192,7 @@ function generateDefaultSink(input) {
|
|
|
8321
8192
|
// for entities with external FK join-keys, fill the marked TODO(s) below.
|
|
8322
8193
|
// Source: definitions entity '${input.entityName}' (surface: ${input.surface}).
|
|
8323
8194
|
import { Injectable } from '@nestjs/common';
|
|
8324
|
-
import type { IIntegrationSink } from '
|
|
8195
|
+
import type { IIntegrationSink } from '${subsystemsImport(input.mode ?? "package", "integration")}';
|
|
8325
8196
|
import {
|
|
8326
8197
|
${n.repoClass},
|
|
8327
8198
|
type ${n.projectionType},
|
|
@@ -8374,7 +8245,7 @@ function relationLabel(writeKey) {
|
|
|
8374
8245
|
}
|
|
8375
8246
|
|
|
8376
8247
|
// src/cli/shared/assembly-emission-generator.ts
|
|
8377
|
-
import { relative, resolve as
|
|
8248
|
+
import { relative, resolve as resolve5, sep } from "path";
|
|
8378
8249
|
function generatedBanner(sourceDesc) {
|
|
8379
8250
|
return `// @generated by @pattern-stack/codegen from ${sourceDesc} \u2014 DO NOT EDIT.
|
|
8380
8251
|
// Hand edits are overwritten on re-emit. Regenerate with \`bun run codegen\`.`;
|
|
@@ -8412,7 +8283,7 @@ import {
|
|
|
8412
8283
|
ExecuteIntegrationUseCase,
|
|
8413
8284
|
INTEGRATION_CHANGE_SOURCE,
|
|
8414
8285
|
INTEGRATION_SINK,
|
|
8415
|
-
} from '
|
|
8286
|
+
} from '${subsystemsImport(input.mode ?? "package", "integration")}';
|
|
8416
8287
|
import { ${adapterClass} } from '${adapterImport}';
|
|
8417
8288
|
import { ${adapterModuleClass} } from '${adapterModuleImport}';
|
|
8418
8289
|
import { ${sinkClass} } from '${sinkImport}';
|
|
@@ -8425,7 +8296,7 @@ import { ${token} } from '${tokensImport}';
|
|
|
8425
8296
|
* inbound-integration assembly (RFC-0002 \xA72, Option A).
|
|
8426
8297
|
*
|
|
8427
8298
|
* Binds this module's INTEGRATION_CHANGE_SOURCE from the adapter's
|
|
8428
|
-
* \`changeSources
|
|
8299
|
+
* \`changeSources.${input.entityName}\` and INTEGRATION_SINK from
|
|
8429
8300
|
* ${sinkClass}, provides a local ExecuteIntegrationUseCase, and aliases+exports
|
|
8430
8301
|
* it under ${token} (the bare class token is ambiguous at app root \u2014 every
|
|
8431
8302
|
* assembly provides it). The substrate (cursor store, run recorder, differ,
|
|
@@ -8437,7 +8308,7 @@ import { ${token} } from '${tokensImport}';
|
|
|
8437
8308
|
providers: [
|
|
8438
8309
|
{
|
|
8439
8310
|
provide: INTEGRATION_CHANGE_SOURCE,
|
|
8440
|
-
useFactory: (adapter: ${adapterClass}) => adapter.changeSources
|
|
8311
|
+
useFactory: (adapter: ${adapterClass}) => adapter.changeSources.${input.entityName},
|
|
8441
8312
|
inject: [${adapterClass}],
|
|
8442
8313
|
},
|
|
8443
8314
|
{
|
|
@@ -8539,17 +8410,17 @@ function resolveEntityModuleImports(input) {
|
|
|
8539
8410
|
const repoClass = `${entityClass}Repository`;
|
|
8540
8411
|
const moduleClass = `${pluralPascalCase(input.entityPlural)}Module`;
|
|
8541
8412
|
const moduleGroupSegs = input.context ? ["modules", input.context, input.entityPlural] : ["modules", input.entityPlural];
|
|
8542
|
-
const repoFileAbs =
|
|
8413
|
+
const repoFileAbs = resolve5(
|
|
8543
8414
|
input.backendSrcAbs,
|
|
8544
8415
|
...moduleGroupSegs,
|
|
8545
8416
|
`${input.entityName}.repository.ts`
|
|
8546
8417
|
);
|
|
8547
|
-
const moduleFileAbs =
|
|
8418
|
+
const moduleFileAbs = resolve5(
|
|
8548
8419
|
input.backendSrcAbs,
|
|
8549
8420
|
...moduleGroupSegs,
|
|
8550
8421
|
`${input.entityPlural}.module.ts`
|
|
8551
8422
|
);
|
|
8552
|
-
const assemblyDirAbs =
|
|
8423
|
+
const assemblyDirAbs = resolve5(
|
|
8553
8424
|
input.backendSrcAbs,
|
|
8554
8425
|
"integrations",
|
|
8555
8426
|
input.surface,
|
|
@@ -8623,8 +8494,24 @@ var SURFACE_REGISTRY = {
|
|
|
8623
8494
|
noCapsConst: "NO_TRANSCRIPT_CAPABILITIES",
|
|
8624
8495
|
l2Ports: [],
|
|
8625
8496
|
readPrimitive: true
|
|
8497
|
+
},
|
|
8498
|
+
// messaging (swe-brain ADR-0008) — interaction surface like transcript: the
|
|
8499
|
+
// adapter contributes per-entity change sources for `channel` + `message`
|
|
8500
|
+
// (`conversation` is domain-derived by segmentation, not vendor-read). The
|
|
8501
|
+
// capability descriptor adds an optional `canWrite` flag for the bot-user write
|
|
8502
|
+
// path, which ships dark in v1; the scaffold still only constructs `entities`.
|
|
8503
|
+
messaging: {
|
|
8504
|
+
packageName: "@pattern-stack/codegen-messaging",
|
|
8505
|
+
portType: "MessagingPort",
|
|
8506
|
+
capabilitiesType: "MessagingCapabilities",
|
|
8507
|
+
noCapsConst: "NO_MESSAGING_CAPABILITIES",
|
|
8508
|
+
l2Ports: [],
|
|
8509
|
+
readPrimitive: true
|
|
8626
8510
|
}
|
|
8627
8511
|
};
|
|
8512
|
+
function isClientlessProvider(surfaces) {
|
|
8513
|
+
return surfaces.length > 0 && surfaces.every((s) => SURFACE_REGISTRY[s]?.readPrimitive === true);
|
|
8514
|
+
}
|
|
8628
8515
|
var SCAFFOLD_SENTINEL2 = "// <CODEGEN-SCAFFOLD-V1>";
|
|
8629
8516
|
function generatedBanner2(sourceDesc) {
|
|
8630
8517
|
return `// @generated by @pattern-stack/codegen from ${sourceDesc} \u2014 DO NOT EDIT.
|
|
@@ -8679,7 +8566,7 @@ function serializeFilterArray(filters) {
|
|
|
8679
8566
|
${items.join("\n")}
|
|
8680
8567
|
]`;
|
|
8681
8568
|
}
|
|
8682
|
-
function buildReadPrimitiveEmission(providerSlug, providerPascal, surface, entities, entityDetection
|
|
8569
|
+
function buildReadPrimitiveEmission(providerSlug, providerPascal, surface, entities, entityDetection) {
|
|
8683
8570
|
const canonicalTypes = [];
|
|
8684
8571
|
const blocks = [];
|
|
8685
8572
|
const entries = [];
|
|
@@ -8711,24 +8598,32 @@ export class ${className} extends IncrementalReadBase<${canonical}, ResolvedFilt
|
|
|
8711
8598
|
// (e.g. Gmail \`q=\`); leave \`false\` to filter post-hydrate via \`matchesRecord\`.
|
|
8712
8599
|
protected override readonly filterPushdown = false;${cursorOverride}
|
|
8713
8600
|
|
|
8714
|
-
constructor(
|
|
8715
|
-
private readonly auth: IAuthStrategy,
|
|
8716
|
-
private readonly client: ${clientExportName},
|
|
8717
|
-
) {
|
|
8601
|
+
constructor(private readonly auth: IAuthStrategy) {
|
|
8718
8602
|
super();
|
|
8719
8603
|
}
|
|
8720
8604
|
|
|
8721
|
-
/**
|
|
8605
|
+
/**
|
|
8606
|
+
* TODO: walk the vendor list endpoint \u2192 pages of \`Ref\` (id + cursor + meta).
|
|
8607
|
+
* Per-connection (multi-account) adapters resolve credentials here from the
|
|
8608
|
+
* threaded subscription, e.g.
|
|
8609
|
+
* \`const client = <vendorClientFactory>({ accessToken: async () => (await this.auth.resolve(_ctx!.subscription!.externalRef)).accessToken });\`
|
|
8610
|
+
* \u2014 there is no provider-level singleton client. Provider-level-auth adapters
|
|
8611
|
+
* ignore \`_ctx\`.
|
|
8612
|
+
*/
|
|
8722
8613
|
protected async *enumerate(
|
|
8723
8614
|
_mode: ReadMode,
|
|
8724
8615
|
_filter?: ResolvedFilter[],
|
|
8725
8616
|
_pageSize?: number,
|
|
8617
|
+
_ctx?: ReadContext,
|
|
8726
8618
|
): AsyncIterable<Ref[]> {
|
|
8727
8619
|
throw new Error('not implemented: ${className}.enumerate');
|
|
8728
8620
|
}
|
|
8729
8621
|
|
|
8730
|
-
/**
|
|
8731
|
-
|
|
8622
|
+
/**
|
|
8623
|
+
* TODO: batched fetch-by-id \u2192 \`Map<id, raw>\` (\`mapConcurrent\`, or a vendor /batch).
|
|
8624
|
+
* Use \`_ctx?.subscription?.id\` to key raw-landing rows per connection.
|
|
8625
|
+
*/
|
|
8626
|
+
protected async hydrate(_ids: string[], _ctx?: ReadContext): Promise<Map<string, unknown>> {
|
|
8732
8627
|
throw new Error('not implemented: ${className}.hydrate');
|
|
8733
8628
|
}
|
|
8734
8629
|
|
|
@@ -8743,15 +8638,16 @@ export class ${className} extends IncrementalReadBase<${canonical}, ResolvedFilt
|
|
|
8743
8638
|
return ${constName};
|
|
8744
8639
|
}
|
|
8745
8640
|
}`);
|
|
8746
|
-
entries.push(` ${entity}: new ${className}(this.auth
|
|
8641
|
+
entries.push(` ${entity}: new ${className}(this.auth),`);
|
|
8747
8642
|
}
|
|
8748
8643
|
return { canonicalTypes, preamble: blocks.join("\n\n"), changeSourceEntries: entries };
|
|
8749
8644
|
}
|
|
8750
|
-
function generateAdapterScaffold(def, surface, entities, entityDetection) {
|
|
8645
|
+
function generateAdapterScaffold(def, surface, entities, entityDetection, mode = "package") {
|
|
8751
8646
|
const spec = SURFACE_REGISTRY[surface];
|
|
8752
8647
|
if (!spec) throw new Error(`no surface package for '${surface}'`);
|
|
8753
8648
|
const n = names(def.slug, surface);
|
|
8754
8649
|
const client = parseImportRef(def.client.class);
|
|
8650
|
+
const subsystemsSpec = subsystemsImport(mode, "integration");
|
|
8755
8651
|
const entitiesLiteral = entities.length ? `[${entities.map((e) => `'${e}'`).join(", ")}]` : "[]";
|
|
8756
8652
|
const readPrimitive = !!spec.readPrimitive && entities.length > 0;
|
|
8757
8653
|
const rp = readPrimitive ? buildReadPrimitiveEmission(
|
|
@@ -8759,21 +8655,26 @@ function generateAdapterScaffold(def, surface, entities, entityDetection) {
|
|
|
8759
8655
|
n.providerPascal,
|
|
8760
8656
|
surface,
|
|
8761
8657
|
entities,
|
|
8762
|
-
entityDetection
|
|
8763
|
-
client.exportName
|
|
8658
|
+
entityDetection
|
|
8764
8659
|
) : null;
|
|
8765
8660
|
const surfaceTypeImports = [
|
|
8766
8661
|
spec.portType,
|
|
8767
8662
|
...spec.l2Ports.map((p) => p.type),
|
|
8768
8663
|
spec.capabilitiesType,
|
|
8769
8664
|
...rp ? rp.canonicalTypes : []
|
|
8770
|
-
].map((t) => ` ${t},`).join("\n");
|
|
8771
|
-
const subsystemValueImport = rp ? `import { IncrementalReadBase } from '
|
|
8665
|
+
].sort().map((t) => ` ${t},`).join("\n");
|
|
8666
|
+
const subsystemValueImport = rp ? `import { IncrementalReadBase } from '${subsystemsSpec}';
|
|
8772
8667
|
` : "";
|
|
8773
8668
|
const subsystemTypeImports = [
|
|
8774
8669
|
"IAuthStrategy",
|
|
8775
8670
|
"IChangeSource",
|
|
8776
|
-
...rp ? [
|
|
8671
|
+
...rp ? [
|
|
8672
|
+
"IntegrationSubscriptionView",
|
|
8673
|
+
"ReadContext",
|
|
8674
|
+
"ReadMode",
|
|
8675
|
+
"Ref",
|
|
8676
|
+
"ResolvedFilter"
|
|
8677
|
+
] : []
|
|
8777
8678
|
].map((t) => ` ${t},`).join("\n");
|
|
8778
8679
|
const changeSourcesAssign = rp ? `
|
|
8779
8680
|
this.changeSources = {
|
|
@@ -8813,6 +8714,14 @@ ${rp.preamble}
|
|
|
8813
8714
|
const l2Section = l2Members ? `
|
|
8814
8715
|
${l2Members}
|
|
8815
8716
|
` : "";
|
|
8717
|
+
const clientTypeImport = rp ? "" : `import type { ${client.exportName} } from '${client.path}';
|
|
8718
|
+
`;
|
|
8719
|
+
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';`;
|
|
8720
|
+
const ctorClientParam = rp ? "" : `
|
|
8721
|
+
@Inject(${n.clientToken}) private readonly client: ${client.exportName},`;
|
|
8722
|
+
const ctorOpen = rp ? ` constructor(@Inject(${n.strategyToken}) readonly auth: IAuthStrategy) {${changeSourcesAssign}}` : ` constructor(
|
|
8723
|
+
@Inject(${n.strategyToken}) readonly auth: IAuthStrategy,${ctorClientParam}
|
|
8724
|
+
) {${changeSourcesAssign}}`;
|
|
8816
8725
|
return `${SCAFFOLD_SENTINEL2}
|
|
8817
8726
|
// Scaffolded once by @pattern-stack/codegen, then author-owned. Re-running
|
|
8818
8727
|
// codegen detects the sentinel above and SKIPS this file \u2014 your edits are safe.
|
|
@@ -8824,9 +8733,8 @@ ${surfaceTypeImports}
|
|
|
8824
8733
|
import { ${spec.noCapsConst} } from '${spec.packageName}';
|
|
8825
8734
|
${subsystemValueImport}import type {
|
|
8826
8735
|
${subsystemTypeImports}
|
|
8827
|
-
} from '
|
|
8828
|
-
|
|
8829
|
-
import { ${n.strategyToken}, ${n.clientToken} } from '../../../providers/${def.slug}/${def.slug}.provider.module';
|
|
8736
|
+
} from '${subsystemsSpec}';
|
|
8737
|
+
${clientTypeImport}${providerTokenImport}
|
|
8830
8738
|
${preambleSection}
|
|
8831
8739
|
@Injectable()
|
|
8832
8740
|
export class ${n.adapterClass} implements ${spec.portType} {
|
|
@@ -8835,10 +8743,7 @@ export class ${n.adapterClass} implements ${spec.portType} {
|
|
|
8835
8743
|
${capabilityBody}
|
|
8836
8744
|
};
|
|
8837
8745
|
|
|
8838
|
-
|
|
8839
|
-
@Inject(${n.strategyToken}) readonly auth: IAuthStrategy,
|
|
8840
|
-
@Inject(${n.clientToken}) private readonly client: ${client.exportName},
|
|
8841
|
-
) {${changeSourcesAssign}}
|
|
8746
|
+
${ctorOpen}
|
|
8842
8747
|
${l2Section}
|
|
8843
8748
|
${changeSourcesDecl}
|
|
8844
8749
|
|
|
@@ -8870,10 +8775,10 @@ function generateAdaptersBarrel(surface, providerSlugs) {
|
|
|
8870
8775
|
${lines}
|
|
8871
8776
|
`;
|
|
8872
8777
|
}
|
|
8873
|
-
function generateSurfaceTokens(surface) {
|
|
8778
|
+
function generateSurfaceTokens(surface, mode = "package") {
|
|
8874
8779
|
const n = names("__placeholder__", surface);
|
|
8875
8780
|
return `${generatedBanner2(`surface: ${surface}`)}
|
|
8876
|
-
import type { IChangeSource } from '
|
|
8781
|
+
import type { IChangeSource } from '${subsystemsImport(mode, "integration")}';
|
|
8877
8782
|
|
|
8878
8783
|
/** The assembled list of every ${surface} adapter's contribution. */
|
|
8879
8784
|
export const ${n.contributionsToken} = Symbol.for('@app/integrations/${surface}.adapter-contributions');
|
|
@@ -8890,7 +8795,7 @@ export interface AdapterContribution {
|
|
|
8890
8795
|
}
|
|
8891
8796
|
`;
|
|
8892
8797
|
}
|
|
8893
|
-
function generateSurfaceAggregator(surface, providerSlugs) {
|
|
8798
|
+
function generateSurfaceAggregator(surface, providerSlugs, mode = "package") {
|
|
8894
8799
|
const n = names("__placeholder__", surface);
|
|
8895
8800
|
const slugs = [...providerSlugs].sort();
|
|
8896
8801
|
const per = slugs.map((slug) => names(slug, surface));
|
|
@@ -8917,7 +8822,7 @@ import {
|
|
|
8917
8822
|
MemoryEntityChangeSourceRegistry,
|
|
8918
8823
|
type IChangeSource,
|
|
8919
8824
|
type IEntityChangeSourceRegistry,
|
|
8920
|
-
} from '
|
|
8825
|
+
} from '${subsystemsImport(mode, "integration")}';
|
|
8921
8826
|
${moduleImport}
|
|
8922
8827
|
${adapterImports}
|
|
8923
8828
|
import {
|
|
@@ -9006,6 +8911,7 @@ function jsKey(key) {
|
|
|
9006
8911
|
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : `'${key}'`;
|
|
9007
8912
|
}
|
|
9008
8913
|
function emitAdapters(opts) {
|
|
8914
|
+
const mode = opts.mode ?? "package";
|
|
9009
8915
|
const result = {
|
|
9010
8916
|
written: [],
|
|
9011
8917
|
scaffoldsWritten: [],
|
|
@@ -9036,14 +8942,14 @@ function emitAdapters(opts) {
|
|
|
9036
8942
|
}
|
|
9037
8943
|
const defBySlug = new Map(opts.providers.map((p) => [p.definition.slug, p.definition]));
|
|
9038
8944
|
for (const [surface, slugs] of bySurface) {
|
|
9039
|
-
const surfaceDir =
|
|
9040
|
-
const adaptersDir =
|
|
8945
|
+
const surfaceDir = join11(opts.outputRoot, surface);
|
|
8946
|
+
const adaptersDir = join11(surfaceDir, "adapters");
|
|
9041
8947
|
for (const slug of slugs) {
|
|
9042
8948
|
const def = defBySlug.get(slug);
|
|
9043
|
-
const providerDir =
|
|
9044
|
-
const scaffoldPath =
|
|
9045
|
-
const modulePath =
|
|
9046
|
-
if (
|
|
8949
|
+
const providerDir = join11(adaptersDir, slug);
|
|
8950
|
+
const scaffoldPath = join11(providerDir, `${slug}-${surface}.adapter.ts`);
|
|
8951
|
+
const modulePath = join11(providerDir, `${slug}-${surface}.adapter.module.ts`);
|
|
8952
|
+
if (existsSync9(scaffoldPath)) {
|
|
9047
8953
|
result.scaffoldsSkipped.push(scaffoldPath);
|
|
9048
8954
|
} else {
|
|
9049
8955
|
const surfaceEntityNames = entitiesBySurface.get(surface) ?? [];
|
|
@@ -9056,27 +8962,28 @@ function emitAdapters(opts) {
|
|
|
9056
8962
|
def,
|
|
9057
8963
|
surface,
|
|
9058
8964
|
surfaceEntityNames,
|
|
9059
|
-
entityDetection
|
|
8965
|
+
entityDetection,
|
|
8966
|
+
mode
|
|
9060
8967
|
);
|
|
9061
8968
|
if (!opts.dryRun) writeFile(scaffoldPath, content);
|
|
9062
8969
|
result.scaffoldsWritten.push(scaffoldPath);
|
|
9063
8970
|
}
|
|
9064
8971
|
const moduleContent = generateAdapterModule(def, surface);
|
|
9065
|
-
if (!opts.dryRun)
|
|
8972
|
+
if (!opts.dryRun) writeIfChanged(modulePath, moduleContent);
|
|
9066
8973
|
result.written.push(modulePath);
|
|
9067
8974
|
}
|
|
9068
|
-
const barrelPath =
|
|
9069
|
-
const tokensPath =
|
|
9070
|
-
const aggregatorPath =
|
|
9071
|
-
const typedViewPath =
|
|
8975
|
+
const barrelPath = join11(adaptersDir, "index.ts");
|
|
8976
|
+
const tokensPath = join11(surfaceDir, `${surface}-adapters.tokens.ts`);
|
|
8977
|
+
const aggregatorPath = join11(surfaceDir, `${surface}-adapters.module.ts`);
|
|
8978
|
+
const typedViewPath = join11(surfaceDir, "types.generated.ts");
|
|
9072
8979
|
const files = [
|
|
9073
8980
|
[barrelPath, generateAdaptersBarrel(surface, slugs)],
|
|
9074
|
-
[tokensPath, generateSurfaceTokens(surface)],
|
|
9075
|
-
[aggregatorPath, generateSurfaceAggregator(surface, slugs)],
|
|
8981
|
+
[tokensPath, generateSurfaceTokens(surface, mode)],
|
|
8982
|
+
[aggregatorPath, generateSurfaceAggregator(surface, slugs, mode)],
|
|
9076
8983
|
[typedViewPath, generateTypedView(surface, slugs, entitiesBySurface.get(surface) ?? [])]
|
|
9077
8984
|
];
|
|
9078
8985
|
for (const [path34, content] of files) {
|
|
9079
|
-
if (!opts.dryRun)
|
|
8986
|
+
if (!opts.dryRun) writeIfChanged(path34, content);
|
|
9080
8987
|
result.written.push(path34);
|
|
9081
8988
|
}
|
|
9082
8989
|
if (opts.backendSrcAbs) {
|
|
@@ -9084,8 +8991,8 @@ function emitAdapters(opts) {
|
|
|
9084
8991
|
const surfaceEntities = entitiesBySurface.get(surface) ?? [];
|
|
9085
8992
|
const tokenEntries = [];
|
|
9086
8993
|
const assemblyEntries = [];
|
|
9087
|
-
const sinksDir =
|
|
9088
|
-
const modulesDir =
|
|
8994
|
+
const sinksDir = join11(surfaceDir, "sinks");
|
|
8995
|
+
const modulesDir = join11(surfaceDir, "modules");
|
|
9089
8996
|
for (const entityName of surfaceEntities) {
|
|
9090
8997
|
const def = entityByName.get(entityName);
|
|
9091
8998
|
const pattern = def?.entity.pattern ?? (Array.isArray(def?.entity.patterns) ? def?.entity.patterns?.[0] : void 0);
|
|
@@ -9110,17 +9017,17 @@ function emitAdapters(opts) {
|
|
|
9110
9017
|
backendSrcAbs: opts.backendSrcAbs,
|
|
9111
9018
|
aliases
|
|
9112
9019
|
});
|
|
9113
|
-
const sinkPath =
|
|
9114
|
-
if (
|
|
9020
|
+
const sinkPath = join11(sinksDir, `${entityName}.sink.ts`);
|
|
9021
|
+
if (existsSync9(sinkPath)) {
|
|
9115
9022
|
result.scaffoldsSkipped.push(sinkPath);
|
|
9116
9023
|
} else {
|
|
9117
9024
|
const sinkInput = buildSinkInput(def, surface, slugs[0], loc.repoImportSpecifier);
|
|
9118
|
-
const sinkContent = generateDefaultSink(sinkInput);
|
|
9025
|
+
const sinkContent = generateDefaultSink({ ...sinkInput, mode });
|
|
9119
9026
|
if (!opts.dryRun) writeFile(sinkPath, sinkContent);
|
|
9120
9027
|
result.scaffoldsWritten.push(sinkPath);
|
|
9121
9028
|
}
|
|
9122
9029
|
for (const slug of slugs) {
|
|
9123
|
-
const assemblyPath =
|
|
9030
|
+
const assemblyPath = join11(
|
|
9124
9031
|
modulesDir,
|
|
9125
9032
|
slug,
|
|
9126
9033
|
`${entityName}-integration.module.ts`
|
|
@@ -9134,23 +9041,24 @@ function emitAdapters(opts) {
|
|
|
9134
9041
|
moduleClass: loc.moduleClass,
|
|
9135
9042
|
repoImportSpecifier: loc.repoImportSpecifier,
|
|
9136
9043
|
repoClass: loc.repoClass,
|
|
9137
|
-
sourceDesc: `definitions/providers/${slug}.yaml
|
|
9044
|
+
sourceDesc: `definitions/providers/${slug}.yaml`,
|
|
9045
|
+
mode
|
|
9138
9046
|
});
|
|
9139
|
-
if (!opts.dryRun)
|
|
9047
|
+
if (!opts.dryRun) writeIfChanged(assemblyPath, assemblyContent);
|
|
9140
9048
|
result.assembliesWritten.push(assemblyPath);
|
|
9141
9049
|
tokenEntries.push({ entityName, entityClass: loc.entityClass, provider: slug });
|
|
9142
9050
|
assemblyEntries.push({ entityName, provider: slug });
|
|
9143
9051
|
}
|
|
9144
9052
|
}
|
|
9145
|
-
const integrationTokensPath =
|
|
9053
|
+
const integrationTokensPath = join11(
|
|
9146
9054
|
surfaceDir,
|
|
9147
9055
|
`${surface}-integration.tokens.ts`
|
|
9148
9056
|
);
|
|
9149
9057
|
const tokensContent = generateIntegrationTokens(surface, tokenEntries);
|
|
9150
|
-
if (!opts.dryRun)
|
|
9058
|
+
if (!opts.dryRun) writeIfChanged(integrationTokensPath, tokensContent);
|
|
9151
9059
|
result.tokensWritten.push(integrationTokensPath);
|
|
9152
9060
|
if (assemblyEntries.length > 0) {
|
|
9153
|
-
const integrationAggregatorPath =
|
|
9061
|
+
const integrationAggregatorPath = join11(
|
|
9154
9062
|
surfaceDir,
|
|
9155
9063
|
`${surface}-integration.module.ts`
|
|
9156
9064
|
);
|
|
@@ -9158,7 +9066,7 @@ function emitAdapters(opts) {
|
|
|
9158
9066
|
surface,
|
|
9159
9067
|
assemblyEntries
|
|
9160
9068
|
);
|
|
9161
|
-
if (!opts.dryRun)
|
|
9069
|
+
if (!opts.dryRun) writeIfChanged(integrationAggregatorPath, aggregatorContent);
|
|
9162
9070
|
result.integrationAggregatorsWritten.push(integrationAggregatorPath);
|
|
9163
9071
|
}
|
|
9164
9072
|
}
|
|
@@ -9215,16 +9123,212 @@ function pascalFromSnake(s) {
|
|
|
9215
9123
|
return camel.charAt(0).toUpperCase() + camel.slice(1);
|
|
9216
9124
|
}
|
|
9217
9125
|
function writeFile(outPath, content) {
|
|
9218
|
-
|
|
9219
|
-
|
|
9126
|
+
mkdirSync2(dirname(outPath), { recursive: true });
|
|
9127
|
+
writeFileSync2(outPath, content);
|
|
9220
9128
|
}
|
|
9221
|
-
function
|
|
9222
|
-
if (
|
|
9129
|
+
function writeIfChanged(outPath, content) {
|
|
9130
|
+
if (existsSync9(outPath) && statSync5(outPath).isFile() && readFileSync7(outPath, "utf-8") === content) {
|
|
9223
9131
|
return;
|
|
9224
9132
|
}
|
|
9225
9133
|
writeFile(outPath, content);
|
|
9226
9134
|
}
|
|
9227
9135
|
|
|
9136
|
+
// src/cli/shared/provider-module-generator.ts
|
|
9137
|
+
function providerPascalCase(slug) {
|
|
9138
|
+
return slug.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
9139
|
+
}
|
|
9140
|
+
function providerConstantCase(slug) {
|
|
9141
|
+
return slug.replace(/-/g, "_").toUpperCase();
|
|
9142
|
+
}
|
|
9143
|
+
function providerModuleBanner(sourceYaml) {
|
|
9144
|
+
return `// @generated by @pattern-stack/codegen from ${sourceYaml} \u2014 DO NOT EDIT.
|
|
9145
|
+
// Hand edits are overwritten on re-emit. Regenerate with \`bun run codegen\`. To change this provider, edit its \`definitions/providers/*.yaml\`.`;
|
|
9146
|
+
}
|
|
9147
|
+
function generateProviderModule(def, sourceYaml, mode = "package") {
|
|
9148
|
+
const { slug } = def;
|
|
9149
|
+
const Pascal = providerPascalCase(slug);
|
|
9150
|
+
const CONST = providerConstantCase(slug);
|
|
9151
|
+
const strategy = parseImportRef(def.auth.strategy);
|
|
9152
|
+
const client = parseImportRef(def.client.class);
|
|
9153
|
+
const strategyToken = `${CONST}_AUTH_STRATEGY`;
|
|
9154
|
+
const clientToken = `${CONST}_CLIENT`;
|
|
9155
|
+
const surfaces = def.surfaces.join(", ");
|
|
9156
|
+
const title = def.display_name ? `${def.display_name} (\`${slug}\`)` : `\`${slug}\``;
|
|
9157
|
+
if (isClientlessProvider(def.surfaces)) {
|
|
9158
|
+
return `${providerModuleBanner(sourceYaml)}
|
|
9159
|
+
/**
|
|
9160
|
+
* Provider module for ${title}.
|
|
9161
|
+
*
|
|
9162
|
+
* Surfaces: ${surfaces}.
|
|
9163
|
+
*
|
|
9164
|
+
* Per-connection (read-primitive) provider \u2014 exposes \`${strategyToken}\`, the
|
|
9165
|
+
* per-connection credential resolver the interaction adapters use (RFC-0003 R5:
|
|
9166
|
+
* \`auth.resolve(ctx.subscription.externalRef)\`). There is NO provider-level
|
|
9167
|
+
* singleton client; adapters build a per-connection client inside their
|
|
9168
|
+
* \`enumerate\`/\`hydrate\`. \`${strategyToken}\` resolves the already-built
|
|
9169
|
+
* \`${slug}\` strategy from the @Global \`STRATEGY_REGISTRY\` (wired by the
|
|
9170
|
+
* consumer's AuthBindings module) \u2014 the strategy may need DI deps a bare class
|
|
9171
|
+
* can't satisfy, so it is registry-resolved, not provided directly.
|
|
9172
|
+
*/
|
|
9173
|
+
import { Module } from '@nestjs/common';
|
|
9174
|
+
import {
|
|
9175
|
+
type ProviderStrategyRegistry,
|
|
9176
|
+
STRATEGY_REGISTRY,
|
|
9177
|
+
} from '${subsystemsImport(mode, "auth")}';
|
|
9178
|
+
|
|
9179
|
+
/** DI token for the \`${slug}\` provider's auth strategy (resolved from STRATEGY_REGISTRY). */
|
|
9180
|
+
export const ${strategyToken} = Symbol('${strategyToken}');
|
|
9181
|
+
|
|
9182
|
+
const PROVIDER_SLUG = '${slug}';
|
|
9183
|
+
|
|
9184
|
+
@Module({
|
|
9185
|
+
providers: [
|
|
9186
|
+
{
|
|
9187
|
+
provide: ${strategyToken},
|
|
9188
|
+
useFactory: (registry: ProviderStrategyRegistry) => {
|
|
9189
|
+
const strategy = registry.get(PROVIDER_SLUG);
|
|
9190
|
+
if (!strategy) {
|
|
9191
|
+
throw new Error(
|
|
9192
|
+
\`${Pascal}ProviderModule: no '\${PROVIDER_SLUG}' strategy registered in STRATEGY_REGISTRY (wire it in your consumer AuthBindings module)\`,
|
|
9193
|
+
);
|
|
9194
|
+
}
|
|
9195
|
+
return strategy;
|
|
9196
|
+
},
|
|
9197
|
+
inject: [STRATEGY_REGISTRY],
|
|
9198
|
+
},
|
|
9199
|
+
],
|
|
9200
|
+
exports: [${strategyToken}],
|
|
9201
|
+
})
|
|
9202
|
+
export class ${Pascal}ProviderModule {}
|
|
9203
|
+
`;
|
|
9204
|
+
}
|
|
9205
|
+
return `${providerModuleBanner(sourceYaml)}
|
|
9206
|
+
/**
|
|
9207
|
+
* Provider module for ${title}.
|
|
9208
|
+
*
|
|
9209
|
+
* Surfaces: ${surfaces}.
|
|
9210
|
+
*
|
|
9211
|
+
* Wires the declared auth strategy and API client under the provider-specific
|
|
9212
|
+
* DI tokens \`${strategyToken}\` and \`${clientToken}\`. Per the auth subsystem
|
|
9213
|
+
* contract, strategies are registered under provider-specific tokens rather
|
|
9214
|
+
* than a single \`AUTH_STRATEGY\`. Registry aggregation (RFC-0001 \xA73) is
|
|
9215
|
+
* emitted by a later codegen step.
|
|
9216
|
+
*/
|
|
9217
|
+
import { Module } from '@nestjs/common';
|
|
9218
|
+
import { ${strategy.exportName} } from '${strategy.path}';
|
|
9219
|
+
import { ${client.exportName} } from '${client.path}';
|
|
9220
|
+
|
|
9221
|
+
/** DI token for the \`${slug}\` provider's auth strategy. */
|
|
9222
|
+
export const ${strategyToken} = Symbol('${strategyToken}');
|
|
9223
|
+
/** DI token for the \`${slug}\` provider's API client. */
|
|
9224
|
+
export const ${clientToken} = Symbol('${clientToken}');
|
|
9225
|
+
|
|
9226
|
+
@Module({
|
|
9227
|
+
providers: [
|
|
9228
|
+
${strategy.exportName},
|
|
9229
|
+
${client.exportName},
|
|
9230
|
+
{ provide: ${strategyToken}, useExisting: ${strategy.exportName} },
|
|
9231
|
+
{ provide: ${clientToken}, useExisting: ${client.exportName} },
|
|
9232
|
+
],
|
|
9233
|
+
exports: [
|
|
9234
|
+
${strategy.exportName},
|
|
9235
|
+
${client.exportName},
|
|
9236
|
+
${strategyToken},
|
|
9237
|
+
${clientToken},
|
|
9238
|
+
],
|
|
9239
|
+
})
|
|
9240
|
+
export class ${Pascal}ProviderModule {}
|
|
9241
|
+
`;
|
|
9242
|
+
}
|
|
9243
|
+
function resolveTsconfigAliases(consumerRoot) {
|
|
9244
|
+
const tsconfigPath = join12(consumerRoot, "tsconfig.json");
|
|
9245
|
+
if (!existsSync10(tsconfigPath)) return null;
|
|
9246
|
+
let parsed;
|
|
9247
|
+
try {
|
|
9248
|
+
parsed = JSON.parse(stripJsonComments(readFileSync8(tsconfigPath, "utf-8")));
|
|
9249
|
+
} catch {
|
|
9250
|
+
return null;
|
|
9251
|
+
}
|
|
9252
|
+
const compilerOptions = parsed.compilerOptions ?? {};
|
|
9253
|
+
const baseUrl = compilerOptions.baseUrl ?? ".";
|
|
9254
|
+
const sourceRoot = isAbsolute2(baseUrl) ? baseUrl : resolve6(consumerRoot, baseUrl);
|
|
9255
|
+
const aliases = {};
|
|
9256
|
+
for (const [pattern, targets] of Object.entries(compilerOptions.paths ?? {})) {
|
|
9257
|
+
if (!Array.isArray(targets) || targets.length === 0) continue;
|
|
9258
|
+
const aliasKey = pattern.replace(/\/\*$/, "");
|
|
9259
|
+
const target = targets[0].replace(/\/\*$/, "");
|
|
9260
|
+
aliases[aliasKey] = isAbsolute2(target) ? target : resolve6(sourceRoot, target);
|
|
9261
|
+
}
|
|
9262
|
+
return { sourceRoot, aliases };
|
|
9263
|
+
}
|
|
9264
|
+
function stripJsonComments(input) {
|
|
9265
|
+
return input.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1");
|
|
9266
|
+
}
|
|
9267
|
+
function generateProviderModules(opts) {
|
|
9268
|
+
const base = {
|
|
9269
|
+
providersDir: opts.providersDir,
|
|
9270
|
+
skipped: false,
|
|
9271
|
+
written: [],
|
|
9272
|
+
loadFailures: [],
|
|
9273
|
+
issues: []
|
|
9274
|
+
};
|
|
9275
|
+
if (!existsSync10(opts.providersDir) || !statSync6(opts.providersDir).isDirectory()) {
|
|
9276
|
+
return { ...base, skipped: true };
|
|
9277
|
+
}
|
|
9278
|
+
const files = findYamlFiles(opts.providersDir);
|
|
9279
|
+
if (files.length === 0) return { ...base, skipped: true };
|
|
9280
|
+
const { successes, failures } = loadProvidersFromYaml(files);
|
|
9281
|
+
const loaded = successes.map((s) => ({
|
|
9282
|
+
definition: s.definition,
|
|
9283
|
+
filePath: s.filePath
|
|
9284
|
+
}));
|
|
9285
|
+
const issues = failures.map((f) => ({
|
|
9286
|
+
severity: "error",
|
|
9287
|
+
type: "provider_load_failed",
|
|
9288
|
+
message: `${f.error}${f.details?.length ? ` \u2014 ${f.details.join("; ")}` : ""}`,
|
|
9289
|
+
path: f.filePath
|
|
9290
|
+
}));
|
|
9291
|
+
issues.push(
|
|
9292
|
+
...validateProviders(loaded, {
|
|
9293
|
+
entitySurfaces: opts.entitySurfaces,
|
|
9294
|
+
sourceRoot: opts.sourceRoot,
|
|
9295
|
+
aliases: opts.aliases,
|
|
9296
|
+
skipImportCheck: opts.skipImportCheck
|
|
9297
|
+
})
|
|
9298
|
+
);
|
|
9299
|
+
if (issues.some((i) => i.severity === "error")) {
|
|
9300
|
+
return { ...base, loadFailures: failures, issues };
|
|
9301
|
+
}
|
|
9302
|
+
const mode = opts.mode ?? "package";
|
|
9303
|
+
const written = [];
|
|
9304
|
+
for (const { definition, filePath } of loaded) {
|
|
9305
|
+
const sourceYaml = relativeSource(filePath);
|
|
9306
|
+
const content = generateProviderModule(definition, sourceYaml, mode);
|
|
9307
|
+
const outPath = join12(
|
|
9308
|
+
opts.outputRoot,
|
|
9309
|
+
definition.slug,
|
|
9310
|
+
`${definition.slug}.provider.module.ts`
|
|
9311
|
+
);
|
|
9312
|
+
if (!opts.dryRun) {
|
|
9313
|
+
writeIfChanged2(outPath, content);
|
|
9314
|
+
}
|
|
9315
|
+
written.push(outPath);
|
|
9316
|
+
}
|
|
9317
|
+
return { ...base, written, loadFailures: failures, issues };
|
|
9318
|
+
}
|
|
9319
|
+
function writeIfChanged2(outPath, content) {
|
|
9320
|
+
if (existsSync10(outPath) && readFileSync8(outPath, "utf-8") === content) return;
|
|
9321
|
+
mkdirSync3(dirname2(outPath), { recursive: true });
|
|
9322
|
+
writeFileSync3(outPath, content);
|
|
9323
|
+
}
|
|
9324
|
+
function relativeSource(filePath) {
|
|
9325
|
+
const marker = "definitions/providers/";
|
|
9326
|
+
const idx = filePath.lastIndexOf(marker);
|
|
9327
|
+
if (idx !== -1) return filePath.slice(idx);
|
|
9328
|
+
const slash = filePath.lastIndexOf("/");
|
|
9329
|
+
return slash === -1 ? filePath : `definitions/providers/${filePath.slice(slash + 1)}`;
|
|
9330
|
+
}
|
|
9331
|
+
|
|
9228
9332
|
// src/cli/shared/events-path.ts
|
|
9229
9333
|
import path12 from "path";
|
|
9230
9334
|
var FALLBACK = "events";
|
|
@@ -9504,6 +9608,7 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9504
9608
|
"bridge/generated"
|
|
9505
9609
|
);
|
|
9506
9610
|
const backendSrcForHandlers = ctx.config?.paths?.backend_src ?? "src";
|
|
9611
|
+
const runtimeMode = resolveRuntimeMode(ctx.config);
|
|
9507
9612
|
const bridgeHandlersDir = path13.resolve(
|
|
9508
9613
|
ctx.cwd,
|
|
9509
9614
|
backendSrcForHandlers,
|
|
@@ -9790,7 +9895,8 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9790
9895
|
entitySurfaces,
|
|
9791
9896
|
sourceRoot: tsAliases?.sourceRoot,
|
|
9792
9897
|
aliases: tsAliases?.aliases,
|
|
9793
|
-
skipImportCheck: tsAliases === null
|
|
9898
|
+
skipImportCheck: tsAliases === null,
|
|
9899
|
+
mode: runtimeMode
|
|
9794
9900
|
});
|
|
9795
9901
|
if (!providerResult.skipped && !isJsonMode()) {
|
|
9796
9902
|
for (const issue of providerResult.issues) {
|
|
@@ -9834,7 +9940,8 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9834
9940
|
entities: entityDefs,
|
|
9835
9941
|
outputRoot: adapterOutputRoot,
|
|
9836
9942
|
backendSrcAbs: path13.resolve(ctx.cwd, backendSrcForHandlers),
|
|
9837
|
-
aliases: assemblyTsAliases?.aliases ?? {}
|
|
9943
|
+
aliases: assemblyTsAliases?.aliases ?? {},
|
|
9944
|
+
mode: runtimeMode
|
|
9838
9945
|
});
|
|
9839
9946
|
if (!isJsonMode()) {
|
|
9840
9947
|
if (adapterResult.written.length || adapterResult.scaffoldsWritten.length) {
|
|
@@ -11907,12 +12014,13 @@ var VENDORED_RUNTIME_FILES = [
|
|
|
11907
12014
|
},
|
|
11908
12015
|
{ runtime: "shared/openapi/index.ts", target: "src/shared/openapi/index.ts" }
|
|
11909
12016
|
];
|
|
11910
|
-
function databaseModuleContent() {
|
|
12017
|
+
function databaseModuleContent(mode) {
|
|
12018
|
+
const drizzleTokenImport = mode === "vendored" ? "../constants/tokens" : runtimeImport(mode, "constants/tokens");
|
|
11911
12019
|
return `import { Module, Global } from '@nestjs/common';
|
|
11912
12020
|
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
11913
12021
|
import { Pool } from 'pg';
|
|
11914
12022
|
import * as schema from '../../schema';
|
|
11915
|
-
import { DRIZZLE } from '
|
|
12023
|
+
import { DRIZZLE } from '${drizzleTokenImport}';
|
|
11916
12024
|
|
|
11917
12025
|
export { DRIZZLE };
|
|
11918
12026
|
export type DrizzleDB = ReturnType<typeof drizzle<typeof schema>>;
|
|
@@ -11939,11 +12047,12 @@ export type DrizzleDB = ReturnType<typeof drizzle<typeof schema>>;
|
|
|
11939
12047
|
export class DatabaseModule {}
|
|
11940
12048
|
`;
|
|
11941
12049
|
}
|
|
11942
|
-
function appModuleContent() {
|
|
12050
|
+
function appModuleContent(mode) {
|
|
12051
|
+
const openApiImport = mode === "vendored" ? "./shared/openapi" : runtimeImport(mode, "shared/openapi");
|
|
11943
12052
|
return `import { Global, Module } from '@nestjs/common';
|
|
11944
12053
|
import { DatabaseModule } from './shared/database/database.module';
|
|
11945
12054
|
import { GENERATED_MODULES } from './generated/modules';
|
|
11946
|
-
import { OPENAPI_REGISTRY, OpenApiRegistry } from '
|
|
12055
|
+
import { OPENAPI_REGISTRY, OpenApiRegistry } from '${openApiImport}';
|
|
11947
12056
|
|
|
11948
12057
|
/**
|
|
11949
12058
|
* OpenApiModule \u2014 @Global() wrapper around the OPENAPI_REGISTRY singleton.
|
|
@@ -11985,7 +12094,8 @@ class OpenApiModule {}
|
|
|
11985
12094
|
export class AppModule {}
|
|
11986
12095
|
`;
|
|
11987
12096
|
}
|
|
11988
|
-
function mainTsContent() {
|
|
12097
|
+
function mainTsContent(mode) {
|
|
12098
|
+
const openApiImport = mode === "vendored" ? "./shared/openapi" : runtimeImport(mode, "shared/openapi");
|
|
11989
12099
|
return `import 'reflect-metadata';
|
|
11990
12100
|
import fs from 'node:fs';
|
|
11991
12101
|
import path from 'node:path';
|
|
@@ -11993,7 +12103,7 @@ import { NestFactory } from '@nestjs/core';
|
|
|
11993
12103
|
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
|
11994
12104
|
import { parse as parseYaml } from 'yaml';
|
|
11995
12105
|
import { AppModule } from './app.module';
|
|
11996
|
-
import { OPENAPI_REGISTRY, OpenApiRegistry } from '
|
|
12106
|
+
import { OPENAPI_REGISTRY, OpenApiRegistry } from '${openApiImport}';
|
|
11997
12107
|
|
|
11998
12108
|
interface OpenApiConfig {
|
|
11999
12109
|
enabled?: boolean;
|
|
@@ -12302,6 +12412,7 @@ function dirEntry(cwd, absPath) {
|
|
|
12302
12412
|
async function buildInitPlan(ctx, options) {
|
|
12303
12413
|
const cwd = options.cwd;
|
|
12304
12414
|
const force = Boolean(options.force);
|
|
12415
|
+
const runtimeMode = options.runtimeMode === "vendored" ? "vendored" : "package";
|
|
12305
12416
|
let framework = "nestjs";
|
|
12306
12417
|
let orm = "drizzle";
|
|
12307
12418
|
let architecture = "clean-lite-ps";
|
|
@@ -12324,6 +12435,11 @@ async function buildInitPlan(ctx, options) {
|
|
|
12324
12435
|
{
|
|
12325
12436
|
const configPath = path23.join(cwd, "codegen.config.yaml");
|
|
12326
12437
|
const config = {
|
|
12438
|
+
// Runtime mode (ADR-037). `package` (default) imports the runtime from
|
|
12439
|
+
// `@pattern-stack/codegen/*`; `vendored` imports it via `@shared/*` and
|
|
12440
|
+
// vendors `src/shared/**`. Existing vendored projects MUST set this to
|
|
12441
|
+
// `vendored` explicitly — the default does not silently flip them.
|
|
12442
|
+
runtime: runtimeMode,
|
|
12327
12443
|
paths: {
|
|
12328
12444
|
backend_src: "src",
|
|
12329
12445
|
entities_dir: "entities",
|
|
@@ -12400,14 +12516,16 @@ async function buildInitPlan(ctx, options) {
|
|
|
12400
12516
|
fileEntry(
|
|
12401
12517
|
cwd,
|
|
12402
12518
|
path23.join(cwd, "src", "shared", "database", "database.module.ts"),
|
|
12403
|
-
databaseModuleContent(),
|
|
12519
|
+
databaseModuleContent(runtimeMode),
|
|
12404
12520
|
{ force }
|
|
12405
12521
|
)
|
|
12406
12522
|
);
|
|
12407
|
-
|
|
12408
|
-
|
|
12409
|
-
|
|
12410
|
-
|
|
12523
|
+
if (runtimeMode === "vendored") {
|
|
12524
|
+
for (const v of VENDORED_RUNTIME_FILES) {
|
|
12525
|
+
entries.push(
|
|
12526
|
+
fileEntry(cwd, path23.join(cwd, v.target), loadRuntimeFile(v.runtime), { force })
|
|
12527
|
+
);
|
|
12528
|
+
}
|
|
12411
12529
|
}
|
|
12412
12530
|
entries.push(
|
|
12413
12531
|
fileEntry(
|
|
@@ -12432,7 +12550,7 @@ async function buildInitPlan(ctx, options) {
|
|
|
12432
12550
|
path: appModulePath,
|
|
12433
12551
|
relPath: relOf(cwd, appModulePath),
|
|
12434
12552
|
action: "create",
|
|
12435
|
-
content: appModuleContent()
|
|
12553
|
+
content: appModuleContent(runtimeMode)
|
|
12436
12554
|
});
|
|
12437
12555
|
} else {
|
|
12438
12556
|
entries.push({
|
|
@@ -12450,7 +12568,7 @@ async function buildInitPlan(ctx, options) {
|
|
|
12450
12568
|
path: mainPath,
|
|
12451
12569
|
relPath: relOf(cwd, mainPath),
|
|
12452
12570
|
action: "create",
|
|
12453
|
-
content: mainTsContent()
|
|
12571
|
+
content: mainTsContent(runtimeMode)
|
|
12454
12572
|
});
|
|
12455
12573
|
} else {
|
|
12456
12574
|
entries.push({
|
|
@@ -13593,7 +13711,8 @@ var ProjectInitCommand = class extends Command7 {
|
|
|
13593
13711
|
static usage = Command7.Usage({
|
|
13594
13712
|
description: "Scaffold a consumer project (config, shims, barrels, app.module)",
|
|
13595
13713
|
examples: [
|
|
13596
|
-
["Initialize with defaults", "codegen project init --yes"],
|
|
13714
|
+
["Initialize with defaults (package runtime)", "codegen project init --yes"],
|
|
13715
|
+
["Vendored runtime (legacy @shared/** model)", "codegen project init --yes --runtime vendored"],
|
|
13597
13716
|
["Preview without writing", "codegen project init --dry-run"],
|
|
13598
13717
|
["Create tsconfig if missing", "codegen project init --yes --with-tsconfig"],
|
|
13599
13718
|
["Overwrite existing shims", "codegen project init --force"]
|
|
@@ -13603,6 +13722,9 @@ var ProjectInitCommand = class extends Command7 {
|
|
|
13603
13722
|
dryRun = Option7.Boolean("--dry-run", false);
|
|
13604
13723
|
force = Option7.Boolean("--force", false);
|
|
13605
13724
|
withTsconfig = Option7.Boolean("--with-tsconfig", false);
|
|
13725
|
+
// Runtime mode (ADR-037). `package` (default) ⇒ depend on the npm package,
|
|
13726
|
+
// vendor nothing; `vendored` ⇒ vendor src/shared/** and import via @shared/*.
|
|
13727
|
+
runtime = Option7.String("--runtime", "package");
|
|
13606
13728
|
// Vendor consumer skills into .claude/skills by default; opt out with --no-skills.
|
|
13607
13729
|
skills = Option7.Boolean("--skills", true);
|
|
13608
13730
|
json = Option7.Boolean("--json", false);
|
|
@@ -13614,11 +13736,18 @@ var ProjectInitCommand = class extends Command7 {
|
|
|
13614
13736
|
json: this.json,
|
|
13615
13737
|
skipDetection: false
|
|
13616
13738
|
});
|
|
13739
|
+
const runtimeMode = this.runtime === "vendored" ? "vendored" : "package";
|
|
13740
|
+
if (this.runtime !== "package" && this.runtime !== "vendored" && !isJsonMode()) {
|
|
13741
|
+
printWarning(
|
|
13742
|
+
`--runtime '${this.runtime}' is not recognized (expected 'package' or 'vendored'); using 'package'.`
|
|
13743
|
+
);
|
|
13744
|
+
}
|
|
13617
13745
|
const plan = await buildInitPlan(ctx, {
|
|
13618
13746
|
cwd: ctx.cwd,
|
|
13619
13747
|
force: this.force,
|
|
13620
13748
|
withTsconfig: this.withTsconfig,
|
|
13621
|
-
skipScan: false
|
|
13749
|
+
skipScan: false,
|
|
13750
|
+
runtimeMode
|
|
13622
13751
|
});
|
|
13623
13752
|
if (this.force && !isJsonMode()) {
|
|
13624
13753
|
printWarning("--force: existing scaffold files will be overwritten.");
|