@kindgi/cli 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -24
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +5 -4
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +84 -13
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/doctor.d.ts +5 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +104 -19
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/guardrails.d.ts.map +1 -1
- package/dist/commands/guardrails.js +13 -2
- package/dist/commands/guardrails.js.map +1 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +4 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +23 -3
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/license.d.ts +3 -0
- package/dist/commands/license.d.ts.map +1 -0
- package/dist/commands/license.js +187 -0
- package/dist/commands/license.js.map +1 -0
- package/dist/commands/mcp.js +1 -1
- package/dist/commands/providers.d.ts.map +1 -1
- package/dist/commands/providers.js +11 -9
- package/dist/commands/providers.js.map +1 -1
- package/dist/commands/test.d.ts.map +1 -1
- package/dist/commands/test.js +21 -9
- package/dist/commands/test.js.map +1 -1
- package/dist/commands/webhooks.d.ts +20 -0
- package/dist/commands/webhooks.d.ts.map +1 -0
- package/dist/commands/webhooks.js +444 -0
- package/dist/commands/webhooks.js.map +1 -0
- package/dist/context.d.ts +4 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +1 -0
- package/dist/context.js.map +1 -1
- package/dist/dev/already-running.d.ts +22 -0
- package/dist/dev/already-running.d.ts.map +1 -0
- package/dist/dev/already-running.js +72 -0
- package/dist/dev/already-running.js.map +1 -0
- package/dist/dev/defaults.d.ts.map +1 -1
- package/dist/dev/defaults.js +5 -2
- package/dist/dev/defaults.js.map +1 -1
- package/dist/dev/dev-lock.d.ts +50 -0
- package/dist/dev/dev-lock.d.ts.map +1 -0
- package/dist/dev/dev-lock.js +203 -0
- package/dist/dev/dev-lock.js.map +1 -0
- package/dist/dev/port.d.ts +6 -2
- package/dist/dev/port.d.ts.map +1 -1
- package/dist/dev/port.js +8 -4
- package/dist/dev/port.js.map +1 -1
- package/dist/dev/providers.d.ts.map +1 -1
- package/dist/dev/providers.js +112 -23
- package/dist/dev/providers.js.map +1 -1
- package/dist/dev/runners.d.ts +21 -2
- package/dist/dev/runners.d.ts.map +1 -1
- package/dist/dev/runtime-container.d.ts +78 -3
- package/dist/dev/runtime-container.d.ts.map +1 -1
- package/dist/dev/runtime-container.js +258 -26
- package/dist/dev/runtime-container.js.map +1 -1
- package/dist/dev/runtime-image.d.ts +4 -3
- package/dist/dev/runtime-image.d.ts.map +1 -1
- package/dist/dev/runtime-image.js +4 -3
- package/dist/dev/runtime-image.js.map +1 -1
- package/dist/dev/runtime-registry.d.ts +0 -9
- package/dist/dev/runtime-registry.d.ts.map +1 -1
- package/dist/dev/runtime-registry.js +12 -2
- package/dist/dev/runtime-registry.js.map +1 -1
- package/dist/dev/start-phases.d.ts +41 -0
- package/dist/dev/start-phases.d.ts.map +1 -0
- package/dist/dev/start-phases.js +103 -0
- package/dist/dev/start-phases.js.map +1 -0
- package/dist/init/augment-scaffolder.d.ts +20 -7
- package/dist/init/augment-scaffolder.d.ts.map +1 -1
- package/dist/init/augment-scaffolder.js +94 -21
- package/dist/init/augment-scaffolder.js.map +1 -1
- package/dist/init/pinning.d.ts +39 -0
- package/dist/init/pinning.d.ts.map +1 -0
- package/dist/init/pinning.js +130 -0
- package/dist/init/pinning.js.map +1 -0
- package/dist/init/template-files.d.ts +1 -1
- package/dist/init/tsconfig-paths.d.ts +29 -0
- package/dist/init/tsconfig-paths.d.ts.map +1 -0
- package/dist/init/tsconfig-paths.js +235 -0
- package/dist/init/tsconfig-paths.js.map +1 -0
- package/dist/init/vitest-setup.d.ts +41 -0
- package/dist/init/vitest-setup.d.ts.map +1 -0
- package/dist/init/vitest-setup.js +163 -0
- package/dist/init/vitest-setup.js.map +1 -0
- package/dist/license/aws.d.ts +24 -0
- package/dist/license/aws.d.ts.map +1 -0
- package/dist/license/aws.js +291 -0
- package/dist/license/aws.js.map +1 -0
- package/dist/license/cloud.d.ts +13 -0
- package/dist/license/cloud.d.ts.map +1 -0
- package/dist/license/cloud.js +193 -0
- package/dist/license/cloud.js.map +1 -0
- package/dist/license/expiry.d.ts +33 -0
- package/dist/license/expiry.d.ts.map +1 -0
- package/dist/license/expiry.js +35 -0
- package/dist/license/expiry.js.map +1 -0
- package/dist/license/license-key.d.ts +32 -0
- package/dist/license/license-key.d.ts.map +1 -0
- package/dist/license/license-key.js +91 -0
- package/dist/license/license-key.js.map +1 -0
- package/dist/license/protocol.d.ts +63 -0
- package/dist/license/protocol.d.ts.map +1 -0
- package/dist/license/protocol.js +102 -0
- package/dist/license/protocol.js.map +1 -0
- package/dist/license/renew.d.ts +59 -0
- package/dist/license/renew.d.ts.map +1 -0
- package/dist/license/renew.js +153 -0
- package/dist/license/renew.js.map +1 -0
- package/dist/license/stores.d.ts +19 -0
- package/dist/license/stores.d.ts.map +1 -0
- package/dist/license/stores.js +150 -0
- package/dist/license/stores.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +1 -0
- package/dist/main.js.map +1 -1
- package/dist/package-manager.d.ts.map +1 -1
- package/dist/package-manager.js +2 -1
- package/dist/package-manager.js.map +1 -1
- package/dist/providers/preset-loader.d.ts +52 -1
- package/dist/providers/preset-loader.d.ts.map +1 -1
- package/dist/providers/preset-loader.js +85 -6
- package/dist/providers/preset-loader.js.map +1 -1
- package/dist/providers/presets/anthropic.json +1 -1
- package/dist/providers/presets/azure-openai.json +65 -0
- package/dist/providers/presets/bedrock.json +102 -0
- package/dist/sdk-skills/kindgi-authoring-agents/SKILL.md +3 -3
- package/dist/sdk-skills/kindgi-authoring-flows/SKILL.md +3 -3
- package/dist/sdk-skills/kindgi-authoring-guardrails/SKILL.md +11 -10
- package/dist/sdk-skills/kindgi-authoring-mcp-servers/SKILL.md +4 -4
- package/dist/sdk-skills/kindgi-authoring-providers/SKILL.md +16 -9
- package/dist/sdk-skills/kindgi-authoring-tools/SKILL.md +9 -11
- package/dist/sdk-skills/kindgi-framework-feedback/SKILL.md +3 -3
- package/dist/sdk-skills/kindgi-getting-started/SKILL.md +28 -5
- package/dist/sdk-skills/kindgi-java-authoring-agents/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-java-authoring-flows/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-java-authoring-guardrails/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-java-authoring-tools/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-java-getting-started/SKILL.md +6 -1
- package/dist/sdk-skills/kindgi-python-authoring-agents/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-python-authoring-flows/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-python-authoring-guardrails/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-python-authoring-tools/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-python-getting-started/SKILL.md +6 -1
- package/dist/sdk-skills/kindgi-scala-authoring-agents/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-scala-authoring-flows/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-scala-authoring-guardrails/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-scala-authoring-tools/SKILL.md +1 -1
- package/dist/sdk-skills/kindgi-scala-getting-started/SKILL.md +6 -1
- package/dist/sdk-skills/kindgi-using/SKILL.md +236 -0
- package/dist/templates/drupal/.nvmrc +1 -0
- package/dist/templates/drupal/AGENTS.md +62 -0
- package/dist/templates/drupal/README.md.tmpl +321 -0
- package/dist/templates/drupal/agents/content-agent/index.test.ts.tmpl +47 -0
- package/dist/templates/drupal/agents/content-agent/index.ts.tmpl +69 -0
- package/dist/templates/drupal/agents/content-reviewer/index.test.ts.tmpl +37 -0
- package/dist/templates/drupal/agents/content-reviewer/index.ts.tmpl +57 -0
- package/dist/templates/drupal/fixtures/node-updated.json +174 -0
- package/dist/templates/drupal/flows/content-review/index.ts.tmpl +66 -0
- package/dist/templates/drupal/gitignore +8 -0
- package/dist/templates/drupal/guardrails/no-contact-details/index.test.ts.tmpl +29 -0
- package/dist/templates/drupal/guardrails/no-contact-details/index.ts.tmpl +73 -0
- package/dist/templates/drupal/kindgi.config.ts.tmpl +41 -0
- package/dist/templates/drupal/lib/drupal.ts.tmpl +64 -0
- package/dist/templates/drupal/package.json.tmpl +31 -0
- package/dist/templates/drupal/pnpm-workspace.yaml +9 -0
- package/dist/templates/drupal/scripts/connect-drupal.mjs.tmpl +57 -0
- package/dist/templates/drupal/tools/check-content-event/index.test.ts.tmpl +72 -0
- package/dist/templates/drupal/tools/check-content-event/index.ts.tmpl +115 -0
- package/dist/templates/drupal/tsconfig.json.tmpl +28 -0
- package/dist/templates/drupal/vitest.config.ts.tmpl +14 -0
- package/dist/templates/java/AGENTS.md +6 -0
- package/dist/templates/java/README.md.tmpl +1 -1
- package/dist/templates/minimal/AGENTS.md +6 -0
- package/dist/templates/minimal/README.md.tmpl +3 -2
- package/dist/templates/minimal/package.json.tmpl +3 -2
- package/dist/templates/python/AGENTS.md +3 -2
- package/dist/templates/sample/AGENTS.md +6 -0
- package/dist/templates/sample/package.json.tmpl +3 -2
- package/dist/templates/scala/AGENTS.md +6 -0
- package/dist/templates/scala/README.md.tmpl +1 -1
- package/dist/templates/woocommerce/.nvmrc +1 -0
- package/dist/templates/woocommerce/AGENTS.md +49 -0
- package/dist/templates/woocommerce/README.md.tmpl +273 -0
- package/dist/templates/woocommerce/agents/order-reviewer/index.test.ts.tmpl +28 -0
- package/dist/templates/woocommerce/agents/order-reviewer/index.ts.tmpl +45 -0
- package/dist/templates/woocommerce/agents/store-agent/index.test.ts.tmpl +47 -0
- package/dist/templates/woocommerce/agents/store-agent/index.ts.tmpl +79 -0
- package/dist/templates/woocommerce/fixtures/order-created.json +67 -0
- package/dist/templates/woocommerce/flows/order-review/index.ts.tmpl +64 -0
- package/dist/templates/woocommerce/gitignore +8 -0
- package/dist/templates/woocommerce/guardrails/no-customer-contact-details/index.test.ts.tmpl +29 -0
- package/dist/templates/woocommerce/guardrails/no-customer-contact-details/index.ts.tmpl +74 -0
- package/dist/templates/woocommerce/kindgi.config.ts.tmpl +41 -0
- package/dist/templates/woocommerce/lib/fake-store.ts.tmpl +82 -0
- package/dist/templates/woocommerce/lib/woo.ts.tmpl +182 -0
- package/dist/templates/woocommerce/package.json.tmpl +30 -0
- package/dist/templates/woocommerce/pnpm-workspace.yaml +9 -0
- package/dist/templates/woocommerce/tools/check-order-event/index.test.ts.tmpl +76 -0
- package/dist/templates/woocommerce/tools/check-order-event/index.ts.tmpl +131 -0
- package/dist/templates/woocommerce/tools/find-orders/index.ts.tmpl +80 -0
- package/dist/templates/woocommerce/tools/publish-product/index.ts.tmpl +34 -0
- package/dist/templates/woocommerce/tools/refund/index.test.ts.tmpl +125 -0
- package/dist/templates/woocommerce/tools/refund/index.ts.tmpl +70 -0
- package/dist/templates/woocommerce/tools/refund-large/index.test.ts.tmpl +53 -0
- package/dist/templates/woocommerce/tools/refund-large/index.ts.tmpl +44 -0
- package/dist/templates/woocommerce/tools/set-price/index.ts.tmpl +36 -0
- package/dist/templates/woocommerce/tsconfig.json.tmpl +28 -0
- package/dist/templates/woocommerce/vitest.config.ts.tmpl +14 -0
- package/dist/test/defaults.d.ts +1 -1
- package/dist/test/defaults.d.ts.map +1 -1
- package/dist/test/defaults.js +2 -7
- package/dist/test/defaults.js.map +1 -1
- package/dist/test/runners.d.ts +6 -0
- package/dist/test/runners.d.ts.map +1 -1
- package/dist/test/runners.js +18 -1
- package/dist/test/runners.js.map +1 -1
- package/package.json +13 -13
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
/**
|
|
4
|
+
* How `kindgi init` writes a third-party dependency it adds to an app
|
|
5
|
+
* (zod; vitest and vite for its tests): at the version Kindgi is tested
|
|
6
|
+
* with, written exactly when the
|
|
7
|
+
* app pins exactly or its package manager saves exact versions, else as a
|
|
8
|
+
* `^` range from that version. Kindgi's own packages are always exact
|
|
9
|
+
* (`dependency-specs.ts`).
|
|
10
|
+
*/
|
|
11
|
+
import { readFile } from 'node:fs/promises';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import semver from 'semver';
|
|
14
|
+
/**
|
|
15
|
+
* The zod Kindgi is tested with: the version the workspace resolves.
|
|
16
|
+
* Bump it with each release; a test checks it against the workspace's zod
|
|
17
|
+
* and `@kindgi/sdk`'s zod range.
|
|
18
|
+
*/
|
|
19
|
+
export const TESTED_ZOD_VERSION = '4.6.5';
|
|
20
|
+
/**
|
|
21
|
+
* The vitest a pack's tests are run with, and the vite it needs (vitest
|
|
22
|
+
* names vite as a peer it doesn't install, so init adds both): what the
|
|
23
|
+
* fresh templates and augment mode write. Bump them with each release
|
|
24
|
+
* after a pack's `kindgi test` passes on them; a test checks the vite is
|
|
25
|
+
* inside vitest's peer range and the templates agree.
|
|
26
|
+
*/
|
|
27
|
+
export const TESTED_VITEST_VERSION = '5.0.3';
|
|
28
|
+
export const TESTED_VITE_VERSION = '8.3.4';
|
|
29
|
+
/** The vites `TESTED_VITEST_VERSION` takes (its `peerDependencies.vite`). */
|
|
30
|
+
export const VITEST_VITE_RANGE = '^6.4.0 || ^7.0.0 || ^8.0.0';
|
|
31
|
+
/** `version` as an app writes it: exact, or a `^` range from it. */
|
|
32
|
+
export function specAt(version, exact) {
|
|
33
|
+
return exact ? version : `^${version}`;
|
|
34
|
+
}
|
|
35
|
+
const PINNED_SECTIONS = ['dependencies', 'devDependencies', 'optionalDependencies'];
|
|
36
|
+
/**
|
|
37
|
+
* Whether the app pins exactly: it has at least one semver spec, and every
|
|
38
|
+
* one is an exact version (`1.2.3`, not `^1.2.3`, `~1.2`, `*`). Specs that
|
|
39
|
+
* aren't semver (`workspace:*`, `catalog:`, `file:`, `npm:…`, a git URL, a
|
|
40
|
+
* tag) say nothing either way, and peer ranges are ranges by nature.
|
|
41
|
+
*/
|
|
42
|
+
export function pinsExactly(pkg) {
|
|
43
|
+
let exact = 0;
|
|
44
|
+
for (const section of PINNED_SECTIONS) {
|
|
45
|
+
const deps = pkg[section];
|
|
46
|
+
if (deps === null || typeof deps !== 'object')
|
|
47
|
+
continue;
|
|
48
|
+
for (const spec of Object.values(deps)) {
|
|
49
|
+
if (typeof spec !== 'string')
|
|
50
|
+
continue;
|
|
51
|
+
const trimmed = spec.trim();
|
|
52
|
+
if (semver.valid(trimmed) !== null)
|
|
53
|
+
exact += 1;
|
|
54
|
+
else if (semver.validRange(trimmed) !== null)
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return exact > 0;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Whether the app's package manager is set to save exact versions:
|
|
62
|
+
* - npm and pnpm: `save-exact=true` or an empty `save-prefix` in the
|
|
63
|
+
* project's `.npmrc`, else in the user's (`~/.npmrc`), the project's
|
|
64
|
+
* winning when it sets either;
|
|
65
|
+
* - pnpm: `saveExact: true` or an empty `savePrefix` in `pnpm-workspace.yaml`;
|
|
66
|
+
* - Yarn (2+): an empty `defaultSemverRangePrefix` in `.yarnrc.yml`;
|
|
67
|
+
* - Bun: `exact = true` under `[install]` in `bunfig.toml`.
|
|
68
|
+
* Only those settings are read: nothing else in these files (a registry
|
|
69
|
+
* token, say) is kept or shown.
|
|
70
|
+
*/
|
|
71
|
+
export async function savesExact(dir, home) {
|
|
72
|
+
const project = npmrcSaveExact(await readText(join(dir, '.npmrc')));
|
|
73
|
+
if (project !== undefined)
|
|
74
|
+
return project;
|
|
75
|
+
if (home !== undefined) {
|
|
76
|
+
const user = npmrcSaveExact(await readText(join(home, '.npmrc')));
|
|
77
|
+
if (user !== undefined)
|
|
78
|
+
return user;
|
|
79
|
+
}
|
|
80
|
+
const pnpm = await readText(join(dir, 'pnpm-workspace.yaml'));
|
|
81
|
+
if (/^\s*saveExact:\s*true\s*$/m.test(pnpm) || /^\s*savePrefix:\s*(''|"")\s*$/m.test(pnpm)) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
const yarn = await readText(join(dir, '.yarnrc.yml'));
|
|
85
|
+
if (/^\s*defaultSemverRangePrefix:\s*(''|"")\s*$/m.test(yarn))
|
|
86
|
+
return true;
|
|
87
|
+
return bunInstallExact(await readText(join(dir, 'bunfig.toml')));
|
|
88
|
+
}
|
|
89
|
+
/** `.npmrc`'s answer: `true`/`false` when it sets `save-exact` or `save-prefix`, else `undefined`. */
|
|
90
|
+
function npmrcSaveExact(text) {
|
|
91
|
+
let saveExact;
|
|
92
|
+
let savePrefix;
|
|
93
|
+
for (const line of text.split(/\r?\n/)) {
|
|
94
|
+
const match = /^\s*(save-exact|save-prefix)\s*=\s*(.*?)\s*$/.exec(line);
|
|
95
|
+
if (match === null)
|
|
96
|
+
continue;
|
|
97
|
+
const value = (match[2] ?? '').replace(/^(['"])(.*)\1$/, '$2');
|
|
98
|
+
if (match[1] === 'save-exact')
|
|
99
|
+
saveExact = value === 'true';
|
|
100
|
+
else
|
|
101
|
+
savePrefix = value;
|
|
102
|
+
}
|
|
103
|
+
if (saveExact === undefined && savePrefix === undefined)
|
|
104
|
+
return undefined;
|
|
105
|
+
// `save-exact=true` wins over any prefix; an empty prefix is exact too.
|
|
106
|
+
return saveExact === true || savePrefix === '';
|
|
107
|
+
}
|
|
108
|
+
/** `exact = true` in `bunfig.toml`'s `[install]` table. */
|
|
109
|
+
function bunInstallExact(text) {
|
|
110
|
+
let inInstall = false;
|
|
111
|
+
for (const line of text.split(/\r?\n/)) {
|
|
112
|
+
const table = /^\s*\[([^\]]+)\]\s*$/.exec(line);
|
|
113
|
+
if (table !== null) {
|
|
114
|
+
inInstall = table[1]?.trim() === 'install';
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (inInstall && /^\s*exact\s*=\s*true\s*(#.*)?$/.test(line))
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
async function readText(path) {
|
|
123
|
+
try {
|
|
124
|
+
return await readFile(path, 'utf8');
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return '';
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=pinning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pinning.js","sourceRoot":"","sources":["../../src/init/pinning.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,7 +30,7 @@ export interface Substitutions {
|
|
|
30
30
|
/**
|
|
31
31
|
* The commands a README shows, as `kindgi init`'s Next steps print them:
|
|
32
32
|
* the install (`pnpm install`), the typecheck script, and how the project
|
|
33
|
-
* runs its `kindgi` (`pnpm exec kindgi`, `npx --no kindgi`, `uv run
|
|
33
|
+
* runs its `kindgi` (`pnpm exec kindgi`, `npx --no -- kindgi`, `uv run
|
|
34
34
|
* kindgi`). Left as placeholders when absent, for a second pass
|
|
35
35
|
* (`fillRunnerPlaceholders`) once the package manager is known.
|
|
36
36
|
*/
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface PathAlias {
|
|
2
|
+
/** The tsconfig pattern: `@/*`, or an exact name. */
|
|
3
|
+
readonly pattern: string;
|
|
4
|
+
/** Where it points, relative to the app's folder, with `/` separators: `src/*`, `../ui/src/*`. */
|
|
5
|
+
readonly target: string;
|
|
6
|
+
}
|
|
7
|
+
export interface TsconfigPaths {
|
|
8
|
+
/** In the order to try them: exact names, then the longest prefix first (TypeScript's choice). */
|
|
9
|
+
readonly aliases: readonly PathAlias[];
|
|
10
|
+
/** What couldn't be carried over as it is, for init's summary. */
|
|
11
|
+
readonly notes: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* `<appDir>/tsconfig.json`'s path aliases. No tsconfig, or one without
|
|
15
|
+
* `paths`: none. `paths` and `baseUrl` come from the nearest config that
|
|
16
|
+
* sets each (the app's own, then what it extends, the last of an array
|
|
17
|
+
* first); targets resolve against `baseUrl`, else the folder of the config
|
|
18
|
+
* that sets `paths`; a leading `${configDir}` is the app's folder, as
|
|
19
|
+
* TypeScript has it. A target list's first entry is used (vitest has no
|
|
20
|
+
* fallback), and a pattern starting with `*` is left out (vitest would
|
|
21
|
+
* send every import, packages too, through it).
|
|
22
|
+
*/
|
|
23
|
+
export declare function readTsconfigPaths(appDir: string): Promise<TsconfigPaths>;
|
|
24
|
+
/**
|
|
25
|
+
* JSON as tsconfig files are written: with `//` and `/* *\/` comments
|
|
26
|
+
* and trailing commas, which TypeScript accepts and `JSON.parse` doesn't.
|
|
27
|
+
*/
|
|
28
|
+
export declare function parseJsonc(text: string): unknown;
|
|
29
|
+
//# sourceMappingURL=tsconfig-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tsconfig-paths.d.ts","sourceRoot":"","sources":["../../src/init/tsconfig-paths.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,SAAS;IACxB,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,kGAAkG;IAClG,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,kGAAkG;IAClG,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IACvC,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAcD;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAkD9E;AAwGD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
/**
|
|
4
|
+
* An app's TypeScript path aliases (`compilerOptions.paths` in its
|
|
5
|
+
* `tsconfig.json`, following `extends`), for the vitest config `kindgi
|
|
6
|
+
* init` adds: vitest doesn't read tsconfig, so without them a tool that
|
|
7
|
+
* imports `@/lib/orders` builds with the app and fails under `kindgi test`.
|
|
8
|
+
* Read once, at init, and written into that config as `resolve.alias`.
|
|
9
|
+
*/
|
|
10
|
+
import { readFile, realpath } from 'node:fs/promises';
|
|
11
|
+
import { createRequire } from 'node:module';
|
|
12
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
13
|
+
const NO_PATHS = { aliases: [], notes: [] };
|
|
14
|
+
/** How deep an `extends` chain is followed. */
|
|
15
|
+
const MAX_EXTENDS_DEPTH = 16;
|
|
16
|
+
/**
|
|
17
|
+
* `<appDir>/tsconfig.json`'s path aliases. No tsconfig, or one without
|
|
18
|
+
* `paths`: none. `paths` and `baseUrl` come from the nearest config that
|
|
19
|
+
* sets each (the app's own, then what it extends, the last of an array
|
|
20
|
+
* first); targets resolve against `baseUrl`, else the folder of the config
|
|
21
|
+
* that sets `paths`; a leading `${configDir}` is the app's folder, as
|
|
22
|
+
* TypeScript has it. A target list's first entry is used (vitest has no
|
|
23
|
+
* fallback), and a pattern starting with `*` is left out (vitest would
|
|
24
|
+
* send every import, packages too, through it).
|
|
25
|
+
*/
|
|
26
|
+
export async function readTsconfigPaths(appDir) {
|
|
27
|
+
// Real paths throughout: a package's tsconfig resolves to one (Node,
|
|
28
|
+
// like TypeScript, follows pnpm's links), and a target is relative to
|
|
29
|
+
// the folder of the config that names it.
|
|
30
|
+
const app = await realOrResolved(appDir);
|
|
31
|
+
const start = join(app, 'tsconfig.json');
|
|
32
|
+
const unread = [];
|
|
33
|
+
const levels = await collectLevels(start, new Set(), 0, unread);
|
|
34
|
+
if (levels === undefined)
|
|
35
|
+
return NO_PATHS;
|
|
36
|
+
const withPaths = levels.find((l) => isRecord(l.compilerOptions.paths));
|
|
37
|
+
if (withPaths === undefined) {
|
|
38
|
+
const notes = unread.map((spec) => `tsconfig.json extends ${spec}, which init couldn't read: any paths it sets aren't in vitest's aliases.`);
|
|
39
|
+
if (levels[0]?.references === true) {
|
|
40
|
+
notes.push("tsconfig.json has project references, and init reads only its own paths: copy any the referenced configs set into vitest's aliases.");
|
|
41
|
+
}
|
|
42
|
+
return { aliases: [], notes };
|
|
43
|
+
}
|
|
44
|
+
const withBaseUrl = levels.find((l) => typeof l.compilerOptions.baseUrl === 'string');
|
|
45
|
+
const base = withBaseUrl !== undefined
|
|
46
|
+
? resolve(withBaseUrl.dir, inConfigDir(withBaseUrl.compilerOptions.baseUrl, app))
|
|
47
|
+
: withPaths.dir;
|
|
48
|
+
const aliases = [];
|
|
49
|
+
const notes = [];
|
|
50
|
+
const paths = withPaths.compilerOptions.paths;
|
|
51
|
+
for (const [pattern, targets] of Object.entries(paths)) {
|
|
52
|
+
if (!Array.isArray(targets))
|
|
53
|
+
continue;
|
|
54
|
+
const first = targets.find((t) => typeof t === 'string');
|
|
55
|
+
if (first === undefined)
|
|
56
|
+
continue;
|
|
57
|
+
if (pattern.startsWith('*')) {
|
|
58
|
+
notes.push(`tsconfig.json's paths map "${pattern}", which would catch every import in vitest, packages too: left out of its aliases.`);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (targets.length > 1) {
|
|
62
|
+
notes.push(`tsconfig.json maps "${pattern}" to ${targets.length} places; vitest's alias takes the first, ${first}.`);
|
|
63
|
+
}
|
|
64
|
+
aliases.push({ pattern, target: fromApp(app, resolve(base, inConfigDir(first, app))) });
|
|
65
|
+
}
|
|
66
|
+
return { aliases: aliases.sort(byPrecedence), notes };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The config at `file` and what it extends, nearest first; `undefined`
|
|
70
|
+
* when `file` can't be read. An `extends` that can't be resolved or read
|
|
71
|
+
* is recorded in `unread` and skipped.
|
|
72
|
+
*/
|
|
73
|
+
async function collectLevels(file, seen, depth, unread) {
|
|
74
|
+
if (seen.has(file) || depth > MAX_EXTENDS_DEPTH)
|
|
75
|
+
return [];
|
|
76
|
+
seen.add(file);
|
|
77
|
+
const parsed = await readJsonc(file);
|
|
78
|
+
if (!isRecord(parsed))
|
|
79
|
+
return undefined;
|
|
80
|
+
const compilerOptions = isRecord(parsed.compilerOptions) ? parsed.compilerOptions : {};
|
|
81
|
+
const levels = [
|
|
82
|
+
{
|
|
83
|
+
dir: dirname(await realOrResolved(file)),
|
|
84
|
+
compilerOptions,
|
|
85
|
+
references: Array.isArray(parsed.references),
|
|
86
|
+
},
|
|
87
|
+
];
|
|
88
|
+
const ext = parsed.extends;
|
|
89
|
+
const specs = typeof ext === 'string' ? [ext] : Array.isArray(ext) ? ext : [];
|
|
90
|
+
// A later entry of an `extends` array overrides an earlier one.
|
|
91
|
+
for (const spec of [...specs].reverse()) {
|
|
92
|
+
if (typeof spec !== 'string')
|
|
93
|
+
continue;
|
|
94
|
+
const target = resolveExtends(spec, file);
|
|
95
|
+
const inner = target === undefined ? undefined : await collectLevels(target, seen, depth + 1, unread);
|
|
96
|
+
if (inner === undefined)
|
|
97
|
+
unread.push(spec);
|
|
98
|
+
else
|
|
99
|
+
levels.push(...inner);
|
|
100
|
+
}
|
|
101
|
+
return levels;
|
|
102
|
+
}
|
|
103
|
+
/** Where an `extends` entry points: a path from the config's folder, or a package's tsconfig. */
|
|
104
|
+
function resolveExtends(spec, from) {
|
|
105
|
+
if (spec.startsWith('./') || spec.startsWith('../') || isAbsolute(spec)) {
|
|
106
|
+
const path = resolve(dirname(from), spec);
|
|
107
|
+
return path.endsWith('.json') ? path : `${path}.json`;
|
|
108
|
+
}
|
|
109
|
+
const require = createRequire(from);
|
|
110
|
+
for (const candidate of [spec, `${spec}/tsconfig.json`, `${spec}.json`]) {
|
|
111
|
+
try {
|
|
112
|
+
return require.resolve(candidate);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// try the next form
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* A path with TypeScript's `${configDir}` (5.5+) at its start made
|
|
122
|
+
* absolute: it names the folder of the tsconfig in use, the app's, even
|
|
123
|
+
* when a config it extends writes it.
|
|
124
|
+
*/
|
|
125
|
+
function inConfigDir(path, app) {
|
|
126
|
+
return path.startsWith(CONFIG_DIR) ? join(app, path.slice(CONFIG_DIR.length)) : path;
|
|
127
|
+
}
|
|
128
|
+
const CONFIG_DIR = '${configDir}';
|
|
129
|
+
/** `path`'s real path, or `path` resolved when it has none. */
|
|
130
|
+
async function realOrResolved(path) {
|
|
131
|
+
try {
|
|
132
|
+
return await realpath(path);
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
return resolve(path);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/** `path` relative to the app's real folder, with `/` separators; the app itself is `.`. */
|
|
139
|
+
function fromApp(app, path) {
|
|
140
|
+
const rel = relative(app, path).split(sep).join('/');
|
|
141
|
+
return rel === '' ? '.' : rel;
|
|
142
|
+
}
|
|
143
|
+
/** Exact names first, then wildcards by the length of what precedes the `*`, longest first. */
|
|
144
|
+
function byPrecedence(a, b) {
|
|
145
|
+
const prefix = (p) => p.includes('*') ? p.indexOf('*') : Number.MAX_SAFE_INTEGER;
|
|
146
|
+
return prefix(b.pattern) - prefix(a.pattern);
|
|
147
|
+
}
|
|
148
|
+
async function readJsonc(path) {
|
|
149
|
+
let text;
|
|
150
|
+
try {
|
|
151
|
+
text = await readFile(path, 'utf8');
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
return parseJsonc(text);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* JSON as tsconfig files are written: with `//` and `/* *\/` comments
|
|
165
|
+
* and trailing commas, which TypeScript accepts and `JSON.parse` doesn't.
|
|
166
|
+
*/
|
|
167
|
+
export function parseJsonc(text) {
|
|
168
|
+
return JSON.parse(withoutTrailingCommas(withoutComments(text.replace(/^/, ''))));
|
|
169
|
+
}
|
|
170
|
+
/** The text with its comments blanked, strings untouched. */
|
|
171
|
+
function withoutComments(text) {
|
|
172
|
+
let out = '';
|
|
173
|
+
let i = 0;
|
|
174
|
+
while (i < text.length) {
|
|
175
|
+
const c = text[i];
|
|
176
|
+
if (c === '"') {
|
|
177
|
+
const end = stringEnd(text, i);
|
|
178
|
+
out += text.slice(i, end);
|
|
179
|
+
i = end;
|
|
180
|
+
}
|
|
181
|
+
else if (c === '/' && (text[i + 1] === '/' || text[i + 1] === '*')) {
|
|
182
|
+
i = commentEnd(text, i);
|
|
183
|
+
out += ' ';
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
out += c;
|
|
187
|
+
i += 1;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return out;
|
|
191
|
+
}
|
|
192
|
+
/** The index just past the comment opening at `start`: a `//` one ends before its newline. */
|
|
193
|
+
function commentEnd(text, start) {
|
|
194
|
+
if (text[start + 1] === '/') {
|
|
195
|
+
const newline = text.indexOf('\n', start);
|
|
196
|
+
return newline === -1 ? text.length : newline;
|
|
197
|
+
}
|
|
198
|
+
const close = text.indexOf('*/', start + 2);
|
|
199
|
+
return close === -1 ? text.length : close + 2;
|
|
200
|
+
}
|
|
201
|
+
/** Whitespace, then a `}` or `]`, from `lastIndex`. */
|
|
202
|
+
const CLOSER_AHEAD = /\s*[}\]]/y;
|
|
203
|
+
/** The text without a `,` that only whitespace separates from a `}` or `]`, strings untouched. */
|
|
204
|
+
function withoutTrailingCommas(text) {
|
|
205
|
+
let out = '';
|
|
206
|
+
let i = 0;
|
|
207
|
+
while (i < text.length) {
|
|
208
|
+
const c = text[i];
|
|
209
|
+
if (c === '"') {
|
|
210
|
+
const end = stringEnd(text, i);
|
|
211
|
+
out += text.slice(i, end);
|
|
212
|
+
i = end;
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
CLOSER_AHEAD.lastIndex = i + 1;
|
|
216
|
+
if (c === ',' && CLOSER_AHEAD.test(text)) {
|
|
217
|
+
i += 1;
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
out += c;
|
|
221
|
+
i += 1;
|
|
222
|
+
}
|
|
223
|
+
return out;
|
|
224
|
+
}
|
|
225
|
+
/** The index just past the string literal opening at `start`. */
|
|
226
|
+
function stringEnd(text, start) {
|
|
227
|
+
let i = start + 1;
|
|
228
|
+
while (i < text.length && text[i] !== '"')
|
|
229
|
+
i += text[i] === '\\' ? 2 : 1;
|
|
230
|
+
return Math.min(i + 1, text.length);
|
|
231
|
+
}
|
|
232
|
+
function isRecord(value) {
|
|
233
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=tsconfig-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tsconfig-paths.js","sourceRoot":"","sources":["../../src/init/tsconfig-paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { WantedDependency } from './package-json-patcher.js';
|
|
2
|
+
import { type PathAlias } from './tsconfig-paths.js';
|
|
3
|
+
/** What `kindgi test` runs in an app Kindgi was added to. */
|
|
4
|
+
export declare const KINDGI_TESTS_GLOB = "kindgi/**/*.test.ts";
|
|
5
|
+
export type VitestSetup = {
|
|
6
|
+
/** Write (or, with --force, rewrite) init's config, and add what it needs. */
|
|
7
|
+
readonly kind: 'write';
|
|
8
|
+
readonly path: string;
|
|
9
|
+
readonly contents: string;
|
|
10
|
+
readonly dependencies: readonly WantedDependency[];
|
|
11
|
+
readonly aliases: readonly PathAlias[];
|
|
12
|
+
readonly notes: readonly string[];
|
|
13
|
+
} | {
|
|
14
|
+
/** init's own config from an earlier run, kept (no --force). */
|
|
15
|
+
readonly kind: 'kept';
|
|
16
|
+
readonly path: string;
|
|
17
|
+
} | {
|
|
18
|
+
/** The app's own vitest setup, left as is; the warning says what `kindgi test` needs. */
|
|
19
|
+
readonly kind: 'app-owned';
|
|
20
|
+
readonly warning: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* What to do about the app's tests:
|
|
24
|
+
* - a vitest config init wrote before: rewritten with --force (its aliases
|
|
25
|
+
* read again), else kept;
|
|
26
|
+
* - the app's own `vitest.config.*`, or vitest without one (`vite.config.*`
|
|
27
|
+
* or vitest's defaults): left as is, with a warning;
|
|
28
|
+
* - else init's config, with vitest and vite pinned as the app pins.
|
|
29
|
+
*/
|
|
30
|
+
export declare function planVitestSetup(args: {
|
|
31
|
+
readonly targetDir: string;
|
|
32
|
+
readonly pkg: Readonly<Record<string, unknown>>;
|
|
33
|
+
/** The app is `"type": "module"`: the config is `.ts`, else `.mts`. */
|
|
34
|
+
readonly esmApp: boolean;
|
|
35
|
+
/** Write exact versions (the app pins exactly, or saves exact). */
|
|
36
|
+
readonly exact: boolean;
|
|
37
|
+
readonly force: boolean;
|
|
38
|
+
}): Promise<VitestSetup>;
|
|
39
|
+
/** The config init writes: Kindgi's tests only, with the app's path aliases. */
|
|
40
|
+
export declare function renderVitestConfig(aliases: readonly PathAlias[]): string;
|
|
41
|
+
//# sourceMappingURL=vitest-setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest-setup.d.ts","sourceRoot":"","sources":["../../src/init/vitest-setup.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAQlE,OAAO,EAAE,KAAK,SAAS,EAAqB,MAAM,qBAAqB,CAAC;AAExE,6DAA6D;AAC7D,eAAO,MAAM,iBAAiB,wBAAwB,CAAC;AAKvD,MAAM,MAAM,WAAW,GACnB;IACE,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACnD,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC,GACD;IACE,gEAAgE;IAChE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,GACD;IACE,yFAAyF;IACzF,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AASN;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAChD,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,GAAG,OAAO,CAAC,WAAW,CAAC,CAqBvB;AA8BD,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,CAgCxE"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
/**
|
|
4
|
+
* The test setup augment-mode `kindgi init` gives an app, so `kindgi test`
|
|
5
|
+
* runs the tests beside its Kindgi primitives: `vitest` and `vite`
|
|
6
|
+
* (vitest's peer, which it doesn't install) in devDependencies, and a
|
|
7
|
+
* vitest config at the app's root (`vitest.config.mts`, `.ts` in a
|
|
8
|
+
* `"type": "module"` app) that runs the `.test.ts` files under `kindgi/`
|
|
9
|
+
* with the app's tsconfig path aliases. An app that runs vitest already keeps its own
|
|
10
|
+
* setup, and init says what `kindgi test` needs from it.
|
|
11
|
+
*/
|
|
12
|
+
import { readFile } from 'node:fs/promises';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
import semver from 'semver';
|
|
15
|
+
import { VITEST_CONFIG_FILENAMES } from '../test/runners.js';
|
|
16
|
+
import { TESTED_VITEST_VERSION, TESTED_VITE_VERSION, VITEST_VITE_RANGE, specAt, } from './pinning.js';
|
|
17
|
+
import { readTsconfigPaths } from './tsconfig-paths.js';
|
|
18
|
+
/** What `kindgi test` runs in an app Kindgi was added to. */
|
|
19
|
+
export const KINDGI_TESTS_GLOB = 'kindgi/**/*.test.ts';
|
|
20
|
+
/** The first line of the config init writes: how a later init knows the file is its own. */
|
|
21
|
+
const HEADER = '// The vitest config for the tests beside your Kindgi primitives, added by';
|
|
22
|
+
const DEPENDENCY_SECTIONS = [
|
|
23
|
+
'dependencies',
|
|
24
|
+
'devDependencies',
|
|
25
|
+
'peerDependencies',
|
|
26
|
+
'optionalDependencies',
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* What to do about the app's tests:
|
|
30
|
+
* - a vitest config init wrote before: rewritten with --force (its aliases
|
|
31
|
+
* read again), else kept;
|
|
32
|
+
* - the app's own `vitest.config.*`, or vitest without one (`vite.config.*`
|
|
33
|
+
* or vitest's defaults): left as is, with a warning;
|
|
34
|
+
* - else init's config, with vitest and vite pinned as the app pins.
|
|
35
|
+
*/
|
|
36
|
+
export async function planVitestSetup(args) {
|
|
37
|
+
for (const name of VITEST_CONFIG_FILENAMES) {
|
|
38
|
+
const path = join(args.targetDir, name);
|
|
39
|
+
const text = await readText(path);
|
|
40
|
+
if (text === undefined)
|
|
41
|
+
continue;
|
|
42
|
+
if (text.startsWith(HEADER)) {
|
|
43
|
+
if (!args.force)
|
|
44
|
+
return { kind: 'kept', path };
|
|
45
|
+
return write(args, path);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
kind: 'app-owned',
|
|
49
|
+
warning: `vitest: the app's own ${name} is left as is, and kindgi test runs it: its test.include needs '${KINDGI_TESTS_GLOB}', and its resolve.alias the tsconfig paths Kindgi's code imports by.`,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (hasDependency(args.pkg, 'vitest')) {
|
|
53
|
+
return {
|
|
54
|
+
kind: 'app-owned',
|
|
55
|
+
warning: `vitest: the app runs vitest without a vitest.config.* (on vite.config.* or vitest's defaults), left as is. kindgi test needs one: a vitest.config.${args.esmApp ? 'ts' : 'mts'} whose test.include has '${KINDGI_TESTS_GLOB}' beside the app's own tests (vitest then reads it instead of vite.config.*).`,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return write(args, join(args.targetDir, args.esmApp ? 'vitest.config.ts' : 'vitest.config.mts'));
|
|
59
|
+
}
|
|
60
|
+
async function write(args, path) {
|
|
61
|
+
const paths = await readTsconfigPaths(args.targetDir);
|
|
62
|
+
const notes = [...viteWarnings(args.pkg), ...paths.notes];
|
|
63
|
+
const { aliases } = paths;
|
|
64
|
+
return {
|
|
65
|
+
kind: 'write',
|
|
66
|
+
path,
|
|
67
|
+
contents: renderVitestConfig(aliases),
|
|
68
|
+
dependencies: [
|
|
69
|
+
{
|
|
70
|
+
name: 'vitest',
|
|
71
|
+
spec: specAt(TESTED_VITEST_VERSION, args.exact),
|
|
72
|
+
section: 'devDependencies',
|
|
73
|
+
},
|
|
74
|
+
{ name: 'vite', spec: specAt(TESTED_VITE_VERSION, args.exact), section: 'devDependencies' },
|
|
75
|
+
],
|
|
76
|
+
aliases,
|
|
77
|
+
notes,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/** The config init writes: Kindgi's tests only, with the app's path aliases. */
|
|
81
|
+
export function renderVitestConfig(aliases) {
|
|
82
|
+
const lines = [
|
|
83
|
+
HEADER,
|
|
84
|
+
'// `kindgi init`: `kindgi test` runs it.',
|
|
85
|
+
...(aliases.length > 0
|
|
86
|
+
? ["import { dirname } from 'node:path';", "import { fileURLToPath } from 'node:url';", '']
|
|
87
|
+
: []),
|
|
88
|
+
"import { defineConfig } from 'vitest/config';",
|
|
89
|
+
'',
|
|
90
|
+
...(aliases.length > 0 ? ['const root = dirname(fileURLToPath(import.meta.url));', ''] : []),
|
|
91
|
+
'export default defineConfig({',
|
|
92
|
+
...(aliases.length > 0
|
|
93
|
+
? [
|
|
94
|
+
' resolve: {',
|
|
95
|
+
" // tsconfig.json's paths, which vitest doesn't read, as `kindgi init`",
|
|
96
|
+
' // found them: when you change those, change these to match.',
|
|
97
|
+
' alias: [',
|
|
98
|
+
...aliases.map((a) => ` { find: ${aliasFind(a.pattern)}, replacement: ${aliasReplacement(a)} },`),
|
|
99
|
+
' ],',
|
|
100
|
+
' },',
|
|
101
|
+
]
|
|
102
|
+
: []),
|
|
103
|
+
' test: {',
|
|
104
|
+
` include: ['${KINDGI_TESTS_GLOB}'],`,
|
|
105
|
+
' passWithNoTests: true,',
|
|
106
|
+
' },',
|
|
107
|
+
'});',
|
|
108
|
+
'',
|
|
109
|
+
];
|
|
110
|
+
return lines.join('\n');
|
|
111
|
+
}
|
|
112
|
+
/** A tsconfig pattern as a regex literal: an exact name, or `prefix*suffix` capturing the `*`. */
|
|
113
|
+
function aliasFind(pattern) {
|
|
114
|
+
const star = pattern.indexOf('*');
|
|
115
|
+
if (star === -1)
|
|
116
|
+
return `/^${escapeRegex(pattern)}$/`;
|
|
117
|
+
return `/^${escapeRegex(pattern.slice(0, star))}(.*)${escapeRegex(pattern.slice(star + 1))}$/`;
|
|
118
|
+
}
|
|
119
|
+
/** The target from the config's folder, as a template literal, with the `*` as the capture. */
|
|
120
|
+
function aliasReplacement(alias) {
|
|
121
|
+
const escaped = alias.target.replace(/[`\\]/g, '\\$&').replace(/\$\{/g, '\\${');
|
|
122
|
+
const target = alias.pattern.includes('*') ? escaped.replace('*', '$1') : escaped;
|
|
123
|
+
return target === '.' ? '`${root}`' : `\`\${root}/${target}\``;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* The app's own vite is kept; one outside vitest's peer range is reported,
|
|
127
|
+
* since installing vitest then fails on its peer. A spec that isn't a
|
|
128
|
+
* semver range is taken on trust.
|
|
129
|
+
*/
|
|
130
|
+
function viteWarnings(pkg) {
|
|
131
|
+
for (const section of DEPENDENCY_SECTIONS) {
|
|
132
|
+
const deps = pkg[section];
|
|
133
|
+
if (deps === null || typeof deps !== 'object')
|
|
134
|
+
continue;
|
|
135
|
+
const spec = deps.vite;
|
|
136
|
+
if (typeof spec !== 'string')
|
|
137
|
+
continue;
|
|
138
|
+
if (semver.validRange(spec) === null || semver.intersects(spec, VITEST_VITE_RANGE))
|
|
139
|
+
return [];
|
|
140
|
+
return [
|
|
141
|
+
`vite: the app has vite ${spec} (${section}), left as is. vitest ${TESTED_VITEST_VERSION}, which kindgi test runs, needs vite ${VITEST_VITE_RANGE}: upgrade vite before installing, or the install stops on vitest's peer.`,
|
|
142
|
+
];
|
|
143
|
+
}
|
|
144
|
+
return [];
|
|
145
|
+
}
|
|
146
|
+
function escapeRegex(text) {
|
|
147
|
+
return text.replace(/[.*+?^${}()|[\]\\/]/g, '\\$&');
|
|
148
|
+
}
|
|
149
|
+
function hasDependency(pkg, name) {
|
|
150
|
+
return DEPENDENCY_SECTIONS.some((section) => {
|
|
151
|
+
const deps = pkg[section];
|
|
152
|
+
return deps !== null && typeof deps === 'object' && name in deps;
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
async function readText(path) {
|
|
156
|
+
try {
|
|
157
|
+
return await readFile(path, 'utf8');
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=vitest-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest-setup.js","sourceRoot":"","sources":["../../src/init/vitest-setup.ts"],"names":[],"mappings":"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"}
|