vite-plus 0.1.24 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +30 -0
- package/README.md +8 -6
- package/bin/oxfmt +5 -2
- package/bin/oxlint +12 -2
- package/binding/index.cjs +84 -67
- package/binding/index.d.cts +155 -4
- package/dist/{agent-Nuk-9l77.js → agent-BD31CsvU.js} +941 -70
- package/dist/bin.js +22 -30
- package/dist/{compat-DXZgnEyq.js → compat-Cql3K40m.js} +1 -1
- package/dist/config/bin.js +30 -14
- package/dist/constants-CrfJQIUX.js +66 -0
- package/dist/create/bin.d.ts +6 -0
- package/dist/create/bin.js +508 -232
- package/dist/define-config-2tfJoXr1.d.ts +305 -0
- package/dist/define-config-BGSjF6Xp.cjs +488 -0
- package/dist/define-config-DJUehepE.js +445 -0
- package/dist/define-config.cjs +8 -1
- package/dist/define-config.d.ts +2 -2
- package/dist/define-config.js +2 -2
- package/dist/dist-DRJUd9bL.js +3 -0
- package/dist/{dist-BgQuvbtq.js → dist-Oxo16Y0q.js} +4 -4
- package/dist/index.cjs +9 -4
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/{main-DpJl3LoU.js → json-Dn87fvjk.js} +137 -1
- package/dist/migration/bin.js +292 -76
- package/dist/{oxlint-plugin-config-B89iKTKN.js → oxlint-plugin-config-q8a5PFch.js} +1 -1
- package/dist/oxlint-plugin.js +11 -3
- package/dist/pack-bin.js +44 -15
- package/dist/{package-PmBUZ-ve.js → package-BHirM1_v.js} +3 -138
- package/dist/{report-DgSBQUdz.js → report-BHSkWqRR.js} +2 -0
- package/dist/{resolve-vite-config-TTvhycU1.js → resolve-vite-config-CmdsfQzS.js} +13 -4
- package/dist/staged/bin.js +3 -3
- package/dist/test/_at-vitest-browser/context.d.ts +2 -0
- package/dist/test/_at-vitest-browser.d.ts +2 -0
- package/dist/test/browser/context.d.ts +2 -2
- package/dist/test/browser/context.js +1 -1
- package/dist/test/browser/providers/playwright/context.d.ts +1 -0
- package/dist/test/browser/providers/playwright/context.js +1 -0
- package/dist/test/browser/providers/playwright.d.ts +124 -2
- package/dist/test/browser/providers/playwright.js +1 -1
- package/dist/test/browser/providers/preview/context.d.ts +1 -0
- package/dist/test/browser/providers/preview/context.js +1 -0
- package/dist/test/browser/providers/preview.d.ts +32 -2
- package/dist/test/browser/providers/preview.js +1 -1
- package/dist/test/browser/providers/webdriverio/context.d.ts +1 -0
- package/dist/test/browser/providers/webdriverio/context.js +1 -0
- package/dist/test/browser/providers/webdriverio.d.ts +77 -2
- package/dist/test/browser/providers/webdriverio.js +1 -1
- package/dist/test/browser-compat.d.ts +2 -0
- package/dist/test/browser-compat.js +1 -1
- package/dist/test/browser-playwright/context.d.ts +1 -0
- package/dist/test/browser-playwright/context.js +1 -0
- package/dist/test/browser-playwright.d.ts +124 -2
- package/dist/test/browser-playwright.js +1 -1
- package/dist/test/browser-preview/context.d.ts +1 -0
- package/dist/test/browser-preview/context.js +1 -0
- package/dist/test/browser-preview.d.ts +32 -2
- package/dist/test/browser-preview.js +1 -1
- package/dist/test/browser-webdriverio/context.d.ts +1 -0
- package/dist/test/browser-webdriverio/context.js +1 -0
- package/dist/test/browser-webdriverio.d.ts +77 -2
- package/dist/test/browser-webdriverio.js +1 -1
- package/dist/test/browser.d.ts +2 -2
- package/dist/test/browser.js +1 -1
- package/dist/test/client.js +1 -1
- package/dist/test/config.cjs +1 -1
- package/dist/test/config.d.ts +2 -2
- package/dist/test/config.js +1 -1
- package/dist/test/context.d.ts +942 -2
- package/dist/test/context.js +1 -1
- package/dist/test/coverage.d.ts +2 -2
- package/dist/test/coverage.js +1 -1
- package/dist/test/environments.d.ts +2 -2
- package/dist/test/environments.js +1 -1
- package/dist/test/globals.d.ts +2 -2
- package/dist/test/import-meta.d.ts +2 -2
- package/dist/test/importMeta.d.ts +2 -2
- package/dist/test/index.cjs +1 -1
- package/dist/test/index.d.cts +2 -2
- package/dist/test/index.d.ts +2 -2
- package/dist/test/index.js +1 -1
- package/dist/test/internal/browser.d.ts +2 -2
- package/dist/test/internal/browser.js +1 -1
- package/dist/test/jsdom.d.ts +2 -2
- package/dist/test/locators.d.ts +294 -0
- package/dist/test/locators.js +1 -1
- package/dist/test/matchers.d.ts +29 -0
- package/dist/test/matchers.js +1 -1
- package/dist/test/node.d.ts +2 -2
- package/dist/test/node.js +1 -1
- package/dist/test/optional-runtime-types.js.d.ts +2 -2
- package/dist/test/optional-types.js.d.ts +2 -2
- package/dist/test/plugins/browser-client.js +1 -1
- package/dist/test/plugins/browser-context.js +1 -1
- package/dist/test/plugins/browser-locators.js +1 -1
- package/dist/test/plugins/browser-playwright.js +1 -1
- package/dist/test/plugins/browser-preview.js +1 -1
- package/dist/test/plugins/browser-webdriverio.js +1 -1
- package/dist/test/plugins/browser.js +1 -1
- package/dist/test/plugins/expect.js +1 -1
- package/dist/test/plugins/mocker-automock.js +1 -1
- package/dist/test/plugins/mocker-browser.js +1 -1
- package/dist/test/plugins/mocker-node.js +1 -1
- package/dist/test/plugins/mocker-redirect.js +1 -1
- package/dist/test/plugins/mocker-register.js +1 -1
- package/dist/test/plugins/mocker-transforms.js +1 -1
- package/dist/test/plugins/mocker.js +1 -1
- package/dist/test/plugins/pretty-format.js +1 -1
- package/dist/test/plugins/runner-types.js +1 -1
- package/dist/test/plugins/runner-utils.js +1 -1
- package/dist/test/plugins/runner.js +1 -1
- package/dist/test/plugins/snapshot-environment.js +1 -1
- package/dist/test/plugins/snapshot-manager.js +1 -1
- package/dist/test/plugins/snapshot.js +1 -1
- package/dist/test/plugins/spy.js +1 -1
- package/dist/test/plugins/utils-constants.js +1 -1
- package/dist/test/plugins/utils-diff.js +1 -1
- package/dist/test/plugins/utils-display.js +1 -1
- package/dist/test/plugins/utils-error.js +1 -1
- package/dist/test/plugins/utils-helpers.js +1 -1
- package/dist/test/plugins/utils-offset.js +1 -1
- package/dist/test/plugins/utils-resolver.js +1 -1
- package/dist/test/plugins/utils-serialize.js +1 -1
- package/dist/test/plugins/utils-source-map-node.js +1 -1
- package/dist/test/plugins/utils-source-map.js +1 -1
- package/dist/test/plugins/utils-timers.js +1 -1
- package/dist/test/plugins/utils.js +1 -1
- package/dist/test/reporters.d.ts +2 -2
- package/dist/test/reporters.js +1 -1
- package/dist/test/runners.d.ts +2 -2
- package/dist/test/runners.js +1 -1
- package/dist/test/runtime.d.ts +2 -2
- package/dist/test/runtime.js +1 -1
- package/dist/test/snapshot.d.ts +2 -2
- package/dist/test/snapshot.js +1 -1
- package/dist/test/suite.d.ts +2 -2
- package/dist/test/suite.js +1 -1
- package/dist/test/utils.js +1 -1
- package/dist/test/worker.d.ts +2 -2
- package/dist/test/worker.js +1 -1
- package/dist/{tsconfig-DFb5BKyT.js → tsconfig-CJ_StdFc.js} +563 -229
- package/dist/tsgolint-path-B-yOos8p.js +32 -0
- package/dist/tsgolint-path.d.ts +8 -0
- package/dist/tsgolint-path.js +2 -0
- package/dist/version.js +3 -3
- package/dist/versions.d.ts +1 -1
- package/dist/versions.js +6 -6
- package/dist/{workspace-NL-m9wgM.js → workspace-Cjoc1c_A.js} +11 -9
- package/docs/_data/team.ts +2 -1
- package/docs/config/create.md +36 -1
- package/docs/config/index.md +7 -5
- package/docs/guide/commit-hooks.md +9 -0
- package/docs/guide/create.md +106 -2
- package/docs/guide/env.md +33 -5
- package/docs/guide/index.md +5 -3
- package/docs/guide/install.md +31 -12
- package/docs/guide/migrate.md +13 -3
- package/docs/guide/troubleshooting.md +2 -2
- package/docs/guide/upgrade.md +26 -7
- package/docs/package.json +3 -3
- package/docs/pnpm-lock.yaml +298 -395
- package/package.json +103 -55
- package/templates/generator/bin/index.ts +6 -3
- package/templates/generator/package.json +2 -3
- package/templates/generator/src/template.ts +0 -2
- package/templates/monorepo/package.json +1 -1
- package/dist/constants-DCBWlNrn.js +0 -33
- package/dist/define-config-BR1Y88zz.cjs +0 -84
- package/dist/define-config-BRC7qPNE.js +0 -21
- package/dist/define-config-COdn-tsn.d.ts +0 -177
- package/dist/dist-Bapm49IR.js +0 -3
- package/dist/test/plugins/utils-highlight.js +0 -1
- /package/dist/{chunk-DnnnRqeS.js → rolldown-runtime-DnnnRqeS.js} +0 -0
package/dist/create/bin.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import { r as __toESM, t as __commonJSMin } from "../
|
|
2
|
-
import {
|
|
1
|
+
import { r as __toESM, t as __commonJSMin } from "../rolldown-runtime-DnnnRqeS.js";
|
|
2
|
+
import { o as VITE_PLUS_NAME } from "../constants-CrfJQIUX.js";
|
|
3
|
+
import { A as select, D as log, E as intro, F as runCommand$1, I as runCommandSilently, L as require_cross_spawn, M as text, N as require_picocolors, O as multiselect, P as R, S as PackageManager, T as confirm, _ as approveBuilds, d as promptGitHooks, f as resolveGitInit, h as selectPackageManager, j as spinner, l as defaultInteractive, m as runViteInstall, p as runViteFmt, u as downloadPackageManager$1, v as detectGatedBuilds, w as cancel, x as DependencyType, y as resolveApproveBuildTargets } from "../tsconfig-CJ_StdFc.js";
|
|
3
4
|
import { a as printHeader, i as muted, o as success, r as log$1, t as accent } from "../terminal-uTv0ZaMr.js";
|
|
4
|
-
import {
|
|
5
|
+
import { r as readJsonFile, t as editJsonFile } from "../json-Dn87fvjk.js";
|
|
6
|
+
import { a as resolveViteConfig, n as findWorkspaceRoot, r as hasViteConfig, t as findViteConfig } from "../resolve-vite-config-CmdsfQzS.js";
|
|
5
7
|
import { t as lib_default } from "../lib-L3DWSRQp.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
8
|
+
import { o as fetchNpmResource, s as getNpmRegistry, t as checkNpmPackageExists } from "../package-BHirM1_v.js";
|
|
9
|
+
import { B as setPackageManager, D as injectCreateDefaultTemplate, F as promptEslintMigration, I as promptPrettierMigration, J as templatesDir, L as rewriteMonorepo, R as rewriteMonorepoProject, T as hasFrameworkShim, a as selectAgentTargets, b as detectPrettierProject, c as writeCopilotSetupWorkflow, h as detectFramework, k as installGitHooks, l as addFrameworkShim, m as detectEslintProject, q as displayRelative, r as detectExistingAgentTargetPaths, s as writeAgentInstructions, t as COPILOT_AGENT_ID, z as rewriteStandaloneProject } from "../agent-BD31CsvU.js";
|
|
10
|
+
import { c as selectEditors, i as updateWorkspaceConfig, l as writeEditorConfigs, n as isBingoTemplate, o as detectExistingEditors, r as updatePackageJsonWithDeps, t as detectWorkspace$1 } from "../workspace-Cjoc1c_A.js";
|
|
9
11
|
import { t as renderCliDoc } from "../help-YP84FSEz.js";
|
|
10
12
|
import path from "node:path";
|
|
11
|
-
import { runCommand, vitePlusHeader } from "../../binding/index.js";
|
|
13
|
+
import { runCommand, upsertJsonConfig, vitePlusHeader } from "../../binding/index.js";
|
|
12
14
|
import fs from "node:fs";
|
|
13
15
|
import { styleText } from "node:util";
|
|
14
16
|
import os from "node:os";
|
|
@@ -32,7 +34,7 @@ async function createInitialCommit(cwd) {
|
|
|
32
34
|
cwd,
|
|
33
35
|
envs: process.env
|
|
34
36
|
});
|
|
35
|
-
|
|
37
|
+
const result = await runCommandSilently({
|
|
36
38
|
command: "git",
|
|
37
39
|
args: [
|
|
38
40
|
"commit",
|
|
@@ -41,7 +43,11 @@ async function createInitialCommit(cwd) {
|
|
|
41
43
|
],
|
|
42
44
|
cwd,
|
|
43
45
|
envs: process.env
|
|
44
|
-
})
|
|
46
|
+
});
|
|
47
|
+
return {
|
|
48
|
+
success: result.exitCode === 0,
|
|
49
|
+
output: `${result.stdout.toString()}${result.stderr.toString()}`.trim()
|
|
50
|
+
};
|
|
45
51
|
}
|
|
46
52
|
//#endregion
|
|
47
53
|
//#region src/create/command.ts
|
|
@@ -121,6 +127,220 @@ function prependToPathToEnvs(extraPath, envs) {
|
|
|
121
127
|
return envs;
|
|
122
128
|
}
|
|
123
129
|
//#endregion
|
|
130
|
+
//#region src/create/org-manifest.ts
|
|
131
|
+
/**
|
|
132
|
+
* Parse the org picker specifier: `@scope` (scope only → picker) or
|
|
133
|
+
* `@scope:name` (direct manifest-entry selection). Colon mirrors the
|
|
134
|
+
* existing `vite:monorepo` / `vite:library` builtin-template syntax and
|
|
135
|
+
* keeps manifest entries syntactically distinct from real
|
|
136
|
+
* `@scope/package-name` npm specifiers.
|
|
137
|
+
*
|
|
138
|
+
* Returns `null` for anything else — including the plain `@scope/name`
|
|
139
|
+
* form, which routes to the existing `@scope/create-name` shorthand as
|
|
140
|
+
* it did before the org-manifest feature.
|
|
141
|
+
*
|
|
142
|
+
* The optional `version` suffix (`@scope@1.2.3`, `@scope:name@1.2.3`)
|
|
143
|
+
* pins `@scope/create` to a specific release rather than `dist-tags.latest`.
|
|
144
|
+
*/
|
|
145
|
+
function parseOrgScopedSpec(spec) {
|
|
146
|
+
if (!spec.startsWith("@")) return null;
|
|
147
|
+
if (spec.includes("/")) return null;
|
|
148
|
+
const colonIndex = spec.indexOf(":");
|
|
149
|
+
if (colonIndex === -1) {
|
|
150
|
+
const atIndex = spec.indexOf("@", 1);
|
|
151
|
+
if (atIndex === -1) return { scope: spec };
|
|
152
|
+
const version = spec.slice(atIndex + 1);
|
|
153
|
+
return version ? {
|
|
154
|
+
scope: spec.slice(0, atIndex),
|
|
155
|
+
version
|
|
156
|
+
} : { scope: spec.slice(0, atIndex) };
|
|
157
|
+
}
|
|
158
|
+
const scope = spec.slice(0, colonIndex);
|
|
159
|
+
const rest = spec.slice(colonIndex + 1);
|
|
160
|
+
const atIndex = rest.indexOf("@");
|
|
161
|
+
const name = atIndex === -1 ? rest : rest.slice(0, atIndex);
|
|
162
|
+
const version = atIndex === -1 ? "" : rest.slice(atIndex + 1);
|
|
163
|
+
if (!name) return version ? {
|
|
164
|
+
scope,
|
|
165
|
+
version
|
|
166
|
+
} : { scope };
|
|
167
|
+
return version ? {
|
|
168
|
+
scope,
|
|
169
|
+
name,
|
|
170
|
+
version
|
|
171
|
+
} : {
|
|
172
|
+
scope,
|
|
173
|
+
name
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Schema-level failure. Never falls through silently — a maintainer who
|
|
178
|
+
* shipped an invalid manifest should see the offending field.
|
|
179
|
+
*/
|
|
180
|
+
var OrgManifestSchemaError = class extends Error {
|
|
181
|
+
packageName;
|
|
182
|
+
constructor(message, packageName) {
|
|
183
|
+
super(`${packageName}: ${message}`);
|
|
184
|
+
this.packageName = packageName;
|
|
185
|
+
this.name = "OrgManifestSchemaError";
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
function isRelativePath(spec) {
|
|
189
|
+
return spec.startsWith("./") || spec.startsWith("../");
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Validate the `{ name, description, template }` fields shared by org manifest
|
|
193
|
+
* entries and local `create.templates` entries. `label` is the config path
|
|
194
|
+
* used in error messages (e.g. `createConfig.templates` or `create.templates`)
|
|
195
|
+
* and `makeError` builds the thrown error so each source uses its own type.
|
|
196
|
+
*/
|
|
197
|
+
function validateTemplateEntry(entry, index, label, makeError) {
|
|
198
|
+
if (!entry || typeof entry !== "object") throw makeError(`${label}[${index}] must be an object`);
|
|
199
|
+
const raw = entry;
|
|
200
|
+
const requireString = (field) => {
|
|
201
|
+
const value = raw[field];
|
|
202
|
+
if (typeof value !== "string" || value.length === 0) throw makeError(`${label}[${index}].${field} must be a non-empty string`);
|
|
203
|
+
return value;
|
|
204
|
+
};
|
|
205
|
+
const name = requireString("name");
|
|
206
|
+
if (name.startsWith("__vp_")) throw makeError(`${label}[${index}].name uses the reserved \`__vp_\` prefix`);
|
|
207
|
+
const description = requireString("description");
|
|
208
|
+
const template = requireString("template");
|
|
209
|
+
if (isRelativePath(template)) {
|
|
210
|
+
const resolved = path.posix.resolve("/root", template.replaceAll("\\", "/"));
|
|
211
|
+
if (resolved !== "/root" && !resolved.startsWith("/root/")) throw makeError(`${label}[${index}].template escapes the package root: ${template}`);
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
name,
|
|
215
|
+
description,
|
|
216
|
+
template
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Validate a list of entries, rejecting duplicate `name`s. Shared by org
|
|
221
|
+
* manifests and local `create.templates`.
|
|
222
|
+
*/
|
|
223
|
+
function validateTemplateEntries(templates, label, makeError, validateOne) {
|
|
224
|
+
const entries = [];
|
|
225
|
+
const seen = /* @__PURE__ */ new Set();
|
|
226
|
+
for (let index = 0; index < templates.length; index += 1) {
|
|
227
|
+
const entry = validateOne(templates[index], index);
|
|
228
|
+
if (seen.has(entry.name)) throw makeError(`${label}[${index}].name duplicates an earlier entry: "${entry.name}"`);
|
|
229
|
+
seen.add(entry.name);
|
|
230
|
+
entries.push(entry);
|
|
231
|
+
}
|
|
232
|
+
return entries;
|
|
233
|
+
}
|
|
234
|
+
function validateEntry(entry, index, packageName) {
|
|
235
|
+
const makeError = (message) => new OrgManifestSchemaError(message, packageName);
|
|
236
|
+
const base = validateTemplateEntry(entry, index, "createConfig.templates", makeError);
|
|
237
|
+
let monorepo;
|
|
238
|
+
const raw = entry;
|
|
239
|
+
if (raw.monorepo !== void 0) {
|
|
240
|
+
if (typeof raw.monorepo !== "boolean") throw makeError(`createConfig.templates[${index}].monorepo must be a boolean`);
|
|
241
|
+
monorepo = raw.monorepo;
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
...base,
|
|
245
|
+
...monorepo !== void 0 ? { monorepo } : {}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
function validateManifest(raw, packageName) {
|
|
249
|
+
if (!raw || typeof raw !== "object") return null;
|
|
250
|
+
const createConfig = raw.createConfig;
|
|
251
|
+
if (!createConfig || typeof createConfig !== "object") return null;
|
|
252
|
+
const templates = createConfig.templates;
|
|
253
|
+
if (templates === void 0) return null;
|
|
254
|
+
if (!Array.isArray(templates)) throw new OrgManifestSchemaError("createConfig.templates must be an array", packageName);
|
|
255
|
+
if (templates.length === 0) return null;
|
|
256
|
+
return validateTemplateEntries(templates, "createConfig.templates", (message) => new OrgManifestSchemaError(message, packageName), (entry, index) => validateEntry(entry, index, packageName));
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Schema-level failure for `create.templates` in `vite.config.ts`. A misconfigured
|
|
260
|
+
* local template should surface clearly rather than silently disappear.
|
|
261
|
+
*/
|
|
262
|
+
var CreateConfigSchemaError = class extends Error {
|
|
263
|
+
constructor(message) {
|
|
264
|
+
super(message);
|
|
265
|
+
this.name = "CreateConfigSchemaError";
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
/**
|
|
269
|
+
* Validate `create.templates` from `vite.config.ts`. Returns `[]` when the field
|
|
270
|
+
* is absent or an empty array; throws {@link CreateConfigSchemaError} when present
|
|
271
|
+
* but malformed.
|
|
272
|
+
*/
|
|
273
|
+
function validateCreateTemplates(templates) {
|
|
274
|
+
if (templates === void 0) return [];
|
|
275
|
+
if (!Array.isArray(templates)) throw new CreateConfigSchemaError("create.templates must be an array");
|
|
276
|
+
const makeError = (message) => new CreateConfigSchemaError(message);
|
|
277
|
+
return validateTemplateEntries(templates, "create.templates", makeError, (entry, index) => {
|
|
278
|
+
const validated = validateTemplateEntry(entry, index, "create.templates", makeError);
|
|
279
|
+
if (validated.name.startsWith("vite:")) throw makeError(`create.templates[${index}].name uses the reserved \`vite:\` prefix`);
|
|
280
|
+
return validated;
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
async function fetchPackument(scope, packageName) {
|
|
284
|
+
const response = await fetchNpmResource(`${getNpmRegistry(scope)}/${packageName}`, {
|
|
285
|
+
headers: { accept: "application/json" },
|
|
286
|
+
timeoutMs: 5e3
|
|
287
|
+
});
|
|
288
|
+
if (response.status === 404) return null;
|
|
289
|
+
if (!response.ok) throw new Error(`npm registry responded with ${response.status} for ${packageName}`);
|
|
290
|
+
return await response.json();
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Fetch `@scope/create` from the npm registry and parse its `createConfig.templates`
|
|
294
|
+
* manifest.
|
|
295
|
+
*
|
|
296
|
+
* Returns `null` when:
|
|
297
|
+
* - the package does not exist on the registry (404), or
|
|
298
|
+
* - the package exists but has no `createConfig.templates` field
|
|
299
|
+
*
|
|
300
|
+
* Throws when:
|
|
301
|
+
* - the `createConfig.templates` field is present but malformed (`OrgManifestSchemaError`), or
|
|
302
|
+
* - the registry request fails for any non-404 reason
|
|
303
|
+
*
|
|
304
|
+
* `requestedVersion` pins the lookup to a specific `versions[...]` entry
|
|
305
|
+
* (equivalent to `vp create @scope@1.2.3`); omit it to resolve `dist-tags.latest`.
|
|
306
|
+
*/
|
|
307
|
+
async function readOrgManifest(scope, requestedVersion) {
|
|
308
|
+
if (!scope.startsWith("@")) return null;
|
|
309
|
+
const packageName = `${scope}/create`;
|
|
310
|
+
const packument = await fetchPackument(scope, packageName);
|
|
311
|
+
if (!packument) return null;
|
|
312
|
+
let resolvedVersion;
|
|
313
|
+
if (requestedVersion) {
|
|
314
|
+
resolvedVersion = packument["dist-tags"]?.[requestedVersion] ?? (packument.versions?.[requestedVersion] ? requestedVersion : void 0);
|
|
315
|
+
if (!resolvedVersion) throw new OrgManifestSchemaError(`version "${requestedVersion}" not found (known tags: ${Object.keys(packument["dist-tags"] ?? {}).join(", ") || "none"})`, packageName);
|
|
316
|
+
} else {
|
|
317
|
+
resolvedVersion = packument["dist-tags"]?.latest;
|
|
318
|
+
if (!resolvedVersion) return null;
|
|
319
|
+
}
|
|
320
|
+
const meta = packument.versions?.[resolvedVersion];
|
|
321
|
+
if (!meta) return null;
|
|
322
|
+
const templates = validateManifest(meta, packageName);
|
|
323
|
+
if (!templates) return null;
|
|
324
|
+
if (!meta.dist?.tarball) throw new OrgManifestSchemaError(`missing dist.tarball for ${resolvedVersion}`, packageName);
|
|
325
|
+
return {
|
|
326
|
+
scope,
|
|
327
|
+
packageName,
|
|
328
|
+
version: resolvedVersion,
|
|
329
|
+
tarballUrl: meta.dist.tarball,
|
|
330
|
+
integrity: meta.dist.integrity,
|
|
331
|
+
templates
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Apply the in-monorepo filter rule from the RFC: entries with
|
|
336
|
+
* `monorepo: true` are hidden when the command is invoked inside an
|
|
337
|
+
* existing monorepo, mirroring `initial-template-options.ts:9-31`.
|
|
338
|
+
*/
|
|
339
|
+
function filterManifestForContext(templates, isMonorepo) {
|
|
340
|
+
if (!isMonorepo) return [...templates];
|
|
341
|
+
return templates.filter((entry) => !entry.monorepo);
|
|
342
|
+
}
|
|
343
|
+
//#endregion
|
|
124
344
|
//#region src/create/templates/types.ts
|
|
125
345
|
const LibraryTemplateRepo = "github:sxzz/tsdown-templates/vite-plus";
|
|
126
346
|
const BuiltinTemplate = {
|
|
@@ -151,9 +371,24 @@ function inferGitHubRepoName(templateName) {
|
|
|
151
371
|
if (!degitPath) return null;
|
|
152
372
|
return degitPath.split("/").pop() || null;
|
|
153
373
|
}
|
|
154
|
-
function
|
|
374
|
+
function localTemplateDir(workspaceInfo, templateName) {
|
|
375
|
+
if (isRelativePath(templateName)) return templateName.replace(/^\.\//, "");
|
|
376
|
+
return workspaceInfo.packages.find((pkg) => pkg.name === templateName)?.path;
|
|
377
|
+
}
|
|
378
|
+
function resolveLocalBinPath(localPackagePath, packageName, bin) {
|
|
379
|
+
if (!bin) return;
|
|
380
|
+
if (typeof bin === "string") return path.join(localPackagePath, bin);
|
|
381
|
+
const entries = Object.entries(bin);
|
|
382
|
+
if (entries.length === 0) return;
|
|
383
|
+
if (entries.length === 1) return path.join(localPackagePath, entries[0][1]);
|
|
384
|
+
const unscopedName = packageName.slice(packageName.lastIndexOf("/") + 1);
|
|
385
|
+
const preferred = bin[packageName] ?? bin[unscopedName];
|
|
386
|
+
if (preferred) return path.join(localPackagePath, preferred);
|
|
387
|
+
throw new Error(`Local template package "${packageName}" defines multiple "bin" entries (${entries.map(([name]) => name).join(", ")}); add a "bin" entry named "${packageName}" so the template entry is unambiguous`);
|
|
388
|
+
}
|
|
389
|
+
function discoverTemplate(templateName, templateArgs, workspaceInfo, interactive, bundledLocalPath, skipShorthand, localTemplate) {
|
|
155
390
|
const envs = prependToPathToEnvs(workspaceInfo.downloadPackageManager.binPrefix, { ...process.env });
|
|
156
|
-
const parentDir = inferParentDir(templateName, workspaceInfo);
|
|
391
|
+
const parentDir = inferParentDir(templateName, workspaceInfo, localTemplate);
|
|
157
392
|
if (bundledLocalPath) return {
|
|
158
393
|
command: "",
|
|
159
394
|
args: [...templateArgs],
|
|
@@ -182,23 +417,22 @@ function discoverTemplate(templateName, templateArgs, workspaceInfo, interactive
|
|
|
182
417
|
interactive
|
|
183
418
|
};
|
|
184
419
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
if (
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
420
|
+
if (localTemplate) {
|
|
421
|
+
const localDir = localTemplateDir(workspaceInfo, templateName);
|
|
422
|
+
if (!localDir) throw new Error(`Local template "${templateName}" does not match any workspace package; update the \`create.templates\` entry in vite.config.ts`);
|
|
423
|
+
const localPackagePath = path.join(workspaceInfo.rootDir, localDir);
|
|
424
|
+
const packageJsonPath = path.join(localPackagePath, "package.json");
|
|
425
|
+
if (!fs.existsSync(packageJsonPath)) throw new Error(`Local template "${templateName}" has no package.json, so it cannot be run as a template`);
|
|
426
|
+
const pkg = readJsonFile(packageJsonPath);
|
|
427
|
+
const binPath = resolveLocalBinPath(localPackagePath, pkg.name ?? templateName, pkg.bin);
|
|
428
|
+
if (!binPath) throw new Error(`Local template "${templateName}" has no "bin" entry in its package.json, so it cannot be run as a template`);
|
|
195
429
|
const args = [binPath, ...templateArgs];
|
|
196
430
|
let type = TemplateType.remote;
|
|
197
|
-
if (
|
|
431
|
+
if (isBingoTemplate(pkg)) {
|
|
198
432
|
type = TemplateType.bingo;
|
|
199
433
|
args.push("--skip-requests");
|
|
200
434
|
}
|
|
201
|
-
|
|
435
|
+
return {
|
|
202
436
|
command: "node",
|
|
203
437
|
args,
|
|
204
438
|
envs,
|
|
@@ -261,8 +495,13 @@ function expandCreateShorthand(templateName) {
|
|
|
261
495
|
if (name === "svelte") return `sv${version}`;
|
|
262
496
|
return `create-${name}${version}`;
|
|
263
497
|
}
|
|
264
|
-
function inferParentDir(templateName, workspaceInfo) {
|
|
498
|
+
function inferParentDir(templateName, workspaceInfo, localTemplate = false) {
|
|
265
499
|
if (workspaceInfo.parentDirs.length === 0) return;
|
|
500
|
+
const localDir = localTemplate ? localTemplateDir(workspaceInfo, templateName) : void 0;
|
|
501
|
+
if (localDir) {
|
|
502
|
+
const ownParentDir = path.dirname(localDir);
|
|
503
|
+
if (workspaceInfo.parentDirs.includes(ownParentDir)) return ownParentDir;
|
|
504
|
+
}
|
|
266
505
|
let rule = /app/i;
|
|
267
506
|
if (templateName === BuiltinTemplate.library) rule = /lib|component|package/i;
|
|
268
507
|
else if (templateName === BuiltinTemplate.generator) rule = /generator|tool/i;
|
|
@@ -270,7 +509,7 @@ function inferParentDir(templateName, workspaceInfo) {
|
|
|
270
509
|
}
|
|
271
510
|
//#endregion
|
|
272
511
|
//#region src/create/initial-template-options.ts
|
|
273
|
-
function getInitialTemplateOptions(isMonorepo) {
|
|
512
|
+
function getInitialTemplateOptions(isMonorepo, templates = []) {
|
|
274
513
|
return [
|
|
275
514
|
...!isMonorepo ? [{
|
|
276
515
|
label: "Vite+ Monorepo",
|
|
@@ -286,178 +525,15 @@ function getInitialTemplateOptions(isMonorepo) {
|
|
|
286
525
|
label: "Vite+ Library",
|
|
287
526
|
value: BuiltinTemplate.library,
|
|
288
527
|
hint: "Create vite libraries"
|
|
289
|
-
}
|
|
528
|
+
},
|
|
529
|
+
...isMonorepo ? templates.map((entry) => ({
|
|
530
|
+
label: entry.name,
|
|
531
|
+
value: entry.name,
|
|
532
|
+
hint: entry.description
|
|
533
|
+
})) : []
|
|
290
534
|
];
|
|
291
535
|
}
|
|
292
536
|
//#endregion
|
|
293
|
-
//#region src/create/org-manifest.ts
|
|
294
|
-
/**
|
|
295
|
-
* Parse the org picker specifier: `@scope` (scope only → picker) or
|
|
296
|
-
* `@scope:name` (direct manifest-entry selection). Colon mirrors the
|
|
297
|
-
* existing `vite:monorepo` / `vite:library` builtin-template syntax and
|
|
298
|
-
* keeps manifest entries syntactically distinct from real
|
|
299
|
-
* `@scope/package-name` npm specifiers.
|
|
300
|
-
*
|
|
301
|
-
* Returns `null` for anything else — including the plain `@scope/name`
|
|
302
|
-
* form, which routes to the existing `@scope/create-name` shorthand as
|
|
303
|
-
* it did before the org-manifest feature.
|
|
304
|
-
*
|
|
305
|
-
* The optional `version` suffix (`@scope@1.2.3`, `@scope:name@1.2.3`)
|
|
306
|
-
* pins `@scope/create` to a specific release rather than `dist-tags.latest`.
|
|
307
|
-
*/
|
|
308
|
-
function parseOrgScopedSpec(spec) {
|
|
309
|
-
if (!spec.startsWith("@")) return null;
|
|
310
|
-
if (spec.includes("/")) return null;
|
|
311
|
-
const colonIndex = spec.indexOf(":");
|
|
312
|
-
if (colonIndex === -1) {
|
|
313
|
-
const atIndex = spec.indexOf("@", 1);
|
|
314
|
-
if (atIndex === -1) return { scope: spec };
|
|
315
|
-
const version = spec.slice(atIndex + 1);
|
|
316
|
-
return version ? {
|
|
317
|
-
scope: spec.slice(0, atIndex),
|
|
318
|
-
version
|
|
319
|
-
} : { scope: spec.slice(0, atIndex) };
|
|
320
|
-
}
|
|
321
|
-
const scope = spec.slice(0, colonIndex);
|
|
322
|
-
const rest = spec.slice(colonIndex + 1);
|
|
323
|
-
const atIndex = rest.indexOf("@");
|
|
324
|
-
const name = atIndex === -1 ? rest : rest.slice(0, atIndex);
|
|
325
|
-
const version = atIndex === -1 ? "" : rest.slice(atIndex + 1);
|
|
326
|
-
if (!name) return version ? {
|
|
327
|
-
scope,
|
|
328
|
-
version
|
|
329
|
-
} : { scope };
|
|
330
|
-
return version ? {
|
|
331
|
-
scope,
|
|
332
|
-
name,
|
|
333
|
-
version
|
|
334
|
-
} : {
|
|
335
|
-
scope,
|
|
336
|
-
name
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
/**
|
|
340
|
-
* Schema-level failure. Never falls through silently — a maintainer who
|
|
341
|
-
* shipped an invalid manifest should see the offending field.
|
|
342
|
-
*/
|
|
343
|
-
var OrgManifestSchemaError = class extends Error {
|
|
344
|
-
packageName;
|
|
345
|
-
constructor(message, packageName) {
|
|
346
|
-
super(`${packageName}: ${message}`);
|
|
347
|
-
this.packageName = packageName;
|
|
348
|
-
this.name = "OrgManifestSchemaError";
|
|
349
|
-
}
|
|
350
|
-
};
|
|
351
|
-
function isRelativePath(spec) {
|
|
352
|
-
return spec.startsWith("./") || spec.startsWith("../");
|
|
353
|
-
}
|
|
354
|
-
function validateEntry(entry, index, packageName) {
|
|
355
|
-
if (!entry || typeof entry !== "object") throw new OrgManifestSchemaError(`createConfig.templates[${index}] must be an object`, packageName);
|
|
356
|
-
const raw = entry;
|
|
357
|
-
const requireString = (field) => {
|
|
358
|
-
const value = raw[field];
|
|
359
|
-
if (typeof value !== "string" || value.length === 0) throw new OrgManifestSchemaError(`createConfig.templates[${index}].${field} must be a non-empty string`, packageName);
|
|
360
|
-
return value;
|
|
361
|
-
};
|
|
362
|
-
const name = requireString("name");
|
|
363
|
-
if (name.startsWith("__vp_")) throw new OrgManifestSchemaError(`createConfig.templates[${index}].name uses the reserved \`__vp_\` prefix`, packageName);
|
|
364
|
-
const description = requireString("description");
|
|
365
|
-
const template = requireString("template");
|
|
366
|
-
let monorepo;
|
|
367
|
-
if (raw.monorepo !== void 0) {
|
|
368
|
-
if (typeof raw.monorepo !== "boolean") throw new OrgManifestSchemaError(`createConfig.templates[${index}].monorepo must be a boolean`, packageName);
|
|
369
|
-
monorepo = raw.monorepo;
|
|
370
|
-
}
|
|
371
|
-
if (isRelativePath(template)) {
|
|
372
|
-
const resolved = path.posix.resolve("/root", template.replaceAll("\\", "/"));
|
|
373
|
-
if (resolved !== "/root" && !resolved.startsWith("/root/")) throw new OrgManifestSchemaError(`createConfig.templates[${index}].template escapes the package root: ${template}`, packageName);
|
|
374
|
-
}
|
|
375
|
-
return {
|
|
376
|
-
name,
|
|
377
|
-
description,
|
|
378
|
-
template,
|
|
379
|
-
...monorepo !== void 0 ? { monorepo } : {}
|
|
380
|
-
};
|
|
381
|
-
}
|
|
382
|
-
function validateManifest(raw, packageName) {
|
|
383
|
-
if (!raw || typeof raw !== "object") return null;
|
|
384
|
-
const createConfig = raw.createConfig;
|
|
385
|
-
if (!createConfig || typeof createConfig !== "object") return null;
|
|
386
|
-
const templates = createConfig.templates;
|
|
387
|
-
if (templates === void 0) return null;
|
|
388
|
-
if (!Array.isArray(templates)) throw new OrgManifestSchemaError("createConfig.templates must be an array", packageName);
|
|
389
|
-
if (templates.length === 0) return null;
|
|
390
|
-
const entries = [];
|
|
391
|
-
const seen = /* @__PURE__ */ new Set();
|
|
392
|
-
for (let index = 0; index < templates.length; index += 1) {
|
|
393
|
-
const entry = validateEntry(templates[index], index, packageName);
|
|
394
|
-
if (seen.has(entry.name)) throw new OrgManifestSchemaError(`createConfig.templates[${index}].name duplicates an earlier entry: "${entry.name}"`, packageName);
|
|
395
|
-
seen.add(entry.name);
|
|
396
|
-
entries.push(entry);
|
|
397
|
-
}
|
|
398
|
-
return entries;
|
|
399
|
-
}
|
|
400
|
-
async function fetchPackument(scope, packageName) {
|
|
401
|
-
const response = await fetchNpmResource(`${getNpmRegistry(scope)}/${packageName}`, {
|
|
402
|
-
headers: { accept: "application/json" },
|
|
403
|
-
timeoutMs: 5e3
|
|
404
|
-
});
|
|
405
|
-
if (response.status === 404) return null;
|
|
406
|
-
if (!response.ok) throw new Error(`npm registry responded with ${response.status} for ${packageName}`);
|
|
407
|
-
return await response.json();
|
|
408
|
-
}
|
|
409
|
-
/**
|
|
410
|
-
* Fetch `@scope/create` from the npm registry and parse its `createConfig.templates`
|
|
411
|
-
* manifest.
|
|
412
|
-
*
|
|
413
|
-
* Returns `null` when:
|
|
414
|
-
* - the package does not exist on the registry (404), or
|
|
415
|
-
* - the package exists but has no `createConfig.templates` field
|
|
416
|
-
*
|
|
417
|
-
* Throws when:
|
|
418
|
-
* - the `createConfig.templates` field is present but malformed (`OrgManifestSchemaError`), or
|
|
419
|
-
* - the registry request fails for any non-404 reason
|
|
420
|
-
*
|
|
421
|
-
* `requestedVersion` pins the lookup to a specific `versions[...]` entry
|
|
422
|
-
* (equivalent to `vp create @scope@1.2.3`); omit it to resolve `dist-tags.latest`.
|
|
423
|
-
*/
|
|
424
|
-
async function readOrgManifest(scope, requestedVersion) {
|
|
425
|
-
if (!scope.startsWith("@")) return null;
|
|
426
|
-
const packageName = `${scope}/create`;
|
|
427
|
-
const packument = await fetchPackument(scope, packageName);
|
|
428
|
-
if (!packument) return null;
|
|
429
|
-
let resolvedVersion;
|
|
430
|
-
if (requestedVersion) {
|
|
431
|
-
resolvedVersion = packument["dist-tags"]?.[requestedVersion] ?? (packument.versions?.[requestedVersion] ? requestedVersion : void 0);
|
|
432
|
-
if (!resolvedVersion) throw new OrgManifestSchemaError(`version "${requestedVersion}" not found (known tags: ${Object.keys(packument["dist-tags"] ?? {}).join(", ") || "none"})`, packageName);
|
|
433
|
-
} else {
|
|
434
|
-
resolvedVersion = packument["dist-tags"]?.latest;
|
|
435
|
-
if (!resolvedVersion) return null;
|
|
436
|
-
}
|
|
437
|
-
const meta = packument.versions?.[resolvedVersion];
|
|
438
|
-
if (!meta) return null;
|
|
439
|
-
const templates = validateManifest(meta, packageName);
|
|
440
|
-
if (!templates) return null;
|
|
441
|
-
if (!meta.dist?.tarball) throw new OrgManifestSchemaError(`missing dist.tarball for ${resolvedVersion}`, packageName);
|
|
442
|
-
return {
|
|
443
|
-
scope,
|
|
444
|
-
packageName,
|
|
445
|
-
version: resolvedVersion,
|
|
446
|
-
tarballUrl: meta.dist.tarball,
|
|
447
|
-
integrity: meta.dist.integrity,
|
|
448
|
-
templates
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
/**
|
|
452
|
-
* Apply the in-monorepo filter rule from the RFC: entries with
|
|
453
|
-
* `monorepo: true` are hidden when the command is invoked inside an
|
|
454
|
-
* existing monorepo, mirroring `initial-template-options.ts:9-31`.
|
|
455
|
-
*/
|
|
456
|
-
function filterManifestForContext(templates, isMonorepo) {
|
|
457
|
-
if (!isMonorepo) return [...templates];
|
|
458
|
-
return templates.filter((entry) => !entry.monorepo);
|
|
459
|
-
}
|
|
460
|
-
//#endregion
|
|
461
537
|
//#region src/create/org-picker.ts
|
|
462
538
|
const ORG_PICKER_CANCEL = Symbol("org-picker-cancel");
|
|
463
539
|
const ORG_PICKER_BUILTIN_ESCAPE = Symbol("org-picker-builtin-escape");
|
|
@@ -4136,24 +4212,133 @@ async function resolveOrgManifestForCreate(args) {
|
|
|
4136
4212
|
return resolveEntry(manifest, entry);
|
|
4137
4213
|
}
|
|
4138
4214
|
/**
|
|
4139
|
-
* Read `create
|
|
4215
|
+
* Read the `create` config (`defaultTemplate` + validated `templates`) from
|
|
4216
|
+
* a workspace's `vite.config.ts` in a single config evaluation.
|
|
4140
4217
|
*
|
|
4141
|
-
*
|
|
4142
|
-
* only — `pnpm-workspace.yaml`, `workspaces` in `package.json`,
|
|
4143
|
-
* `lerna.json`) so monorepo invocations from any subdirectory still
|
|
4144
|
-
*
|
|
4145
|
-
*
|
|
4218
|
+
* By default, walks up from `startDir` via `findWorkspaceRoot` (monorepo
|
|
4219
|
+
* markers only — `pnpm-workspace.yaml`, `workspaces` in `package.json`,
|
|
4220
|
+
* `lerna.json`) so monorepo invocations from any subdirectory still pick up
|
|
4221
|
+
* the root config. Pass `walkUp: false` to read `startDir` directly when the
|
|
4222
|
+
* caller already holds the exact workspace root.
|
|
4146
4223
|
*
|
|
4147
|
-
* Best-effort
|
|
4148
|
-
*
|
|
4224
|
+
* Best-effort for resolution: a missing or unresolvable config reads as
|
|
4225
|
+
* empty. A present-but-malformed `create.templates` still throws a
|
|
4226
|
+
* {@link CreateConfigSchemaError} so the misconfiguration surfaces.
|
|
4227
|
+
*
|
|
4228
|
+
* Pass `throwOnReadError: true` for read-modify-write callers (registration):
|
|
4229
|
+
* if a config file exists but cannot be evaluated, an empty read would let a
|
|
4230
|
+
* later write clobber the real `create` block, so the eval error is rethrown
|
|
4231
|
+
* instead of swallowed.
|
|
4232
|
+
*/
|
|
4233
|
+
async function getConfiguredCreate(startDir, options) {
|
|
4234
|
+
const projectRoot = options?.walkUp === false ? startDir : findWorkspaceRoot(startDir) ?? startDir;
|
|
4235
|
+
if (!hasViteConfig(projectRoot)) return { templates: [] };
|
|
4236
|
+
let create;
|
|
4237
|
+
try {
|
|
4238
|
+
create = (await resolveViteConfig(projectRoot)).create;
|
|
4239
|
+
} catch (error) {
|
|
4240
|
+
if (options?.throwOnReadError) throw error;
|
|
4241
|
+
return { templates: [] };
|
|
4242
|
+
}
|
|
4243
|
+
const defaultTemplate = typeof create?.defaultTemplate === "string" && create.defaultTemplate.length > 0 ? create.defaultTemplate : void 0;
|
|
4244
|
+
const templates = validateCreateTemplates(create?.templates);
|
|
4245
|
+
return {
|
|
4246
|
+
...defaultTemplate !== void 0 ? { defaultTemplate } : {},
|
|
4247
|
+
templates
|
|
4248
|
+
};
|
|
4249
|
+
}
|
|
4250
|
+
/**
|
|
4251
|
+
* Read `create.defaultTemplate` only. Best-effort for missing or unresolvable
|
|
4252
|
+
* configs (returns `undefined`), but a malformed `create.templates` still
|
|
4253
|
+
* rethrows its {@link CreateConfigSchemaError}: swallowing it here would
|
|
4254
|
+
* silently drop a valid `defaultTemplate` along with the diagnostic.
|
|
4149
4255
|
*/
|
|
4150
4256
|
async function getConfiguredDefaultTemplate(startDir) {
|
|
4151
|
-
const projectRoot = findWorkspaceRoot(startDir) ?? startDir;
|
|
4152
|
-
if (!hasViteConfig(projectRoot)) return;
|
|
4153
4257
|
try {
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4258
|
+
return (await getConfiguredCreate(startDir)).defaultTemplate;
|
|
4259
|
+
} catch (error) {
|
|
4260
|
+
if (error instanceof CreateConfigSchemaError) throw error;
|
|
4261
|
+
return;
|
|
4262
|
+
}
|
|
4263
|
+
}
|
|
4264
|
+
//#endregion
|
|
4265
|
+
//#region src/create/register-template.ts
|
|
4266
|
+
/**
|
|
4267
|
+
* Register a local template into `create.templates` in a monorepo's root
|
|
4268
|
+
* `vite.config.ts`. Used after `vp create vite:generator` scaffolds a
|
|
4269
|
+
* generator so the generated template shows up in this workspace's
|
|
4270
|
+
* `vp create` picker.
|
|
4271
|
+
*
|
|
4272
|
+
* Behavior:
|
|
4273
|
+
* - Reads the existing `create` config from the workspace root's `vite.config.*`.
|
|
4274
|
+
* - If an entry with the same `name` already exists → no-op (idempotent),
|
|
4275
|
+
* warning when it points at a different `template` so a stale entry does
|
|
4276
|
+
* not silently shadow the new generator.
|
|
4277
|
+
* - Otherwise appends `entry` to `create.templates`, preserving any sibling
|
|
4278
|
+
* `create.defaultTemplate` and any existing entries, and writes back.
|
|
4279
|
+
* - If there is no `vite.config.*` yet, or no `create` block, it is created.
|
|
4280
|
+
*
|
|
4281
|
+
* Read-modify-write: the existing `create` object is read in full first and
|
|
4282
|
+
* the complete, recomputed object is written back via `upsertJsonConfig`
|
|
4283
|
+
* (replace the existing `create` value, or insert the key), so
|
|
4284
|
+
* `defaultTemplate` and prior `templates` are kept. Throws when the config
|
|
4285
|
+
* shape is not supported by the upsert, rather than writing nothing or a key
|
|
4286
|
+
* that is dead at runtime.
|
|
4287
|
+
*
|
|
4288
|
+
* Returns the absolute path of the config file written, so the caller can fold
|
|
4289
|
+
* it into its own formatting pass (the upsert writes a JSON-style block that
|
|
4290
|
+
* needs reformatting). Returns `undefined` for the idempotent no-op.
|
|
4291
|
+
*/
|
|
4292
|
+
async function registerLocalTemplate(workspaceRoot, entry, silent = false) {
|
|
4293
|
+
const configPath = findViteConfig(workspaceRoot);
|
|
4294
|
+
const existing = await getConfiguredCreate(workspaceRoot, {
|
|
4295
|
+
walkUp: false,
|
|
4296
|
+
throwOnReadError: true
|
|
4297
|
+
});
|
|
4298
|
+
const existingEntry = existing.templates.find((t) => t.name === entry.name);
|
|
4299
|
+
if (existingEntry) {
|
|
4300
|
+
if (existingEntry.template !== entry.template) log.warn(`create.templates already has an entry named '${entry.name}' pointing at '${existingEntry.template}'; left unchanged.\nUpdate it by hand if it should run '${entry.template}' instead.`);
|
|
4301
|
+
return;
|
|
4302
|
+
}
|
|
4303
|
+
const nextCreate = {
|
|
4304
|
+
...existing.defaultTemplate !== void 0 ? { defaultTemplate: existing.defaultTemplate } : {},
|
|
4305
|
+
templates: [...existing.templates, entry]
|
|
4306
|
+
};
|
|
4307
|
+
const targetPath = configPath ?? ensureViteConfig(workspaceRoot, silent);
|
|
4308
|
+
writeCreateBlock(targetPath, nextCreate);
|
|
4309
|
+
return targetPath;
|
|
4310
|
+
}
|
|
4311
|
+
/**
|
|
4312
|
+
* Create a minimal `vite.config.ts` (matching the migrator's
|
|
4313
|
+
* `ensureViteConfig` shape) and return its absolute path.
|
|
4314
|
+
*/
|
|
4315
|
+
function ensureViteConfig(workspaceRoot, silent) {
|
|
4316
|
+
const configPath = path.join(workspaceRoot, "vite.config.ts");
|
|
4317
|
+
fs.writeFileSync(configPath, `import { defineConfig } from '${VITE_PLUS_NAME}';\n\nexport default defineConfig({});\n`);
|
|
4318
|
+
if (!silent) log.success(`✔ Created vite.config.ts in ${displayRelative(configPath)}`);
|
|
4319
|
+
return configPath;
|
|
4320
|
+
}
|
|
4321
|
+
/**
|
|
4322
|
+
* Write the full `create` object into vite.config.ts via the shared config
|
|
4323
|
+
* upsert: replace the existing `create:` value in place, or insert the key
|
|
4324
|
+
* when absent. The caller reformats the file afterward, so the JSON-style
|
|
4325
|
+
* block written here is normalized to the surrounding style.
|
|
4326
|
+
*
|
|
4327
|
+
* Throws when the config shape is not supported (`updated: false`, e.g.
|
|
4328
|
+
* `module.exports` or `export default someVar`), so the caller can warn and
|
|
4329
|
+
* point at a manual edit instead of reporting a registration that never
|
|
4330
|
+
* happened.
|
|
4331
|
+
*/
|
|
4332
|
+
function writeCreateBlock(configPath, create) {
|
|
4333
|
+
const tempPath = path.join(os.tmpdir(), `vite-plus-create-register-${randomUUID()}.json`);
|
|
4334
|
+
fs.writeFileSync(tempPath, JSON.stringify(create));
|
|
4335
|
+
try {
|
|
4336
|
+
const result = upsertJsonConfig(configPath, tempPath, "create");
|
|
4337
|
+
if (!result.updated) throw new Error(`could not find a supported config object in ${displayRelative(configPath)}`);
|
|
4338
|
+
fs.writeFileSync(configPath, result.content);
|
|
4339
|
+
} finally {
|
|
4340
|
+
fs.rmSync(tempPath, { force: true });
|
|
4341
|
+
}
|
|
4157
4342
|
}
|
|
4158
4343
|
//#endregion
|
|
4159
4344
|
//#region src/create/templates/generator.ts
|
|
@@ -4448,7 +4633,7 @@ const helpMessage = renderCliDoc({
|
|
|
4448
4633
|
`- Default: ${accent("vite:monorepo")}, ${accent("vite:application")}, ${accent("vite:library")}, ${accent("vite:generator")}`,
|
|
4449
4634
|
"- Remote: vite, @tanstack/start, create-next-app,",
|
|
4450
4635
|
" create-nuxt, github:user/repo, https://github.com/user/template-repo, etc.",
|
|
4451
|
-
"- Local:
|
|
4636
|
+
"- Local: a `create.templates` entry name from vite.config.ts (monorepo)",
|
|
4452
4637
|
`- Org scope: ${accent("@your-org")} → picker from ${accent("@your-org/create")}'s ${accent("createConfig.templates")} manifest`,
|
|
4453
4638
|
`- Org entry: ${accent("@your-org:web")} → manifest entry "web" from ${accent("@your-org/create")}`,
|
|
4454
4639
|
`When omitted, uses \`create.defaultTemplate\` from vite.config.ts if set.`
|
|
@@ -4466,10 +4651,18 @@ const helpMessage = renderCliDoc({
|
|
|
4466
4651
|
label: "--agent NAME",
|
|
4467
4652
|
description: "Write coding agent instructions to AGENTS.md, CLAUDE.md, etc."
|
|
4468
4653
|
},
|
|
4654
|
+
{
|
|
4655
|
+
label: "--no-agent",
|
|
4656
|
+
description: "Skip writing coding agent instructions"
|
|
4657
|
+
},
|
|
4469
4658
|
{
|
|
4470
4659
|
label: "--editor NAME",
|
|
4471
4660
|
description: "Write editor config files for the specified editor."
|
|
4472
4661
|
},
|
|
4662
|
+
{
|
|
4663
|
+
label: "--no-editor",
|
|
4664
|
+
description: "Skip writing editor config files"
|
|
4665
|
+
},
|
|
4473
4666
|
{
|
|
4474
4667
|
label: "--git",
|
|
4475
4668
|
description: "Initialize a git repository with an initial commit"
|
|
@@ -4490,6 +4683,10 @@ const helpMessage = renderCliDoc({
|
|
|
4490
4683
|
label: "--package-manager NAME",
|
|
4491
4684
|
description: "Use specified package manager (pnpm, npm, yarn, bun)"
|
|
4492
4685
|
},
|
|
4686
|
+
{
|
|
4687
|
+
label: "--approve-builds",
|
|
4688
|
+
description: "Approve and run gated dependency build scripts without prompting"
|
|
4689
|
+
},
|
|
4493
4690
|
{
|
|
4494
4691
|
label: "--verbose",
|
|
4495
4692
|
description: "Show detailed scaffolding output"
|
|
@@ -4638,7 +4835,8 @@ function parseArgs() {
|
|
|
4638
4835
|
"interactive",
|
|
4639
4836
|
"hooks",
|
|
4640
4837
|
"verbose",
|
|
4641
|
-
"git"
|
|
4838
|
+
"git",
|
|
4839
|
+
"approve-builds"
|
|
4642
4840
|
],
|
|
4643
4841
|
string: [
|
|
4644
4842
|
"directory",
|
|
@@ -4660,7 +4858,8 @@ function parseArgs() {
|
|
|
4660
4858
|
editor: normalizeEditorOption(parsed.editor),
|
|
4661
4859
|
git: parsed.git,
|
|
4662
4860
|
hooks: parsed.hooks,
|
|
4663
|
-
packageManager: parsed["package-manager"]
|
|
4861
|
+
packageManager: parsed["package-manager"],
|
|
4862
|
+
approveBuilds: parsed["approve-builds"] || false
|
|
4664
4863
|
},
|
|
4665
4864
|
templateArgs
|
|
4666
4865
|
};
|
|
@@ -4770,11 +4969,28 @@ async function main() {
|
|
|
4770
4969
|
let shouldSetupHooks = false;
|
|
4771
4970
|
let bundled;
|
|
4772
4971
|
let skipShorthandExpansion = false;
|
|
4972
|
+
let registeredConfigPath;
|
|
4773
4973
|
const installArgs = process.env.CI ? ["--no-frozen-lockfile"] : void 0;
|
|
4774
|
-
|
|
4775
|
-
|
|
4974
|
+
let localTemplates = [];
|
|
4975
|
+
if (isMonorepo) try {
|
|
4976
|
+
const configuredCreate = await getConfiguredCreate(workspaceInfoOptional.rootDir, { throwOnReadError: true });
|
|
4977
|
+
localTemplates = configuredCreate.templates;
|
|
4978
|
+
if (!selectedTemplateName && configuredCreate.defaultTemplate) selectedTemplateName = configuredCreate.defaultTemplate;
|
|
4979
|
+
} catch (error) {
|
|
4980
|
+
if (error instanceof CreateConfigSchemaError) cancelAndExit(error.message, 1);
|
|
4981
|
+
log.warn(`Could not read \`create\` config from the workspace vite.config (${error.message}); local templates are unavailable`);
|
|
4982
|
+
}
|
|
4983
|
+
else if (!selectedTemplateName) {
|
|
4984
|
+
let defaultTemplate;
|
|
4985
|
+
try {
|
|
4986
|
+
defaultTemplate = await getConfiguredDefaultTemplate(workspaceInfoOptional.rootDir);
|
|
4987
|
+
} catch (error) {
|
|
4988
|
+
if (error instanceof CreateConfigSchemaError) cancelAndExit(error.message, 1);
|
|
4989
|
+
throw error;
|
|
4990
|
+
}
|
|
4776
4991
|
if (defaultTemplate) selectedTemplateName = defaultTemplate;
|
|
4777
4992
|
}
|
|
4993
|
+
let resolvedByOrg = false;
|
|
4778
4994
|
if (selectedTemplateName) {
|
|
4779
4995
|
const resolved = await resolveOrgManifestForCreate({
|
|
4780
4996
|
templateName: selectedTemplateName,
|
|
@@ -4784,8 +5000,11 @@ async function main() {
|
|
|
4784
5000
|
if (resolved.kind === "replaced") {
|
|
4785
5001
|
selectedTemplateName = resolved.templateName;
|
|
4786
5002
|
skipShorthandExpansion = true;
|
|
4787
|
-
|
|
4788
|
-
else if (resolved.kind === "
|
|
5003
|
+
resolvedByOrg = true;
|
|
5004
|
+
} else if (resolved.kind === "bundled") {
|
|
5005
|
+
bundled = resolved;
|
|
5006
|
+
resolvedByOrg = true;
|
|
5007
|
+
} else if (resolved.kind === "escape-hatch") selectedTemplateName = "";
|
|
4789
5008
|
}
|
|
4790
5009
|
if (!selectedTemplateName && !options.interactive) {
|
|
4791
5010
|
console.error(`
|
|
@@ -4804,11 +5023,17 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
4804
5023
|
if (!selectedTemplateName) {
|
|
4805
5024
|
const template = await select({
|
|
4806
5025
|
message: "",
|
|
4807
|
-
options: getInitialTemplateOptions(isMonorepo)
|
|
5026
|
+
options: getInitialTemplateOptions(isMonorepo, localTemplates)
|
|
4808
5027
|
});
|
|
4809
5028
|
if (R(template)) cancelAndExit();
|
|
4810
5029
|
selectedTemplateName = template;
|
|
4811
5030
|
}
|
|
5031
|
+
const matchedLocalTemplate = resolvedByOrg ? void 0 : localTemplates.find((entry) => entry.name === selectedTemplateName);
|
|
5032
|
+
if (matchedLocalTemplate) {
|
|
5033
|
+
selectedTemplateName = matchedLocalTemplate.template;
|
|
5034
|
+
skipShorthandExpansion = true;
|
|
5035
|
+
}
|
|
5036
|
+
const isLocalTemplate = matchedLocalTemplate !== void 0;
|
|
4812
5037
|
const isBuiltinTemplate = selectedTemplateName.startsWith("vite:");
|
|
4813
5038
|
const isBundledTemplate = bundled !== void 0;
|
|
4814
5039
|
const isBundledMonorepo = bundled?.monorepo === true;
|
|
@@ -4823,6 +5048,7 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
4823
5048
|
log.info("The vite:generator template requires a monorepo workspace.\nRun this command inside a Vite+ monorepo, or create one first with `vp create vite:monorepo`");
|
|
4824
5049
|
cancelAndExit("Cannot create a generator outside a monorepo", 1);
|
|
4825
5050
|
}
|
|
5051
|
+
if (isMonorepo && options.git !== void 0) cancelAndExit("The --git/--no-git options are not available when adding a package to an existing monorepo", 1);
|
|
4826
5052
|
if (isInSubdirectory && !compactOutput) log.info(`Detected monorepo root at ${accent(workspaceInfoOptional.rootDir)}`);
|
|
4827
5053
|
if (isMonorepo && options.interactive && !targetDir) {
|
|
4828
5054
|
let parentDir;
|
|
@@ -4845,7 +5071,7 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
4845
5071
|
const selected = await select({
|
|
4846
5072
|
message: "Where should the new package be added to the monorepo:",
|
|
4847
5073
|
options: dirOptions,
|
|
4848
|
-
initialValue: shouldOfferCwdOption ? cwdRelativeToRoot : inferParentDir(selectedTemplateName, workspaceInfoOptional) ?? workspaceInfoOptional.parentDirs[0]
|
|
5074
|
+
initialValue: shouldOfferCwdOption ? cwdRelativeToRoot : inferParentDir(selectedTemplateName, workspaceInfoOptional, isLocalTemplate) ?? workspaceInfoOptional.parentDirs[0]
|
|
4849
5075
|
});
|
|
4850
5076
|
if (R(selected)) cancelAndExit();
|
|
4851
5077
|
if (selected !== "other") parentDir = selected;
|
|
@@ -4865,7 +5091,7 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
4865
5091
|
}
|
|
4866
5092
|
if (isMonorepo && !options.interactive && !targetDir) {
|
|
4867
5093
|
if (isInSubdirectory && !compactOutput) log.info(`Use ${accent("--directory")} to specify a different target location.`);
|
|
4868
|
-
selectedParentDir = inferParentDir(selectedTemplateName, workspaceInfoOptional) ?? workspaceInfoOptional.parentDirs[0];
|
|
5094
|
+
selectedParentDir = inferParentDir(selectedTemplateName, workspaceInfoOptional, isLocalTemplate) ?? workspaceInfoOptional.parentDirs[0];
|
|
4869
5095
|
}
|
|
4870
5096
|
if (isGitHubUrl(selectedTemplateName)) if (hasExplicitTargetDir(selectedTemplateArgs)) remoteTargetDir = selectedTemplateArgs[0];
|
|
4871
5097
|
else {
|
|
@@ -4931,7 +5157,7 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
4931
5157
|
editor: options.editor,
|
|
4932
5158
|
onCancel: () => cancelAndExit()
|
|
4933
5159
|
});
|
|
4934
|
-
const shouldSetupGit = await
|
|
5160
|
+
const shouldSetupGit = await resolveGitInit(options, isMonorepo);
|
|
4935
5161
|
if (!isMonorepo) shouldSetupHooks = await promptGitHooks(options);
|
|
4936
5162
|
const createProgress = options.interactive && compactOutput ? spinner({ indicator: "timer" }) : void 0;
|
|
4937
5163
|
let createProgressStarted = false;
|
|
@@ -4970,8 +5196,28 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
4970
5196
|
createProgressStarted = true;
|
|
4971
5197
|
}
|
|
4972
5198
|
};
|
|
5199
|
+
let migratePendingBuilds = [];
|
|
5200
|
+
const handleIgnoredBuilds = async (projectPath, installCwd, summary) => {
|
|
5201
|
+
if (summary?.status !== "installed") return;
|
|
5202
|
+
const reportedBuilds = [...new Set([...summary.pendingBuilds ?? [], ...migratePendingBuilds])];
|
|
5203
|
+
const targets = resolveApproveBuildTargets(projectPath, await detectGatedBuilds(installCwd, workspaceInfo.packageManager, reportedBuilds), workspaceInfo.packageManager);
|
|
5204
|
+
if (targets.length === 0) return;
|
|
5205
|
+
pauseCreateProgress();
|
|
5206
|
+
const approved = await approveBuilds({
|
|
5207
|
+
cwd: installCwd,
|
|
5208
|
+
projectDir: projectPath,
|
|
5209
|
+
packageManager: workspaceInfo.packageManager,
|
|
5210
|
+
packageManagerVersion: workspaceInfo.downloadPackageManager.version,
|
|
5211
|
+
targets,
|
|
5212
|
+
interactive: options.interactive,
|
|
5213
|
+
autoApprove: options.approveBuilds === true,
|
|
5214
|
+
silent: compactOutput
|
|
5215
|
+
});
|
|
5216
|
+
resumeCreateProgress();
|
|
5217
|
+
if (!approved && !options.interactive && options.approveBuilds === true) process.exitCode = 1;
|
|
5218
|
+
};
|
|
4973
5219
|
updateCreateProgress("Scaffolding project");
|
|
4974
|
-
const templateInfo = discoverTemplate(selectedTemplateName, selectedTemplateArgs, workspaceInfo, options.interactive, bundled?.bundledLocalPath, skipShorthandExpansion);
|
|
5220
|
+
const templateInfo = discoverTemplate(selectedTemplateName, selectedTemplateArgs, workspaceInfo, options.interactive, bundled?.bundledLocalPath, skipShorthandExpansion, isLocalTemplate);
|
|
4975
5221
|
if (selectedParentDir) templateInfo.parentDir = selectedParentDir;
|
|
4976
5222
|
if (targetDir) templateInfo.parentDir = void 0;
|
|
4977
5223
|
if (remoteTargetDir) {
|
|
@@ -4982,7 +5228,7 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
4982
5228
|
}
|
|
4983
5229
|
if (templateInfo.command === BuiltinTemplate.monorepo || isBundledMonorepo) {
|
|
4984
5230
|
let shouldInitGit = shouldSetupGit;
|
|
4985
|
-
if (options.interactive && !compactOutput) {
|
|
5231
|
+
if (options.interactive && !compactOutput && options.git === void 0) {
|
|
4986
5232
|
pauseCreateProgress();
|
|
4987
5233
|
const selected = await confirm({
|
|
4988
5234
|
message: "Initialize git repository:",
|
|
@@ -5061,13 +5307,19 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
5061
5307
|
const installSummary = await runViteInstall(fullPath, options.interactive, installArgs, {
|
|
5062
5308
|
silent: compactOutput,
|
|
5063
5309
|
packageManager: workspaceInfo.packageManager,
|
|
5064
|
-
packageManagerVersion: workspaceInfo.downloadPackageManager.version
|
|
5310
|
+
packageManagerVersion: workspaceInfo.downloadPackageManager.version,
|
|
5311
|
+
detectIgnoredBuilds: true
|
|
5065
5312
|
});
|
|
5313
|
+
await handleIgnoredBuilds(fullPath, fullPath, installSummary);
|
|
5066
5314
|
updateCreateProgress("Formatting code");
|
|
5067
5315
|
await runViteFmt(fullPath, options.interactive, void 0, { silent: compactOutput });
|
|
5068
5316
|
if (shouldSetupGit) {
|
|
5069
5317
|
updateCreateProgress("Creating initial commit");
|
|
5070
|
-
|
|
5318
|
+
const commitResult = await createInitialCommit(fullPath);
|
|
5319
|
+
if (!commitResult.success) {
|
|
5320
|
+
log.warn("Initial commit failed");
|
|
5321
|
+
if (commitResult.output) log.info(commitResult.output);
|
|
5322
|
+
}
|
|
5071
5323
|
}
|
|
5072
5324
|
clearCreateProgress();
|
|
5073
5325
|
showCreateSummary({
|
|
@@ -5123,6 +5375,24 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
5123
5375
|
process.exit(0);
|
|
5124
5376
|
}
|
|
5125
5377
|
const fullPath = path.join(workspaceInfo.rootDir, projectDir);
|
|
5378
|
+
if (selectedTemplateName === BuiltinTemplate.generator && isMonorepo) {
|
|
5379
|
+
updateCreateProgress("Registering generator");
|
|
5380
|
+
pauseCreateProgress();
|
|
5381
|
+
const generatorTemplatePath = `./${projectDir.split(path.sep).join("/")}`;
|
|
5382
|
+
let generatorName = packageName;
|
|
5383
|
+
try {
|
|
5384
|
+
const generatorPkg = readJsonFile(path.join(fullPath, "package.json"));
|
|
5385
|
+
generatorName = generatorPkg.name ?? packageName;
|
|
5386
|
+
if (generatorName) registeredConfigPath = await registerLocalTemplate(workspaceInfo.rootDir, {
|
|
5387
|
+
name: generatorName,
|
|
5388
|
+
description: generatorPkg.description || `Run the ${generatorName} generator`,
|
|
5389
|
+
template: generatorTemplatePath
|
|
5390
|
+
}, compactOutput);
|
|
5391
|
+
} catch (error) {
|
|
5392
|
+
log.warn(`Could not register the generator in create.templates (${error.message}).\nAdd it by hand: { name: '${generatorName || path.basename(projectDir)}', template: '${generatorTemplatePath}' }`);
|
|
5393
|
+
}
|
|
5394
|
+
resumeCreateProgress();
|
|
5395
|
+
}
|
|
5126
5396
|
const agentInstructionsRoot = isMonorepo ? workspaceInfo.rootDir : fullPath;
|
|
5127
5397
|
updateCreateProgress("Writing agent instructions");
|
|
5128
5398
|
pauseCreateProgress();
|
|
@@ -5162,9 +5432,11 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
5162
5432
|
installSummary = await runViteInstall(installCwd, options.interactive, installArgs, {
|
|
5163
5433
|
silent: compactOutput,
|
|
5164
5434
|
packageManager: workspaceInfo.packageManager,
|
|
5165
|
-
packageManagerVersion: workspaceInfo.downloadPackageManager.version
|
|
5435
|
+
packageManagerVersion: workspaceInfo.downloadPackageManager.version,
|
|
5436
|
+
detectIgnoredBuilds: true
|
|
5166
5437
|
});
|
|
5167
5438
|
if (installSummary.status !== "installed") return;
|
|
5439
|
+
if (installSummary.pendingBuilds && installSummary.pendingBuilds.length > 0) migratePendingBuilds = installSummary.pendingBuilds;
|
|
5168
5440
|
updateCreateProgress("Migrating lint and format tools");
|
|
5169
5441
|
pauseCreateProgress();
|
|
5170
5442
|
await promptEslintMigration(fullPath, false);
|
|
@@ -5213,15 +5485,13 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
5213
5485
|
installSummary = await runViteInstall(workspaceInfo.rootDir, options.interactive, installArgs, {
|
|
5214
5486
|
silent: compactOutput,
|
|
5215
5487
|
packageManager: workspaceInfo.packageManager,
|
|
5216
|
-
packageManagerVersion: workspaceInfo.downloadPackageManager.version
|
|
5488
|
+
packageManagerVersion: workspaceInfo.downloadPackageManager.version,
|
|
5489
|
+
detectIgnoredBuilds: true
|
|
5217
5490
|
});
|
|
5491
|
+
await handleIgnoredBuilds(fullPath, workspaceInfo.rootDir, installSummary);
|
|
5218
5492
|
updateCreateProgress("Formatting code");
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
updateCreateProgress("Creating initial commit");
|
|
5222
|
-
await initGitRepository(workspaceInfo.rootDir);
|
|
5223
|
-
await createInitialCommit(workspaceInfo.rootDir);
|
|
5224
|
-
}
|
|
5493
|
+
const fmtPaths = registeredConfigPath ? [projectDir, path.relative(workspaceInfo.rootDir, registeredConfigPath)] : [projectDir];
|
|
5494
|
+
await runViteFmt(workspaceInfo.rootDir, options.interactive, fmtPaths, { silent: compactOutput });
|
|
5225
5495
|
} else {
|
|
5226
5496
|
if (shouldMigrateLintFmtTools) await installAndMigrate(fullPath);
|
|
5227
5497
|
updateCreateProgress("Applying Vite+ project setup");
|
|
@@ -5236,13 +5506,19 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
|
|
|
5236
5506
|
installSummary = await runViteInstall(fullPath, options.interactive, installArgs, {
|
|
5237
5507
|
silent: compactOutput,
|
|
5238
5508
|
packageManager: workspaceInfo.packageManager,
|
|
5239
|
-
packageManagerVersion: workspaceInfo.downloadPackageManager.version
|
|
5509
|
+
packageManagerVersion: workspaceInfo.downloadPackageManager.version,
|
|
5510
|
+
detectIgnoredBuilds: true
|
|
5240
5511
|
});
|
|
5512
|
+
await handleIgnoredBuilds(fullPath, fullPath, installSummary);
|
|
5241
5513
|
updateCreateProgress("Formatting code");
|
|
5242
5514
|
await runViteFmt(fullPath, options.interactive, void 0, { silent: compactOutput });
|
|
5243
5515
|
if (shouldSetupGit) {
|
|
5244
5516
|
updateCreateProgress("Creating initial commit");
|
|
5245
|
-
|
|
5517
|
+
const commitResult = await createInitialCommit(fullPath);
|
|
5518
|
+
if (!commitResult.success) {
|
|
5519
|
+
log.warn("Initial commit failed");
|
|
5520
|
+
if (commitResult.output) log.info(commitResult.output);
|
|
5521
|
+
}
|
|
5246
5522
|
}
|
|
5247
5523
|
}
|
|
5248
5524
|
clearCreateProgress();
|