@metaobjectsdev/cli 1.0.12 → 1.1.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/README.md +32 -22
- package/dist/bin/meta.js +14 -2
- package/dist/bin/meta.js.map +1 -1
- package/dist/src/commands/docs.d.ts +1 -14
- package/dist/src/commands/docs.d.ts.map +1 -1
- package/dist/src/commands/docs.js +11 -835
- package/dist/src/commands/docs.js.map +1 -1
- package/dist/src/commands/eject.d.ts +24 -1
- package/dist/src/commands/eject.d.ts.map +1 -1
- package/dist/src/commands/eject.js +240 -69
- package/dist/src/commands/eject.js.map +1 -1
- package/dist/src/commands/gen.d.ts +7 -0
- package/dist/src/commands/gen.d.ts.map +1 -1
- package/dist/src/commands/gen.js +91 -21
- package/dist/src/commands/gen.js.map +1 -1
- package/dist/src/commands/generator.js +2 -2
- package/dist/src/commands/generator.js.map +1 -1
- package/dist/src/commands/init.d.ts +7 -0
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +71 -36
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/migrate.d.ts +1 -1
- package/dist/src/commands/migrate.d.ts.map +1 -1
- package/dist/src/commands/migrate.js +224 -125
- package/dist/src/commands/migrate.js.map +1 -1
- package/dist/src/commands/types.d.ts.map +1 -1
- package/dist/src/commands/types.js +16 -2
- package/dist/src/commands/types.js.map +1 -1
- package/dist/src/commands/upgrade.d.ts.map +1 -1
- package/dist/src/commands/upgrade.js +4 -1
- package/dist/src/commands/upgrade.js.map +1 -1
- package/dist/src/commands/verify.d.ts.map +1 -1
- package/dist/src/commands/verify.js +189 -125
- package/dist/src/commands/verify.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +59 -72
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib/agent-context-staleness.d.ts +8 -1
- package/dist/src/lib/agent-context-staleness.d.ts.map +1 -1
- package/dist/src/lib/agent-context-staleness.js +20 -5
- package/dist/src/lib/agent-context-staleness.js.map +1 -1
- package/dist/src/lib/agent-schema.d.ts +9 -0
- package/dist/src/lib/agent-schema.d.ts.map +1 -0
- package/dist/src/lib/agent-schema.js +61 -0
- package/dist/src/lib/agent-schema.js.map +1 -0
- package/dist/src/lib/allow.d.ts +6 -0
- package/dist/src/lib/allow.d.ts.map +1 -1
- package/dist/src/lib/allow.js +49 -5
- package/dist/src/lib/allow.js.map +1 -1
- package/dist/src/lib/anti-patterns.d.ts.map +1 -1
- package/dist/src/lib/anti-patterns.js +4 -2
- package/dist/src/lib/anti-patterns.js.map +1 -1
- package/dist/src/lib/args.d.ts +51 -10
- package/dist/src/lib/args.d.ts.map +1 -1
- package/dist/src/lib/args.js +44 -18
- package/dist/src/lib/args.js.map +1 -1
- package/dist/src/lib/catalog-listing.d.ts +21 -1
- package/dist/src/lib/catalog-listing.d.ts.map +1 -1
- package/dist/src/lib/catalog-listing.js +85 -16
- package/dist/src/lib/catalog-listing.js.map +1 -1
- package/dist/src/lib/catalog.d.ts +30 -0
- package/dist/src/lib/catalog.d.ts.map +1 -1
- package/dist/src/lib/catalog.js +40 -5
- package/dist/src/lib/catalog.js.map +1 -1
- package/dist/src/lib/codegen-drift.d.ts +31 -2
- package/dist/src/lib/codegen-drift.d.ts.map +1 -1
- package/dist/src/lib/codegen-drift.js +109 -4
- package/dist/src/lib/codegen-drift.js.map +1 -1
- package/dist/src/lib/collection-load-options.d.ts +1 -1
- package/dist/src/lib/collection-load-options.d.ts.map +1 -1
- package/dist/src/lib/collection-load-options.js +1 -0
- package/dist/src/lib/collection-load-options.js.map +1 -1
- package/dist/src/lib/config.d.ts +4 -2
- package/dist/src/lib/config.d.ts.map +1 -1
- package/dist/src/lib/config.js +4 -2
- package/dist/src/lib/config.js.map +1 -1
- package/dist/src/lib/decimal-precision-advisory.d.ts +10 -0
- package/dist/src/lib/decimal-precision-advisory.d.ts.map +1 -0
- package/dist/src/lib/decimal-precision-advisory.js +34 -0
- package/dist/src/lib/decimal-precision-advisory.js.map +1 -0
- package/dist/src/lib/deprecation-lint.d.ts.map +1 -1
- package/dist/src/lib/deprecation-lint.js +17 -26
- package/dist/src/lib/deprecation-lint.js.map +1 -1
- package/dist/src/lib/docs-removed.d.ts +13 -0
- package/dist/src/lib/docs-removed.d.ts.map +1 -0
- package/dist/src/lib/docs-removed.js +31 -0
- package/dist/src/lib/docs-removed.js.map +1 -0
- package/dist/src/lib/docs-site-eject.d.ts +13 -0
- package/dist/src/lib/docs-site-eject.d.ts.map +1 -0
- package/dist/src/lib/docs-site-eject.js +40 -0
- package/dist/src/lib/docs-site-eject.js.map +1 -0
- package/dist/src/lib/field-lint.d.ts +25 -0
- package/dist/src/lib/field-lint.d.ts.map +1 -0
- package/dist/src/lib/field-lint.js +102 -0
- package/dist/src/lib/field-lint.js.map +1 -0
- package/dist/src/lib/fk-index-advisory.d.ts +1 -2
- package/dist/src/lib/fk-index-advisory.d.ts.map +1 -1
- package/dist/src/lib/fk-index-advisory.js +4 -3
- package/dist/src/lib/fk-index-advisory.js.map +1 -1
- package/dist/src/lib/format.d.ts +7 -0
- package/dist/src/lib/format.d.ts.map +1 -1
- package/dist/src/lib/format.js +13 -0
- package/dist/src/lib/format.js.map +1 -1
- package/dist/src/lib/gen-migrate-advice.d.ts +3 -1
- package/dist/src/lib/gen-migrate-advice.d.ts.map +1 -1
- package/dist/src/lib/gen-migrate-advice.js +3 -4
- package/dist/src/lib/gen-migrate-advice.js.map +1 -1
- package/dist/src/lib/install-set.d.ts +10 -1
- package/dist/src/lib/install-set.d.ts.map +1 -1
- package/dist/src/lib/install-set.js +20 -2
- package/dist/src/lib/install-set.js.map +1 -1
- package/dist/src/lib/load-metaobjects-config.d.ts +13 -11
- package/dist/src/lib/load-metaobjects-config.d.ts.map +1 -1
- package/dist/src/lib/load-metaobjects-config.js +53 -75
- package/dist/src/lib/load-metaobjects-config.js.map +1 -1
- package/dist/src/lib/manifest-ignored-check.d.ts +4 -1
- package/dist/src/lib/manifest-ignored-check.d.ts.map +1 -1
- package/dist/src/lib/manifest-ignored-check.js +9 -4
- package/dist/src/lib/manifest-ignored-check.js.map +1 -1
- package/dist/src/lib/output.d.ts +15 -0
- package/dist/src/lib/output.d.ts.map +1 -1
- package/dist/src/lib/output.js +9 -1
- package/dist/src/lib/output.js.map +1 -1
- package/dist/src/lib/payload-field-tree.d.ts +4 -5
- package/dist/src/lib/payload-field-tree.d.ts.map +1 -1
- package/dist/src/lib/payload-field-tree.js +16 -31
- package/dist/src/lib/payload-field-tree.js.map +1 -1
- package/dist/src/lib/requirement-check.d.ts +7 -0
- package/dist/src/lib/requirement-check.d.ts.map +1 -1
- package/dist/src/lib/requirement-check.js +14 -7
- package/dist/src/lib/requirement-check.js.map +1 -1
- package/dist/src/lib/strict-args.d.ts +28 -0
- package/dist/src/lib/strict-args.d.ts.map +1 -0
- package/dist/src/lib/strict-args.js +49 -0
- package/dist/src/lib/strict-args.js.map +1 -0
- package/dist/src/lib/template-eject.d.ts +108 -0
- package/dist/src/lib/template-eject.d.ts.map +1 -0
- package/dist/src/lib/template-eject.js +438 -0
- package/dist/src/lib/template-eject.js.map +1 -0
- package/dist/src/lib/version.d.ts +9 -0
- package/dist/src/lib/version.d.ts.map +1 -1
- package/dist/src/lib/version.js +15 -0
- package/dist/src/lib/version.js.map +1 -1
- package/package.json +10 -10
- package/src/commands/docs.ts +11 -952
- package/src/commands/eject.ts +318 -73
- package/src/commands/gen.ts +94 -22
- package/src/commands/generator.ts +2 -2
- package/src/commands/init.ts +80 -38
- package/src/commands/migrate.ts +248 -117
- package/src/commands/types.ts +18 -2
- package/src/commands/upgrade.ts +5 -1
- package/src/commands/verify.ts +229 -136
- package/src/index.ts +59 -72
- package/src/lib/agent-context-staleness.ts +20 -5
- package/src/lib/agent-schema.ts +74 -0
- package/src/lib/allow.ts +57 -6
- package/src/lib/anti-patterns.ts +4 -2
- package/src/lib/args.ts +83 -28
- package/src/lib/catalog-listing.ts +105 -25
- package/src/lib/catalog.ts +51 -6
- package/src/lib/codegen-drift.ts +138 -3
- package/src/lib/collection-load-options.ts +2 -1
- package/src/lib/config.ts +5 -3
- package/src/lib/decimal-precision-advisory.ts +50 -0
- package/src/lib/deprecation-lint.ts +16 -24
- package/src/lib/docs-removed.ts +41 -0
- package/src/lib/docs-site-eject.ts +48 -0
- package/src/lib/field-lint.ts +122 -0
- package/src/lib/fk-index-advisory.ts +4 -4
- package/src/lib/format.ts +12 -0
- package/src/lib/gen-migrate-advice.ts +6 -4
- package/src/lib/install-set.ts +20 -1
- package/src/lib/load-metaobjects-config.ts +57 -78
- package/src/lib/manifest-ignored-check.ts +14 -10
- package/src/lib/output.ts +18 -1
- package/src/lib/payload-field-tree.ts +18 -35
- package/src/lib/requirement-check.ts +21 -6
- package/src/lib/strict-args.ts +52 -0
- package/src/lib/template-eject.ts +526 -0
- package/src/lib/version.ts +18 -0
- package/dist/src/lib/docs-drift.d.ts +0 -42
- package/dist/src/lib/docs-drift.d.ts.map +0 -1
- package/dist/src/lib/docs-drift.js +0 -264
- package/dist/src/lib/docs-drift.js.map +0 -1
- package/src/lib/docs-drift.ts +0 -312
package/src/commands/eject.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// FR-040 §4.2(a) — `meta eject <generator>...` takes ownership of any reference-template
|
|
2
2
|
// generator, in any package, at any time after `meta init`.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
// empty selection,
|
|
4
|
+
// This is the copy door, for a generator an adopter wants to CHANGE: `meta init`
|
|
5
|
+
// scaffolds the layout and an empty selection, and a generator run as shipped is
|
|
6
|
+
// imported from its package without coming through here (ADR-0034 Amendment 5). It takes
|
|
6
7
|
// MANY names, because a real selection is several — choosing a client tier is
|
|
7
8
|
// `form hooks grid` — and three separate invocations produce three separate install
|
|
8
9
|
// lines for the same package. The consolidated install set is the point.
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
// config-array edit has regressed across at least four filed issues). The primary
|
|
15
16
|
// consumer performs two file edits and one install trivially when told exactly what
|
|
16
17
|
// they are. `meta gen` plus `tsc` is the audit.
|
|
18
|
+
import { existsSync } from "node:fs";
|
|
17
19
|
import { mkdir, writeFile, stat, readFile } from "node:fs/promises";
|
|
18
20
|
import { join } from "node:path";
|
|
19
21
|
import { cliVersion } from "../lib/version.js";
|
|
@@ -24,12 +26,16 @@ import { parseEjectArgs } from "../lib/args.js";
|
|
|
24
26
|
import { log } from "../lib/log.js";
|
|
25
27
|
import { declaredDependencyNames, readPackageManifest } from "../lib/package-manifest.js";
|
|
26
28
|
import { compareOwnedCopy, type OwnedComparison } from "../lib/owned-copy.js";
|
|
27
|
-
import { composeCatalog, packageOf } from "../lib/catalog.js";
|
|
28
|
-
import { installSetFor, type InstallSet, type OwnedRuntimeInstall } from "../lib/install-set.js";
|
|
29
|
+
import { composeCatalog, CORE_CODEGEN_PACKAGE, factoryModuleOf, packageOf } from "../lib/catalog.js";
|
|
30
|
+
import { dependencyRangesOf, installSetFor, type InstallSet, type OwnedRuntimeInstall } from "../lib/install-set.js";
|
|
29
31
|
import {
|
|
30
32
|
ejectRuntime, ejectsRuntime, runtimeCopyStatus, runtimeDiffCommand, runtimeInstall,
|
|
31
33
|
type RuntimeEjectResult, type RuntimeFileResult,
|
|
32
34
|
} from "../lib/runtime-eject.js";
|
|
35
|
+
import {
|
|
36
|
+
closureOf, ejectTemplates, OWNED_TEMPLATES_DIR, packagedTemplates, predatesTemplateHandOver,
|
|
37
|
+
templateCopyStatus, templateDiffCommand, type TemplateEjectResult, type TemplateFileResult,
|
|
38
|
+
} from "../lib/template-eject.js";
|
|
33
39
|
import { HTTP_RUNTIME_PACKAGE, OWNED_RUNTIME_DIR } from "@metaobjectsdev/codegen-ts";
|
|
34
40
|
import { emitStructured, type OutputFormat } from "../lib/format.js";
|
|
35
41
|
import {
|
|
@@ -37,6 +43,7 @@ import {
|
|
|
37
43
|
type LibraryEjectResult,
|
|
38
44
|
} from "../lib/library-eject.js";
|
|
39
45
|
import { describeError } from "../lib/error-text.js";
|
|
46
|
+
import { DOCS_SITE_NAME, ejectDocsSite, type DocsSiteFileResult } from "../lib/docs-site-eject.js";
|
|
40
47
|
|
|
41
48
|
// Mirrors `OWNED_GENERATORS_DIR` in init.ts's `writeOwnedGenerators` — same directory,
|
|
42
49
|
// same never-clobber-without-consent contract. Kept as its own local constant rather
|
|
@@ -61,8 +68,6 @@ interface TemplateSource {
|
|
|
61
68
|
// runtime by selecting this entry via `names.includes(name)`. Reading from the root
|
|
62
69
|
// deletes that machinery without weakening anything: membership is still checked, once,
|
|
63
70
|
// where the untrusted value enters.
|
|
64
|
-
const CORE_CODEGEN_PACKAGE = "@metaobjectsdev/codegen-ts";
|
|
65
|
-
|
|
66
71
|
const SOURCES: TemplateSource[] = [
|
|
67
72
|
{
|
|
68
73
|
packageName: CORE_CODEGEN_PACKAGE,
|
|
@@ -85,6 +90,7 @@ function resolveSource(name: string): TemplateSource | undefined {
|
|
|
85
90
|
return SOURCES.find((s) => s.names.includes(name));
|
|
86
91
|
}
|
|
87
92
|
|
|
93
|
+
|
|
88
94
|
/** Every ejectable name, in registry order (stable — matches `meta eject --list`). */
|
|
89
95
|
export function ejectableNames(): string[] {
|
|
90
96
|
return SOURCES.flatMap((s) => s.names);
|
|
@@ -112,6 +118,19 @@ function extractExportName(importLine: string, name: string): string {
|
|
|
112
118
|
return match[1];
|
|
113
119
|
}
|
|
114
120
|
|
|
121
|
+
// The CALL a template's header documents, when it is not the bare `<export>()`. A factory
|
|
122
|
+
// that cannot be called without options says so where it says how to import it
|
|
123
|
+
// (`// generators: [sharedModelFile({ name, include })]`). Read from the header for the
|
|
124
|
+
// reason the import line is: the template is the one thing that knows, and the catalog
|
|
125
|
+
// deliberately does not derive a call from an options summary.
|
|
126
|
+
const HEADER_ENTRY_RE = /^\/\/\s+generators: \[(\w+\(.*\))\],?\s*$/m;
|
|
127
|
+
|
|
128
|
+
/** The call to wire: the header's, when it documents one for this template's own export. */
|
|
129
|
+
function extractEntry(templateSource: string, exportName: string): string {
|
|
130
|
+
const call = HEADER_ENTRY_RE.exec(templateSource)?.[1];
|
|
131
|
+
return call !== undefined && call.startsWith(`${exportName}(`) ? call : `${exportName}()`;
|
|
132
|
+
}
|
|
133
|
+
|
|
115
134
|
function extractImportLine(templateSource: string, name: string): string {
|
|
116
135
|
const match = HEADER_IMPORT_RE.exec(templateSource);
|
|
117
136
|
if (!match?.[1]) {
|
|
@@ -144,6 +163,9 @@ export interface EjectResult {
|
|
|
144
163
|
importLine: string;
|
|
145
164
|
/** The symbol the template exports — the binding to REPLACE in the config. */
|
|
146
165
|
exportName: string;
|
|
166
|
+
/** The call to wire, with any options the factory cannot be called without
|
|
167
|
+
* (`sharedModelFile({ name, include })`), as the template's header documents it. */
|
|
168
|
+
entry: string;
|
|
147
169
|
/** The package the generator currently comes from, i.e. the import to remove. */
|
|
148
170
|
packageName: string;
|
|
149
171
|
/** Advisory lines about packages the ejected file imports but the project lacks. */
|
|
@@ -171,6 +193,12 @@ export interface EjectResult {
|
|
|
171
193
|
* generator whose output imports no adapter.
|
|
172
194
|
*/
|
|
173
195
|
runtime?: RuntimeEjectResult | undefined;
|
|
196
|
+
/**
|
|
197
|
+
* ADR-0034 Amendment 8: the template modules this generator calls to write its output,
|
|
198
|
+
* copied into `codegen/templates/` so the adopter owns those too. Absent for a generator
|
|
199
|
+
* that calls none (`barrel`).
|
|
200
|
+
*/
|
|
201
|
+
templates?: TemplateEjectResult | undefined;
|
|
174
202
|
}
|
|
175
203
|
|
|
176
204
|
/** The `@metaobjectsdev/*` packages an ejected template imports, read from the file
|
|
@@ -205,8 +233,13 @@ function requiredPackages(templateSource: string): string[] {
|
|
|
205
233
|
* missing package and the version to match is the useful half; silently rewriting
|
|
206
234
|
* someone's manifest is not.
|
|
207
235
|
*/
|
|
208
|
-
export async function dependencyNotesForTemplate(
|
|
209
|
-
|
|
236
|
+
export async function dependencyNotesForTemplate(
|
|
237
|
+
cwd: string,
|
|
238
|
+
templateSource: string,
|
|
239
|
+
/** Packages the template modules copied beside the generator import, as well. */
|
|
240
|
+
alsoImported: readonly string[] = [],
|
|
241
|
+
): Promise<string[]> {
|
|
242
|
+
const required = [...new Set([...requiredPackages(templateSource), ...alsoImported.filter((p) => p.startsWith("@metaobjectsdev/"))])].sort();
|
|
210
243
|
if (required.length === 0) return [];
|
|
211
244
|
|
|
212
245
|
const pkg = readPackageManifest(cwd);
|
|
@@ -234,19 +267,23 @@ export async function ejectGenerator(opts: EjectOptions): Promise<EjectResult> {
|
|
|
234
267
|
);
|
|
235
268
|
}
|
|
236
269
|
|
|
237
|
-
|
|
270
|
+
// What is written is the reference with its module specifiers pointed at the project:
|
|
271
|
+
// its template modules are copied beside it (ADR-0034 Amendment 8).
|
|
272
|
+
const closure = closureOf(opts.name);
|
|
273
|
+
const templateSource = closure.generator.content;
|
|
238
274
|
const importLine = extractImportLine(templateSource, opts.name);
|
|
239
275
|
const exportName = extractExportName(importLine, opts.name);
|
|
240
276
|
const rel = `${OWNED_GENERATORS_DIR}/${opts.name}.ts`;
|
|
241
277
|
const abs = join(opts.cwd, rel);
|
|
242
|
-
const notes = await dependencyNotesForTemplate(opts.cwd, templateSource);
|
|
278
|
+
const notes = await dependencyNotesForTemplate(opts.cwd, templateSource, closure.packages);
|
|
243
279
|
const common = {
|
|
244
280
|
path: rel,
|
|
245
281
|
importLine,
|
|
246
282
|
exportName,
|
|
283
|
+
entry: extractEntry(templateSource, exportName),
|
|
247
284
|
packageName: source.packageName,
|
|
248
285
|
dependencyNotes: notes,
|
|
249
|
-
templatePackages:
|
|
286
|
+
templatePackages: closure.packages.filter((p) => p.startsWith("@metaobjectsdev/")),
|
|
250
287
|
};
|
|
251
288
|
|
|
252
289
|
const existing = (await fileExists(abs)) ? await readFile(abs, "utf8") : undefined;
|
|
@@ -265,8 +302,17 @@ export async function ejectGenerator(opts: EjectOptions): Promise<EjectResult> {
|
|
|
265
302
|
? await ejectRuntime(opts.cwd, [opts.name], opts.force === true)
|
|
266
303
|
: undefined;
|
|
267
304
|
|
|
305
|
+
// The template modules follow the same rule, for the same reason: a kept copy that predates
|
|
306
|
+
// the hand-over still imports the emit code from the package, so copying the modules beside
|
|
307
|
+
// it would be dead code in the project.
|
|
308
|
+
const keptCopyPredatesTemplates =
|
|
309
|
+
existing !== undefined && !opts.force && predatesTemplateHandOver(existing, closure);
|
|
310
|
+
const templates = closure.templates.length > 0 && !keptCopyPredatesTemplates
|
|
311
|
+
? await ejectTemplates(opts.cwd, [closure], opts.force === true)
|
|
312
|
+
: undefined;
|
|
313
|
+
|
|
268
314
|
if (!opts.force && existing !== undefined) {
|
|
269
|
-
return { ...common, status: "preserved", comparison, runtime };
|
|
315
|
+
return { ...common, status: "preserved", comparison, runtime, templates };
|
|
270
316
|
}
|
|
271
317
|
|
|
272
318
|
await mkdir(join(opts.cwd, OWNED_GENERATORS_DIR), { recursive: true });
|
|
@@ -276,6 +322,7 @@ export async function ejectGenerator(opts: EjectOptions): Promise<EjectResult> {
|
|
|
276
322
|
status: existing === undefined ? "created" : "replaced",
|
|
277
323
|
comparison,
|
|
278
324
|
runtime,
|
|
325
|
+
templates,
|
|
279
326
|
};
|
|
280
327
|
}
|
|
281
328
|
|
|
@@ -314,6 +361,47 @@ export async function runtimeCopyLines(cwd: string): Promise<string[]> {
|
|
|
314
361
|
return lines;
|
|
315
362
|
}
|
|
316
363
|
|
|
364
|
+
/**
|
|
365
|
+
* The owned template modules under `codegen/templates/`, file by file, against what the
|
|
366
|
+
* installed packages would write there today. Shared by `meta eject --list` and
|
|
367
|
+
* `meta gen --list`. Empty when the project owns no template copy.
|
|
368
|
+
*
|
|
369
|
+
* Only the import lines of a copy differ from the package by design, so the comparison is
|
|
370
|
+
* the one the generator copies get: `identical` says an upgrade can be taken by re-copying
|
|
371
|
+
* (`meta eject <name> --force`); `DIFFERS` says the copy is yours in a way the package is
|
|
372
|
+
* not, and names the diff that tells whose change it is.
|
|
373
|
+
*/
|
|
374
|
+
export async function templateCopyLines(cwd: string): Promise<string[]> {
|
|
375
|
+
if (!existsSync(join(cwd, OWNED_TEMPLATES_DIR))) return [];
|
|
376
|
+
const rows = await templateCopyStatus(cwd, packagedTemplates());
|
|
377
|
+
if (rows.length === 0) return [];
|
|
378
|
+
const lines: string[] = [
|
|
379
|
+
`Template source this project owns (${OWNED_TEMPLATES_DIR}/), against the installed codegen packages:`,
|
|
380
|
+
];
|
|
381
|
+
const differing: string[] = [];
|
|
382
|
+
for (const r of rows) {
|
|
383
|
+
if (r.verdict === "identical") lines.push(` ${r.path} [identical to the package]`);
|
|
384
|
+
else if (r.verdict === "reformatted") lines.push(` ${r.path} [same content as the package, your formatting]`);
|
|
385
|
+
else if (r.verdict === "not-in-package") lines.push(` ${r.path} [not in the package — yours, or removed upstream]`);
|
|
386
|
+
else {
|
|
387
|
+
const diff = templateDiffCommand(r);
|
|
388
|
+
if (diff !== undefined) differing.push(diff);
|
|
389
|
+
lines.push(
|
|
390
|
+
` ${r.path} [DIFFERS: ${r.referenceOnly} line(s) only in the package, ${r.localOnly} line(s) only in yours]`,
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
if (differing.length > 0) {
|
|
395
|
+
lines.push(
|
|
396
|
+
" See the difference (upstream fix, or your own?) before taking an upgrade. " +
|
|
397
|
+
"Only the import lines of a copy differ from the package by design:",
|
|
398
|
+
);
|
|
399
|
+
for (const d of differing) lines.push(` ${d}`);
|
|
400
|
+
}
|
|
401
|
+
lines.push("");
|
|
402
|
+
return lines;
|
|
403
|
+
}
|
|
404
|
+
|
|
317
405
|
/**
|
|
318
406
|
* `--list` doubles as the staleness report for what this project ALREADY owns.
|
|
319
407
|
*
|
|
@@ -323,38 +411,120 @@ export async function runtimeCopyLines(cwd: string): Promise<string[]> {
|
|
|
323
411
|
* gate green. Marking each owned copy `identical` / `differs` makes it a one-command
|
|
324
412
|
* answer instead of a diff nobody thinks to run.
|
|
325
413
|
*/
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
414
|
+
/** One reference generator as `--list` reports it: is a copy owned, and how far it moved. */
|
|
415
|
+
interface GeneratorListRow {
|
|
416
|
+
name: string;
|
|
417
|
+
package: string;
|
|
418
|
+
/** `available` = not ejected; `owned` = ejected but the reference could not be read. */
|
|
419
|
+
status: "available" | "owned" | "identical" | "reformatted" | "differs";
|
|
420
|
+
/** Lines behind / of your own in the GENERATOR file alone. */
|
|
421
|
+
behind: number;
|
|
422
|
+
own: number;
|
|
423
|
+
/**
|
|
424
|
+
* The renderers this generator owns under `codegen/templates/` (those it imports that
|
|
425
|
+
* exist in the project), each against the installed package. A generator is `identical`
|
|
426
|
+
* only when its file AND every one of these is; `status` is `differs` when any differs.
|
|
427
|
+
* Absent when the project owns none of its renderers.
|
|
428
|
+
*/
|
|
429
|
+
templates?: GeneratorTemplateRow[];
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
interface GeneratorTemplateRow {
|
|
433
|
+
path: string;
|
|
434
|
+
status: "identical" | "reformatted" | "differs";
|
|
435
|
+
behind: number;
|
|
436
|
+
own: number;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/** One `SOURCES` entry and the rows walked for it — the grouping the text list prints. */
|
|
440
|
+
interface GeneratorListGroup {
|
|
441
|
+
packageName: string;
|
|
442
|
+
rows: GeneratorListRow[];
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
async function generatorListGroups(cwd: string): Promise<GeneratorListGroup[]> {
|
|
446
|
+
const groups: GeneratorListGroup[] = [];
|
|
447
|
+
// Every renderer the project holds, against the package: attributed to a generator by what
|
|
448
|
+
// that generator imports, so a renderer another generator owns never flags this one.
|
|
449
|
+
const templateStatus = await templateCopyStatus(cwd, packagedTemplates());
|
|
331
450
|
for (const source of SOURCES) {
|
|
332
|
-
|
|
451
|
+
const rows: GeneratorListRow[] = [];
|
|
452
|
+
groups.push({ packageName: source.packageName, rows });
|
|
333
453
|
for (const name of source.names) {
|
|
454
|
+
const row: GeneratorListRow = { name, package: source.packageName, status: "available", behind: 0, own: 0 };
|
|
455
|
+
rows.push(row);
|
|
334
456
|
const abs = join(cwd, OWNED_GENERATORS_DIR, `${name}.ts`);
|
|
335
|
-
if (!(await fileExists(abs)))
|
|
336
|
-
lines.push(` ${name}`);
|
|
337
|
-
continue;
|
|
338
|
-
}
|
|
457
|
+
if (!(await fileExists(abs))) continue;
|
|
339
458
|
let ref: string;
|
|
340
459
|
try {
|
|
341
|
-
ref =
|
|
460
|
+
ref = closureOf(name).generator.content;
|
|
342
461
|
} catch {
|
|
343
|
-
|
|
462
|
+
row.status = "owned";
|
|
344
463
|
continue;
|
|
345
464
|
}
|
|
346
|
-
const
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
lines.push(` ${name} [owned — identical to the reference]`);
|
|
350
|
-
} else if (cmp.verdict === "reformatted") {
|
|
351
|
-
lines.push(` ${name} [owned — same content as the reference, your formatting]`);
|
|
465
|
+
const cmp = await compareOwnedCopy(await readFile(abs, "utf8"), ref);
|
|
466
|
+
if (cmp.verdict === "identical" || cmp.verdict === "reformatted") {
|
|
467
|
+
row.status = cmp.verdict;
|
|
352
468
|
} else {
|
|
353
|
-
|
|
469
|
+
row.status = "differs";
|
|
470
|
+
row.behind = cmp.referenceOnly;
|
|
471
|
+
row.own = cmp.localOnly;
|
|
472
|
+
}
|
|
473
|
+
const reached = new Set(closureOf(name).templates.map((f) => f.path));
|
|
474
|
+
const renderers: GeneratorTemplateRow[] = [];
|
|
475
|
+
for (const t of templateStatus) {
|
|
476
|
+
if (!reached.has(t.path) || t.verdict === "not-in-package") continue;
|
|
477
|
+
renderers.push({
|
|
478
|
+
path: t.path,
|
|
479
|
+
status: t.verdict === "identical" || t.verdict === "reformatted" ? t.verdict : "differs",
|
|
480
|
+
behind: t.referenceOnly,
|
|
481
|
+
own: t.localOnly,
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
if (renderers.length > 0) row.templates = renderers;
|
|
485
|
+
if (renderers.some((r) => r.status === "differs")) row.status = "differs";
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
return groups;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/** `--list` as one structured document: the generators and the shipped libraries. */
|
|
492
|
+
async function listData(cwd: string): Promise<Record<string, unknown>> {
|
|
493
|
+
const generators = (await generatorListGroups(cwd)).flatMap((g) => g.rows);
|
|
494
|
+
return {
|
|
495
|
+
generators,
|
|
496
|
+
libraries: ejectableLibraryNames(),
|
|
497
|
+
help: [
|
|
498
|
+
"run `meta eject <name>...` to copy a generator into codegen/generators/ and own it",
|
|
499
|
+
"`meta eject --list --format text` also reports owned runtime copies and ejected-library drift",
|
|
500
|
+
],
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
async function listOutput(cwd: string): Promise<string> {
|
|
505
|
+
const lines: string[] = [];
|
|
506
|
+
lines.push("Ejectable generators (copy any of these into codegen/generators/ and own it):");
|
|
507
|
+
lines.push("");
|
|
508
|
+
const groups = await generatorListGroups(cwd);
|
|
509
|
+
const anyStale = groups.some((g) => g.rows.some((r) => r.status === "differs"));
|
|
510
|
+
const generatorFileDiffers = (r: GeneratorListRow): boolean => r.behind > 0 || r.own > 0;
|
|
511
|
+
for (const group of groups) {
|
|
512
|
+
lines.push(`${group.packageName}:`);
|
|
513
|
+
for (const r of group.rows) {
|
|
514
|
+
if (r.status === "available") lines.push(` ${r.name}`);
|
|
515
|
+
else if (r.status === "owned") lines.push(` ${r.name} [owned]`);
|
|
516
|
+
else if (r.status === "identical") lines.push(` ${r.name} [owned — identical to the reference]`);
|
|
517
|
+
else if (r.status === "reformatted") lines.push(` ${r.name} [owned — same content as the reference, your formatting]`);
|
|
518
|
+
else {
|
|
519
|
+
const differing = (r.templates ?? []).filter((t) => t.status === "differs");
|
|
354
520
|
lines.push(
|
|
355
|
-
|
|
356
|
-
|
|
521
|
+
generatorFileDiffers(r)
|
|
522
|
+
? ` ${r.name} [owned — DIFFERS: ${r.behind} line(s) behind, ${r.own} line(s) of your own]`
|
|
523
|
+
: ` ${r.name} [owned — DIFFERS: generator identical, ${differing.length} renderer(s) differ]`,
|
|
357
524
|
);
|
|
525
|
+
for (const t of differing) {
|
|
526
|
+
lines.push(` renderer ${t.path} [DIFFERS: ${t.behind} line(s) behind, ${t.own} line(s) of your own]`);
|
|
527
|
+
}
|
|
358
528
|
}
|
|
359
529
|
}
|
|
360
530
|
lines.push("");
|
|
@@ -376,6 +546,12 @@ async function listOutput(cwd: string): Promise<string> {
|
|
|
376
546
|
lines.push("");
|
|
377
547
|
}
|
|
378
548
|
lines.push(...(await runtimeCopyLines(cwd)));
|
|
549
|
+
lines.push(...(await templateCopyLines(cwd)));
|
|
550
|
+
// The docs site's theme: not a generator copy (its builder stays packaged), but a name
|
|
551
|
+
// `meta eject` takes all the same.
|
|
552
|
+
lines.push("The docs site's theme (its templates and assets, into codegen/docs-site/):");
|
|
553
|
+
lines.push(` ${DOCS_SITE_NAME}`);
|
|
554
|
+
lines.push("");
|
|
379
555
|
// FR-043 — the shipped libraries, and how far this project's copies have drifted.
|
|
380
556
|
lines.push("Shipped libraries (copy one into your own sources and own it):");
|
|
381
557
|
for (const name of ejectableLibraryNames()) lines.push(` ${name}`);
|
|
@@ -422,16 +598,28 @@ async function listOutput(cwd: string): Promise<string> {
|
|
|
422
598
|
// the command
|
|
423
599
|
// ---------------------------------------------------------------------------
|
|
424
600
|
|
|
601
|
+
/**
|
|
602
|
+
* The entry an ejected generator is wired by. Every generator, documentation included, goes
|
|
603
|
+
* in the top-level `generators` and is run by `meta gen` (ADR-0034 Amendment 9).
|
|
604
|
+
*/
|
|
605
|
+
interface EjectWiring {
|
|
606
|
+
/** The call, with the options the factory cannot be called without. */
|
|
607
|
+
entry: string;
|
|
608
|
+
}
|
|
609
|
+
|
|
425
610
|
/** One row of the `--format json` payload. */
|
|
426
611
|
interface EjectedRow {
|
|
427
612
|
name: string;
|
|
428
613
|
path: string;
|
|
429
614
|
status: EjectResult["status"];
|
|
430
|
-
/** The two edits an adopter makes in `metaobjects.config.ts
|
|
615
|
+
/** The two edits an adopter makes in `metaobjects.config.ts`: the import, and the entry in
|
|
616
|
+
* `generators`. */
|
|
431
617
|
wire: { import: string; entry: string };
|
|
432
618
|
requires: readonly string[];
|
|
433
619
|
/** The adapter source copied beside it (ADR-0034 Amendment 3). Absent when none. */
|
|
434
620
|
runtime?: RuntimeFileResult[];
|
|
621
|
+
/** The template modules copied beside it (ADR-0034 Amendment 8). Absent when none. */
|
|
622
|
+
templates?: TemplateFileResult[];
|
|
435
623
|
}
|
|
436
624
|
|
|
437
625
|
interface EjectPayload {
|
|
@@ -441,6 +629,22 @@ interface EjectPayload {
|
|
|
441
629
|
config: { keys: string[] };
|
|
442
630
|
/** FR-043 — libraries ejected in this call. Absent when none were. */
|
|
443
631
|
libraries?: LibraryEjectResult[];
|
|
632
|
+
/** `meta eject docs-site`: the site's templates and assets. Absent when not asked for. */
|
|
633
|
+
docsSite?: DocsSiteFileResult[];
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/** The text report for `meta eject docs-site`. */
|
|
637
|
+
function reportDocsSite(files: readonly DocsSiteFileResult[]): void {
|
|
638
|
+
const written = files.filter((f) => f.status !== "preserved").length;
|
|
639
|
+
log.info(
|
|
640
|
+
`Ejected the docs-site theme -> codegen/docs-site/: ${written} file(s) written, ` +
|
|
641
|
+
`${files.length - written} already there and kept (--force replaces them).`,
|
|
642
|
+
);
|
|
643
|
+
log.info(
|
|
644
|
+
" docsSiteFile() reads these in place of the bundled templates and assets; edit them to own " +
|
|
645
|
+
"the site's look. The site builder stays in the package. Wire the generator, if you have " +
|
|
646
|
+
"not: `docsSiteFile()` in `generators`, with a `docs` target.",
|
|
647
|
+
);
|
|
444
648
|
}
|
|
445
649
|
|
|
446
650
|
/** The text report for one ejected library. */
|
|
@@ -486,20 +690,14 @@ function reportLibrary(result: LibraryEjectResult): void {
|
|
|
486
690
|
* already-copied half as "preserved" and the adopter cannot tell what happened.
|
|
487
691
|
* Returns the unknown names, or an empty array.
|
|
488
692
|
*/
|
|
489
|
-
/** Where a package-only generator's factory is imported from. The core package serves
|
|
490
|
-
* its generator factories from the `/generators` subpath; the UI packages from the root. */
|
|
491
|
-
function packageFactoryPath(name: string): string {
|
|
492
|
-
const pkg = packageOf(name) ?? "";
|
|
493
|
-
return pkg === CORE_CODEGEN_PACKAGE ? `${pkg}/generators` : pkg;
|
|
494
|
-
}
|
|
495
693
|
|
|
496
694
|
function unknownNames(names: readonly string[]): string[] {
|
|
497
|
-
return names.filter((n) => resolveSource(n) === undefined && !isLibraryName(n));
|
|
695
|
+
return names.filter((n) => resolveSource(n) === undefined && !isLibraryName(n) && n !== DOCS_SITE_NAME);
|
|
498
696
|
}
|
|
499
697
|
|
|
500
698
|
/** Print the per-name text report — every branch below predates this command taking
|
|
501
699
|
* more than one name, and each was written against a real incident. */
|
|
502
|
-
function reportOne(result: EjectResult, name: string): void {
|
|
700
|
+
function reportOne(result: EjectResult, name: string, wiring: EjectWiring): void {
|
|
503
701
|
if (result.status === "preserved") {
|
|
504
702
|
// "already exists — left untouched" was the whole message, and it answered the
|
|
505
703
|
// question nobody has. What an owner needs to know is whether their copy still
|
|
@@ -534,6 +732,7 @@ function reportOne(result: EjectResult, name: string): void {
|
|
|
534
732
|
"See which, before deciding:",
|
|
535
733
|
);
|
|
536
734
|
log.info(` diff -u node_modules/${result.packageName}/src/reference/${name}.ts ${result.path}`);
|
|
735
|
+
log.info(" (A copy differs from the reference in its import lines by design: they point at your project.)");
|
|
537
736
|
log.info(
|
|
538
737
|
" To take upstream changes AND keep your customization, three-way merge them — " +
|
|
539
738
|
"`git merge-file --diff3 <your copy> <the reference you ejected from> <the reference above>`. " +
|
|
@@ -556,32 +755,61 @@ function reportOne(result: EjectResult, name: string): void {
|
|
|
556
755
|
log.info(`Ejected "${name}" -> ${result.path}. You own it now (ADR-0034 scaffold-and-own).`);
|
|
557
756
|
}
|
|
558
757
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
758
|
+
{
|
|
759
|
+
// REPLACE, never "paste". A generator reaches `generators: [...]` under ONE binding,
|
|
760
|
+
// so a reader told to "paste" gets a duplicate identifier at best — and at worst
|
|
761
|
+
// deletes nothing, keeps `formFile()` in the array bound to the PACKAGE import, and
|
|
762
|
+
// silently runs the packaged generator while editing the ejected file. That failure
|
|
763
|
+
// is invisible and is the exact one ejecting exists to prevent.
|
|
764
|
+
//
|
|
765
|
+
// But eject reads no config, so it cannot know WHICH of the three states this project
|
|
766
|
+
// is in, and stating one of them as fact is wrong in the other two. Name the goal,
|
|
767
|
+
// then the three branches; the reader knows which one they are looking at.
|
|
768
|
+
log.info(`In metaobjects.config.ts, "${result.exportName}" must resolve to this file:`);
|
|
769
|
+
log.info(` ${result.importLine}`);
|
|
770
|
+
log.info(
|
|
771
|
+
` - If it is imported from "${factoryModuleOf(name) ?? result.packageName}", REPLACE that import with the ` +
|
|
772
|
+
"line above. Adding a second one leaves `generators` bound to the PACKAGED " +
|
|
773
|
+
"generator, and your edits to this file do nothing.",
|
|
774
|
+
);
|
|
775
|
+
log.info(
|
|
776
|
+
" - If it is already imported from ./codegen/generators/, it points here already " +
|
|
777
|
+
"— nothing to change.",
|
|
778
|
+
);
|
|
779
|
+
log.info(
|
|
780
|
+
` - If ${wiring.entry} is not in \`generators\` yet, add the import above ` +
|
|
781
|
+
"AND the entry.",
|
|
782
|
+
);
|
|
783
|
+
}
|
|
583
784
|
for (const line of result.dependencyNotes) log.info(line);
|
|
584
785
|
if (result.runtime !== undefined && result.runtime.files.length > 0) reportRuntime(result.runtime.files);
|
|
786
|
+
if (result.templates !== undefined && result.templates.files.length > 0) reportTemplates(result.templates.files);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
/** What the template copy handed over, and how the owned generator reaches it. */
|
|
790
|
+
function reportTemplates(files: readonly TemplateFileResult[]): void {
|
|
791
|
+
const written = files.filter((f) => f.status !== "preserved");
|
|
792
|
+
// A kept file that already matches the package is not news (ejecting `entity queries` copies
|
|
793
|
+
// the shared validators once, then finds them) — only a kept file that differs is.
|
|
794
|
+
const kept = files.filter((f) => f.status === "preserved" && f.comparison?.verdict !== "identical");
|
|
795
|
+
log.info(
|
|
796
|
+
`The code this generator calls to write its output is yours too: its template modules are in ` +
|
|
797
|
+
`${OWNED_TEMPLATES_DIR}/, not in the codegen package. What stays in the package is the engine ` +
|
|
798
|
+
"(the generator base, the model walks, the naming and type-mapping tables).",
|
|
799
|
+
);
|
|
800
|
+
if (written.length > 0) {
|
|
801
|
+
log.info(
|
|
802
|
+
` Copied ${written.length} file(s) into ${OWNED_TEMPLATES_DIR}/ (from the installed package; only their import lines differ).`,
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
const keptDiffering = kept.filter((f) => f.comparison?.verdict === "differs");
|
|
806
|
+
if (kept.length > 0) {
|
|
807
|
+
log.info(
|
|
808
|
+
` ${kept.length} file(s) were already there and were left untouched` +
|
|
809
|
+
(keptDiffering.length > 0 ? `, ${keptDiffering.length} of them differing from the package` : "") +
|
|
810
|
+
" (--force replaces them). `meta eject --list` compares each one.",
|
|
811
|
+
);
|
|
812
|
+
}
|
|
585
813
|
}
|
|
586
814
|
|
|
587
815
|
/** What the adapter copy handed over, and how the emitted code reaches it. */
|
|
@@ -624,7 +852,8 @@ export async function ejectCommand(
|
|
|
624
852
|
}
|
|
625
853
|
|
|
626
854
|
if (flags.list) {
|
|
627
|
-
log.info(await listOutput(cwd));
|
|
855
|
+
if (fmt === "text") log.info(await listOutput(cwd));
|
|
856
|
+
else emitStructured(await listData(cwd), fmt);
|
|
628
857
|
return 0;
|
|
629
858
|
}
|
|
630
859
|
|
|
@@ -645,7 +874,7 @@ export async function ejectCommand(
|
|
|
645
874
|
const unknown = unmatched.filter((n) => packageOf(n) === undefined);
|
|
646
875
|
if (packageOnly.length > 0) {
|
|
647
876
|
log.error(
|
|
648
|
-
`package-only generator(s): ${packageOnly.map((n) => `${n} (${
|
|
877
|
+
`package-only generator(s): ${packageOnly.map((n) => `${n} (${factoryModuleOf(n) ?? ""})`).join(", ")}. ` +
|
|
649
878
|
"No reference template ships for them, so they cannot be ejected: import the factory " +
|
|
650
879
|
"from the package named beside each one and wire it in `generators: [...]`. " +
|
|
651
880
|
"Nothing was ejected.",
|
|
@@ -665,11 +894,20 @@ export async function ejectCommand(
|
|
|
665
894
|
const rows: EjectedRow[] = [];
|
|
666
895
|
const libraries: LibraryEjectResult[] = [];
|
|
667
896
|
const templatePackages = new Set<string>();
|
|
897
|
+
// Packages OUTSIDE @metaobjectsdev that the copied template modules import (a Markdown/TOON
|
|
898
|
+
// writer, say): read from the codegen package that ships them, never restated here.
|
|
899
|
+
const templateThirdParty = new Map<string, string | undefined>();
|
|
668
900
|
// ADR-0034 Amendment 3: the generators whose adapter source was copied, and what it imports.
|
|
669
901
|
const runtimeGenerators = new Set<string>();
|
|
670
902
|
const runtimePackages = new Set<string>();
|
|
903
|
+
let docsSite: DocsSiteFileResult[] | undefined;
|
|
671
904
|
try {
|
|
672
905
|
for (const name of flags.names) {
|
|
906
|
+
if (name === DOCS_SITE_NAME) {
|
|
907
|
+
docsSite = await ejectDocsSite(cwd, flags.force);
|
|
908
|
+
if (fmt === "text") reportDocsSite(docsSite);
|
|
909
|
+
continue;
|
|
910
|
+
}
|
|
673
911
|
if (isLibraryName(name)) {
|
|
674
912
|
const lib = await ejectLibrary({ cwd, name, force: flags.force });
|
|
675
913
|
libraries.push(lib);
|
|
@@ -678,19 +916,25 @@ export async function ejectCommand(
|
|
|
678
916
|
}
|
|
679
917
|
const result = await ejectGenerator({ cwd, name, force: flags.force });
|
|
680
918
|
for (const p of result.templatePackages) templatePackages.add(p);
|
|
919
|
+
for (const p of closureOf(name).packages.filter((q) => !q.startsWith("@metaobjectsdev/"))) {
|
|
920
|
+
templateThirdParty.set(p, dependencyRangesOf(CORE_CODEGEN_PACKAGE)[p]);
|
|
921
|
+
}
|
|
681
922
|
if (result.runtime !== undefined) {
|
|
682
923
|
runtimeGenerators.add(name);
|
|
683
924
|
for (const p of result.runtime.packages) runtimePackages.add(p);
|
|
684
925
|
}
|
|
926
|
+
const catalogEntry = catalog[name];
|
|
927
|
+
const wiring: EjectWiring = { entry: result.entry };
|
|
685
928
|
rows.push({
|
|
686
929
|
name,
|
|
687
930
|
path: result.path,
|
|
688
931
|
status: result.status,
|
|
689
|
-
wire: { import: result.importLine, entry:
|
|
690
|
-
requires:
|
|
932
|
+
wire: { import: result.importLine, entry: wiring.entry },
|
|
933
|
+
requires: catalogEntry?.requires ?? [],
|
|
691
934
|
...(result.runtime !== undefined ? { runtime: result.runtime.files } : {}),
|
|
935
|
+
...(result.templates !== undefined ? { templates: result.templates.files } : {}),
|
|
692
936
|
});
|
|
693
|
-
if (fmt === "text") reportOne(result, name);
|
|
937
|
+
if (fmt === "text") reportOne(result, name, wiring);
|
|
694
938
|
}
|
|
695
939
|
} catch (err) {
|
|
696
940
|
log.error(describeError(err));
|
|
@@ -705,7 +949,7 @@ export async function ejectCommand(
|
|
|
705
949
|
// names, so a summary built from the catalog alone printed a line that omitted a
|
|
706
950
|
// package each per-file note had just asked for.
|
|
707
951
|
const entries = flags.names
|
|
708
|
-
.filter((n) => !isLibraryName(n))
|
|
952
|
+
.filter((n) => !isLibraryName(n) && n !== DOCS_SITE_NAME)
|
|
709
953
|
.map((n) => catalog[n])
|
|
710
954
|
.filter((e) => e !== undefined);
|
|
711
955
|
// The copied adapter source imports its own dependencies (qs, the framework, the core
|
|
@@ -716,7 +960,7 @@ export async function ejectCommand(
|
|
|
716
960
|
const { runtime, dev } = runtimeInstall([...runtimePackages]);
|
|
717
961
|
ownedRuntime = { generators: runtimeGenerators, runtime, dev };
|
|
718
962
|
}
|
|
719
|
-
const install = installSetFor(entries, [...templatePackages], ownedRuntime);
|
|
963
|
+
const install = installSetFor(entries, [...templatePackages], ownedRuntime, templateThirdParty);
|
|
720
964
|
const configKeys = [...new Set(entries.flatMap((e) => e.configKeys ?? []))].sort();
|
|
721
965
|
|
|
722
966
|
if (fmt === "text") {
|
|
@@ -749,6 +993,7 @@ export async function ejectCommand(
|
|
|
749
993
|
install,
|
|
750
994
|
config: { keys: configKeys },
|
|
751
995
|
...(libraries.length > 0 ? { libraries } : {}),
|
|
996
|
+
...(docsSite !== undefined ? { docsSite } : {}),
|
|
752
997
|
};
|
|
753
998
|
emitStructured(payload, fmt);
|
|
754
999
|
}
|