@metaobjectsdev/cli 1.0.2 → 1.0.4-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -5
- package/dist/src/commands/deps.d.ts +3 -0
- package/dist/src/commands/deps.d.ts.map +1 -0
- package/dist/src/commands/deps.js +200 -0
- package/dist/src/commands/deps.js.map +1 -0
- package/dist/src/commands/docs.d.ts.map +1 -1
- package/dist/src/commands/docs.js +19 -3
- package/dist/src/commands/docs.js.map +1 -1
- package/dist/src/commands/eject.d.ts +2 -1
- package/dist/src/commands/eject.d.ts.map +1 -1
- package/dist/src/commands/eject.js +235 -75
- package/dist/src/commands/eject.js.map +1 -1
- package/dist/src/commands/gen.d.ts.map +1 -1
- package/dist/src/commands/gen.js +173 -30
- package/dist/src/commands/gen.js.map +1 -1
- package/dist/src/commands/init.d.ts +5 -9
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +92 -402
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/migrate.d.ts.map +1 -1
- package/dist/src/commands/migrate.js +24 -19
- package/dist/src/commands/migrate.js.map +1 -1
- package/dist/src/commands/prompt-snapshot.d.ts.map +1 -1
- package/dist/src/commands/prompt-snapshot.js +2 -1
- package/dist/src/commands/prompt-snapshot.js.map +1 -1
- package/dist/src/commands/verify.d.ts.map +1 -1
- package/dist/src/commands/verify.js +186 -29
- package/dist/src/commands/verify.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +97 -15
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib/advisory.d.ts +6 -0
- package/dist/src/lib/advisory.d.ts.map +1 -1
- package/dist/src/lib/advisory.js +10 -0
- package/dist/src/lib/advisory.js.map +1 -1
- package/dist/src/lib/agent-context-staleness.d.ts.map +1 -1
- package/dist/src/lib/agent-context-staleness.js +7 -1
- package/dist/src/lib/agent-context-staleness.js.map +1 -1
- package/dist/src/lib/args.d.ts +75 -3
- package/dist/src/lib/args.d.ts.map +1 -1
- package/dist/src/lib/args.js +54 -5
- package/dist/src/lib/args.js.map +1 -1
- package/dist/src/lib/catalog-listing.d.ts +92 -0
- package/dist/src/lib/catalog-listing.d.ts.map +1 -0
- package/dist/src/lib/catalog-listing.js +268 -0
- package/dist/src/lib/catalog-listing.js.map +1 -0
- package/dist/src/lib/catalog.d.ts +41 -0
- package/dist/src/lib/catalog.d.ts.map +1 -0
- package/dist/src/lib/catalog.js +89 -0
- package/dist/src/lib/catalog.js.map +1 -0
- package/dist/src/lib/collection-load-options.d.ts +13 -0
- package/dist/src/lib/collection-load-options.d.ts.map +1 -0
- package/dist/src/lib/collection-load-options.js +25 -0
- package/dist/src/lib/collection-load-options.js.map +1 -0
- package/dist/src/lib/dependency-sync.d.ts +170 -0
- package/dist/src/lib/dependency-sync.d.ts.map +1 -0
- package/dist/src/lib/dependency-sync.js +457 -0
- package/dist/src/lib/dependency-sync.js.map +1 -0
- package/dist/src/lib/install-set.d.ts +31 -0
- package/dist/src/lib/install-set.d.ts.map +1 -0
- package/dist/src/lib/install-set.js +103 -0
- package/dist/src/lib/install-set.js.map +1 -0
- package/dist/src/lib/library-eject.d.ts +79 -0
- package/dist/src/lib/library-eject.d.ts.map +1 -0
- package/dist/src/lib/library-eject.js +241 -0
- package/dist/src/lib/library-eject.js.map +1 -0
- package/dist/src/lib/library-listing.d.ts +63 -0
- package/dist/src/lib/library-listing.d.ts.map +1 -0
- package/dist/src/lib/library-listing.js +178 -0
- package/dist/src/lib/library-listing.js.map +1 -0
- package/dist/src/lib/library-prefix-advisory.d.ts +17 -0
- package/dist/src/lib/library-prefix-advisory.d.ts.map +1 -0
- package/dist/src/lib/library-prefix-advisory.js +67 -0
- package/dist/src/lib/library-prefix-advisory.js.map +1 -0
- package/dist/src/lib/load-metaobjects-config.d.ts +1 -2
- package/dist/src/lib/load-metaobjects-config.d.ts.map +1 -1
- package/dist/src/lib/load-metaobjects-config.js +11 -17
- package/dist/src/lib/load-metaobjects-config.js.map +1 -1
- package/dist/src/lib/migrate-scope.d.ts +32 -1
- package/dist/src/lib/migrate-scope.d.ts.map +1 -1
- package/dist/src/lib/migrate-scope.js +51 -3
- package/dist/src/lib/migrate-scope.js.map +1 -1
- package/dist/src/lib/overlay-lint.d.ts +37 -0
- package/dist/src/lib/overlay-lint.d.ts.map +1 -0
- package/dist/src/lib/overlay-lint.js +102 -0
- package/dist/src/lib/overlay-lint.js.map +1 -0
- package/dist/src/lib/requirement-check.d.ts +26 -3
- package/dist/src/lib/requirement-check.d.ts.map +1 -1
- package/dist/src/lib/requirement-check.js +71 -13
- package/dist/src/lib/requirement-check.js.map +1 -1
- package/package.json +10 -10
- package/src/commands/deps.ts +231 -0
- package/src/commands/docs.ts +19 -3
- package/src/commands/eject.ts +304 -90
- package/src/commands/gen.ts +189 -29
- package/src/commands/init.ts +95 -407
- package/src/commands/migrate.ts +26 -16
- package/src/commands/prompt-snapshot.ts +2 -1
- package/src/commands/verify.ts +213 -30
- package/src/index.ts +97 -15
- package/src/lib/advisory.ts +13 -0
- package/src/lib/agent-context-staleness.ts +7 -1
- package/src/lib/args.ts +118 -8
- package/src/lib/catalog-listing.ts +369 -0
- package/src/lib/catalog.ts +107 -0
- package/src/lib/collection-load-options.ts +42 -0
- package/src/lib/dependency-sync.ts +656 -0
- package/src/lib/install-set.ts +116 -0
- package/src/lib/library-eject.ts +298 -0
- package/src/lib/library-listing.ts +258 -0
- package/src/lib/library-prefix-advisory.ts +78 -0
- package/src/lib/load-metaobjects-config.ts +15 -21
- package/src/lib/migrate-scope.ts +59 -4
- package/src/lib/overlay-lint.ts +129 -0
- package/src/lib/requirement-check.ts +100 -14
|
@@ -1,45 +1,28 @@
|
|
|
1
1
|
import { mkdir, writeFile, readFile, readdir, stat, rm } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
4
|
import { existsSync as existsSyncWrap, readFileSync as readFileSyncWrap } from "node:fs";
|
|
5
|
-
import {
|
|
6
|
-
import { DEFAULT_CONFIG, ConfigSchema, saveConfig, PACKAGE_MANIFEST_FILE, DEFAULT_METADATA_DIR, DEFAULT_METAOBJECTS_DIR } from "@metaobjectsdev/sdk";
|
|
5
|
+
import { DEFAULT_CONFIG, ConfigSchema, saveConfig, PACKAGE_MANIFEST_FILE, DEFAULT_METADATA_DIR, DEFAULT_METAOBJECTS_DIR, DEPS_DIR, LOCK_FILE } from "@metaobjectsdev/sdk";
|
|
7
6
|
import { assemble, resolveAgentContextRoot, planScaffold, AGENT_CONTEXT_MANIFEST_PATH, } from "@metaobjectsdev/sdk/agent-context";
|
|
8
7
|
import { assertKnownStackValues, resolveStack } from "../lib/detect-stack.js";
|
|
9
8
|
import { reportIgnoredScaffold } from "../lib/ignored-scaffold-check.js";
|
|
10
9
|
import { parseInitArgs } from "../lib/args.js";
|
|
11
10
|
import { log } from "../lib/log.js";
|
|
12
11
|
import { cliVersion } from "../lib/version.js";
|
|
13
|
-
import { declaredDependencyNames } from "../lib/package-manifest.js";
|
|
14
12
|
import { findWranglerConfig, parseWranglerConfig } from "@metaobjectsdev/migrate-ts";
|
|
15
|
-
import { DEFAULT_DOCS_DIR
|
|
13
|
+
import { DEFAULT_DOCS_DIR } from "@metaobjectsdev/codegen-ts";
|
|
16
14
|
// ADR-0034 scaffold-and-own — `meta init` copies the codegen reference templates into
|
|
17
15
|
// the consumer's repo so they OWN them; metaobjects.config.ts imports them locally.
|
|
18
16
|
const OWNED_GENERATORS_DIR = "codegen/generators";
|
|
19
|
-
// The
|
|
20
|
-
//
|
|
21
|
-
// full list of everything `meta eject` can copy). Looping over that array unconditionally
|
|
22
|
-
// used to mean init scaffolded whatever it contained: when a later task registered
|
|
23
|
-
// "routes-hono" there, init started writing an unwired Hono generator nothing in the
|
|
24
|
-
// scaffolded config imports, on every fresh project, silently. This constant is the
|
|
25
|
-
// scaffolded metaobjects.config.ts's import list (buildMetaobjectsConfigBody below) made
|
|
26
|
-
// explicit and checkable — anything else is eject-on-demand via `meta eject <name>`, which
|
|
27
|
-
// exists exactly so eager copying isn't the only way to take ownership of a template.
|
|
17
|
+
// The scaffolded config's outDir, as a named constant so the config template and
|
|
18
|
+
// anything derived from it cannot drift.
|
|
28
19
|
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
export const SCAFFOLDED_GENERATOR_NAMES = ["entity", "queries", "routes", "barrel", "names"];
|
|
35
|
-
// The scaffolded config's outDir + dbImport, as named constants so the throwing-stub
|
|
36
|
-
// path below is DERIVED from the same values the config template embeds rather than
|
|
37
|
-
// duplicated as a second literal that could drift from it.
|
|
20
|
+
// `dbImport` is deliberately NOT here any more. It existed only because the scaffold
|
|
21
|
+
// wired `routesFile()`, whose output emits `import { db } from …`; with nothing wired
|
|
22
|
+
// there is no such import, so the throwing `src/db.ts` stub that made it resolve has
|
|
23
|
+
// gone too. `dbImport` is now a `configKey` on the `routes` catalog entry — reported by
|
|
24
|
+
// `meta gen --list` and by `meta eject routes`, to the adopter who actually chose it.
|
|
38
25
|
const SCAFFOLD_OUT_DIR = "src/generated";
|
|
39
|
-
const SCAFFOLD_DB_IMPORT = "../db";
|
|
40
|
-
// "src/generated" + "../db" -> "src/db" -> "src/db.ts" (dbImport resolves relative
|
|
41
|
-
// to outDir, same as the module specifier a generated route file emits).
|
|
42
|
-
const DB_STUB_REL_PATH = `${join(SCAFFOLD_OUT_DIR, SCAFFOLD_DB_IMPORT)}.ts`;
|
|
43
26
|
const META_COMMON_JSON = JSON.stringify({
|
|
44
27
|
metadata: {
|
|
45
28
|
package: "",
|
|
@@ -73,7 +56,8 @@ const METAOBJECTS_GITIGNORE_BODY = `# The codegen merge base. The snapshot BODIE
|
|
|
73
56
|
# These ARE meant to be tracked — keep them even if a broad pattern matches.
|
|
74
57
|
!migrations/
|
|
75
58
|
!config.json
|
|
76
|
-
|
|
59
|
+
!${DEPS_DIR}/
|
|
60
|
+
!${LOCK_FILE}
|
|
77
61
|
`;
|
|
78
62
|
// A minimal root .gitignore for a fresh project — only written when none exists,
|
|
79
63
|
// never clobbering the user's own. Keeps a `git add -A` right after `meta init`
|
|
@@ -92,129 +76,62 @@ dist/
|
|
|
92
76
|
`;
|
|
93
77
|
function buildMetaobjectsConfigBody(dialect = "sqlite") {
|
|
94
78
|
return `import { defineConfig } from "@metaobjectsdev/cli";
|
|
95
|
-
// Owned codegen generators (ADR-0034 scaffold-and-own). \`meta init\` copied these
|
|
96
|
-
// reference templates into ./codegen/generators/ — they are YOURS to edit, and
|
|
97
|
-
// \`meta gen\` runs from these local copies, not from the package. Read each file's
|
|
98
|
-
// header doc-block for what it emits and how to customize it.
|
|
99
|
-
import { entityFile } from "./codegen/generators/entity.js";
|
|
100
|
-
import { queriesFile } from "./codegen/generators/queries.js";
|
|
101
|
-
import { routesFile } from "./codegen/generators/routes.js";
|
|
102
|
-
import { namesFile } from "./codegen/generators/names.js";
|
|
103
|
-
import { barrel } from "./codegen/generators/barrel.js";
|
|
104
79
|
|
|
105
80
|
export default defineConfig({
|
|
106
|
-
outDir:
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
81
|
+
outDir: "${SCAFFOLD_OUT_DIR}",
|
|
82
|
+
dialect: "${dialect}",
|
|
83
|
+
|
|
84
|
+
// NOTHING IS GENERATED UNTIL YOU CHOOSE IT.
|
|
85
|
+
//
|
|
86
|
+
// MetaObjects does not decide which code your application needs — you do, or the
|
|
87
|
+
// agent working in this repo does. The catalog is:
|
|
88
|
+
//
|
|
89
|
+
// meta gen --list --format json --probe
|
|
90
|
+
//
|
|
91
|
+
// \`--probe\` runs every generator against YOUR model and reports how many files each
|
|
92
|
+
// would emit, so you can see what your metadata is already asking for. Group by
|
|
93
|
+
// \`layer\`: model / persistence / api / client / docs / capability.
|
|
94
|
+
//
|
|
95
|
+
// Then take the ones you want:
|
|
96
|
+
//
|
|
97
|
+
// meta eject entity queries routes barrel
|
|
98
|
+
//
|
|
99
|
+
// That copies each generator into ./codegen/generators/ — YOURS to edit, and what
|
|
100
|
+
// \`meta gen\` runs — and prints the import line to add here, the entry to add below,
|
|
101
|
+
// what to install, and any config keys those generators read (\`dbImport\`,
|
|
102
|
+
// \`apiPrefix\`, \`extStyle\`, …). Add them here as you go.
|
|
103
|
+
generators: [],
|
|
104
|
+
|
|
127
105
|
docs: {
|
|
128
|
-
outDir:
|
|
106
|
+
outDir: "${DEFAULT_DOCS_DIR}", // every surface lands here (run: meta docs).
|
|
129
107
|
// A SUB-directory on purpose: these pages are regenerated
|
|
130
108
|
// and overwritten, and docs/ itself is usually yours.
|
|
131
|
-
layout:
|
|
109
|
+
layout: "flat", // or "package" for multi-package models
|
|
132
110
|
// surfaces defaults to ["model", "api", "requirements", "agent"] — all four.
|
|
133
|
-
//
|
|
134
|
-
// files for a project
|
|
135
|
-
// agent context points at the agent/ pages by name.
|
|
136
|
-
// turned that pointer into a pointer at nothing. Narrow it yourself if you want
|
|
137
|
-
// fewer docs — but note it says what your docs ARE, not which of them you commit
|
|
138
|
-
// (a page you do not commit is exempt from verify --docs once it is git-ignored).
|
|
111
|
+
// Documentation is the one thing that IS on by default, because the requirements
|
|
112
|
+
// and agent surfaces emit ZERO files for a project with nothing to describe, and
|
|
113
|
+
// the always-on agent context points at the agent/ pages by name.
|
|
139
114
|
},
|
|
140
115
|
});
|
|
141
116
|
`;
|
|
142
117
|
}
|
|
143
|
-
// The throwing-stub scaffolded at `dbImport`'s resolved path (DB_STUB_REL_PATH,
|
|
144
|
-
// "src/db.ts" by default). It exists so `meta gen` and a fresh project's FIRST
|
|
145
|
-
// `tsc` both succeed with no driver chosen and no dependency added — deliberately
|
|
146
|
-
// NOT a real connection. Every generated route only ever passes `db` straight
|
|
147
|
-
// through to `mountCrudRoutes(...)`; nothing reads a property off it at import
|
|
148
|
-
// time, so a value typed `unknown` (not `any`) satisfies every call site while
|
|
149
|
-
// making a genuine runtime use (mountCrudRoutes calling `db.select()` etc.) throw
|
|
150
|
-
// immediately with an actionable message instead of failing to resolve at all.
|
|
151
|
-
// Built as an array of plain single-quoted lines (not a template literal) so the
|
|
152
|
-
// backticks and quotes inside the comment/message need no escaping.
|
|
153
|
-
const DB_STUB_BODY = [
|
|
154
|
-
"// `meta init` scaffolded this file because the generated Fastify routes",
|
|
155
|
-
'// `import { db } from "../db.js"` (see `dbImport` in metaobjects.config.ts) —',
|
|
156
|
-
"// a module that has to exist for `meta gen` and `tsc` to succeed. MetaObjects",
|
|
157
|
-
"// cannot fill it in for real without choosing a database driver on your",
|
|
158
|
-
"// behalf (better-sqlite3 vs @libsql/client vs pg vs postgres.js) and adding a",
|
|
159
|
-
"// dependency you may not want, so this is a STUB, not a connection.",
|
|
160
|
-
"//",
|
|
161
|
-
"// It type-checks and satisfies every generated import, but throws the first",
|
|
162
|
-
"// time anything actually touches `db` at runtime. Replace the export below",
|
|
163
|
-
"// with your real Drizzle connection, e.g.:",
|
|
164
|
-
"//",
|
|
165
|
-
'// import { drizzle } from "drizzle-orm/better-sqlite3";',
|
|
166
|
-
'// import Database from "better-sqlite3";',
|
|
167
|
-
'// export const db = drizzle(new Database("dev.sqlite"));',
|
|
168
|
-
"//",
|
|
169
|
-
"// (swap the driver import for your dialect — see",
|
|
170
|
-
"// https://github.com/metaobjectsdev/metaobjects/blob/main/docs/recipes/wiring-generated-queries.md",
|
|
171
|
-
"// for SQLite/libsql, Cloudflare D1, Postgres and multi-tenant setups.)",
|
|
172
|
-
"",
|
|
173
|
-
"const UNWIRED_MESSAGE =",
|
|
174
|
-
' "src/db.ts is still the scaffolded stub meta init wrote — it cannot choose " +',
|
|
175
|
-
" \"a database driver for you. Replace 'export const db = ...' below with \" +",
|
|
176
|
-
' "your real Drizzle connection, e.g.:\\n\\n" +',
|
|
177
|
-
" \" import { drizzle } from 'drizzle-orm/better-sqlite3';\\n\" +",
|
|
178
|
-
" \" import Database from 'better-sqlite3';\\n\" +",
|
|
179
|
-
" \" export const db = drizzle(new Database('dev.sqlite'));\\n\";",
|
|
180
|
-
"",
|
|
181
|
-
"function unwired(): never {",
|
|
182
|
-
" throw new Error(UNWIRED_MESSAGE);",
|
|
183
|
-
"}",
|
|
184
|
-
"",
|
|
185
|
-
"/**",
|
|
186
|
-
" * Stand-in for your real Drizzle database connection. Generated code only",
|
|
187
|
-
" * ever passes `db` straight through to `mountCrudRoutes(...)` — it never",
|
|
188
|
-
" * reads a property off it at import time — so this typechecks everywhere",
|
|
189
|
-
" * `db` is used, and throws the message above the first time anything really",
|
|
190
|
-
" * touches it.",
|
|
191
|
-
" */",
|
|
192
|
-
"export const db: unknown = new Proxy({}, { get: unwired });",
|
|
193
|
-
"",
|
|
194
|
-
].join("\n");
|
|
195
|
-
// Printed only when the stub was ACTUALLY written this run. It is gated on having just
|
|
196
|
-
// written the scaffolded config (see the db-stub block in `init`), so a re-run in a
|
|
197
|
-
// project that keeps its own config writes nothing — and a block claiming otherwise is
|
|
198
|
-
// the same "asserting things about its own scaffold that aren't true" defect the rest of
|
|
199
|
-
// this file was corrected for.
|
|
200
|
-
const DB_STUB_NOTE = `Also scaffolded ${DB_STUB_REL_PATH}: a THROWING STUB standing in for your database
|
|
201
|
-
connection, so the generated routes' \`db\` import resolves and the first tsc is clean.
|
|
202
|
-
Replace it with a real connection before running the app — until you do, the first
|
|
203
|
-
request that touches \`db\` throws with instructions.
|
|
204
|
-
`;
|
|
205
118
|
const SCAFFOLD_SUMMARY = `
|
|
206
119
|
Initialized metaobjects/ + .metaobjects/ + metaobjects.config.ts
|
|
207
|
-
|
|
120
|
+
codegen/generators/ is EMPTY on purpose: no code is generated until you choose it.
|
|
208
121
|
`;
|
|
209
122
|
const NEXT_STEPS = `
|
|
210
123
|
Next steps:
|
|
211
124
|
0. Everything here is ESM — package.json needs "type": "module" (init sets it
|
|
212
125
|
unless the project has CommonJS sources; without it the first tsc fails).
|
|
213
126
|
1. Author entities under metaobjects/ (start from the scaffolded meta.common.json)
|
|
214
|
-
2. meta gen
|
|
215
|
-
|
|
216
|
-
3. meta
|
|
217
|
-
|
|
127
|
+
2. meta gen --list --probe # the catalog: every generator, grouped by layer, with
|
|
128
|
+
# how many files each would emit for YOUR model
|
|
129
|
+
3. meta eject <name>... # take the ones you want — copies them into
|
|
130
|
+
# codegen/generators/ (yours to edit) and prints the
|
|
131
|
+
# import, the entry to wire, and what to install
|
|
132
|
+
4. meta gen # generate from exactly what you wired
|
|
133
|
+
5. meta docs # neutral model + API docs (on by default)
|
|
134
|
+
6. Create your tables: meta migrate --from-db --db file:dev.sqlite --dialect sqlite --slug init --apply
|
|
218
135
|
|
|
219
136
|
Ship in later sub-projects: meta ingest (propose entities from existing code),
|
|
220
137
|
meta serve (local viewer), meta install-hooks (MCP server + Claude Code hooks).
|
|
@@ -401,29 +318,19 @@ async function wireRootMemory(cwd, result, dryRun = false) {
|
|
|
401
318
|
}
|
|
402
319
|
}
|
|
403
320
|
/**
|
|
404
|
-
*
|
|
405
|
-
* `codegen/generators/<name>.ts` so they own them. Each file is written only if absent,
|
|
406
|
-
* so a re-run with --force never clobbers a hand-edited generator. The scaffolded
|
|
407
|
-
* metaobjects.config.ts imports these local copies (not the package `/generators` export).
|
|
321
|
+
* Scaffold the owned-codegen TIER: the directory and its tsconfig, and nothing in it.
|
|
408
322
|
*
|
|
409
|
-
*
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
* `meta eject <name
|
|
323
|
+
* `meta init` used to copy five reference generators here eagerly and wire all five in
|
|
324
|
+
* the scaffolded config. Codegen is opt-in now, so it copies NONE: the directory exists
|
|
325
|
+
* because it is part of the layout ADR-0034 promises (and `tsconfig.codegen.json`
|
|
326
|
+
* covers it the moment something lands), and `meta eject <name>...` is the door.
|
|
327
|
+
*
|
|
328
|
+
* The empty directory is not a placeholder for a decision deferred — it is the decision.
|
|
329
|
+
* A scaffold that wires a suite pre-empts the one judgement this design exists to leave
|
|
330
|
+
* to whoever is building the app.
|
|
413
331
|
*/
|
|
414
332
|
async function writeOwnedGenerators(opts, result) {
|
|
415
|
-
|
|
416
|
-
await mkdir(dir, { recursive: true });
|
|
417
|
-
for (const name of SCAFFOLDED_GENERATOR_NAMES) {
|
|
418
|
-
const rel = `${OWNED_GENERATORS_DIR}/${name}.ts`;
|
|
419
|
-
const abs = join(dir, `${name}.ts`);
|
|
420
|
-
if (await fileExists(abs)) {
|
|
421
|
-
result.preserved.push(rel);
|
|
422
|
-
continue;
|
|
423
|
-
}
|
|
424
|
-
await writeFile(abs, readReferenceTemplate(name), "utf8");
|
|
425
|
-
result.created.push(rel);
|
|
426
|
-
}
|
|
333
|
+
await mkdir(join(opts.cwd, OWNED_GENERATORS_DIR), { recursive: true });
|
|
427
334
|
await writeCodegenTsconfig(opts, result);
|
|
428
335
|
}
|
|
429
336
|
/** The owned codegen tier's own tsconfig — see writeCodegenTsconfig. */
|
|
@@ -592,12 +499,10 @@ export async function init(opts) {
|
|
|
592
499
|
if (opts.printOnly) {
|
|
593
500
|
for (const d of dirs)
|
|
594
501
|
result.created.push(d);
|
|
595
|
-
result.created.push("metaobjects/meta.common.json", ".metaobjects/config.json", ".metaobjects/.gitignore"
|
|
502
|
+
result.created.push("metaobjects/meta.common.json", ".metaobjects/config.json", ".metaobjects/.gitignore");
|
|
596
503
|
result.created.push(".metaobjects/AGENTS.md", ".metaobjects/CLAUDE.md", ".claude/skills/metaobjects-*", AGENT_CONTEXT_MANIFEST_PATH);
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
result.created.push(CODEGEN_TSCONFIG_REL);
|
|
600
|
-
result.created.push("metaobjects.config.ts", DB_STUB_REL_PATH, ".gitignore");
|
|
504
|
+
result.created.push(OWNED_GENERATORS_DIR, CODEGEN_TSCONFIG_REL);
|
|
505
|
+
result.created.push("metaobjects.config.ts", ".gitignore");
|
|
601
506
|
return result;
|
|
602
507
|
}
|
|
603
508
|
for (const d of dirs) {
|
|
@@ -619,73 +524,24 @@ export async function init(opts) {
|
|
|
619
524
|
// .metaobjects/.gitignore
|
|
620
525
|
await writeFile(join(agentDir, ".gitignore"), METAOBJECTS_GITIGNORE_BODY, "utf8");
|
|
621
526
|
result.created.push(".metaobjects/.gitignore");
|
|
622
|
-
// .metaobjects/package.meta.json —
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
extends: [],
|
|
630
|
-
};
|
|
631
|
-
await writeFile(manifestPath, JSON.stringify(manifestBody, null, 2) + "\n", "utf8");
|
|
632
|
-
result.created.push(`.metaobjects/${PACKAGE_MANIFEST_FILE}`);
|
|
633
|
-
}
|
|
634
|
-
else {
|
|
635
|
-
result.preserved.push(`.metaobjects/${PACKAGE_MANIFEST_FILE}`);
|
|
527
|
+
// .metaobjects/package.meta.json — the v0.3 prototype manifest is deprecated
|
|
528
|
+
// (nothing reads it; FR-023 metadata dependencies is its replacement), so
|
|
529
|
+
// `meta init` no longer scaffolds it. A pre-existing one is left untouched;
|
|
530
|
+
// just note the deprecation so an existing project sees it.
|
|
531
|
+
const legacyManifestPath = join(agentDir, PACKAGE_MANIFEST_FILE);
|
|
532
|
+
if (await fileExists(legacyManifestPath)) {
|
|
533
|
+
result.warnings.push(`note: .metaobjects/${PACKAGE_MANIFEST_FILE} is deprecated (nothing reads it; removed in 2.0) — see docs/features/metadata-dependencies.md`);
|
|
636
534
|
}
|
|
637
535
|
await writeAgentContext(opts, result);
|
|
638
|
-
// ADR-0034 —
|
|
639
|
-
//
|
|
536
|
+
// ADR-0034 — the owned-codegen TIER: the directory and its tsconfig. Nothing is
|
|
537
|
+
// copied into it; `meta eject <name>...` is the door (see writeOwnedGenerators).
|
|
640
538
|
await writeOwnedGenerators(opts, result);
|
|
641
539
|
// Scaffold metaobjects.config.ts at the project root. Never overwrite if it exists.
|
|
642
540
|
const forgeConfigPath = join(opts.cwd, "metaobjects.config.ts");
|
|
643
|
-
|
|
644
|
-
if (wroteScaffoldedConfig) {
|
|
541
|
+
if (!(await fileExists(forgeConfigPath))) {
|
|
645
542
|
await writeFile(forgeConfigPath, buildMetaobjectsConfigBody(opts.d1 ? "d1" : "sqlite"), "utf8");
|
|
646
543
|
result.created.push("metaobjects.config.ts");
|
|
647
544
|
}
|
|
648
|
-
// Scaffold the `dbImport` throwing stub at DB_STUB_REL_PATH ("src/db.ts" by
|
|
649
|
-
// default) — ONLY if absent, so a re-run never clobbers a user's real db module
|
|
650
|
-
// (same "write once" precedent as writeOwnedGenerators above). Without this, the
|
|
651
|
-
// scaffolded config declares `dbImport: "../db"` pointing at a module `meta init`
|
|
652
|
-
// never creates, and a fresh project's FIRST `tsc` fails to resolve it.
|
|
653
|
-
//
|
|
654
|
-
// Gated on having just WRITTEN that config, not merely on the stub being absent.
|
|
655
|
-
// DB_STUB_REL_PATH is derived from SCAFFOLD_OUT_DIR + SCAFFOLD_DB_IMPORT — the
|
|
656
|
-
// scaffold's own constants — so it describes where the SCAFFOLDED config points and
|
|
657
|
-
// nowhere else. Re-running `meta init` in a project that already has a config with
|
|
658
|
-
// its own `outDir`/`dbImport` preserves that config (above) and would otherwise still
|
|
659
|
-
// drop a src/db.ts that nothing in the project references: a stray file, in the
|
|
660
|
-
// adopter's application source, answering a question they had already answered.
|
|
661
|
-
const dbStubPath = join(opts.cwd, DB_STUB_REL_PATH);
|
|
662
|
-
const dbStubExists = await fileExists(dbStubPath);
|
|
663
|
-
if (wroteScaffoldedConfig && !dbStubExists) {
|
|
664
|
-
await mkdir(dirname(dbStubPath), { recursive: true });
|
|
665
|
-
await writeFile(dbStubPath, DB_STUB_BODY, "utf8");
|
|
666
|
-
result.created.push(DB_STUB_REL_PATH);
|
|
667
|
-
}
|
|
668
|
-
else if (dbStubExists) {
|
|
669
|
-
// "preserved" means a file we would have written was left alone. Skipping because
|
|
670
|
-
// this project keeps its own config is not preservation — there is nothing there.
|
|
671
|
-
result.preserved.push(DB_STUB_REL_PATH);
|
|
672
|
-
}
|
|
673
|
-
else {
|
|
674
|
-
// Neither written nor preserved: this project keeps its own config AND has no stub.
|
|
675
|
-
// Usually correct — its `dbImport` points at a real module somewhere else. But it is
|
|
676
|
-
// ALSO what a scaffolded project looks like after someone deletes or moves src/db.ts,
|
|
677
|
-
// and `meta init --force` cannot tell those apart: `wroteScaffoldedConfig` is only
|
|
678
|
-
// "no config existed", so it is false for the config init itself wrote. Silently
|
|
679
|
-
// doing nothing there leaves the scaffolded `dbImport: "../db"` and the generated
|
|
680
|
-
// routes' `import { db } from "../db.js"` pointing at nothing, and the adopter meets
|
|
681
|
-
// it as a TS2307 from `tsc` with no word from the command that could have said so.
|
|
682
|
-
// Say it here rather than writing: dropping a file into a project that owns its
|
|
683
|
-
// config is what the branch above deliberately refuses.
|
|
684
|
-
result.warnings.push(`${DB_STUB_REL_PATH} was not scaffolded — this project has its own ` +
|
|
685
|
-
"metaobjects.config.ts, so init leaves the database module to it. If that config's " +
|
|
686
|
-
`\`dbImport\` resolves to ${DB_STUB_REL_PATH}, create it or the generated routes will ` +
|
|
687
|
-
"not resolve.");
|
|
688
|
-
}
|
|
689
545
|
// Scaffold a minimal root .gitignore ONLY when the project has none — never
|
|
690
546
|
// clobber a user's existing one (they may have their own rules).
|
|
691
547
|
const rootGitignorePath = join(opts.cwd, ".gitignore");
|
|
@@ -783,187 +639,23 @@ async function prepareManifestForScaffold(cwd, result) {
|
|
|
783
639
|
"which a CommonJS project cannot compile.";
|
|
784
640
|
}
|
|
785
641
|
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
642
|
+
// NO DEPENDENCIES ARE ADDED. `meta init` used to declare five packages here —
|
|
643
|
+
// codegen-ts and metadata for the generators it copied, drizzle-orm / zod / fastify
|
|
644
|
+
// for the code those generators would write — and every one of them was a
|
|
645
|
+
// consequence of the scaffold WIRING a suite. It wires nothing now, so declaring
|
|
646
|
+
// anything would be declaring a dependency on code this project may never generate.
|
|
647
|
+
//
|
|
648
|
+
// The need did not vanish, it MOVED to the moment a generator is chosen:
|
|
649
|
+
// `meta eject <name>...` reports the exact install set for what you took, with
|
|
650
|
+
// third-party ranges read from the runtime package's own peerDependencies (see
|
|
651
|
+
// lib/install-set.ts), and `meta gen --list --format json` carries the same set per
|
|
652
|
+
// entry before you commit to anything.
|
|
653
|
+
if (moduleSystemNote !== undefined) {
|
|
789
654
|
// Preserve the file's existing indentation rather than reformatting someone's manifest.
|
|
790
655
|
const indent = /\n(\s+)"/.exec(raw)?.[1] ?? " ";
|
|
791
656
|
await writeFile(pkgPath, `${JSON.stringify(pkg, null, indent)}\n`, "utf8");
|
|
792
|
-
}
|
|
793
|
-
if (moduleSystemNote !== undefined)
|
|
794
657
|
result.warnings.push(moduleSystemNote);
|
|
795
|
-
if (added.length > 0) {
|
|
796
|
-
result.warnings.push(`added ${added.join(" + ")} to devDependencies — the scaffolded ` +
|
|
797
|
-
"codegen/generators/ are YOUR source now (ADR-0034) and import them. " +
|
|
798
|
-
"Run your package manager's install before `meta gen`.");
|
|
799
|
-
}
|
|
800
|
-
if (addedRuntime.length > 0) {
|
|
801
|
-
result.warnings.push(`added ${addedRuntime.join(" + ")} to dependencies — the code \`meta gen\` writes ` +
|
|
802
|
-
"imports them, so `npx tsc` reports TS2307 on the generated files until they are " +
|
|
803
|
-
"installed. Run your package manager's install before `meta gen`.");
|
|
804
|
-
}
|
|
805
|
-
// Never degrade in silence. The first version of this returned `{}` on any failure to
|
|
806
|
-
// read runtime-ts's peer ranges and skipped the three packages that come from them —
|
|
807
|
-
// which is exactly what happened against the published package, and the run looked
|
|
808
|
-
// successful while leaving the project with the six TS2307s this code exists to
|
|
809
|
-
// prevent. A fallback that cannot be observed is indistinguishable from a bug.
|
|
810
|
-
const undeclarable = SCAFFOLD_OUTPUT_PEERS.filter((name) => !declaredDependencyNames(pkg).has(name));
|
|
811
|
-
if (undeclarable.length > 0) {
|
|
812
|
-
result.warnings.push(`could NOT declare ${undeclarable.join(" + ")} — the version ranges are read from ` +
|
|
813
|
-
"@metaobjectsdev/runtime-ts's own peerDependencies and that manifest could not be " +
|
|
814
|
-
"read. Generated code imports them, so add them to dependencies by hand or " +
|
|
815
|
-
"`npx tsc` will report TS2307 on files `meta gen` writes.");
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
/**
|
|
819
|
-
* ADR-0034 scaffold-and-own hands the project real source files under
|
|
820
|
-
* `codegen/generators/`, and those files import `@metaobjectsdev/codegen-ts` and
|
|
821
|
-
* `@metaobjectsdev/metadata`. Installing `@metaobjectsdev/cli` alone does not put
|
|
822
|
-
* either of them where the project can resolve them, so the scaffold arrived
|
|
823
|
-
* un-typecheckable: ten TS2307s on files `meta init` had just written.
|
|
824
|
-
*
|
|
825
|
-
* Declaring them is the honest fix — they are dependencies of code that now lives in
|
|
826
|
-
* the adopter's repo. Deliberately NOT declared: `ts-poet`. The scaffolded templates
|
|
827
|
-
* import the ts-poet combinators via @metaobjectsdev/codegen-ts (re-exported from its
|
|
828
|
-
* own ts-poet instance) precisely so that the Code objects they compose share ONE
|
|
829
|
-
* ts-poet copy with the engine's render* primitives — a project-local ts-poet is the
|
|
830
|
-
* second physical copy that split the class identity under a globally-installed /
|
|
831
|
-
* linked CLI (duplicate imports in generated files, TS2300 on first tsc; see the
|
|
832
|
-
* gen-split-tree gate). Only ever ADDS a missing key: an existing pin is the user's.
|
|
833
|
-
* Returns what it added so the caller can tell them to install.
|
|
834
|
-
*/
|
|
835
|
-
function addScaffoldDevDependencies(pkg) {
|
|
836
|
-
const version = cliVersion();
|
|
837
|
-
const wanted = {
|
|
838
|
-
"@metaobjectsdev/codegen-ts": `^${version}`,
|
|
839
|
-
"@metaobjectsdev/metadata": `^${version}`,
|
|
840
|
-
};
|
|
841
|
-
const dev = (pkg.devDependencies ?? {});
|
|
842
|
-
// "Already declared" spans all four dependency fields — the shared rule, so this
|
|
843
|
-
// cannot drift from what `meta eject` means by the same words. It used to ask only
|
|
844
|
-
// dependencies + devDependencies, which meant a project declaring codegen-ts as a
|
|
845
|
-
// PEER dependency (correct for a library whose consumer supplies the version) got it
|
|
846
|
-
// added to devDependencies as well: the same package pinned twice in one manifest,
|
|
847
|
-
// and a second physical copy is the class-identity split this repo has been bitten
|
|
848
|
-
// by twice.
|
|
849
|
-
const declared = declaredDependencyNames(pkg);
|
|
850
|
-
const added = [];
|
|
851
|
-
for (const [name, range] of Object.entries(wanted)) {
|
|
852
|
-
if (declared.has(name))
|
|
853
|
-
continue;
|
|
854
|
-
dev[name] = range;
|
|
855
|
-
added.push(name);
|
|
856
|
-
}
|
|
857
|
-
if (added.length > 0) {
|
|
858
|
-
pkg.devDependencies = Object.fromEntries(Object.entries(dev).sort(([a], [b]) => a.localeCompare(b)));
|
|
859
|
-
}
|
|
860
|
-
return added;
|
|
861
|
-
}
|
|
862
|
-
/**
|
|
863
|
-
* The third-party packages the scaffolded suite's GENERATED OUTPUT imports, each named
|
|
864
|
-
* with the artifact that imports it. This is the set, not the ranges — see
|
|
865
|
-
* `scaffoldRuntimeDependencies` for where those come from.
|
|
866
|
-
*
|
|
867
|
-
* `@metaobjectsdev/runtime-ts` is deliberately not here: its range is the CLI's own
|
|
868
|
-
* version, like the two build-time packages above, not a peer range read off itself.
|
|
869
|
-
*/
|
|
870
|
-
const SCAFFOLD_OUTPUT_PEERS = [
|
|
871
|
-
"drizzle-orm", // <Entity>.ts (the table + column builders) and <Entity>.queries.ts
|
|
872
|
-
"zod", // <Entity>.ts — the Insert/Update schemas
|
|
873
|
-
"fastify", // <Entity>.routes.ts — `import type { FastifyInstance }`
|
|
874
|
-
];
|
|
875
|
-
/**
|
|
876
|
-
* The runtime dependencies of the code `meta gen` will WRITE, for `dependencies`.
|
|
877
|
-
*
|
|
878
|
-
* `addScaffoldDevDependencies` above fixed this defect one layer in: the generator
|
|
879
|
-
* SOURCES under `codegen/generators/` import `@metaobjectsdev/codegen-ts` and
|
|
880
|
-
* `@metaobjectsdev/metadata`, nothing declared them, and the scaffold arrived
|
|
881
|
-
* un-typecheckable. The same argument reaches one layer further out and was not
|
|
882
|
-
* followed there. Generated `<Entity>.ts` / `.queries.ts` / `.routes.ts` import
|
|
883
|
-
* drizzle-orm, zod, fastify and `@metaobjectsdev/runtime-ts/drizzle-fastify` — five
|
|
884
|
-
* specifiers, none declared — so `npx tsc`, which is the next step `meta gen` itself
|
|
885
|
-
* prints, reported NINE TS2307s on a brand-new project that had done nothing wrong.
|
|
886
|
-
* npm hides four of the five by hoisting them out of the CLI's own tree; pnpm's strict
|
|
887
|
-
* layout, which is the point of testing both, shows all five.
|
|
888
|
-
*
|
|
889
|
-
* `dependencies`, not `devDependencies`: generated routes and queries are application
|
|
890
|
-
* source that runs in production. The two build-time packages stay where they are.
|
|
891
|
-
*
|
|
892
|
-
* The RANGES are read from `@metaobjectsdev/runtime-ts`'s own `peerDependencies` rather
|
|
893
|
-
* than written here. That package already declares the versions its helpers are built
|
|
894
|
-
* against, bounded above (the peer-range gate enforces the bound), so a second copy of
|
|
895
|
-
* those ranges in the scaffolder is a second thing to keep in step — and the failure
|
|
896
|
-
* mode of drift is an adopter installing a major nothing was tested against. If a range
|
|
897
|
-
* cannot be read, the package is SKIPPED rather than guessed at, and `meta gen` still
|
|
898
|
-
* type-checks for anyone whose manifest already declares it.
|
|
899
|
-
*/
|
|
900
|
-
function scaffoldRuntimeDependencies() {
|
|
901
|
-
const wanted = {
|
|
902
|
-
"@metaobjectsdev/runtime-ts": `^${cliVersion()}`,
|
|
903
|
-
};
|
|
904
|
-
const peers = runtimeTsPeerRanges();
|
|
905
|
-
for (const name of SCAFFOLD_OUTPUT_PEERS) {
|
|
906
|
-
const range = peers[name];
|
|
907
|
-
if (range !== undefined)
|
|
908
|
-
wanted[name] = range;
|
|
909
|
-
}
|
|
910
|
-
return wanted;
|
|
911
|
-
}
|
|
912
|
-
/**
|
|
913
|
-
* `@metaobjectsdev/runtime-ts`'s declared peer ranges, or `{}` if they cannot be read.
|
|
914
|
-
*
|
|
915
|
-
* Resolves the package's ENTRY and walks up to the nearest package.json, rather than
|
|
916
|
-
* asking for `"@metaobjectsdev/runtime-ts/package.json"` directly. That direct form is
|
|
917
|
-
* the obvious one and it is WRONG: a package's `exports` map gates every subpath, and
|
|
918
|
-
* runtime-ts's exports are `.` / `./drivers` / `./fastify` / `./drizzle-fastify` /
|
|
919
|
-
* `./hono` — no `./package.json`. Under real Node it throws
|
|
920
|
-
* ERR_PACKAGE_PATH_NOT_EXPORTED. It appeared to work here only because the workspace
|
|
921
|
-
* runs this under bun against a symlinked source tree; against the published package it
|
|
922
|
-
* failed on the first try, silently, and `meta init` declared one package instead of
|
|
923
|
-
* four. Resolving the entry is never gated — `.` is the one subpath every package
|
|
924
|
-
* exports — so this form works under npm, pnpm, bun and a linked checkout alike.
|
|
925
|
-
*/
|
|
926
|
-
function runtimeTsPeerRanges() {
|
|
927
|
-
try {
|
|
928
|
-
const req = createRequire(import.meta.url);
|
|
929
|
-
let dir = dirname(req.resolve("@metaobjectsdev/runtime-ts"));
|
|
930
|
-
// The entry sits under dist/; the manifest is at the package root above it.
|
|
931
|
-
for (let hops = 0; hops < 8; hops++) {
|
|
932
|
-
const candidate = join(dir, "package.json");
|
|
933
|
-
if (existsSyncWrap(candidate)) {
|
|
934
|
-
const manifest = JSON.parse(readFileSyncWrap(candidate, "utf8"));
|
|
935
|
-
// Guard against stopping at a nested manifest that is not the package itself.
|
|
936
|
-
if (manifest.name === "@metaobjectsdev/runtime-ts") {
|
|
937
|
-
return (manifest.peerDependencies ?? {});
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
const up = dirname(dir);
|
|
941
|
-
if (up === dir)
|
|
942
|
-
break;
|
|
943
|
-
dir = up;
|
|
944
|
-
}
|
|
945
|
-
return {};
|
|
946
|
-
}
|
|
947
|
-
catch {
|
|
948
|
-
return {};
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
/** Adds any missing `scaffoldRuntimeDependencies()` to `dependencies`. Only ever ADDS a
|
|
952
|
-
* missing key — an existing pin, in any of the four dependency fields, is the user's. */
|
|
953
|
-
function addScaffoldRuntimeDependencies(pkg) {
|
|
954
|
-
const deps = (pkg.dependencies ?? {});
|
|
955
|
-
const declared = declaredDependencyNames(pkg);
|
|
956
|
-
const added = [];
|
|
957
|
-
for (const [name, range] of Object.entries(scaffoldRuntimeDependencies())) {
|
|
958
|
-
if (declared.has(name))
|
|
959
|
-
continue;
|
|
960
|
-
deps[name] = range;
|
|
961
|
-
added.push(name);
|
|
962
|
-
}
|
|
963
|
-
if (added.length > 0) {
|
|
964
|
-
pkg.dependencies = Object.fromEntries(Object.entries(deps).sort(([a], [b]) => a.localeCompare(b)));
|
|
965
658
|
}
|
|
966
|
-
return added;
|
|
967
659
|
}
|
|
968
660
|
/** True when the project has hand-written CommonJS at the root (excluding tooling dirs). */
|
|
969
661
|
async function hasCommonJsSources(cwd) {
|
|
@@ -1021,15 +713,13 @@ function buildD1MigrateBlock(cwd) {
|
|
|
1021
713
|
/**
|
|
1022
714
|
* The post-init message.
|
|
1023
715
|
*
|
|
1024
|
-
*
|
|
1025
|
-
*
|
|
1026
|
-
*
|
|
1027
|
-
*
|
|
1028
|
-
* `metaobjects.config.ts`, where the stub is deliberately not written. Callers pass
|
|
1029
|
-
* `result.created.includes(DB_STUB_REL_PATH)` — the same list the message describes.
|
|
716
|
+
* Takes no arguments now. It used to take `dbStubWritten`, because the scaffold wrote a
|
|
717
|
+
* throwing `src/db.ts` on some runs and not others and a static string claimed it on
|
|
718
|
+
* every one. With nothing wired there is no `dbImport` and no stub, so the message is
|
|
719
|
+
* the same on every path again.
|
|
1030
720
|
*/
|
|
1031
|
-
export function nextStepsBlock(
|
|
1032
|
-
return SCAFFOLD_SUMMARY +
|
|
721
|
+
export function nextStepsBlock() {
|
|
722
|
+
return SCAFFOLD_SUMMARY + NEXT_STEPS;
|
|
1033
723
|
}
|
|
1034
724
|
async function dirExists(p) {
|
|
1035
725
|
try {
|
|
@@ -1108,7 +798,7 @@ export async function initCommand(args, cwd) {
|
|
|
1108
798
|
log.warn(w);
|
|
1109
799
|
}
|
|
1110
800
|
else {
|
|
1111
|
-
log.info(nextStepsBlock(
|
|
801
|
+
log.info(nextStepsBlock());
|
|
1112
802
|
// Surface any scaffold warnings (e.g. the #77 monorepo-subdir agent-context
|
|
1113
803
|
// discovery warning) — these are otherwise dropped on the normal init path.
|
|
1114
804
|
for (const w of result.warnings)
|