@invinite-org/create-chartlang 0.1.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/CHANGELOG.md +38 -0
- package/LICENSE +21 -0
- package/README.md +68 -0
- package/dist/chartlangVersions.d.ts +36 -0
- package/dist/chartlangVersions.d.ts.map +1 -0
- package/dist/chartlangVersions.js +45 -0
- package/dist/chartlangVersions.js.map +1 -0
- package/dist/createApp.d.ts +198 -0
- package/dist/createApp.d.ts.map +1 -0
- package/dist/createApp.js +392 -0
- package/dist/createApp.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/rewritePackageJson.d.ts +59 -0
- package/dist/rewritePackageJson.d.ts.map +1 -0
- package/dist/rewritePackageJson.js +128 -0
- package/dist/rewritePackageJson.js.map +1 -0
- package/dist/seamTemplates.d.ts +51 -0
- package/dist/seamTemplates.d.ts.map +1 -0
- package/dist/seamTemplates.js +318 -0
- package/dist/seamTemplates.js.map +1 -0
- package/dist/starterTsconfig.d.ts +54 -0
- package/dist/starterTsconfig.d.ts.map +1 -0
- package/dist/starterTsconfig.js +83 -0
- package/dist/starterTsconfig.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
// Copyright (c) 2026 Invinite. Licensed under the MIT License.
|
|
2
|
+
// See the LICENSE file in the repo root for full license text.
|
|
3
|
+
import { mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { basename, dirname, isAbsolute, join, resolve as resolvePath } from "node:path";
|
|
5
|
+
import { createInterface } from "node:readline/promises";
|
|
6
|
+
import { parseArgs } from "node:util";
|
|
7
|
+
import { ADAPTER_REGISTRY, BUNDLED_ADAPTERS, } from "@invinite-org/chartlang-cli";
|
|
8
|
+
import { STARTER_CLONE_REF } from "./chartlangVersions.js";
|
|
9
|
+
import { rewriteStarterPackageJson } from "./rewritePackageJson.js";
|
|
10
|
+
import { isSeamId, seamTemplateFor } from "./seamTemplates.js";
|
|
11
|
+
import { writeStandaloneTsconfig } from "./starterTsconfig.js";
|
|
12
|
+
const PKG_NAME_PLACEHOLDER = "__PKG_NAME__";
|
|
13
|
+
const CHARTLANG_SCOPE = "@invinite-org/chartlang-";
|
|
14
|
+
const PACKAGE_MANAGERS = ["npm", "pnpm", "yarn", "bun"];
|
|
15
|
+
const NPMRC_FILE = ".npmrc";
|
|
16
|
+
// Published `@invinite-org/chartlang-compiler` depends on `esbuild@^0.24`, but
|
|
17
|
+
// `vite@8`'s optional peer wants `esbuild@^0.27 || ^0.28`. The app builds + runs
|
|
18
|
+
// fine on esbuild 0.24 — npm's strict optional-peer check is the only blocker —
|
|
19
|
+
// so the clone opts into `legacy-peer-deps` instead of bumping any esbuild.
|
|
20
|
+
const NPMRC_CONTENTS = "# vite@8's optional esbuild peer (^0.27||^0.28) conflicts with the\n# chartlang-compiler esbuild dep (^0.24); the app runs fine on 0.24.\nlegacy-peer-deps=true\n";
|
|
21
|
+
const DEFAULT_TARGET = "./chartlang-starter";
|
|
22
|
+
const DEFAULT_LIBRARY = "echarts";
|
|
23
|
+
const SEAM_PATH = ["src", "lib", "chart", "activeAdapter.ts"];
|
|
24
|
+
const ENV_EXAMPLE = ".env.example";
|
|
25
|
+
const ENV_FILE = ".env";
|
|
26
|
+
// Repo-internal artefacts that must not ship to the user's clone. The e2e
|
|
27
|
+
// suite lives under `tests/`; `playwright.config.ts` references it (a mock
|
|
28
|
+
// server + global setup), so it is stripped too — otherwise the cloned
|
|
29
|
+
// project ships a `playwright.config.ts` pointing at deleted files.
|
|
30
|
+
const STRIP_ENTRIES = ["CLAUDE.md", "tests", ".changeset", ".github", "playwright.config.ts"];
|
|
31
|
+
/**
|
|
32
|
+
* The starter source giget clones, minus the ref suffix. The installer
|
|
33
|
+
* appends {@link STARTER_CLONE_REF} to pin the matching tagged tree.
|
|
34
|
+
*
|
|
35
|
+
* @since 0.1
|
|
36
|
+
* @stable
|
|
37
|
+
* @example
|
|
38
|
+
* import { STARTER_SOURCE_BASE } from "@invinite-org/create-chartlang";
|
|
39
|
+
* void STARTER_SOURCE_BASE;
|
|
40
|
+
*/
|
|
41
|
+
export const STARTER_SOURCE_BASE = "github:outraday-org/chartlang/apps/react-starter";
|
|
42
|
+
function isPackageManager(value) {
|
|
43
|
+
return PACKAGE_MANAGERS.includes(value);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Look up an adapter's bundle + registry metadata by id, throwing if either is
|
|
47
|
+
* missing. The `runCreateChartlang` flow only calls this with an `isSeamId`-
|
|
48
|
+
* validated id (so it never throws in production), but the guard fails loudly
|
|
49
|
+
* if `SEAM_IDS` ever drifts from the generated bundle/registry set.
|
|
50
|
+
*
|
|
51
|
+
* @since 0.1
|
|
52
|
+
* @stable
|
|
53
|
+
* @example
|
|
54
|
+
* import { resolveAdapter } from "@invinite-org/create-chartlang";
|
|
55
|
+
* const { bundle, meta } = resolveAdapter("echarts");
|
|
56
|
+
* void bundle.id;
|
|
57
|
+
* void meta.library;
|
|
58
|
+
*/
|
|
59
|
+
export function resolveAdapter(id) {
|
|
60
|
+
const bundle = BUNDLED_ADAPTERS.find((b) => b.id === id);
|
|
61
|
+
const meta = ADAPTER_REGISTRY.find((m) => m.id === id);
|
|
62
|
+
if (bundle === undefined || meta === undefined) {
|
|
63
|
+
throw new Error(`no bundle/registry entry for adapter "${id}"`);
|
|
64
|
+
}
|
|
65
|
+
return { bundle, meta };
|
|
66
|
+
}
|
|
67
|
+
async function isNonEmptyDir(path) {
|
|
68
|
+
try {
|
|
69
|
+
return (await readdir(path)).length > 0;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Render the library-choice prompt list from the registry, echarts first
|
|
77
|
+
* (the default) then the rest in registry order. Pure: no IO.
|
|
78
|
+
*
|
|
79
|
+
* @since 0.1
|
|
80
|
+
* @stable
|
|
81
|
+
* @example
|
|
82
|
+
* import { renderLibraryChoices } from "@invinite-org/create-chartlang";
|
|
83
|
+
* const text = renderLibraryChoices([]);
|
|
84
|
+
* void text;
|
|
85
|
+
*/
|
|
86
|
+
export function renderLibraryChoices(registry) {
|
|
87
|
+
const ordered = orderedRegistry(registry);
|
|
88
|
+
const lines = ["Choose a chart library:", ""];
|
|
89
|
+
for (const meta of ordered) {
|
|
90
|
+
const suffix = meta.id === DEFAULT_LIBRARY ? " (default)" : "";
|
|
91
|
+
const lib = meta.library === "(none)" ? "no runtime dep" : meta.library;
|
|
92
|
+
lines.push(` ${meta.id} — ${meta.displayName} (${lib})${suffix}`);
|
|
93
|
+
}
|
|
94
|
+
lines.push("");
|
|
95
|
+
return lines.join("\n");
|
|
96
|
+
}
|
|
97
|
+
function orderedRegistry(registry) {
|
|
98
|
+
const def = registry.filter((m) => m.id === DEFAULT_LIBRARY);
|
|
99
|
+
const rest = registry.filter((m) => m.id !== DEFAULT_LIBRARY);
|
|
100
|
+
return [...def, ...rest];
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Harvest the published `@invinite-org/chartlang-*` `^`-ranges from a bundle's
|
|
104
|
+
* own (generator-pinned) `package.json` deps + devDeps. These take precedence
|
|
105
|
+
* over the baked manifest when rewriting the starter's workspace deps.
|
|
106
|
+
*
|
|
107
|
+
* @since 0.1
|
|
108
|
+
* @stable
|
|
109
|
+
* @example
|
|
110
|
+
* import { bundleChartlangVersions } from "@invinite-org/create-chartlang";
|
|
111
|
+
* const map = bundleChartlangVersions({ id: "x", files: {} });
|
|
112
|
+
* void map;
|
|
113
|
+
*/
|
|
114
|
+
export function bundleChartlangVersions(bundle) {
|
|
115
|
+
// Every generated bundle carries a `package.json` (the generator always
|
|
116
|
+
// emits one), so `?? "{}"` is only a parse-safety floor, never the path.
|
|
117
|
+
const parsed = JSON.parse(bundle.files["package.json"] ?? "{}");
|
|
118
|
+
const out = {};
|
|
119
|
+
for (const block of [parsed.dependencies, parsed.devDependencies]) {
|
|
120
|
+
for (const [name, range] of Object.entries(block ?? {})) {
|
|
121
|
+
if (name.startsWith(CHARTLANG_SCOPE)) {
|
|
122
|
+
out[name] = range;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return out;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Repoint a single `main`/`types`/`exports` entry string from the bundle's
|
|
130
|
+
* unbuilt `./dist/*.{js,d.ts}` to the vendored TypeScript source `./src/*.ts`.
|
|
131
|
+
* The vendored bundle ships only `src/` (create-chartlang never builds it), so
|
|
132
|
+
* Vite + tsc resolve the adapter directly from source with NO build step. A
|
|
133
|
+
* non-`./dist/` value is returned unchanged.
|
|
134
|
+
*/
|
|
135
|
+
function repointDistToSrc(value) {
|
|
136
|
+
if (!value.startsWith("./dist/")) {
|
|
137
|
+
return value;
|
|
138
|
+
}
|
|
139
|
+
return value
|
|
140
|
+
.replace(/^\.\/dist\//, "./src/")
|
|
141
|
+
.replace(/\.d\.ts$/, ".ts")
|
|
142
|
+
.replace(/\.js$/, ".ts");
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Rewrite the vendored adapter `package.json`: substitute the `__PKG_NAME__`
|
|
146
|
+
* placeholder, then repoint `main`/`types` and every `exports` entry's
|
|
147
|
+
* `types`/`import` from `./dist/*` to the vendored `./src/*.ts` source. This is
|
|
148
|
+
* an intentional DIVERGENCE from `cli add-adapter`, which keeps the
|
|
149
|
+
* dist-pointing bundle (it expects a build); create-chartlang vendors source
|
|
150
|
+
* only and never builds, so the manifest must resolve straight from `src/`.
|
|
151
|
+
* Absent fields are left untouched.
|
|
152
|
+
*
|
|
153
|
+
* @since 0.1
|
|
154
|
+
* @stable
|
|
155
|
+
* @example
|
|
156
|
+
* import { repointVendoredPackageJson } from "@invinite-org/create-chartlang";
|
|
157
|
+
* const next = repointVendoredPackageJson('{"main":"./dist/index.js"}', "@local/x-adapter");
|
|
158
|
+
* void next;
|
|
159
|
+
*/
|
|
160
|
+
export function repointVendoredPackageJson(contents, localName) {
|
|
161
|
+
const named = contents.split(PKG_NAME_PLACEHOLDER).join(localName);
|
|
162
|
+
const pkg = JSON.parse(named);
|
|
163
|
+
if (pkg.main !== undefined) {
|
|
164
|
+
pkg.main = repointDistToSrc(pkg.main);
|
|
165
|
+
}
|
|
166
|
+
if (pkg.types !== undefined) {
|
|
167
|
+
pkg.types = repointDistToSrc(pkg.types);
|
|
168
|
+
}
|
|
169
|
+
if (pkg.exports !== undefined) {
|
|
170
|
+
for (const entry of Object.values(pkg.exports)) {
|
|
171
|
+
if (entry.types !== undefined) {
|
|
172
|
+
entry.types = repointDistToSrc(entry.types);
|
|
173
|
+
}
|
|
174
|
+
if (entry.import !== undefined) {
|
|
175
|
+
entry.import = repointDistToSrc(entry.import);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return `${JSON.stringify(pkg, null, 4)}\n`;
|
|
180
|
+
}
|
|
181
|
+
/** Write a vendored adapter bundle, substituting the local name (Windows-safe paths). */
|
|
182
|
+
async function writeVendoredAdapter(bundle, dir, localName) {
|
|
183
|
+
for (const [relPath, contents] of Object.entries(bundle.files)) {
|
|
184
|
+
const dest = join(dir, ...relPath.split("/"));
|
|
185
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
186
|
+
const out = relPath === "package.json" ? repointVendoredPackageJson(contents, localName) : contents;
|
|
187
|
+
await writeFile(dest, out, "utf8");
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
async function stripRepoArtefacts(dir) {
|
|
191
|
+
for (const entry of STRIP_ENTRIES) {
|
|
192
|
+
await rm(join(dir, entry), { recursive: true, force: true });
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function defaultEnv() {
|
|
196
|
+
return [
|
|
197
|
+
"# chartlang starter environment. `.env` is git-ignored.",
|
|
198
|
+
"DATABASE_URL=file:./data/starter.db",
|
|
199
|
+
"",
|
|
200
|
+
"# EODData API key — free tier: 100 calls/day, daily EOD, US symbols.",
|
|
201
|
+
"# Register at https://eoddata.com/myaccount/api.aspx",
|
|
202
|
+
"EODDATA_API_KEY=",
|
|
203
|
+
"",
|
|
204
|
+
].join("\n");
|
|
205
|
+
}
|
|
206
|
+
async function writeNpmrc(dir) {
|
|
207
|
+
await writeFile(join(dir, NPMRC_FILE), NPMRC_CONTENTS, "utf8");
|
|
208
|
+
}
|
|
209
|
+
async function writeEnv(dir) {
|
|
210
|
+
const examplePath = join(dir, ENV_EXAMPLE);
|
|
211
|
+
let contents = defaultEnv();
|
|
212
|
+
try {
|
|
213
|
+
contents = await readFile(examplePath, "utf8");
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// No committed `.env.example` in the clone — fall back to the baked default.
|
|
217
|
+
}
|
|
218
|
+
await writeFile(join(dir, ENV_FILE), contents, "utf8");
|
|
219
|
+
}
|
|
220
|
+
function renderNextSteps(dir, pm, installed) {
|
|
221
|
+
const lines = [`Created chartlang starter in ${dir}`, "", "Next steps:", ` cd ${dir}`];
|
|
222
|
+
if (!installed) {
|
|
223
|
+
lines.push(` ${pm} install`);
|
|
224
|
+
}
|
|
225
|
+
lines.push(" # add your free EODData key to .env (EODDATA_API_KEY=)", ` ${pm} run dev`, "", "Switch chart libraries later:", " npx @invinite-org/chartlang-cli add-adapter <id>", " # then edit src/lib/chart/activeAdapter.ts", "");
|
|
226
|
+
return lines.join("\n");
|
|
227
|
+
}
|
|
228
|
+
function parse(argv) {
|
|
229
|
+
// `node:util.parseArgs` has no native `--no-<flag>` negation, so model the
|
|
230
|
+
// documented `--no-install` opt-out as a `--no-install` boolean flag and
|
|
231
|
+
// invert it (parity with the CLI's `--force`-style boolean opts).
|
|
232
|
+
const parsed = parseArgs({
|
|
233
|
+
args: argv.slice(),
|
|
234
|
+
options: {
|
|
235
|
+
library: { type: "string" },
|
|
236
|
+
pm: { type: "string" },
|
|
237
|
+
"no-install": { type: "boolean", default: false },
|
|
238
|
+
yes: { type: "boolean", default: false },
|
|
239
|
+
force: { type: "boolean", default: false },
|
|
240
|
+
},
|
|
241
|
+
allowPositionals: true,
|
|
242
|
+
strict: true,
|
|
243
|
+
});
|
|
244
|
+
return {
|
|
245
|
+
dir: parsed.positionals[0] ?? DEFAULT_TARGET,
|
|
246
|
+
library: parsed.values.library,
|
|
247
|
+
pm: parsed.values.pm ?? "npm",
|
|
248
|
+
install: !parsed.values["no-install"],
|
|
249
|
+
yes: parsed.values.yes || parsed.values.force,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Resolve the chosen library id: an explicit `--library` (validated), else the
|
|
254
|
+
* default on `--yes` / non-TTY, else an interactive prompt (default echarts on
|
|
255
|
+
* an empty answer). Returns `undefined` (after writing an error) on an unknown
|
|
256
|
+
* `--library`.
|
|
257
|
+
*/
|
|
258
|
+
async function resolveLibrary(explicit, yes, deps) {
|
|
259
|
+
if (explicit !== undefined) {
|
|
260
|
+
if (!isSeamId(explicit)) {
|
|
261
|
+
deps.stderr.write(`error: unknown --library "${explicit}" — valid ids: ${ADAPTER_REGISTRY.map((m) => m.id).join(", ")}\n`);
|
|
262
|
+
return undefined;
|
|
263
|
+
}
|
|
264
|
+
return explicit;
|
|
265
|
+
}
|
|
266
|
+
if (yes || !deps.isTTY) {
|
|
267
|
+
return DEFAULT_LIBRARY;
|
|
268
|
+
}
|
|
269
|
+
const prompter = deps.createPrompter();
|
|
270
|
+
try {
|
|
271
|
+
deps.stdout.write(renderLibraryChoices(ADAPTER_REGISTRY));
|
|
272
|
+
const answer = (await prompter.question(`Library [${DEFAULT_LIBRARY}]: `)).trim();
|
|
273
|
+
if (answer === "") {
|
|
274
|
+
return DEFAULT_LIBRARY;
|
|
275
|
+
}
|
|
276
|
+
if (!isSeamId(answer)) {
|
|
277
|
+
deps.stderr.write(`error: unknown library "${answer}" — valid ids: ${ADAPTER_REGISTRY.map((m) => m.id).join(", ")}\n`);
|
|
278
|
+
return undefined;
|
|
279
|
+
}
|
|
280
|
+
return answer;
|
|
281
|
+
}
|
|
282
|
+
finally {
|
|
283
|
+
prompter.close();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* The production IO seam — real process streams, a `node:readline/promises`
|
|
288
|
+
* prompter, a giget-backed clone, and a child-process install. The
|
|
289
|
+
* `cloneStarter` argument is injected (giget lives in `index.ts`) so this
|
|
290
|
+
* module carries no network dependency.
|
|
291
|
+
*
|
|
292
|
+
* @since 0.1
|
|
293
|
+
* @stable
|
|
294
|
+
* @example
|
|
295
|
+
* import { defaultDeps } from "@invinite-org/create-chartlang";
|
|
296
|
+
* const deps = defaultDeps({
|
|
297
|
+
* cloneStarter: async () => {},
|
|
298
|
+
* runInstall: async () => {},
|
|
299
|
+
* });
|
|
300
|
+
* deps.createPrompter().close();
|
|
301
|
+
*/
|
|
302
|
+
export function defaultDeps(io) {
|
|
303
|
+
return {
|
|
304
|
+
stdout: process.stdout,
|
|
305
|
+
stderr: process.stderr,
|
|
306
|
+
isTTY: process.stdin.isTTY === true,
|
|
307
|
+
createPrompter: () => createInterface({ input: process.stdin, output: process.stdout }),
|
|
308
|
+
cloneStarter: io.cloneStarter,
|
|
309
|
+
runInstall: io.runInstall,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Scaffold a runnable chartlang starter: clone `apps/react-starter` from
|
|
314
|
+
* GitHub (the one networked step), prompt for a chart library (default
|
|
315
|
+
* echarts), vendor the chosen adapter from the CLI's offline bundle, rewrite
|
|
316
|
+
* the single `activeAdapter.ts` seam + the `package.json` workspace deps, strip
|
|
317
|
+
* repo-internal artefacts, write `.env`, optionally install, and print next
|
|
318
|
+
* steps. Sets `process.exitCode = 1` on an unknown library or a non-empty
|
|
319
|
+
* target dir without `--yes`.
|
|
320
|
+
*
|
|
321
|
+
* Flags: `[dir]` (default `./chartlang-starter`), `--library <id>`,
|
|
322
|
+
* `--pm <npm|pnpm|yarn|bun>`, `--no-install`, `--yes` (accept defaults +
|
|
323
|
+
* overwrite a non-empty dir).
|
|
324
|
+
*
|
|
325
|
+
* @since 0.1
|
|
326
|
+
* @stable
|
|
327
|
+
* @example
|
|
328
|
+
* import { runCreateChartlang, defaultDeps } from "@invinite-org/create-chartlang";
|
|
329
|
+
* await runCreateChartlang(["my-app", "--library", "echarts"], defaultDeps({
|
|
330
|
+
* cloneStarter: async () => {},
|
|
331
|
+
* runInstall: async () => {},
|
|
332
|
+
* }));
|
|
333
|
+
*/
|
|
334
|
+
export async function runCreateChartlang(argv, deps) {
|
|
335
|
+
const args = parse(argv);
|
|
336
|
+
if (!isPackageManager(args.pm)) {
|
|
337
|
+
deps.stderr.write(`error: invalid --pm "${args.pm}" — expected one of ${PACKAGE_MANAGERS.join(", ")}\n`);
|
|
338
|
+
process.exitCode = 1;
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const pm = args.pm;
|
|
342
|
+
const targetDir = isAbsolute(args.dir) ? args.dir : resolvePath(process.cwd(), args.dir);
|
|
343
|
+
if (!args.yes && (await isNonEmptyDir(targetDir))) {
|
|
344
|
+
deps.stderr.write(`error: target directory not empty: ${targetDir} (use --yes to overwrite)\n`);
|
|
345
|
+
process.exitCode = 1;
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
const library = await resolveLibrary(args.library, args.yes, deps);
|
|
349
|
+
if (library === undefined) {
|
|
350
|
+
process.exitCode = 1;
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
// `library` is `isSeamId`-validated, so this resolves (the parity test
|
|
354
|
+
// asserts every SeamId has a bundle + registry entry).
|
|
355
|
+
const { bundle, meta } = resolveAdapter(library);
|
|
356
|
+
await deps.cloneStarter({
|
|
357
|
+
source: `${STARTER_SOURCE_BASE}${STARTER_CLONE_REF}`,
|
|
358
|
+
dir: targetDir,
|
|
359
|
+
});
|
|
360
|
+
await stripRepoArtefacts(targetDir);
|
|
361
|
+
// Make the clone standalone: bake the monorepo tsconfig base + repoint
|
|
362
|
+
// `extends`, and opt into legacy-peer-deps so `npm install` resolves the
|
|
363
|
+
// vite8/esbuild optional-peer conflict.
|
|
364
|
+
await writeStandaloneTsconfig(targetDir);
|
|
365
|
+
await writeNpmrc(targetDir);
|
|
366
|
+
const vendorRel = `vendor/${library}-adapter`;
|
|
367
|
+
const vendoredAdapterName = `@local/${library}-adapter`;
|
|
368
|
+
await writeVendoredAdapter(bundle, join(targetDir, ...vendorRel.split("/")), vendoredAdapterName);
|
|
369
|
+
const seamBody = seamTemplateFor(library, vendoredAdapterName);
|
|
370
|
+
const seamDest = join(targetDir, ...SEAM_PATH);
|
|
371
|
+
await mkdir(dirname(seamDest), { recursive: true });
|
|
372
|
+
await writeFile(seamDest, seamBody, "utf8");
|
|
373
|
+
const pkgPath = join(targetDir, "package.json");
|
|
374
|
+
const pkgSource = await readFile(pkgPath, "utf8");
|
|
375
|
+
const rewritten = rewriteStarterPackageJson({
|
|
376
|
+
source: pkgSource,
|
|
377
|
+
projectName: basename(targetDir),
|
|
378
|
+
libraryId: library,
|
|
379
|
+
chartLibrary: meta.library === "(none)" ? "" : meta.library,
|
|
380
|
+
chartLibraryRange: meta.libraryRange,
|
|
381
|
+
vendoredAdapterName,
|
|
382
|
+
vendoredAdapterSpec: `file:./${vendorRel}`,
|
|
383
|
+
bundleVersions: bundleChartlangVersions(bundle),
|
|
384
|
+
});
|
|
385
|
+
await writeFile(pkgPath, rewritten, "utf8");
|
|
386
|
+
await writeEnv(targetDir);
|
|
387
|
+
if (args.install) {
|
|
388
|
+
await deps.runInstall(pm, targetDir);
|
|
389
|
+
}
|
|
390
|
+
deps.stdout.write(renderNextSteps(targetDir, pm, args.install));
|
|
391
|
+
}
|
|
392
|
+
//# sourceMappingURL=createApp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createApp.js","sourceRoot":"","sources":["../src/createApp.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport { mkdir, readFile, readdir, rm, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, isAbsolute, join, resolve as resolvePath } from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport { parseArgs } from \"node:util\";\n\nimport {\n ADAPTER_REGISTRY,\n BUNDLED_ADAPTERS,\n type GeneratedAdapterBundle,\n type GeneratedAdapterMeta,\n} from \"@invinite-org/chartlang-cli\";\n\nimport { STARTER_CLONE_REF } from \"./chartlangVersions.js\";\nimport { rewriteStarterPackageJson } from \"./rewritePackageJson.js\";\nimport { type SeamId, isSeamId, seamTemplateFor } from \"./seamTemplates.js\";\nimport { writeStandaloneTsconfig } from \"./starterTsconfig.js\";\n\nconst PKG_NAME_PLACEHOLDER = \"__PKG_NAME__\";\nconst CHARTLANG_SCOPE = \"@invinite-org/chartlang-\";\nconst PACKAGE_MANAGERS = [\"npm\", \"pnpm\", \"yarn\", \"bun\"] as const;\ntype PackageManager = (typeof PACKAGE_MANAGERS)[number];\n\nconst NPMRC_FILE = \".npmrc\";\n// Published `@invinite-org/chartlang-compiler` depends on `esbuild@^0.24`, but\n// `vite@8`'s optional peer wants `esbuild@^0.27 || ^0.28`. The app builds + runs\n// fine on esbuild 0.24 — npm's strict optional-peer check is the only blocker —\n// so the clone opts into `legacy-peer-deps` instead of bumping any esbuild.\nconst NPMRC_CONTENTS =\n \"# vite@8's optional esbuild peer (^0.27||^0.28) conflicts with the\\n# chartlang-compiler esbuild dep (^0.24); the app runs fine on 0.24.\\nlegacy-peer-deps=true\\n\";\n\nconst DEFAULT_TARGET = \"./chartlang-starter\";\nconst DEFAULT_LIBRARY: SeamId = \"echarts\";\nconst SEAM_PATH = [\"src\", \"lib\", \"chart\", \"activeAdapter.ts\"];\nconst ENV_EXAMPLE = \".env.example\";\nconst ENV_FILE = \".env\";\n\n// Repo-internal artefacts that must not ship to the user's clone. The e2e\n// suite lives under `tests/`; `playwright.config.ts` references it (a mock\n// server + global setup), so it is stripped too — otherwise the cloned\n// project ships a `playwright.config.ts` pointing at deleted files.\nconst STRIP_ENTRIES = [\"CLAUDE.md\", \"tests\", \".changeset\", \".github\", \"playwright.config.ts\"];\n\n/**\n * The starter source giget clones, minus the ref suffix. The installer\n * appends {@link STARTER_CLONE_REF} to pin the matching tagged tree.\n *\n * @since 0.1\n * @stable\n * @example\n * import { STARTER_SOURCE_BASE } from \"@invinite-org/create-chartlang\";\n * void STARTER_SOURCE_BASE;\n */\nexport const STARTER_SOURCE_BASE = \"github:outraday-org/chartlang/apps/react-starter\";\n\n/**\n * A minimal `node:readline/promises`-like surface — the subset the\n * interactive library prompt needs. Lets a test inject a fixed answer\n * instead of driving the real TTY. Mirrors the CLI's `Prompter`.\n *\n * @since 0.1\n * @stable\n * @example\n * import type { Prompter } from \"@invinite-org/create-chartlang\";\n * const p: Prompter = { question: async () => \"echarts\", close: () => {} };\n * void p;\n */\nexport type Prompter = {\n question(query: string): Promise<string>;\n close(): void;\n};\n\n/**\n * Where + how to clone the starter. Passed to a {@link CloneStarter} so the\n * caller (or a test) decides the implementation — production wires giget's\n * `downloadTemplate`; tests write a fixture tree.\n *\n * @since 0.1\n * @stable\n * @example\n * import type { CloneRequest } from \"@invinite-org/create-chartlang\";\n * declare const req: CloneRequest;\n * void req.dir;\n */\nexport type CloneRequest = Readonly<{\n /** The giget source (`STARTER_SOURCE_BASE` + `STARTER_CLONE_REF`). */\n source: string;\n /** The absolute target directory to clone into. */\n dir: string;\n}>;\n\n/**\n * Clone the starter tree into `req.dir`. Injected so the network clone stays\n * out of the unit tests (the only networked step in the flow).\n *\n * @since 0.1\n * @stable\n * @example\n * import type { CloneStarter } from \"@invinite-org/create-chartlang\";\n * const clone: CloneStarter = async () => {};\n * void clone;\n */\nexport type CloneStarter = (req: CloneRequest) => Promise<void>;\n\n/**\n * The injectable IO seam for {@link runCreateChartlang} — output streams,\n * whether stdin is a TTY (gates the interactive prompt), a prompter factory,\n * the clone implementation, and the install runner. Tests override every\n * field so the flow runs offline with no real stdin/network.\n *\n * @since 0.1\n * @stable\n * @example\n * import type { CreateChartlangDeps } from \"@invinite-org/create-chartlang\";\n * declare const deps: CreateChartlangDeps;\n * void deps.isTTY;\n */\nexport type CreateChartlangDeps = Readonly<{\n stdout: NodeJS.WritableStream;\n stderr: NodeJS.WritableStream;\n isTTY: boolean;\n createPrompter: () => Prompter;\n cloneStarter: CloneStarter;\n runInstall: (pm: PackageManager, dir: string) => Promise<void>;\n}>;\n\nfunction isPackageManager(value: string): value is PackageManager {\n return (PACKAGE_MANAGERS as ReadonlyArray<string>).includes(value);\n}\n\n/**\n * A resolved adapter: its offline bundle + its registry metadata, the pair\n * {@link resolveAdapter} returns for a bundled id.\n *\n * @since 0.1\n * @stable\n * @example\n * import type { ResolvedAdapter } from \"@invinite-org/create-chartlang\";\n * declare const r: ResolvedAdapter;\n * void r.bundle.id;\n */\nexport type ResolvedAdapter = Readonly<{\n bundle: GeneratedAdapterBundle;\n meta: GeneratedAdapterMeta;\n}>;\n\n/**\n * Look up an adapter's bundle + registry metadata by id, throwing if either is\n * missing. The `runCreateChartlang` flow only calls this with an `isSeamId`-\n * validated id (so it never throws in production), but the guard fails loudly\n * if `SEAM_IDS` ever drifts from the generated bundle/registry set.\n *\n * @since 0.1\n * @stable\n * @example\n * import { resolveAdapter } from \"@invinite-org/create-chartlang\";\n * const { bundle, meta } = resolveAdapter(\"echarts\");\n * void bundle.id;\n * void meta.library;\n */\nexport function resolveAdapter(id: string): ResolvedAdapter {\n const bundle = BUNDLED_ADAPTERS.find((b) => b.id === id);\n const meta = ADAPTER_REGISTRY.find((m) => m.id === id);\n if (bundle === undefined || meta === undefined) {\n throw new Error(`no bundle/registry entry for adapter \"${id}\"`);\n }\n return { bundle, meta };\n}\n\nasync function isNonEmptyDir(path: string): Promise<boolean> {\n try {\n return (await readdir(path)).length > 0;\n } catch {\n return false;\n }\n}\n\n/**\n * Render the library-choice prompt list from the registry, echarts first\n * (the default) then the rest in registry order. Pure: no IO.\n *\n * @since 0.1\n * @stable\n * @example\n * import { renderLibraryChoices } from \"@invinite-org/create-chartlang\";\n * const text = renderLibraryChoices([]);\n * void text;\n */\nexport function renderLibraryChoices(registry: ReadonlyArray<GeneratedAdapterMeta>): string {\n const ordered = orderedRegistry(registry);\n const lines = [\"Choose a chart library:\", \"\"];\n for (const meta of ordered) {\n const suffix = meta.id === DEFAULT_LIBRARY ? \" (default)\" : \"\";\n const lib = meta.library === \"(none)\" ? \"no runtime dep\" : meta.library;\n lines.push(` ${meta.id} — ${meta.displayName} (${lib})${suffix}`);\n }\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\nfunction orderedRegistry(\n registry: ReadonlyArray<GeneratedAdapterMeta>,\n): ReadonlyArray<GeneratedAdapterMeta> {\n const def = registry.filter((m) => m.id === DEFAULT_LIBRARY);\n const rest = registry.filter((m) => m.id !== DEFAULT_LIBRARY);\n return [...def, ...rest];\n}\n\n/**\n * Harvest the published `@invinite-org/chartlang-*` `^`-ranges from a bundle's\n * own (generator-pinned) `package.json` deps + devDeps. These take precedence\n * over the baked manifest when rewriting the starter's workspace deps.\n *\n * @since 0.1\n * @stable\n * @example\n * import { bundleChartlangVersions } from \"@invinite-org/create-chartlang\";\n * const map = bundleChartlangVersions({ id: \"x\", files: {} });\n * void map;\n */\nexport function bundleChartlangVersions(\n bundle: GeneratedAdapterBundle,\n): Readonly<Record<string, string>> {\n // Every generated bundle carries a `package.json` (the generator always\n // emits one), so `?? \"{}\"` is only a parse-safety floor, never the path.\n const parsed = JSON.parse(bundle.files[\"package.json\"] ?? \"{}\") as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const out: Record<string, string> = {};\n for (const block of [parsed.dependencies, parsed.devDependencies]) {\n for (const [name, range] of Object.entries(block ?? {})) {\n if (name.startsWith(CHARTLANG_SCOPE)) {\n out[name] = range;\n }\n }\n }\n return out;\n}\n\n/**\n * Repoint a single `main`/`types`/`exports` entry string from the bundle's\n * unbuilt `./dist/*.{js,d.ts}` to the vendored TypeScript source `./src/*.ts`.\n * The vendored bundle ships only `src/` (create-chartlang never builds it), so\n * Vite + tsc resolve the adapter directly from source with NO build step. A\n * non-`./dist/` value is returned unchanged.\n */\nfunction repointDistToSrc(value: string): string {\n if (!value.startsWith(\"./dist/\")) {\n return value;\n }\n return value\n .replace(/^\\.\\/dist\\//, \"./src/\")\n .replace(/\\.d\\.ts$/, \".ts\")\n .replace(/\\.js$/, \".ts\");\n}\n\ntype VendoredExportEntry = { types?: string; import?: string };\ntype VendoredAdapterPkg = {\n main?: string;\n types?: string;\n exports?: Record<string, VendoredExportEntry>;\n [key: string]: unknown;\n};\n\n/**\n * Rewrite the vendored adapter `package.json`: substitute the `__PKG_NAME__`\n * placeholder, then repoint `main`/`types` and every `exports` entry's\n * `types`/`import` from `./dist/*` to the vendored `./src/*.ts` source. This is\n * an intentional DIVERGENCE from `cli add-adapter`, which keeps the\n * dist-pointing bundle (it expects a build); create-chartlang vendors source\n * only and never builds, so the manifest must resolve straight from `src/`.\n * Absent fields are left untouched.\n *\n * @since 0.1\n * @stable\n * @example\n * import { repointVendoredPackageJson } from \"@invinite-org/create-chartlang\";\n * const next = repointVendoredPackageJson('{\"main\":\"./dist/index.js\"}', \"@local/x-adapter\");\n * void next;\n */\nexport function repointVendoredPackageJson(contents: string, localName: string): string {\n const named = contents.split(PKG_NAME_PLACEHOLDER).join(localName);\n const pkg = JSON.parse(named) as VendoredAdapterPkg;\n if (pkg.main !== undefined) {\n pkg.main = repointDistToSrc(pkg.main);\n }\n if (pkg.types !== undefined) {\n pkg.types = repointDistToSrc(pkg.types);\n }\n if (pkg.exports !== undefined) {\n for (const entry of Object.values(pkg.exports)) {\n if (entry.types !== undefined) {\n entry.types = repointDistToSrc(entry.types);\n }\n if (entry.import !== undefined) {\n entry.import = repointDistToSrc(entry.import);\n }\n }\n }\n return `${JSON.stringify(pkg, null, 4)}\\n`;\n}\n\n/** Write a vendored adapter bundle, substituting the local name (Windows-safe paths). */\nasync function writeVendoredAdapter(\n bundle: GeneratedAdapterBundle,\n dir: string,\n localName: string,\n): Promise<void> {\n for (const [relPath, contents] of Object.entries(bundle.files)) {\n const dest = join(dir, ...relPath.split(\"/\"));\n await mkdir(dirname(dest), { recursive: true });\n const out =\n relPath === \"package.json\" ? repointVendoredPackageJson(contents, localName) : contents;\n await writeFile(dest, out, \"utf8\");\n }\n}\n\nasync function stripRepoArtefacts(dir: string): Promise<void> {\n for (const entry of STRIP_ENTRIES) {\n await rm(join(dir, entry), { recursive: true, force: true });\n }\n}\n\nfunction defaultEnv(): string {\n return [\n \"# chartlang starter environment. `.env` is git-ignored.\",\n \"DATABASE_URL=file:./data/starter.db\",\n \"\",\n \"# EODData API key — free tier: 100 calls/day, daily EOD, US symbols.\",\n \"# Register at https://eoddata.com/myaccount/api.aspx\",\n \"EODDATA_API_KEY=\",\n \"\",\n ].join(\"\\n\");\n}\n\nasync function writeNpmrc(dir: string): Promise<void> {\n await writeFile(join(dir, NPMRC_FILE), NPMRC_CONTENTS, \"utf8\");\n}\n\nasync function writeEnv(dir: string): Promise<void> {\n const examplePath = join(dir, ENV_EXAMPLE);\n let contents = defaultEnv();\n try {\n contents = await readFile(examplePath, \"utf8\");\n } catch {\n // No committed `.env.example` in the clone — fall back to the baked default.\n }\n await writeFile(join(dir, ENV_FILE), contents, \"utf8\");\n}\n\nfunction renderNextSteps(dir: string, pm: PackageManager, installed: boolean): string {\n const lines = [`Created chartlang starter in ${dir}`, \"\", \"Next steps:\", ` cd ${dir}`];\n if (!installed) {\n lines.push(` ${pm} install`);\n }\n lines.push(\n \" # add your free EODData key to .env (EODDATA_API_KEY=)\",\n ` ${pm} run dev`,\n \"\",\n \"Switch chart libraries later:\",\n \" npx @invinite-org/chartlang-cli add-adapter <id>\",\n \" # then edit src/lib/chart/activeAdapter.ts\",\n \"\",\n );\n return lines.join(\"\\n\");\n}\n\ntype ParsedArgs = Readonly<{\n dir: string;\n library: string | undefined;\n pm: string;\n install: boolean;\n yes: boolean;\n}>;\n\nfunction parse(argv: ReadonlyArray<string>): ParsedArgs {\n // `node:util.parseArgs` has no native `--no-<flag>` negation, so model the\n // documented `--no-install` opt-out as a `--no-install` boolean flag and\n // invert it (parity with the CLI's `--force`-style boolean opts).\n const parsed = parseArgs({\n args: argv.slice(),\n options: {\n library: { type: \"string\" },\n pm: { type: \"string\" },\n \"no-install\": { type: \"boolean\", default: false },\n yes: { type: \"boolean\", default: false },\n force: { type: \"boolean\", default: false },\n },\n allowPositionals: true,\n strict: true,\n });\n return {\n dir: parsed.positionals[0] ?? DEFAULT_TARGET,\n library: parsed.values.library,\n pm: parsed.values.pm ?? \"npm\",\n install: !parsed.values[\"no-install\"],\n yes: parsed.values.yes || parsed.values.force,\n };\n}\n\n/**\n * Resolve the chosen library id: an explicit `--library` (validated), else the\n * default on `--yes` / non-TTY, else an interactive prompt (default echarts on\n * an empty answer). Returns `undefined` (after writing an error) on an unknown\n * `--library`.\n */\nasync function resolveLibrary(\n explicit: string | undefined,\n yes: boolean,\n deps: CreateChartlangDeps,\n): Promise<SeamId | undefined> {\n if (explicit !== undefined) {\n if (!isSeamId(explicit)) {\n deps.stderr.write(\n `error: unknown --library \"${explicit}\" — valid ids: ${ADAPTER_REGISTRY.map((m) => m.id).join(\", \")}\\n`,\n );\n return undefined;\n }\n return explicit;\n }\n if (yes || !deps.isTTY) {\n return DEFAULT_LIBRARY;\n }\n const prompter = deps.createPrompter();\n try {\n deps.stdout.write(renderLibraryChoices(ADAPTER_REGISTRY));\n const answer = (await prompter.question(`Library [${DEFAULT_LIBRARY}]: `)).trim();\n if (answer === \"\") {\n return DEFAULT_LIBRARY;\n }\n if (!isSeamId(answer)) {\n deps.stderr.write(\n `error: unknown library \"${answer}\" — valid ids: ${ADAPTER_REGISTRY.map((m) => m.id).join(\", \")}\\n`,\n );\n return undefined;\n }\n return answer;\n } finally {\n prompter.close();\n }\n}\n\n/**\n * The production IO seam — real process streams, a `node:readline/promises`\n * prompter, a giget-backed clone, and a child-process install. The\n * `cloneStarter` argument is injected (giget lives in `index.ts`) so this\n * module carries no network dependency.\n *\n * @since 0.1\n * @stable\n * @example\n * import { defaultDeps } from \"@invinite-org/create-chartlang\";\n * const deps = defaultDeps({\n * cloneStarter: async () => {},\n * runInstall: async () => {},\n * });\n * deps.createPrompter().close();\n */\nexport function defaultDeps(\n io: Readonly<{ cloneStarter: CloneStarter; runInstall: CreateChartlangDeps[\"runInstall\"] }>,\n): CreateChartlangDeps {\n return {\n stdout: process.stdout,\n stderr: process.stderr,\n isTTY: process.stdin.isTTY === true,\n createPrompter: () => createInterface({ input: process.stdin, output: process.stdout }),\n cloneStarter: io.cloneStarter,\n runInstall: io.runInstall,\n };\n}\n\n/**\n * Scaffold a runnable chartlang starter: clone `apps/react-starter` from\n * GitHub (the one networked step), prompt for a chart library (default\n * echarts), vendor the chosen adapter from the CLI's offline bundle, rewrite\n * the single `activeAdapter.ts` seam + the `package.json` workspace deps, strip\n * repo-internal artefacts, write `.env`, optionally install, and print next\n * steps. Sets `process.exitCode = 1` on an unknown library or a non-empty\n * target dir without `--yes`.\n *\n * Flags: `[dir]` (default `./chartlang-starter`), `--library <id>`,\n * `--pm <npm|pnpm|yarn|bun>`, `--no-install`, `--yes` (accept defaults +\n * overwrite a non-empty dir).\n *\n * @since 0.1\n * @stable\n * @example\n * import { runCreateChartlang, defaultDeps } from \"@invinite-org/create-chartlang\";\n * await runCreateChartlang([\"my-app\", \"--library\", \"echarts\"], defaultDeps({\n * cloneStarter: async () => {},\n * runInstall: async () => {},\n * }));\n */\nexport async function runCreateChartlang(\n argv: ReadonlyArray<string>,\n deps: CreateChartlangDeps,\n): Promise<void> {\n const args = parse(argv);\n\n if (!isPackageManager(args.pm)) {\n deps.stderr.write(\n `error: invalid --pm \"${args.pm}\" — expected one of ${PACKAGE_MANAGERS.join(\", \")}\\n`,\n );\n process.exitCode = 1;\n return;\n }\n const pm: PackageManager = args.pm;\n\n const targetDir = isAbsolute(args.dir) ? args.dir : resolvePath(process.cwd(), args.dir);\n if (!args.yes && (await isNonEmptyDir(targetDir))) {\n deps.stderr.write(\n `error: target directory not empty: ${targetDir} (use --yes to overwrite)\\n`,\n );\n process.exitCode = 1;\n return;\n }\n\n const library = await resolveLibrary(args.library, args.yes, deps);\n if (library === undefined) {\n process.exitCode = 1;\n return;\n }\n\n // `library` is `isSeamId`-validated, so this resolves (the parity test\n // asserts every SeamId has a bundle + registry entry).\n const { bundle, meta } = resolveAdapter(library);\n\n await deps.cloneStarter({\n source: `${STARTER_SOURCE_BASE}${STARTER_CLONE_REF}`,\n dir: targetDir,\n });\n await stripRepoArtefacts(targetDir);\n\n // Make the clone standalone: bake the monorepo tsconfig base + repoint\n // `extends`, and opt into legacy-peer-deps so `npm install` resolves the\n // vite8/esbuild optional-peer conflict.\n await writeStandaloneTsconfig(targetDir);\n await writeNpmrc(targetDir);\n\n const vendorRel = `vendor/${library}-adapter`;\n const vendoredAdapterName = `@local/${library}-adapter`;\n await writeVendoredAdapter(\n bundle,\n join(targetDir, ...vendorRel.split(\"/\")),\n vendoredAdapterName,\n );\n\n const seamBody = seamTemplateFor(library, vendoredAdapterName);\n const seamDest = join(targetDir, ...SEAM_PATH);\n await mkdir(dirname(seamDest), { recursive: true });\n await writeFile(seamDest, seamBody, \"utf8\");\n\n const pkgPath = join(targetDir, \"package.json\");\n const pkgSource = await readFile(pkgPath, \"utf8\");\n const rewritten = rewriteStarterPackageJson({\n source: pkgSource,\n projectName: basename(targetDir),\n libraryId: library,\n chartLibrary: meta.library === \"(none)\" ? \"\" : meta.library,\n chartLibraryRange: meta.libraryRange,\n vendoredAdapterName,\n vendoredAdapterSpec: `file:./${vendorRel}`,\n bundleVersions: bundleChartlangVersions(bundle),\n });\n await writeFile(pkgPath, rewritten, \"utf8\");\n\n await writeEnv(targetDir);\n\n if (args.install) {\n await deps.runInstall(pm, targetDir);\n }\n\n deps.stdout.write(renderNextSteps(targetDir, pm, args.install));\n}\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
export { bundleChartlangVersions, defaultDeps, renderLibraryChoices, repointVendoredPackageJson, resolveAdapter, runCreateChartlang, STARTER_SOURCE_BASE, } from "./createApp.js";
|
|
3
|
+
export type { CloneRequest, CloneStarter, CreateChartlangDeps, Prompter, ResolvedAdapter, } from "./createApp.js";
|
|
4
|
+
export { CHARTLANG_VERSIONS, STARTER_CLONE_REF } from "./chartlangVersions.js";
|
|
5
|
+
export { rewriteStarterPackageJson } from "./rewritePackageJson.js";
|
|
6
|
+
export type { RewriteOpts } from "./rewritePackageJson.js";
|
|
7
|
+
export { isSeamId, SEAM_IDS, seamTemplateFor } from "./seamTemplates.js";
|
|
8
|
+
export type { SeamId } from "./seamTemplates.js";
|
|
9
|
+
export { STANDALONE_TSCONFIG_BASE, writeStandaloneTsconfig } from "./starterTsconfig.js";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAUA,OAAO,EACH,uBAAuB,EACvB,WAAW,EACX,oBAAoB,EACpB,0BAA0B,EAC1B,cAAc,EACd,kBAAkB,EAClB,mBAAmB,GACtB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACR,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,QAAQ,EACR,eAAe,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACzE,YAAY,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Copyright (c) 2026 Invinite. Licensed under the MIT License.
|
|
3
|
+
// See the LICENSE file in the repo root for full license text.
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
import { downloadTemplate } from "giget";
|
|
6
|
+
import { defaultDeps, runCreateChartlang } from "./createApp.js";
|
|
7
|
+
export { bundleChartlangVersions, defaultDeps, renderLibraryChoices, repointVendoredPackageJson, resolveAdapter, runCreateChartlang, STARTER_SOURCE_BASE, } from "./createApp.js";
|
|
8
|
+
export { CHARTLANG_VERSIONS, STARTER_CLONE_REF } from "./chartlangVersions.js";
|
|
9
|
+
export { rewriteStarterPackageJson } from "./rewritePackageJson.js";
|
|
10
|
+
export { isSeamId, SEAM_IDS, seamTemplateFor } from "./seamTemplates.js";
|
|
11
|
+
export { STANDALONE_TSCONFIG_BASE, writeStandaloneTsconfig } from "./starterTsconfig.js";
|
|
12
|
+
await runCreateChartlang(process.argv.slice(2), defaultDeps({
|
|
13
|
+
cloneStarter: async ({ source, dir }) => {
|
|
14
|
+
await downloadTemplate(source, { dir, forceClean: true });
|
|
15
|
+
},
|
|
16
|
+
runInstall: (pm, dir) => new Promise((resolve, reject) => {
|
|
17
|
+
const child = spawn(pm, ["install"], { cwd: dir, stdio: "inherit", shell: true });
|
|
18
|
+
child.on("error", reject);
|
|
19
|
+
child.on("exit", (code) => code === 0 ? resolve() : reject(new Error(`${pm} install exited with ${code}`)));
|
|
20
|
+
}),
|
|
21
|
+
}));
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,+DAA+D;AAC/D,+DAA+D;AAE/D,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EACH,uBAAuB,EACvB,WAAW,EACX,oBAAoB,EACpB,0BAA0B,EAC1B,cAAc,EACd,kBAAkB,EAClB,mBAAmB,GACtB,MAAM,gBAAgB,CAAC;AAQxB,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAEpE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEzE,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAEzF,MAAM,kBAAkB,CACpB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EACrB,WAAW,CAAC;IACR,YAAY,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE;QACpC,MAAM,gBAAgB,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,UAAU,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CACpB,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAClC,MAAM,KAAK,GAAG,KAAK,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1B,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CACtB,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,EAAE,wBAAwB,IAAI,EAAE,CAAC,CAAC,CAClF,CAAC;IACN,CAAC,CAAC;CACT,CAAC,CACL,CAAC","sourcesContent":["#!/usr/bin/env node\n// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport { spawn } from \"node:child_process\";\n\nimport { downloadTemplate } from \"giget\";\n\nimport { defaultDeps, runCreateChartlang } from \"./createApp.js\";\n\nexport {\n bundleChartlangVersions,\n defaultDeps,\n renderLibraryChoices,\n repointVendoredPackageJson,\n resolveAdapter,\n runCreateChartlang,\n STARTER_SOURCE_BASE,\n} from \"./createApp.js\";\nexport type {\n CloneRequest,\n CloneStarter,\n CreateChartlangDeps,\n Prompter,\n ResolvedAdapter,\n} from \"./createApp.js\";\nexport { CHARTLANG_VERSIONS, STARTER_CLONE_REF } from \"./chartlangVersions.js\";\nexport { rewriteStarterPackageJson } from \"./rewritePackageJson.js\";\nexport type { RewriteOpts } from \"./rewritePackageJson.js\";\nexport { isSeamId, SEAM_IDS, seamTemplateFor } from \"./seamTemplates.js\";\nexport type { SeamId } from \"./seamTemplates.js\";\nexport { STANDALONE_TSCONFIG_BASE, writeStandaloneTsconfig } from \"./starterTsconfig.js\";\n\nawait runCreateChartlang(\n process.argv.slice(2),\n defaultDeps({\n cloneStarter: async ({ source, dir }) => {\n await downloadTemplate(source, { dir, forceClean: true });\n },\n runInstall: (pm, dir) =>\n new Promise<void>((resolve, reject) => {\n const child = spawn(pm, [\"install\"], { cwd: dir, stdio: \"inherit\", shell: true });\n child.on(\"error\", reject);\n child.on(\"exit\", (code) =>\n code === 0 ? resolve() : reject(new Error(`${pm} install exited with ${code}`)),\n );\n }),\n }),\n);\n"]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { SeamId } from "./seamTemplates.js";
|
|
2
|
+
/**
|
|
3
|
+
* Options for {@link rewriteStarterPackageJson}.
|
|
4
|
+
*
|
|
5
|
+
* @since 0.1
|
|
6
|
+
* @stable
|
|
7
|
+
* @example
|
|
8
|
+
* import type { RewriteOpts } from "@invinite-org/create-chartlang";
|
|
9
|
+
* declare const opts: RewriteOpts;
|
|
10
|
+
* void opts.projectName;
|
|
11
|
+
*/
|
|
12
|
+
export type RewriteOpts = Readonly<{
|
|
13
|
+
/** The cloned starter's raw `package.json` text. */
|
|
14
|
+
source: string;
|
|
15
|
+
/** The project name to stamp into the rewritten `package.json`. */
|
|
16
|
+
projectName: string;
|
|
17
|
+
/** The chosen chart-library adapter id. */
|
|
18
|
+
libraryId: SeamId;
|
|
19
|
+
/** The npm chart library the chosen adapter depends on (empty for canvas2d). */
|
|
20
|
+
chartLibrary: string;
|
|
21
|
+
/** The semver range for {@link chartLibrary} (from the adapter registry). */
|
|
22
|
+
chartLibraryRange: string;
|
|
23
|
+
/** The local package name the chosen adapter was vendored under. */
|
|
24
|
+
vendoredAdapterName: string;
|
|
25
|
+
/** The dependency value for the vendored adapter (e.g. `file:./vendor/echarts-adapter`). */
|
|
26
|
+
vendoredAdapterSpec: string;
|
|
27
|
+
/**
|
|
28
|
+
* Published `^`-ranges harvested from the vendored bundle's own (already
|
|
29
|
+
* generator-pinned) `package.json` deps. Preferred over the baked
|
|
30
|
+
* {@link CHARTLANG_VERSIONS} manifest for the packages it covers.
|
|
31
|
+
*/
|
|
32
|
+
bundleVersions: Readonly<Record<string, string>>;
|
|
33
|
+
}>;
|
|
34
|
+
/**
|
|
35
|
+
* Rewrite the cloned starter's `package.json` for a standalone, installable
|
|
36
|
+
* project: stamp the project name, replace every `workspace:*` chartlang dep
|
|
37
|
+
* with its published `^`-range, drop the unused example-adapter deps, wire the
|
|
38
|
+
* vendored adapter as a local `file:` dep, and add the chosen chart library +
|
|
39
|
+
* range. The result contains NO `workspace:` ranges (asserted) so it resolves
|
|
40
|
+
* straight from npm.
|
|
41
|
+
*
|
|
42
|
+
* @since 0.1
|
|
43
|
+
* @stable
|
|
44
|
+
* @example
|
|
45
|
+
* import { rewriteStarterPackageJson } from "@invinite-org/create-chartlang";
|
|
46
|
+
* const next = rewriteStarterPackageJson({
|
|
47
|
+
* source: '{"name":"x","dependencies":{}}',
|
|
48
|
+
* projectName: "my-app",
|
|
49
|
+
* libraryId: "echarts",
|
|
50
|
+
* chartLibrary: "echarts",
|
|
51
|
+
* chartLibraryRange: "^5",
|
|
52
|
+
* vendoredAdapterName: "@local/echarts-adapter",
|
|
53
|
+
* vendoredAdapterSpec: "file:./vendor/echarts-adapter",
|
|
54
|
+
* bundleVersions: {},
|
|
55
|
+
* });
|
|
56
|
+
* void next;
|
|
57
|
+
*/
|
|
58
|
+
export declare function rewriteStarterPackageJson(opts: RewriteOpts): string;
|
|
59
|
+
//# sourceMappingURL=rewritePackageJson.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rewritePackageJson.d.ts","sourceRoot":"","sources":["../src/rewritePackageJson.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAkBjD;;;;;;;;;GASG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;IAC/B,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,WAAW,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,YAAY,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,mBAAmB,EAAE,MAAM,CAAC;IAC5B,4FAA4F;IAC5F,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACpD,CAAC,CAAC;AAuFH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CA+BnE"}
|