@pattern-stack/codegen 0.13.1 → 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 +2 -2
- package/dist/runtime/subsystems/index.js +25 -20
- 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 +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 +349 -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 +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-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,163 +8105,34 @@ 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
|
-
`;
|
|
8121
|
+
// src/cli/shared/runtime-import.ts
|
|
8122
|
+
var PACKAGE = "@pattern-stack/codegen";
|
|
8123
|
+
function resolveRuntimeMode(config) {
|
|
8124
|
+
return config?.runtime === "vendored" ? "vendored" : "package";
|
|
8167
8125
|
}
|
|
8168
|
-
function
|
|
8169
|
-
|
|
8170
|
-
|
|
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);
|
|
8126
|
+
function subsystemsImport(mode, subsystem) {
|
|
8127
|
+
if (mode === "vendored") {
|
|
8128
|
+
return subsystem ? `@shared/subsystems/${subsystem}` : "@shared/subsystems";
|
|
8186
8129
|
}
|
|
8187
|
-
return {
|
|
8130
|
+
return `${PACKAGE}/subsystems`;
|
|
8188
8131
|
}
|
|
8189
|
-
function
|
|
8190
|
-
|
|
8132
|
+
function runtimeImport(mode, relpath) {
|
|
8133
|
+
const clean = relpath.replace(/^\/+/, "");
|
|
8134
|
+
return mode === "vendored" ? `@shared/${clean}` : `${PACKAGE}/runtime/${clean}`;
|
|
8191
8135
|
}
|
|
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
|
-
}
|
|
8255
|
-
|
|
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
8136
|
|
|
8266
8137
|
// src/cli/shared/sink-emission-generator.ts
|
|
8267
8138
|
var SCAFFOLD_SENTINEL = "// <CODEGEN-SCAFFOLD-V1>";
|
|
@@ -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,
|
|
@@ -8638,6 +8509,9 @@ var SURFACE_REGISTRY = {
|
|
|
8638
8509
|
readPrimitive: true
|
|
8639
8510
|
}
|
|
8640
8511
|
};
|
|
8512
|
+
function isClientlessProvider(surfaces) {
|
|
8513
|
+
return surfaces.length > 0 && surfaces.every((s) => SURFACE_REGISTRY[s]?.readPrimitive === true);
|
|
8514
|
+
}
|
|
8641
8515
|
var SCAFFOLD_SENTINEL2 = "// <CODEGEN-SCAFFOLD-V1>";
|
|
8642
8516
|
function generatedBanner2(sourceDesc) {
|
|
8643
8517
|
return `// @generated by @pattern-stack/codegen from ${sourceDesc} \u2014 DO NOT EDIT.
|
|
@@ -8692,7 +8566,7 @@ function serializeFilterArray(filters) {
|
|
|
8692
8566
|
${items.join("\n")}
|
|
8693
8567
|
]`;
|
|
8694
8568
|
}
|
|
8695
|
-
function buildReadPrimitiveEmission(providerSlug, providerPascal, surface, entities, entityDetection
|
|
8569
|
+
function buildReadPrimitiveEmission(providerSlug, providerPascal, surface, entities, entityDetection) {
|
|
8696
8570
|
const canonicalTypes = [];
|
|
8697
8571
|
const blocks = [];
|
|
8698
8572
|
const entries = [];
|
|
@@ -8724,24 +8598,32 @@ export class ${className} extends IncrementalReadBase<${canonical}, ResolvedFilt
|
|
|
8724
8598
|
// (e.g. Gmail \`q=\`); leave \`false\` to filter post-hydrate via \`matchesRecord\`.
|
|
8725
8599
|
protected override readonly filterPushdown = false;${cursorOverride}
|
|
8726
8600
|
|
|
8727
|
-
constructor(
|
|
8728
|
-
private readonly auth: IAuthStrategy,
|
|
8729
|
-
private readonly client: ${clientExportName},
|
|
8730
|
-
) {
|
|
8601
|
+
constructor(private readonly auth: IAuthStrategy) {
|
|
8731
8602
|
super();
|
|
8732
8603
|
}
|
|
8733
8604
|
|
|
8734
|
-
/**
|
|
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
|
+
*/
|
|
8735
8613
|
protected async *enumerate(
|
|
8736
8614
|
_mode: ReadMode,
|
|
8737
8615
|
_filter?: ResolvedFilter[],
|
|
8738
8616
|
_pageSize?: number,
|
|
8617
|
+
_ctx?: ReadContext,
|
|
8739
8618
|
): AsyncIterable<Ref[]> {
|
|
8740
8619
|
throw new Error('not implemented: ${className}.enumerate');
|
|
8741
8620
|
}
|
|
8742
8621
|
|
|
8743
|
-
/**
|
|
8744
|
-
|
|
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>> {
|
|
8745
8627
|
throw new Error('not implemented: ${className}.hydrate');
|
|
8746
8628
|
}
|
|
8747
8629
|
|
|
@@ -8756,15 +8638,16 @@ export class ${className} extends IncrementalReadBase<${canonical}, ResolvedFilt
|
|
|
8756
8638
|
return ${constName};
|
|
8757
8639
|
}
|
|
8758
8640
|
}`);
|
|
8759
|
-
entries.push(` ${entity}: new ${className}(this.auth
|
|
8641
|
+
entries.push(` ${entity}: new ${className}(this.auth),`);
|
|
8760
8642
|
}
|
|
8761
8643
|
return { canonicalTypes, preamble: blocks.join("\n\n"), changeSourceEntries: entries };
|
|
8762
8644
|
}
|
|
8763
|
-
function generateAdapterScaffold(def, surface, entities, entityDetection) {
|
|
8645
|
+
function generateAdapterScaffold(def, surface, entities, entityDetection, mode = "package") {
|
|
8764
8646
|
const spec = SURFACE_REGISTRY[surface];
|
|
8765
8647
|
if (!spec) throw new Error(`no surface package for '${surface}'`);
|
|
8766
8648
|
const n = names(def.slug, surface);
|
|
8767
8649
|
const client = parseImportRef(def.client.class);
|
|
8650
|
+
const subsystemsSpec = subsystemsImport(mode, "integration");
|
|
8768
8651
|
const entitiesLiteral = entities.length ? `[${entities.map((e) => `'${e}'`).join(", ")}]` : "[]";
|
|
8769
8652
|
const readPrimitive = !!spec.readPrimitive && entities.length > 0;
|
|
8770
8653
|
const rp = readPrimitive ? buildReadPrimitiveEmission(
|
|
@@ -8772,21 +8655,26 @@ function generateAdapterScaffold(def, surface, entities, entityDetection) {
|
|
|
8772
8655
|
n.providerPascal,
|
|
8773
8656
|
surface,
|
|
8774
8657
|
entities,
|
|
8775
|
-
entityDetection
|
|
8776
|
-
client.exportName
|
|
8658
|
+
entityDetection
|
|
8777
8659
|
) : null;
|
|
8778
8660
|
const surfaceTypeImports = [
|
|
8779
8661
|
spec.portType,
|
|
8780
8662
|
...spec.l2Ports.map((p) => p.type),
|
|
8781
8663
|
spec.capabilitiesType,
|
|
8782
8664
|
...rp ? rp.canonicalTypes : []
|
|
8783
|
-
].map((t) => ` ${t},`).join("\n");
|
|
8784
|
-
const subsystemValueImport = rp ? `import { IncrementalReadBase } from '
|
|
8665
|
+
].sort().map((t) => ` ${t},`).join("\n");
|
|
8666
|
+
const subsystemValueImport = rp ? `import { IncrementalReadBase } from '${subsystemsSpec}';
|
|
8785
8667
|
` : "";
|
|
8786
8668
|
const subsystemTypeImports = [
|
|
8787
8669
|
"IAuthStrategy",
|
|
8788
8670
|
"IChangeSource",
|
|
8789
|
-
...rp ? [
|
|
8671
|
+
...rp ? [
|
|
8672
|
+
"IntegrationSubscriptionView",
|
|
8673
|
+
"ReadContext",
|
|
8674
|
+
"ReadMode",
|
|
8675
|
+
"Ref",
|
|
8676
|
+
"ResolvedFilter"
|
|
8677
|
+
] : []
|
|
8790
8678
|
].map((t) => ` ${t},`).join("\n");
|
|
8791
8679
|
const changeSourcesAssign = rp ? `
|
|
8792
8680
|
this.changeSources = {
|
|
@@ -8826,6 +8714,14 @@ ${rp.preamble}
|
|
|
8826
8714
|
const l2Section = l2Members ? `
|
|
8827
8715
|
${l2Members}
|
|
8828
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}}`;
|
|
8829
8725
|
return `${SCAFFOLD_SENTINEL2}
|
|
8830
8726
|
// Scaffolded once by @pattern-stack/codegen, then author-owned. Re-running
|
|
8831
8727
|
// codegen detects the sentinel above and SKIPS this file \u2014 your edits are safe.
|
|
@@ -8837,9 +8733,8 @@ ${surfaceTypeImports}
|
|
|
8837
8733
|
import { ${spec.noCapsConst} } from '${spec.packageName}';
|
|
8838
8734
|
${subsystemValueImport}import type {
|
|
8839
8735
|
${subsystemTypeImports}
|
|
8840
|
-
} from '
|
|
8841
|
-
|
|
8842
|
-
import { ${n.strategyToken}, ${n.clientToken} } from '../../../providers/${def.slug}/${def.slug}.provider.module';
|
|
8736
|
+
} from '${subsystemsSpec}';
|
|
8737
|
+
${clientTypeImport}${providerTokenImport}
|
|
8843
8738
|
${preambleSection}
|
|
8844
8739
|
@Injectable()
|
|
8845
8740
|
export class ${n.adapterClass} implements ${spec.portType} {
|
|
@@ -8848,10 +8743,7 @@ export class ${n.adapterClass} implements ${spec.portType} {
|
|
|
8848
8743
|
${capabilityBody}
|
|
8849
8744
|
};
|
|
8850
8745
|
|
|
8851
|
-
|
|
8852
|
-
@Inject(${n.strategyToken}) readonly auth: IAuthStrategy,
|
|
8853
|
-
@Inject(${n.clientToken}) private readonly client: ${client.exportName},
|
|
8854
|
-
) {${changeSourcesAssign}}
|
|
8746
|
+
${ctorOpen}
|
|
8855
8747
|
${l2Section}
|
|
8856
8748
|
${changeSourcesDecl}
|
|
8857
8749
|
|
|
@@ -8883,10 +8775,10 @@ function generateAdaptersBarrel(surface, providerSlugs) {
|
|
|
8883
8775
|
${lines}
|
|
8884
8776
|
`;
|
|
8885
8777
|
}
|
|
8886
|
-
function generateSurfaceTokens(surface) {
|
|
8778
|
+
function generateSurfaceTokens(surface, mode = "package") {
|
|
8887
8779
|
const n = names("__placeholder__", surface);
|
|
8888
8780
|
return `${generatedBanner2(`surface: ${surface}`)}
|
|
8889
|
-
import type { IChangeSource } from '
|
|
8781
|
+
import type { IChangeSource } from '${subsystemsImport(mode, "integration")}';
|
|
8890
8782
|
|
|
8891
8783
|
/** The assembled list of every ${surface} adapter's contribution. */
|
|
8892
8784
|
export const ${n.contributionsToken} = Symbol.for('@app/integrations/${surface}.adapter-contributions');
|
|
@@ -8903,7 +8795,7 @@ export interface AdapterContribution {
|
|
|
8903
8795
|
}
|
|
8904
8796
|
`;
|
|
8905
8797
|
}
|
|
8906
|
-
function generateSurfaceAggregator(surface, providerSlugs) {
|
|
8798
|
+
function generateSurfaceAggregator(surface, providerSlugs, mode = "package") {
|
|
8907
8799
|
const n = names("__placeholder__", surface);
|
|
8908
8800
|
const slugs = [...providerSlugs].sort();
|
|
8909
8801
|
const per = slugs.map((slug) => names(slug, surface));
|
|
@@ -8930,7 +8822,7 @@ import {
|
|
|
8930
8822
|
MemoryEntityChangeSourceRegistry,
|
|
8931
8823
|
type IChangeSource,
|
|
8932
8824
|
type IEntityChangeSourceRegistry,
|
|
8933
|
-
} from '
|
|
8825
|
+
} from '${subsystemsImport(mode, "integration")}';
|
|
8934
8826
|
${moduleImport}
|
|
8935
8827
|
${adapterImports}
|
|
8936
8828
|
import {
|
|
@@ -9019,6 +8911,7 @@ function jsKey(key) {
|
|
|
9019
8911
|
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : `'${key}'`;
|
|
9020
8912
|
}
|
|
9021
8913
|
function emitAdapters(opts) {
|
|
8914
|
+
const mode = opts.mode ?? "package";
|
|
9022
8915
|
const result = {
|
|
9023
8916
|
written: [],
|
|
9024
8917
|
scaffoldsWritten: [],
|
|
@@ -9049,14 +8942,14 @@ function emitAdapters(opts) {
|
|
|
9049
8942
|
}
|
|
9050
8943
|
const defBySlug = new Map(opts.providers.map((p) => [p.definition.slug, p.definition]));
|
|
9051
8944
|
for (const [surface, slugs] of bySurface) {
|
|
9052
|
-
const surfaceDir =
|
|
9053
|
-
const adaptersDir =
|
|
8945
|
+
const surfaceDir = join11(opts.outputRoot, surface);
|
|
8946
|
+
const adaptersDir = join11(surfaceDir, "adapters");
|
|
9054
8947
|
for (const slug of slugs) {
|
|
9055
8948
|
const def = defBySlug.get(slug);
|
|
9056
|
-
const providerDir =
|
|
9057
|
-
const scaffoldPath =
|
|
9058
|
-
const modulePath =
|
|
9059
|
-
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)) {
|
|
9060
8953
|
result.scaffoldsSkipped.push(scaffoldPath);
|
|
9061
8954
|
} else {
|
|
9062
8955
|
const surfaceEntityNames = entitiesBySurface.get(surface) ?? [];
|
|
@@ -9069,27 +8962,28 @@ function emitAdapters(opts) {
|
|
|
9069
8962
|
def,
|
|
9070
8963
|
surface,
|
|
9071
8964
|
surfaceEntityNames,
|
|
9072
|
-
entityDetection
|
|
8965
|
+
entityDetection,
|
|
8966
|
+
mode
|
|
9073
8967
|
);
|
|
9074
8968
|
if (!opts.dryRun) writeFile(scaffoldPath, content);
|
|
9075
8969
|
result.scaffoldsWritten.push(scaffoldPath);
|
|
9076
8970
|
}
|
|
9077
8971
|
const moduleContent = generateAdapterModule(def, surface);
|
|
9078
|
-
if (!opts.dryRun)
|
|
8972
|
+
if (!opts.dryRun) writeIfChanged(modulePath, moduleContent);
|
|
9079
8973
|
result.written.push(modulePath);
|
|
9080
8974
|
}
|
|
9081
|
-
const barrelPath =
|
|
9082
|
-
const tokensPath =
|
|
9083
|
-
const aggregatorPath =
|
|
9084
|
-
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");
|
|
9085
8979
|
const files = [
|
|
9086
8980
|
[barrelPath, generateAdaptersBarrel(surface, slugs)],
|
|
9087
|
-
[tokensPath, generateSurfaceTokens(surface)],
|
|
9088
|
-
[aggregatorPath, generateSurfaceAggregator(surface, slugs)],
|
|
8981
|
+
[tokensPath, generateSurfaceTokens(surface, mode)],
|
|
8982
|
+
[aggregatorPath, generateSurfaceAggregator(surface, slugs, mode)],
|
|
9089
8983
|
[typedViewPath, generateTypedView(surface, slugs, entitiesBySurface.get(surface) ?? [])]
|
|
9090
8984
|
];
|
|
9091
8985
|
for (const [path34, content] of files) {
|
|
9092
|
-
if (!opts.dryRun)
|
|
8986
|
+
if (!opts.dryRun) writeIfChanged(path34, content);
|
|
9093
8987
|
result.written.push(path34);
|
|
9094
8988
|
}
|
|
9095
8989
|
if (opts.backendSrcAbs) {
|
|
@@ -9097,8 +8991,8 @@ function emitAdapters(opts) {
|
|
|
9097
8991
|
const surfaceEntities = entitiesBySurface.get(surface) ?? [];
|
|
9098
8992
|
const tokenEntries = [];
|
|
9099
8993
|
const assemblyEntries = [];
|
|
9100
|
-
const sinksDir =
|
|
9101
|
-
const modulesDir =
|
|
8994
|
+
const sinksDir = join11(surfaceDir, "sinks");
|
|
8995
|
+
const modulesDir = join11(surfaceDir, "modules");
|
|
9102
8996
|
for (const entityName of surfaceEntities) {
|
|
9103
8997
|
const def = entityByName.get(entityName);
|
|
9104
8998
|
const pattern = def?.entity.pattern ?? (Array.isArray(def?.entity.patterns) ? def?.entity.patterns?.[0] : void 0);
|
|
@@ -9123,17 +9017,17 @@ function emitAdapters(opts) {
|
|
|
9123
9017
|
backendSrcAbs: opts.backendSrcAbs,
|
|
9124
9018
|
aliases
|
|
9125
9019
|
});
|
|
9126
|
-
const sinkPath =
|
|
9127
|
-
if (
|
|
9020
|
+
const sinkPath = join11(sinksDir, `${entityName}.sink.ts`);
|
|
9021
|
+
if (existsSync9(sinkPath)) {
|
|
9128
9022
|
result.scaffoldsSkipped.push(sinkPath);
|
|
9129
9023
|
} else {
|
|
9130
9024
|
const sinkInput = buildSinkInput(def, surface, slugs[0], loc.repoImportSpecifier);
|
|
9131
|
-
const sinkContent = generateDefaultSink(sinkInput);
|
|
9025
|
+
const sinkContent = generateDefaultSink({ ...sinkInput, mode });
|
|
9132
9026
|
if (!opts.dryRun) writeFile(sinkPath, sinkContent);
|
|
9133
9027
|
result.scaffoldsWritten.push(sinkPath);
|
|
9134
9028
|
}
|
|
9135
9029
|
for (const slug of slugs) {
|
|
9136
|
-
const assemblyPath =
|
|
9030
|
+
const assemblyPath = join11(
|
|
9137
9031
|
modulesDir,
|
|
9138
9032
|
slug,
|
|
9139
9033
|
`${entityName}-integration.module.ts`
|
|
@@ -9147,23 +9041,24 @@ function emitAdapters(opts) {
|
|
|
9147
9041
|
moduleClass: loc.moduleClass,
|
|
9148
9042
|
repoImportSpecifier: loc.repoImportSpecifier,
|
|
9149
9043
|
repoClass: loc.repoClass,
|
|
9150
|
-
sourceDesc: `definitions/providers/${slug}.yaml
|
|
9044
|
+
sourceDesc: `definitions/providers/${slug}.yaml`,
|
|
9045
|
+
mode
|
|
9151
9046
|
});
|
|
9152
|
-
if (!opts.dryRun)
|
|
9047
|
+
if (!opts.dryRun) writeIfChanged(assemblyPath, assemblyContent);
|
|
9153
9048
|
result.assembliesWritten.push(assemblyPath);
|
|
9154
9049
|
tokenEntries.push({ entityName, entityClass: loc.entityClass, provider: slug });
|
|
9155
9050
|
assemblyEntries.push({ entityName, provider: slug });
|
|
9156
9051
|
}
|
|
9157
9052
|
}
|
|
9158
|
-
const integrationTokensPath =
|
|
9053
|
+
const integrationTokensPath = join11(
|
|
9159
9054
|
surfaceDir,
|
|
9160
9055
|
`${surface}-integration.tokens.ts`
|
|
9161
9056
|
);
|
|
9162
9057
|
const tokensContent = generateIntegrationTokens(surface, tokenEntries);
|
|
9163
|
-
if (!opts.dryRun)
|
|
9058
|
+
if (!opts.dryRun) writeIfChanged(integrationTokensPath, tokensContent);
|
|
9164
9059
|
result.tokensWritten.push(integrationTokensPath);
|
|
9165
9060
|
if (assemblyEntries.length > 0) {
|
|
9166
|
-
const integrationAggregatorPath =
|
|
9061
|
+
const integrationAggregatorPath = join11(
|
|
9167
9062
|
surfaceDir,
|
|
9168
9063
|
`${surface}-integration.module.ts`
|
|
9169
9064
|
);
|
|
@@ -9171,7 +9066,7 @@ function emitAdapters(opts) {
|
|
|
9171
9066
|
surface,
|
|
9172
9067
|
assemblyEntries
|
|
9173
9068
|
);
|
|
9174
|
-
if (!opts.dryRun)
|
|
9069
|
+
if (!opts.dryRun) writeIfChanged(integrationAggregatorPath, aggregatorContent);
|
|
9175
9070
|
result.integrationAggregatorsWritten.push(integrationAggregatorPath);
|
|
9176
9071
|
}
|
|
9177
9072
|
}
|
|
@@ -9228,16 +9123,212 @@ function pascalFromSnake(s) {
|
|
|
9228
9123
|
return camel.charAt(0).toUpperCase() + camel.slice(1);
|
|
9229
9124
|
}
|
|
9230
9125
|
function writeFile(outPath, content) {
|
|
9231
|
-
|
|
9232
|
-
|
|
9126
|
+
mkdirSync2(dirname(outPath), { recursive: true });
|
|
9127
|
+
writeFileSync2(outPath, content);
|
|
9233
9128
|
}
|
|
9234
|
-
function
|
|
9235
|
-
if (
|
|
9129
|
+
function writeIfChanged(outPath, content) {
|
|
9130
|
+
if (existsSync9(outPath) && statSync5(outPath).isFile() && readFileSync7(outPath, "utf-8") === content) {
|
|
9236
9131
|
return;
|
|
9237
9132
|
}
|
|
9238
9133
|
writeFile(outPath, content);
|
|
9239
9134
|
}
|
|
9240
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
|
+
|
|
9241
9332
|
// src/cli/shared/events-path.ts
|
|
9242
9333
|
import path12 from "path";
|
|
9243
9334
|
var FALLBACK = "events";
|
|
@@ -9517,6 +9608,7 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9517
9608
|
"bridge/generated"
|
|
9518
9609
|
);
|
|
9519
9610
|
const backendSrcForHandlers = ctx.config?.paths?.backend_src ?? "src";
|
|
9611
|
+
const runtimeMode = resolveRuntimeMode(ctx.config);
|
|
9520
9612
|
const bridgeHandlersDir = path13.resolve(
|
|
9521
9613
|
ctx.cwd,
|
|
9522
9614
|
backendSrcForHandlers,
|
|
@@ -9803,7 +9895,8 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9803
9895
|
entitySurfaces,
|
|
9804
9896
|
sourceRoot: tsAliases?.sourceRoot,
|
|
9805
9897
|
aliases: tsAliases?.aliases,
|
|
9806
|
-
skipImportCheck: tsAliases === null
|
|
9898
|
+
skipImportCheck: tsAliases === null,
|
|
9899
|
+
mode: runtimeMode
|
|
9807
9900
|
});
|
|
9808
9901
|
if (!providerResult.skipped && !isJsonMode()) {
|
|
9809
9902
|
for (const issue of providerResult.issues) {
|
|
@@ -9847,7 +9940,8 @@ var EntityNewCommand = class extends Command2 {
|
|
|
9847
9940
|
entities: entityDefs,
|
|
9848
9941
|
outputRoot: adapterOutputRoot,
|
|
9849
9942
|
backendSrcAbs: path13.resolve(ctx.cwd, backendSrcForHandlers),
|
|
9850
|
-
aliases: assemblyTsAliases?.aliases ?? {}
|
|
9943
|
+
aliases: assemblyTsAliases?.aliases ?? {},
|
|
9944
|
+
mode: runtimeMode
|
|
9851
9945
|
});
|
|
9852
9946
|
if (!isJsonMode()) {
|
|
9853
9947
|
if (adapterResult.written.length || adapterResult.scaffoldsWritten.length) {
|
|
@@ -11920,12 +12014,13 @@ var VENDORED_RUNTIME_FILES = [
|
|
|
11920
12014
|
},
|
|
11921
12015
|
{ runtime: "shared/openapi/index.ts", target: "src/shared/openapi/index.ts" }
|
|
11922
12016
|
];
|
|
11923
|
-
function databaseModuleContent() {
|
|
12017
|
+
function databaseModuleContent(mode) {
|
|
12018
|
+
const drizzleTokenImport = mode === "vendored" ? "../constants/tokens" : runtimeImport(mode, "constants/tokens");
|
|
11924
12019
|
return `import { Module, Global } from '@nestjs/common';
|
|
11925
12020
|
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
11926
12021
|
import { Pool } from 'pg';
|
|
11927
12022
|
import * as schema from '../../schema';
|
|
11928
|
-
import { DRIZZLE } from '
|
|
12023
|
+
import { DRIZZLE } from '${drizzleTokenImport}';
|
|
11929
12024
|
|
|
11930
12025
|
export { DRIZZLE };
|
|
11931
12026
|
export type DrizzleDB = ReturnType<typeof drizzle<typeof schema>>;
|
|
@@ -11952,11 +12047,12 @@ export type DrizzleDB = ReturnType<typeof drizzle<typeof schema>>;
|
|
|
11952
12047
|
export class DatabaseModule {}
|
|
11953
12048
|
`;
|
|
11954
12049
|
}
|
|
11955
|
-
function appModuleContent() {
|
|
12050
|
+
function appModuleContent(mode) {
|
|
12051
|
+
const openApiImport = mode === "vendored" ? "./shared/openapi" : runtimeImport(mode, "shared/openapi");
|
|
11956
12052
|
return `import { Global, Module } from '@nestjs/common';
|
|
11957
12053
|
import { DatabaseModule } from './shared/database/database.module';
|
|
11958
12054
|
import { GENERATED_MODULES } from './generated/modules';
|
|
11959
|
-
import { OPENAPI_REGISTRY, OpenApiRegistry } from '
|
|
12055
|
+
import { OPENAPI_REGISTRY, OpenApiRegistry } from '${openApiImport}';
|
|
11960
12056
|
|
|
11961
12057
|
/**
|
|
11962
12058
|
* OpenApiModule \u2014 @Global() wrapper around the OPENAPI_REGISTRY singleton.
|
|
@@ -11998,7 +12094,8 @@ class OpenApiModule {}
|
|
|
11998
12094
|
export class AppModule {}
|
|
11999
12095
|
`;
|
|
12000
12096
|
}
|
|
12001
|
-
function mainTsContent() {
|
|
12097
|
+
function mainTsContent(mode) {
|
|
12098
|
+
const openApiImport = mode === "vendored" ? "./shared/openapi" : runtimeImport(mode, "shared/openapi");
|
|
12002
12099
|
return `import 'reflect-metadata';
|
|
12003
12100
|
import fs from 'node:fs';
|
|
12004
12101
|
import path from 'node:path';
|
|
@@ -12006,7 +12103,7 @@ import { NestFactory } from '@nestjs/core';
|
|
|
12006
12103
|
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
|
12007
12104
|
import { parse as parseYaml } from 'yaml';
|
|
12008
12105
|
import { AppModule } from './app.module';
|
|
12009
|
-
import { OPENAPI_REGISTRY, OpenApiRegistry } from '
|
|
12106
|
+
import { OPENAPI_REGISTRY, OpenApiRegistry } from '${openApiImport}';
|
|
12010
12107
|
|
|
12011
12108
|
interface OpenApiConfig {
|
|
12012
12109
|
enabled?: boolean;
|
|
@@ -12315,6 +12412,7 @@ function dirEntry(cwd, absPath) {
|
|
|
12315
12412
|
async function buildInitPlan(ctx, options) {
|
|
12316
12413
|
const cwd = options.cwd;
|
|
12317
12414
|
const force = Boolean(options.force);
|
|
12415
|
+
const runtimeMode = options.runtimeMode === "vendored" ? "vendored" : "package";
|
|
12318
12416
|
let framework = "nestjs";
|
|
12319
12417
|
let orm = "drizzle";
|
|
12320
12418
|
let architecture = "clean-lite-ps";
|
|
@@ -12337,6 +12435,11 @@ async function buildInitPlan(ctx, options) {
|
|
|
12337
12435
|
{
|
|
12338
12436
|
const configPath = path23.join(cwd, "codegen.config.yaml");
|
|
12339
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,
|
|
12340
12443
|
paths: {
|
|
12341
12444
|
backend_src: "src",
|
|
12342
12445
|
entities_dir: "entities",
|
|
@@ -12413,14 +12516,16 @@ async function buildInitPlan(ctx, options) {
|
|
|
12413
12516
|
fileEntry(
|
|
12414
12517
|
cwd,
|
|
12415
12518
|
path23.join(cwd, "src", "shared", "database", "database.module.ts"),
|
|
12416
|
-
databaseModuleContent(),
|
|
12519
|
+
databaseModuleContent(runtimeMode),
|
|
12417
12520
|
{ force }
|
|
12418
12521
|
)
|
|
12419
12522
|
);
|
|
12420
|
-
|
|
12421
|
-
|
|
12422
|
-
|
|
12423
|
-
|
|
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
|
+
}
|
|
12424
12529
|
}
|
|
12425
12530
|
entries.push(
|
|
12426
12531
|
fileEntry(
|
|
@@ -12445,7 +12550,7 @@ async function buildInitPlan(ctx, options) {
|
|
|
12445
12550
|
path: appModulePath,
|
|
12446
12551
|
relPath: relOf(cwd, appModulePath),
|
|
12447
12552
|
action: "create",
|
|
12448
|
-
content: appModuleContent()
|
|
12553
|
+
content: appModuleContent(runtimeMode)
|
|
12449
12554
|
});
|
|
12450
12555
|
} else {
|
|
12451
12556
|
entries.push({
|
|
@@ -12463,7 +12568,7 @@ async function buildInitPlan(ctx, options) {
|
|
|
12463
12568
|
path: mainPath,
|
|
12464
12569
|
relPath: relOf(cwd, mainPath),
|
|
12465
12570
|
action: "create",
|
|
12466
|
-
content: mainTsContent()
|
|
12571
|
+
content: mainTsContent(runtimeMode)
|
|
12467
12572
|
});
|
|
12468
12573
|
} else {
|
|
12469
12574
|
entries.push({
|
|
@@ -13606,7 +13711,8 @@ var ProjectInitCommand = class extends Command7 {
|
|
|
13606
13711
|
static usage = Command7.Usage({
|
|
13607
13712
|
description: "Scaffold a consumer project (config, shims, barrels, app.module)",
|
|
13608
13713
|
examples: [
|
|
13609
|
-
["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"],
|
|
13610
13716
|
["Preview without writing", "codegen project init --dry-run"],
|
|
13611
13717
|
["Create tsconfig if missing", "codegen project init --yes --with-tsconfig"],
|
|
13612
13718
|
["Overwrite existing shims", "codegen project init --force"]
|
|
@@ -13616,6 +13722,9 @@ var ProjectInitCommand = class extends Command7 {
|
|
|
13616
13722
|
dryRun = Option7.Boolean("--dry-run", false);
|
|
13617
13723
|
force = Option7.Boolean("--force", false);
|
|
13618
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");
|
|
13619
13728
|
// Vendor consumer skills into .claude/skills by default; opt out with --no-skills.
|
|
13620
13729
|
skills = Option7.Boolean("--skills", true);
|
|
13621
13730
|
json = Option7.Boolean("--json", false);
|
|
@@ -13627,11 +13736,18 @@ var ProjectInitCommand = class extends Command7 {
|
|
|
13627
13736
|
json: this.json,
|
|
13628
13737
|
skipDetection: false
|
|
13629
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
|
+
}
|
|
13630
13745
|
const plan = await buildInitPlan(ctx, {
|
|
13631
13746
|
cwd: ctx.cwd,
|
|
13632
13747
|
force: this.force,
|
|
13633
13748
|
withTsconfig: this.withTsconfig,
|
|
13634
|
-
skipScan: false
|
|
13749
|
+
skipScan: false,
|
|
13750
|
+
runtimeMode
|
|
13635
13751
|
});
|
|
13636
13752
|
if (this.force && !isJsonMode()) {
|
|
13637
13753
|
printWarning("--force: existing scaffold files will be overwritten.");
|