create-gtkx 1.0.0-rc.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/build-allowance.d.ts +4 -0
- package/dist/build-allowance.d.ts.map +1 -0
- package/dist/build-allowance.js +35 -0
- package/dist/build-allowance.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/command.d.ts +1 -7
- package/dist/command.d.ts.map +1 -1
- package/dist/command.js +0 -6
- package/dist/command.js.map +1 -1
- package/dist/install-hints.d.ts +3 -0
- package/dist/install-hints.d.ts.map +1 -0
- package/dist/install-hints.js +35 -0
- package/dist/install-hints.js.map +1 -0
- package/dist/manifest.d.ts +3 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +13 -0
- package/dist/manifest.js.map +1 -0
- package/dist/package-managers.d.ts +3 -3
- package/dist/package-managers.js +3 -3
- package/dist/package-managers.js.map +1 -1
- package/dist/scaffolder.d.ts.map +1 -1
- package/dist/scaffolder.js +63 -23
- package/dist/scaffolder.js.map +1 -1
- package/dist/templates/package.json.ejs +1 -5
- package/dist/templates/tsconfig.json.ejs +5 -2
- package/package.json +6 -6
- package/src/build-allowance.ts +46 -0
- package/src/cli.ts +1 -1
- package/src/command.ts +1 -7
- package/src/install-hints.ts +54 -0
- package/src/manifest.ts +15 -0
- package/src/package-managers.ts +3 -3
- package/src/scaffolder.ts +82 -28
- package/src/templates/package.json.ejs +1 -5
- package/src/templates/tsconfig.json.ejs +5 -2
package/README.md
CHANGED
|
@@ -108,7 +108,7 @@ React Native and similar frameworks hide the native toolkit so one API can run e
|
|
|
108
108
|
|
|
109
109
|
### Why Node.js, and why generated bindings
|
|
110
110
|
|
|
111
|
-
GTKX runs on Node.js, which puts native modules, the npm ecosystem, and the tooling built for Node.js APIs within reach. GJS is GNOME's own runtime, built on SpiderMonkey rather than V8; node-gtk runs on Node.js but is lightly maintained, on the older nan/V8 ABI rather than N-API, and still centered on GTK3. The [Why GTKX guide](https://gtkx.dev/guide/why-gtkx) covers
|
|
111
|
+
GTKX runs on Node.js, which puts native modules, the npm ecosystem, and the tooling built for Node.js APIs within reach. GJS is GNOME's own runtime, built on SpiderMonkey rather than V8; node-gtk runs on Node.js but is lightly maintained, on the older nan/V8 ABI rather than N-API, and still centered on GTK3. The [Why GTKX guide](https://gtkx.dev/guide/why-gtkx) covers what running on Node.js means day to day.
|
|
112
112
|
|
|
113
113
|
GTKX generates the TypeScript types and the native FFI calls from the same GObject-Introspection data, so the types cannot drift from the calls they back. Codegen covers the whole GTK4 and Adwaita surface.
|
|
114
114
|
|
|
@@ -121,10 +121,10 @@ GTKX is Linux-only and needs Node.js 24 or later. See [Requirements](#requiremen
|
|
|
121
121
|
Scaffold a new app with the `create-gtkx` initializer:
|
|
122
122
|
|
|
123
123
|
```sh
|
|
124
|
-
npm create gtkx
|
|
124
|
+
npm create gtkx
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
-
The same command works with other package managers: `pnpm create gtkx
|
|
127
|
+
The same command works with other package managers: `pnpm create gtkx` or `yarn create gtkx`.
|
|
128
128
|
|
|
129
129
|
Then run your new app:
|
|
130
130
|
|
|
@@ -145,7 +145,7 @@ The documentation at **[gtkx.dev](https://gtkx.dev)** includes a step-by-step tu
|
|
|
145
145
|
|
|
146
146
|
GTKX is Linux-only. You need:
|
|
147
147
|
|
|
148
|
-
- Linux with the GTK4 (4.20 or later), Adwaita (1.8 or later)
|
|
148
|
+
- Linux with the GTK4 (4.20 or later) and GLib development libraries, plus Adwaita (1.8 or later) once your project binds `Adw-1`
|
|
149
149
|
- Node.js 24 or later
|
|
150
150
|
|
|
151
151
|
The `@gtkx/native` addon ships prebuilt for x64 and arm64 glibc Linux; other targets need to build it from the GTKX repository, which requires a Rust toolchain.
|
|
@@ -161,7 +161,7 @@ Explore the [example apps](https://github.com/gtkx-org/gtkx/tree/main/examples):
|
|
|
161
161
|
|
|
162
162
|
## Status
|
|
163
163
|
|
|
164
|
-
GTKX 1.0 is
|
|
164
|
+
GTKX 1.0 is released.
|
|
165
165
|
|
|
166
166
|
## Contributing
|
|
167
167
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-allowance.d.ts","sourceRoot":"","sources":["../src/build-allowance.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AA2B5D,QAAA,MAAM,mBAAmB,GAAI,MAAM,MAAM,EAAE,gBAAgB,cAAc,KAAG,IAc3E,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { updateManifest } from "./manifest.js";
|
|
4
|
+
const BUILT_DEPENDENCIES = ["@swc/core", "esbuild"];
|
|
5
|
+
const PNPM_WORKSPACE_FILE = "pnpm-workspace.yaml";
|
|
6
|
+
const SAFE_YAML_KEY = /^[A-Za-z][A-Za-z0-9-]*$/;
|
|
7
|
+
const PNPM_PACKAGES_BLOCK = "packages:\n - '.'\n";
|
|
8
|
+
const quoteYamlKey = (name) => (SAFE_YAML_KEY.test(name) ? name : `'${name}'`);
|
|
9
|
+
const writePnpmAllowance = (root) => {
|
|
10
|
+
const entries = BUILT_DEPENDENCIES.map((name) => ` ${quoteYamlKey(name)}: true`).join("\n");
|
|
11
|
+
writeFileSync(join(root, PNPM_WORKSPACE_FILE), `${PNPM_PACKAGES_BLOCK}allowBuilds:\n${entries}\n`);
|
|
12
|
+
};
|
|
13
|
+
const writeNpmAllowance = (root) => {
|
|
14
|
+
updateManifest(root, (manifest) => {
|
|
15
|
+
manifest.allowScripts = Object.fromEntries(BUILT_DEPENDENCIES.map((name) => [name, true]));
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
const writeYarnAllowance = (root) => {
|
|
19
|
+
updateManifest(root, (manifest) => {
|
|
20
|
+
manifest.dependenciesMeta = Object.fromEntries(BUILT_DEPENDENCIES.map((name) => [name, { built: true }]));
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
const writeBuildAllowance = (root, packageManager) => {
|
|
24
|
+
if (packageManager === "pnpm") {
|
|
25
|
+
writePnpmAllowance(root);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (packageManager === "yarn") {
|
|
29
|
+
writeYarnAllowance(root);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
writeNpmAllowance(root);
|
|
33
|
+
};
|
|
34
|
+
export { writeBuildAllowance };
|
|
35
|
+
//# sourceMappingURL=build-allowance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-allowance.js","sourceRoot":"","sources":["../src/build-allowance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,kBAAkB,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AACpD,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AAClD,MAAM,aAAa,GAAG,yBAAyB,CAAC;AAChD,MAAM,mBAAmB,GAAG,sBAAsB,CAAC;AAEnD,MAAM,YAAY,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC;AAE/F,MAAM,kBAAkB,GAAG,CAAC,IAAY,EAAQ,EAAE;IAC9C,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7F,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,mBAAmB,CAAC,EAAE,GAAG,mBAAmB,iBAAiB,OAAO,IAAI,CAAC,CAAC;AACvG,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAQ,EAAE;IAC7C,cAAc,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,EAAE;QAC9B,QAAQ,CAAC,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/F,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,IAAY,EAAQ,EAAE;IAC9C,cAAc,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,EAAE;QAC9B,QAAQ,CAAC,gBAAgB,GAAG,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9G,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,IAAY,EAAE,cAA8B,EAAQ,EAAE;IAC/E,IAAI,cAAc,KAAK,MAAM,EAAE,CAAC;QAC5B,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAEzB,OAAO;IACX,CAAC;IAED,IAAI,cAAc,KAAK,MAAM,EAAE,CAAC;QAC5B,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAEzB,OAAO;IACX,CAAC;IAED,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,CAAC","sourcesContent":["import { writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { PackageManager } from \"./package-managers.js\";\nimport { updateManifest } from \"./manifest.js\";\n\nconst BUILT_DEPENDENCIES = [\"@swc/core\", \"esbuild\"];\nconst PNPM_WORKSPACE_FILE = \"pnpm-workspace.yaml\";\nconst SAFE_YAML_KEY = /^[A-Za-z][A-Za-z0-9-]*$/;\nconst PNPM_PACKAGES_BLOCK = \"packages:\\n - '.'\\n\";\n\nconst quoteYamlKey = (name: string): string => (SAFE_YAML_KEY.test(name) ? name : `'${name}'`);\n\nconst writePnpmAllowance = (root: string): void => {\n const entries = BUILT_DEPENDENCIES.map((name) => ` ${quoteYamlKey(name)}: true`).join(\"\\n\");\n writeFileSync(join(root, PNPM_WORKSPACE_FILE), `${PNPM_PACKAGES_BLOCK}allowBuilds:\\n${entries}\\n`);\n};\n\nconst writeNpmAllowance = (root: string): void => {\n updateManifest(root, (manifest) => {\n manifest.allowScripts = Object.fromEntries(BUILT_DEPENDENCIES.map((name) => [name, true]));\n });\n};\n\nconst writeYarnAllowance = (root: string): void => {\n updateManifest(root, (manifest) => {\n manifest.dependenciesMeta = Object.fromEntries(BUILT_DEPENDENCIES.map((name) => [name, { built: true }]));\n });\n};\n\nconst writeBuildAllowance = (root: string, packageManager: PackageManager): void => {\n if (packageManager === \"pnpm\") {\n writePnpmAllowance(root);\n\n return;\n }\n\n if (packageManager === \"yarn\") {\n writeYarnAllowance(root);\n\n return;\n }\n\n writeNpmAllowance(root);\n};\n\nexport { writeBuildAllowance };\n"]}
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { packageVersion } from "@gtkx/utils";
|
|
2
2
|
import { defineCommand, runMain } from "citty";
|
|
3
3
|
import { scaffoldCommand } from "./command.js";
|
|
4
|
-
const version = packageVersion(import.meta.url);
|
|
4
|
+
const version = packageVersion(import.meta.url, "../package.json");
|
|
5
5
|
const main = defineCommand({
|
|
6
6
|
...scaffoldCommand,
|
|
7
7
|
meta: {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;AAEnE,MAAM,IAAI,GAAG,aAAa,CAAC;IACvB,GAAG,eAAe;IAClB,IAAI,EAAE;QACF,IAAI,EAAE,aAAa;QACnB,OAAO;QACP,WAAW,EAAE,iCAAiC;KACjD;CACJ,CAAC,CAAC;AAEH,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC","sourcesContent":["import { packageVersion } from \"@gtkx/utils\";\nimport { defineCommand, runMain } from \"citty\";\nimport { scaffoldCommand } from \"./command.js\";\n\nconst version = packageVersion(import.meta.url, \"../package.json\");\n\nconst main = defineCommand({\n ...scaffoldCommand,\n meta: {\n name: \"create-gtkx\",\n version,\n description: \"Scaffold a new GTKX application\",\n },\n});\n\nvoid runMain(main);\n"]}
|
package/dist/command.d.ts
CHANGED
|
@@ -8,12 +8,6 @@ type CreateCommandArgs = {
|
|
|
8
8
|
"no-interactive"?: boolean | undefined;
|
|
9
9
|
overwrite?: boolean | undefined;
|
|
10
10
|
};
|
|
11
|
-
/**
|
|
12
|
-
* Citty command definition for the CLI `create` subcommand. It declares the
|
|
13
|
-
* scaffolder's arguments (target name, application ID, package manager,
|
|
14
|
-
* TypeScript and Vitest toggles, prompt behavior, and overwrite) and runs the
|
|
15
|
-
* scaffolder to generate a new GTKX application.
|
|
16
|
-
*/
|
|
17
11
|
declare const scaffoldCommand: import("citty").CommandDef<{
|
|
18
12
|
readonly name: {
|
|
19
13
|
readonly type: "positional";
|
|
@@ -54,5 +48,5 @@ declare const scaffoldCommand: import("citty").CommandDef<{
|
|
|
54
48
|
};
|
|
55
49
|
}>;
|
|
56
50
|
declare const runCreate: (args: CreateCommandArgs) => Promise<void>;
|
|
57
|
-
export { scaffoldCommand, runCreate
|
|
51
|
+
export { scaffoldCommand, runCreate };
|
|
58
52
|
//# sourceMappingURL=command.d.ts.map
|
package/dist/command.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAKA,KAAK,iBAAiB,GAAG;IACrB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,GAAG,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACnC,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAKA,KAAK,iBAAiB,GAAG;IACrB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,GAAG,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACnC,CAAC;AAEF,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+CnB,CAAC;AA4BH,QAAA,MAAM,SAAS,GAAU,MAAM,iBAAiB,KAAG,OAAO,CAAC,IAAI,CAiB9D,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC"}
|
package/dist/command.js
CHANGED
|
@@ -2,12 +2,6 @@ import { defineCommand } from "citty";
|
|
|
2
2
|
import { OperationCanceledError, ScaffoldAbortedError } from "./errors.js";
|
|
3
3
|
import { isKnownPackageManager, PACKAGE_MANAGER_FLAG_DESCRIPTION } from "./package-managers.js";
|
|
4
4
|
import { scaffold } from "./scaffolder.js";
|
|
5
|
-
/**
|
|
6
|
-
* Citty command definition for the CLI `create` subcommand. It declares the
|
|
7
|
-
* scaffolder's arguments (target name, application ID, package manager,
|
|
8
|
-
* TypeScript and Vitest toggles, prompt behavior, and overwrite) and runs the
|
|
9
|
-
* scaffolder to generate a new GTKX application.
|
|
10
|
-
*/
|
|
11
5
|
const scaffoldCommand = defineCommand({
|
|
12
6
|
meta: {
|
|
13
7
|
name: "create",
|
package/dist/command.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,gCAAgC,EAAuB,MAAM,uBAAuB,CAAC;AACrH,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAa3C
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"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","sourcesContent":["import { defineCommand } from \"citty\";\nimport { OperationCanceledError, ScaffoldAbortedError } from \"./errors.js\";\nimport { isKnownPackageManager, PACKAGE_MANAGER_FLAG_DESCRIPTION, type PackageManager } from \"./package-managers.js\";\nimport { scaffold } from \"./scaffolder.js\";\n\ntype CreateCommandArgs = {\n name?: string | undefined;\n \"application-id\"?: string | undefined;\n \"package-manager\"?: string | undefined;\n typescript?: boolean | undefined;\n vitest?: boolean | undefined;\n yes?: boolean | undefined;\n \"no-interactive\"?: boolean | undefined;\n overwrite?: boolean | undefined;\n};\n\nconst scaffoldCommand = defineCommand({\n meta: {\n name: \"create\",\n description: \"Create a new GTKX application\",\n },\n args: {\n name: {\n type: \"positional\",\n description: \"Target directory or project name (e.g. my-app, ., apps/my-app)\",\n required: false,\n },\n \"application-id\": {\n type: \"string\",\n description: \"Application ID (e.g., com.example.myapp)\",\n },\n \"package-manager\": {\n type: \"string\",\n alias: \"pm\",\n description: PACKAGE_MANAGER_FLAG_DESCRIPTION,\n },\n typescript: {\n type: \"boolean\",\n negativeDescription: \"Scaffold the application in JavaScript instead of TypeScript\",\n description: \"Scaffold the application in TypeScript\",\n },\n vitest: {\n type: \"boolean\",\n description: \"Include a Vitest testing setup\",\n },\n yes: {\n type: \"boolean\",\n alias: \"y\",\n description: \"Skip prompts and accept defaults for unspecified options\",\n },\n \"no-interactive\": {\n type: \"boolean\",\n description:\n \"Run without prompts, using the default for every option not passed on the command line \" +\n \"(same as --yes)\",\n },\n overwrite: {\n type: \"boolean\",\n alias: \"force\",\n description: \"Overwrite the contents of a non-empty target directory when running without prompts\",\n },\n },\n run: ({ args }) => runCreate(args),\n});\n\nconst parsePackageManager = (value: string | undefined): PackageManager | undefined => {\n if (value === undefined) {\n return undefined;\n }\n\n if (!isKnownPackageManager(value)) {\n throw new Error(`Unknown package manager \"${value}\". Expected one of: ${PACKAGE_MANAGER_FLAG_DESCRIPTION}.`);\n }\n\n return value;\n};\n\nconst settleScaffoldFailure = (error: unknown): void => {\n if (error instanceof OperationCanceledError) {\n return;\n }\n\n if (error instanceof ScaffoldAbortedError) {\n process.exitCode = 1;\n\n return;\n }\n\n throw error;\n};\n\nconst runCreate = async (args: CreateCommandArgs): Promise<void> => {\n const isInteractive = args[\"no-interactive\"] || args.yes ? false : process.stdin.isTTY;\n const packageManager = parsePackageManager(args[\"package-manager\"]);\n\n try {\n await scaffold({\n name: args.name,\n applicationId: args[\"application-id\"],\n packageManager,\n isTypescript: args.typescript,\n shouldIncludeTesting: args.vitest,\n isInteractive,\n shouldOverwrite: args.overwrite,\n });\n } catch (error) {\n settleScaffoldFailure(error);\n }\n};\n\nexport { scaffoldCommand, runCreate };\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-hints.d.ts","sourceRoot":"","sources":["../src/install-hints.ts"],"names":[],"mappings":"AAkDA,QAAA,MAAM,cAAc,GAAI,SAAS,MAAM,KAAG,MAAM,GAAG,SAC4B,CAAC;AAEhF,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const RELEASE_AGE_PATTERN = /ERR_PNPM_(?:MINIMUM_RELEASE_AGE_VIOLATION|NO_MATURE_MATCHING_VERSION)/;
|
|
2
|
+
const BLOCKED_VERSION_PATTERN = /^[ \t]*(\S+) was published at .+ within the minimumReleaseAge cutoff/gm;
|
|
3
|
+
const RELEASE_AGE_POLICY = "pnpm refused the install under its minimumReleaseAge policy, which by default holds back every package " +
|
|
4
|
+
"published in the last 24 hours so a compromised release has time to be caught and pulled. Nothing is wrong " +
|
|
5
|
+
"with these versions other than their age.";
|
|
6
|
+
const RELEASE_AGE_REMEDY = "Wait for them to clear that window and install again, or allow the versions pnpm named. They belong at the " +
|
|
7
|
+
"top level of pnpm-workspace.yaml, as a sibling of packages: and allowBuilds: rather than nested inside " +
|
|
8
|
+
"either of them:";
|
|
9
|
+
const RELEASE_AGE_REMEDY_WITHOUT_VERSIONS = "Wait for them to clear that window and install again, or list the versions pnpm reported under a top-level " +
|
|
10
|
+
"minimumReleaseAgeExclude key in pnpm-workspace.yaml.";
|
|
11
|
+
const RELEASE_AGE_PARTIAL_LIST = "pnpm reports only the versions the command it stopped on had to resolve, so a later install can name more. " +
|
|
12
|
+
"Add each one to the same list.";
|
|
13
|
+
const RELEASE_AGE_OPT_OUT = 'Listing exact versions keeps the policy on for every other package. Setting "minimumReleaseAge: 0" in the ' +
|
|
14
|
+
"same file turns it off for all of them, so prefer the list above. npm and yarn apply no such policy.";
|
|
15
|
+
const getBlockedVersions = (message) => {
|
|
16
|
+
const matches = Array.from(message.matchAll(BLOCKED_VERSION_PATTERN), (match) => match[1] ?? "");
|
|
17
|
+
return [...new Set(matches.filter(Boolean))];
|
|
18
|
+
};
|
|
19
|
+
const formatExcludeBlock = (versions) => ["minimumReleaseAgeExclude:", ...versions.map((version) => ` - '${version}'`)].join("\n");
|
|
20
|
+
const describeReleaseAge = (message) => {
|
|
21
|
+
const versions = getBlockedVersions(message);
|
|
22
|
+
if (versions.length === 0) {
|
|
23
|
+
return [RELEASE_AGE_POLICY, RELEASE_AGE_REMEDY_WITHOUT_VERSIONS].join("\n\n");
|
|
24
|
+
}
|
|
25
|
+
return [
|
|
26
|
+
RELEASE_AGE_POLICY,
|
|
27
|
+
RELEASE_AGE_REMEDY,
|
|
28
|
+
formatExcludeBlock(versions),
|
|
29
|
+
RELEASE_AGE_PARTIAL_LIST,
|
|
30
|
+
RELEASE_AGE_OPT_OUT,
|
|
31
|
+
].join("\n\n");
|
|
32
|
+
};
|
|
33
|
+
const getInstallHint = (message) => RELEASE_AGE_PATTERN.test(message) ? describeReleaseAge(message) : undefined;
|
|
34
|
+
export { getInstallHint };
|
|
35
|
+
//# sourceMappingURL=install-hints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-hints.js","sourceRoot":"","sources":["../src/install-hints.ts"],"names":[],"mappings":"AAAA,MAAM,mBAAmB,GAAG,uEAAuE,CAAC;AACpG,MAAM,uBAAuB,GAAG,wEAAwE,CAAC;AAEzG,MAAM,kBAAkB,GACpB,yGAAyG;IACzG,6GAA6G;IAC7G,2CAA2C,CAAC;AAEhD,MAAM,kBAAkB,GACpB,6GAA6G;IAC7G,yGAAyG;IACzG,iBAAiB,CAAC;AAEtB,MAAM,mCAAmC,GACrC,6GAA6G;IAC7G,sDAAsD,CAAC;AAE3D,MAAM,wBAAwB,GAC1B,6GAA6G;IAC7G,gCAAgC,CAAC;AAErC,MAAM,mBAAmB,GACrB,4GAA4G;IAC5G,sGAAsG,CAAC;AAE3G,MAAM,kBAAkB,GAAG,CAAC,OAAe,EAAY,EAAE;IACrD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAEjG,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,QAAkB,EAAU,EAAE,CACtD,CAAC,2BAA2B,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAE/F,MAAM,kBAAkB,GAAG,CAAC,OAAe,EAAU,EAAE;IACnD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAE7C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,kBAAkB,EAAE,mCAAmC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClF,CAAC;IAED,OAAO;QACH,kBAAkB;QAClB,kBAAkB;QAClB,kBAAkB,CAAC,QAAQ,CAAC;QAC5B,wBAAwB;QACxB,mBAAmB;KACtB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,OAAe,EAAsB,EAAE,CAC3D,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAEhF,OAAO,EAAE,cAAc,EAAE,CAAC","sourcesContent":["const RELEASE_AGE_PATTERN = /ERR_PNPM_(?:MINIMUM_RELEASE_AGE_VIOLATION|NO_MATURE_MATCHING_VERSION)/;\nconst BLOCKED_VERSION_PATTERN = /^[ \\t]*(\\S+) was published at .+ within the minimumReleaseAge cutoff/gm;\n\nconst RELEASE_AGE_POLICY =\n \"pnpm refused the install under its minimumReleaseAge policy, which by default holds back every package \" +\n \"published in the last 24 hours so a compromised release has time to be caught and pulled. Nothing is wrong \" +\n \"with these versions other than their age.\";\n\nconst RELEASE_AGE_REMEDY =\n \"Wait for them to clear that window and install again, or allow the versions pnpm named. They belong at the \" +\n \"top level of pnpm-workspace.yaml, as a sibling of packages: and allowBuilds: rather than nested inside \" +\n \"either of them:\";\n\nconst RELEASE_AGE_REMEDY_WITHOUT_VERSIONS =\n \"Wait for them to clear that window and install again, or list the versions pnpm reported under a top-level \" +\n \"minimumReleaseAgeExclude key in pnpm-workspace.yaml.\";\n\nconst RELEASE_AGE_PARTIAL_LIST =\n \"pnpm reports only the versions the command it stopped on had to resolve, so a later install can name more. \" +\n \"Add each one to the same list.\";\n\nconst RELEASE_AGE_OPT_OUT =\n 'Listing exact versions keeps the policy on for every other package. Setting \"minimumReleaseAge: 0\" in the ' +\n \"same file turns it off for all of them, so prefer the list above. npm and yarn apply no such policy.\";\n\nconst getBlockedVersions = (message: string): string[] => {\n const matches = Array.from(message.matchAll(BLOCKED_VERSION_PATTERN), (match) => match[1] ?? \"\");\n\n return [...new Set(matches.filter(Boolean))];\n};\n\nconst formatExcludeBlock = (versions: string[]): string =>\n [\"minimumReleaseAgeExclude:\", ...versions.map((version) => ` - '${version}'`)].join(\"\\n\");\n\nconst describeReleaseAge = (message: string): string => {\n const versions = getBlockedVersions(message);\n\n if (versions.length === 0) {\n return [RELEASE_AGE_POLICY, RELEASE_AGE_REMEDY_WITHOUT_VERSIONS].join(\"\\n\\n\");\n }\n\n return [\n RELEASE_AGE_POLICY,\n RELEASE_AGE_REMEDY,\n formatExcludeBlock(versions),\n RELEASE_AGE_PARTIAL_LIST,\n RELEASE_AGE_OPT_OUT,\n ].join(\"\\n\\n\");\n};\n\nconst getInstallHint = (message: string): string | undefined =>\n RELEASE_AGE_PATTERN.test(message) ? describeReleaseAge(message) : undefined;\n\nexport { getInstallHint };\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAKA,QAAA,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,KAAG,IAO3F,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
const PACKAGE_JSON_FILE = "package.json";
|
|
4
|
+
const updateManifest = (root, mutate) => {
|
|
5
|
+
const manifestPath = join(root, PACKAGE_JSON_FILE);
|
|
6
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
7
|
+
mutate(manifest);
|
|
8
|
+
const pendingPath = `${manifestPath}.pending`;
|
|
9
|
+
writeFileSync(pendingPath, `${JSON.stringify(manifest, null, 4)}\n`);
|
|
10
|
+
renameSync(pendingPath, manifestPath);
|
|
11
|
+
};
|
|
12
|
+
export { updateManifest };
|
|
13
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAEzC,MAAM,cAAc,GAAG,CAAC,IAAY,EAAE,MAAmD,EAAQ,EAAE;IAC/F,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAA4B,CAAC;IAC3F,MAAM,CAAC,QAAQ,CAAC,CAAC;IACjB,MAAM,WAAW,GAAG,GAAG,YAAY,UAAU,CAAC;IAC9C,aAAa,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACrE,UAAU,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;AAC1C,CAAC,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,CAAC","sourcesContent":["import { readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst PACKAGE_JSON_FILE = \"package.json\";\n\nconst updateManifest = (root: string, mutate: (manifest: Record<string, unknown>) => void): void => {\n const manifestPath = join(root, PACKAGE_JSON_FILE);\n const manifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as Record<string, unknown>;\n mutate(manifest);\n const pendingPath = `${manifestPath}.pending`;\n writeFileSync(pendingPath, `${JSON.stringify(manifest, null, 4)}\\n`);\n renameSync(pendingPath, manifestPath);\n};\n\nexport { updateManifest };\n"]}
|
|
@@ -3,19 +3,19 @@ declare const PACKAGE_MANAGERS: readonly [{
|
|
|
3
3
|
readonly value: "pnpm";
|
|
4
4
|
readonly label: "pnpm";
|
|
5
5
|
readonly devCommand: "pnpm dev";
|
|
6
|
-
readonly
|
|
6
|
+
readonly addCommand: "pnpm add";
|
|
7
7
|
readonly isRecommended: true;
|
|
8
8
|
}, {
|
|
9
9
|
readonly value: "npm";
|
|
10
10
|
readonly label: "npm";
|
|
11
11
|
readonly devCommand: "npm run dev";
|
|
12
|
-
readonly
|
|
12
|
+
readonly addCommand: "npm install";
|
|
13
13
|
readonly isRecommended: false;
|
|
14
14
|
}, {
|
|
15
15
|
readonly value: "yarn";
|
|
16
16
|
readonly label: "yarn";
|
|
17
17
|
readonly devCommand: "yarn dev";
|
|
18
|
-
readonly
|
|
18
|
+
readonly addCommand: "yarn add";
|
|
19
19
|
readonly isRecommended: false;
|
|
20
20
|
}];
|
|
21
21
|
declare const PACKAGE_MANAGER_FLAG_DESCRIPTION: string;
|
package/dist/package-managers.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const PACKAGE_MANAGERS = [
|
|
2
|
-
{ value: "pnpm", label: "pnpm", devCommand: "pnpm dev",
|
|
3
|
-
{ value: "npm", label: "npm", devCommand: "npm run dev",
|
|
4
|
-
{ value: "yarn", label: "yarn", devCommand: "yarn dev",
|
|
2
|
+
{ value: "pnpm", label: "pnpm", devCommand: "pnpm dev", addCommand: "pnpm add", isRecommended: true },
|
|
3
|
+
{ value: "npm", label: "npm", devCommand: "npm run dev", addCommand: "npm install", isRecommended: false },
|
|
4
|
+
{ value: "yarn", label: "yarn", devCommand: "yarn dev", addCommand: "yarn add", isRecommended: false },
|
|
5
5
|
];
|
|
6
6
|
const PACKAGE_MANAGER_VALUES = PACKAGE_MANAGERS.map((manager) => manager.value);
|
|
7
7
|
const PACKAGE_MANAGER_FLAG_DESCRIPTION = `Package manager (${PACKAGE_MANAGER_VALUES.join(", ")})`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-managers.js","sourceRoot":"","sources":["../src/package-managers.ts"],"names":[],"mappings":"AAEA,MAAM,gBAAgB,GAAG;IACrB,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"package-managers.js","sourceRoot":"","sources":["../src/package-managers.ts"],"names":[],"mappings":"AAEA,MAAM,gBAAgB,GAAG;IACrB,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,IAAI,EAAE;IACrG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,EAAE;IAC1G,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,KAAK,EAAE;CAChG,CAAC;AAEX,MAAM,sBAAsB,GAAqB,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAClG,MAAM,gCAAgC,GAAG,oBAAoB,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AAElG,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAA0B,EAAE,CAClE,sBAAmC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAExD,OAAO,EAAE,gBAAgB,EAAE,gCAAgC,EAAE,qBAAqB,EAAuB,CAAC","sourcesContent":["type PackageManager = (typeof PACKAGE_MANAGERS)[number][\"value\"];\n\nconst PACKAGE_MANAGERS = [\n { value: \"pnpm\", label: \"pnpm\", devCommand: \"pnpm dev\", addCommand: \"pnpm add\", isRecommended: true },\n { value: \"npm\", label: \"npm\", devCommand: \"npm run dev\", addCommand: \"npm install\", isRecommended: false },\n { value: \"yarn\", label: \"yarn\", devCommand: \"yarn dev\", addCommand: \"yarn add\", isRecommended: false },\n] as const;\n\nconst PACKAGE_MANAGER_VALUES: PackageManager[] = PACKAGE_MANAGERS.map((manager) => manager.value);\nconst PACKAGE_MANAGER_FLAG_DESCRIPTION = `Package manager (${PACKAGE_MANAGER_VALUES.join(\", \")})`;\n\nconst isKnownPackageManager = (name: string): name is PackageManager =>\n (PACKAGE_MANAGER_VALUES as string[]).includes(name);\n\nexport { PACKAGE_MANAGERS, PACKAGE_MANAGER_FLAG_DESCRIPTION, isKnownPackageManager, type PackageManager };\n"]}
|
package/dist/scaffolder.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffolder.d.ts","sourceRoot":"","sources":["../src/scaffolder.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scaffolder.d.ts","sourceRoot":"","sources":["../src/scaffolder.ts"],"names":[],"mappings":"AAWA,OAAO,EAA2C,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAIrG,KAAK,aAAa,GAAG;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,cAAc,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IAC5C,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,oBAAoB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3C,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACzC,CAAC;AAwfF,QAAA,MAAM,QAAQ,GAAU,UAAS,aAAkB,KAAG,OAAO,CAAC,IAAI,CAwBjE,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,CAAC"}
|
package/dist/scaffolder.js
CHANGED
|
@@ -1,35 +1,39 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
2
|
import { isValidApplicationId } from "@gtkx/config/internal";
|
|
3
3
|
import { errorMessage, packageVersion, upperFirst } from "@gtkx/utils";
|
|
4
|
-
import { existsSync, mkdirSync, readdirSync,
|
|
4
|
+
import { existsSync, mkdirSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { basename, dirname, join, resolve } from "node:path";
|
|
6
6
|
import { addDependency, detectPackageManager as nypmDetectPackageManager } from "nypm";
|
|
7
7
|
import { x } from "tinyexec";
|
|
8
|
+
import { writeBuildAllowance } from "./build-allowance.js";
|
|
8
9
|
import { OperationCanceledError, ScaffoldAbortedError } from "./errors.js";
|
|
10
|
+
import { getInstallHint } from "./install-hints.js";
|
|
11
|
+
import { updateManifest } from "./manifest.js";
|
|
9
12
|
import { isKnownPackageManager, PACKAGE_MANAGERS } from "./package-managers.js";
|
|
10
13
|
import { isValidProjectName } from "./project-name.js";
|
|
11
14
|
import { listTemplates, renderFile } from "./templates.js";
|
|
12
|
-
const selfVersion = packageVersion(import.meta.url);
|
|
15
|
+
const selfVersion = packageVersion(import.meta.url, "../package.json");
|
|
13
16
|
const GTKX_ENV_MODULE_HEADER = `/**
|
|
14
17
|
* Generated by \`gtkx codegen\`, \`gtkx dev\`, and \`gtkx build\`; do not edit.
|
|
15
18
|
*/`;
|
|
16
19
|
const DEPENDENCIES = ["@gtkx/css", "@gtkx/runtime", "@gtkx/react", "react"];
|
|
17
|
-
const DEV_DEPENDENCIES = ["@gtkx/cli", "@gtkx/config", "vite"];
|
|
20
|
+
const DEV_DEPENDENCIES = ["@gtkx/cli", "@gtkx/config", "@gtkx/mcp", "vite"];
|
|
18
21
|
const TYPESCRIPT_DEV_DEPENDENCIES = ["@types/node", "@types/react", "typescript"];
|
|
19
22
|
const TESTING_DEV_DEPENDENCIES = ["@gtkx/testing", "vitest"];
|
|
20
23
|
const DEV_COMMAND = Object.fromEntries(PACKAGE_MANAGERS.map((manager) => [manager.value, manager.devCommand]));
|
|
21
|
-
const
|
|
24
|
+
const ADD_COMMAND = Object.fromEntries(PACKAGE_MANAGERS.map((manager) => [manager.value, manager.addCommand]));
|
|
25
|
+
const INHERITED_SCRIPT_POLICY_VARS = ["npm_config_allow_scripts", "npm_config_allow-scripts"];
|
|
22
26
|
const TESTING_TEMPLATES = new Set(["vitest.config.ts", "tests/app.test.tsx"]);
|
|
23
27
|
const TYPESCRIPT_TEMPLATES = new Set(["tsconfig.json", "src/gtkx-env.d.ts"]);
|
|
24
|
-
const PACKAGE_JSON_TEMPLATE = "package.json";
|
|
25
28
|
const HEADLESS_COMPOSITOR_NOTE = `
|
|
26
29
|
|
|
27
30
|
To run tests, you need a headless Wayland compositor installed:
|
|
28
31
|
Fedora: sudo dnf install sway
|
|
29
32
|
Ubuntu: sudo apt install sway`;
|
|
33
|
+
const RECOVERY_HEADING = "Finish the setup by adding the dependencies again, which is safe to repeat:";
|
|
30
34
|
const pinGtkxDependency = (name, version) => name.startsWith("@gtkx/") ? `${name}@^${version}` : name;
|
|
31
35
|
const getDevCommand = (packageManager) => DEV_COMMAND[packageManager];
|
|
32
|
-
const
|
|
36
|
+
const getAddCommand = (packageManager) => ADD_COMMAND[packageManager];
|
|
33
37
|
const titleFromName = (name) => name.split("-").map((part) => upperFirst(part)).join(" ");
|
|
34
38
|
const suggestApplicationId = (name) => `com.${name.replaceAll("-", "")}.app`;
|
|
35
39
|
const stripTrailingSlashes = (value) => {
|
|
@@ -141,11 +145,11 @@ const promptPackageManager = async () => {
|
|
|
141
145
|
initialValue: initial,
|
|
142
146
|
}));
|
|
143
147
|
};
|
|
144
|
-
const
|
|
148
|
+
const shouldUseTypeScript = async () => guardCancellation(await p.confirm({
|
|
145
149
|
message: "Use TypeScript?",
|
|
146
150
|
initialValue: true,
|
|
147
151
|
}));
|
|
148
|
-
const
|
|
152
|
+
const shouldSetUpTesting = async () => guardCancellation(await p.confirm({
|
|
149
153
|
message: "Include testing setup (Vitest)?",
|
|
150
154
|
initialValue: true,
|
|
151
155
|
}));
|
|
@@ -167,7 +171,7 @@ const validateResolvedOptions = (name, applicationId) => {
|
|
|
167
171
|
fail(applicationIdError);
|
|
168
172
|
}
|
|
169
173
|
};
|
|
170
|
-
const
|
|
174
|
+
const shouldOverwriteDirectory = async (target, options) => {
|
|
171
175
|
if (!options.isInteractive) {
|
|
172
176
|
return options.shouldOverwrite === true;
|
|
173
177
|
}
|
|
@@ -180,7 +184,7 @@ const handleTargetDirectory = async (root, target, options) => {
|
|
|
180
184
|
if (!existsSync(root) || isDirEmpty(root)) {
|
|
181
185
|
return;
|
|
182
186
|
}
|
|
183
|
-
if (await
|
|
187
|
+
if (await shouldOverwriteDirectory(target, options)) {
|
|
184
188
|
emptyDir(root);
|
|
185
189
|
return;
|
|
186
190
|
}
|
|
@@ -210,17 +214,17 @@ const resolvePackageManager = async (options) => {
|
|
|
210
214
|
}
|
|
211
215
|
return (await detectedPackageManager()) ?? "pnpm";
|
|
212
216
|
};
|
|
213
|
-
const
|
|
217
|
+
const isTypescriptSelected = async (options) => {
|
|
214
218
|
if (options.isTypescript !== undefined) {
|
|
215
219
|
return options.isTypescript;
|
|
216
220
|
}
|
|
217
|
-
return options.isInteractive ?
|
|
221
|
+
return options.isInteractive ? shouldUseTypeScript() : true;
|
|
218
222
|
};
|
|
219
|
-
const
|
|
223
|
+
const isTestingIncluded = async (options) => {
|
|
220
224
|
if (options.shouldIncludeTesting !== undefined) {
|
|
221
225
|
return options.shouldIncludeTesting;
|
|
222
226
|
}
|
|
223
|
-
return options.isInteractive ?
|
|
227
|
+
return options.isInteractive ? shouldSetUpTesting() : true;
|
|
224
228
|
};
|
|
225
229
|
const resolveOptions = async (options) => {
|
|
226
230
|
const target = await resolveTarget(options);
|
|
@@ -230,8 +234,8 @@ const resolveOptions = async (options) => {
|
|
|
230
234
|
const root = resolve(process.cwd(), target);
|
|
231
235
|
await handleTargetDirectory(root, target, options);
|
|
232
236
|
const packageManager = await resolvePackageManager(options);
|
|
233
|
-
const isTypescript = await
|
|
234
|
-
const shouldIncludeTesting = await
|
|
237
|
+
const isTypescript = await isTypescriptSelected(options);
|
|
238
|
+
const shouldIncludeTesting = await isTestingIncluded(options);
|
|
235
239
|
return { target, name, applicationId, packageManager, isTypescript, shouldIncludeTesting };
|
|
236
240
|
};
|
|
237
241
|
const isTemplateIncluded = (templateRelativePath, resolved) => {
|
|
@@ -245,10 +249,9 @@ const isTemplateIncluded = (templateRelativePath, resolved) => {
|
|
|
245
249
|
};
|
|
246
250
|
const toDestinationPath = (templateRelativePath, isTypescript) => isTypescript ? templateRelativePath : templateRelativePath.replace(/\.tsx$/, ".jsx").replace(/\.ts$/, ".js");
|
|
247
251
|
const addTestScript = (root) => {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
writeFileSync(packageJsonPath, `${JSON.stringify(manifest, null, 4)}\n`);
|
|
252
|
+
updateManifest(root, (manifest) => {
|
|
253
|
+
manifest.scripts.test = "vitest run";
|
|
254
|
+
});
|
|
252
255
|
};
|
|
253
256
|
const scaffoldProject = async (root, resolved) => {
|
|
254
257
|
const { name, applicationId, isTypescript, shouldIncludeTesting } = resolved;
|
|
@@ -273,11 +276,48 @@ const scaffoldProject = async (root, resolved) => {
|
|
|
273
276
|
addTestScript(root);
|
|
274
277
|
}
|
|
275
278
|
};
|
|
279
|
+
const withoutInheritedScriptPolicy = async (run) => {
|
|
280
|
+
const saved = INHERITED_SCRIPT_POLICY_VARS.map((key) => [key, process.env[key]]);
|
|
281
|
+
for (const [key] of saved) {
|
|
282
|
+
Reflect.deleteProperty(process.env, key);
|
|
283
|
+
}
|
|
284
|
+
try {
|
|
285
|
+
await run();
|
|
286
|
+
}
|
|
287
|
+
finally {
|
|
288
|
+
for (const [key, value] of saved) {
|
|
289
|
+
if (value !== undefined) {
|
|
290
|
+
process.env[key] = value;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
};
|
|
276
295
|
const installDependencies = async (options) => {
|
|
277
296
|
const { cwd, packageManager, dependencies, isDev } = options;
|
|
278
|
-
await
|
|
297
|
+
await withoutInheritedScriptPolicy(async () => {
|
|
298
|
+
await addDependency(dependencies, { cwd, packageManager, dev: isDev, silent: true });
|
|
299
|
+
});
|
|
279
300
|
};
|
|
280
301
|
const pin = (names) => names.map((dependency) => pinGtkxDependency(dependency, selfVersion));
|
|
302
|
+
const formatRecovery = ({ target, packageManager, devDependencies }) => {
|
|
303
|
+
const add = getAddCommand(packageManager);
|
|
304
|
+
const steps = [
|
|
305
|
+
...(target === "." ? [] : [`cd ${target}`]),
|
|
306
|
+
`${add} ${pin(DEPENDENCIES).join(" ")}`,
|
|
307
|
+
`${add} -D ${pin(devDependencies).join(" ")}`,
|
|
308
|
+
];
|
|
309
|
+
const indented = steps.map((step) => ` ${step}`).join("\n");
|
|
310
|
+
return `${RECOVERY_HEADING}\n${indented}`;
|
|
311
|
+
};
|
|
312
|
+
const reportInstallFailure = (options) => {
|
|
313
|
+
const message = errorMessage(options.error);
|
|
314
|
+
p.log.error(`Failed to install dependencies: ${message}`);
|
|
315
|
+
const hint = getInstallHint(message);
|
|
316
|
+
if (hint !== undefined) {
|
|
317
|
+
p.log.warn(hint);
|
|
318
|
+
}
|
|
319
|
+
p.log.info(formatRecovery(options));
|
|
320
|
+
};
|
|
281
321
|
const installAllDependencies = async (options) => {
|
|
282
322
|
const { root, target, packageManager, devDependencies } = options;
|
|
283
323
|
const spinner = p.spinner();
|
|
@@ -289,8 +329,7 @@ const installAllDependencies = async (options) => {
|
|
|
289
329
|
}
|
|
290
330
|
catch (error) {
|
|
291
331
|
spinner.stop("Failed to install dependencies");
|
|
292
|
-
|
|
293
|
-
p.log.info(`Install them manually by running:\n cd ${target}\n ${getInstallCommand(packageManager)}`);
|
|
332
|
+
reportInstallFailure({ error, target, packageManager, devDependencies });
|
|
294
333
|
throw new ScaffoldAbortedError("Failed to install dependencies");
|
|
295
334
|
}
|
|
296
335
|
};
|
|
@@ -327,6 +366,7 @@ const scaffold = async (options = {}) => {
|
|
|
327
366
|
const projectSpinner = p.spinner();
|
|
328
367
|
projectSpinner.start("Creating project structure...");
|
|
329
368
|
await scaffoldProject(root, resolved);
|
|
369
|
+
writeBuildAllowance(root, resolved.packageManager);
|
|
330
370
|
projectSpinner.stop("Project structure created");
|
|
331
371
|
await installAllDependencies({
|
|
332
372
|
root,
|
package/dist/scaffolder.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffolder.js","sourceRoot":"","sources":["../src/scaffolder.ts"],"names":[],"mappings":"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","sourcesContent":["import * as p from \"@clack/prompts\";\nimport { isValidApplicationId } from \"@gtkx/config/internal\";\nimport { errorMessage, packageVersion, upperFirst } from \"@gtkx/utils\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { addDependency, detectPackageManager as nypmDetectPackageManager } from \"nypm\";\nimport { x } from \"tinyexec\";\nimport { OperationCanceledError, ScaffoldAbortedError } from \"./errors.js\";\nimport { isKnownPackageManager, PACKAGE_MANAGERS, type PackageManager } from \"./package-managers.js\";\nimport { isValidProjectName } from \"./project-name.js\";\nimport { listTemplates, renderFile, type TemplateContext } from \"./templates.js\";\n\ntype CreateOptions = {\n name?: string | undefined;\n applicationId?: string | undefined;\n packageManager?: PackageManager | undefined;\n isTypescript?: boolean | undefined;\n shouldIncludeTesting?: boolean | undefined;\n isInteractive?: boolean | undefined;\n shouldOverwrite?: boolean | undefined;\n};\n\ntype ResolvedOptions = {\n target: string;\n name: string;\n applicationId: string;\n packageManager: PackageManager;\n isTypescript: boolean;\n shouldIncludeTesting: boolean;\n};\n\ntype InstallDependenciesOptions = {\n cwd: string;\n packageManager: PackageManager;\n dependencies: string[];\n isDev: boolean;\n};\n\ntype InstallAllOptions = {\n root: string;\n target: string;\n packageManager: PackageManager;\n devDependencies: string[];\n};\n\nconst selfVersion = packageVersion(import.meta.url);\n\nconst GTKX_ENV_MODULE_HEADER = `/**\n * Generated by \\`gtkx codegen\\`, \\`gtkx dev\\`, and \\`gtkx build\\`; do not edit.\n */`;\n\nconst DEPENDENCIES = [\"@gtkx/css\", \"@gtkx/runtime\", \"@gtkx/react\", \"react\"];\nconst DEV_DEPENDENCIES = [\"@gtkx/cli\", \"@gtkx/config\", \"vite\"];\nconst TYPESCRIPT_DEV_DEPENDENCIES = [\"@types/node\", \"@types/react\", \"typescript\"];\nconst TESTING_DEV_DEPENDENCIES = [\"@gtkx/testing\", \"vitest\"];\n\nconst DEV_COMMAND: Record<PackageManager, string> = Object.fromEntries(\n PACKAGE_MANAGERS.map((manager) => [manager.value, manager.devCommand]),\n) as Record<PackageManager, string>;\n\nconst INSTALL_COMMAND: Record<PackageManager, string> = Object.fromEntries(\n PACKAGE_MANAGERS.map((manager) => [manager.value, manager.installCommand]),\n) as Record<PackageManager, string>;\n\nconst TESTING_TEMPLATES = new Set([\"vitest.config.ts\", \"tests/app.test.tsx\"]);\nconst TYPESCRIPT_TEMPLATES = new Set([\"tsconfig.json\", \"src/gtkx-env.d.ts\"]);\nconst PACKAGE_JSON_TEMPLATE = \"package.json\";\n\nconst HEADLESS_COMPOSITOR_NOTE = `\n\nTo run tests, you need a headless Wayland compositor installed:\n Fedora: sudo dnf install sway\n Ubuntu: sudo apt install sway`;\n\nconst pinGtkxDependency = (name: string, version: string): string =>\n name.startsWith(\"@gtkx/\") ? `${name}@^${version}` : name;\n\nconst getDevCommand = (packageManager: PackageManager): string => DEV_COMMAND[packageManager];\nconst getInstallCommand = (packageManager: PackageManager): string => INSTALL_COMMAND[packageManager];\nconst titleFromName = (name: string): string => name.split(\"-\").map((part) => upperFirst(part)).join(\" \");\nconst suggestApplicationId = (name: string): string => `com.${name.replaceAll(\"-\", \"\")}.app`;\n\nconst stripTrailingSlashes = (value: string): string => {\n let end = value.length;\n\n while (end > 0 && value[end - 1] === \"/\") {\n end--;\n }\n\n return value.slice(0, end);\n};\n\nconst formatTargetDir = (target: string): string => stripTrailingSlashes(target.trim().replaceAll(/[<>:\"\\\\|?*]/g, \"\"));\nconst deriveProjectName = (target: string): string => basename(resolve(process.cwd(), target));\n\nconst isDirEmpty = (dir: string): boolean => {\n const entries = readdirSync(dir);\n\n return entries.length === 0 || (entries.length === 1 && entries[0] === \".git\");\n};\n\nconst getDevDependencies = ({\n isTypescript,\n shouldIncludeTesting,\n}: Pick<ResolvedOptions, \"isTypescript\" | \"shouldIncludeTesting\">): string[] => {\n const devDeps = [...DEV_DEPENDENCIES];\n\n if (isTypescript) {\n devDeps.push(...TYPESCRIPT_DEV_DEPENDENCIES);\n }\n\n if (shouldIncludeTesting) {\n devDeps.push(...TESTING_DEV_DEPENDENCIES);\n }\n\n return devDeps;\n};\n\nconst guardCancellation = <T>(value: T | symbol): T => {\n if (p.isCancel(value)) {\n p.cancel(\"Operation canceled\");\n throw new OperationCanceledError();\n }\n\n return value;\n};\n\nconst validateProjectName = (value: string | undefined): string | undefined => {\n if (!value) {\n return \"Project name is required\";\n }\n\n if (!isValidProjectName(value)) {\n return \"Project name must be lowercase letters, numbers, and hyphens only\";\n }\n\n return undefined;\n};\n\nconst validateApplicationIdInput = (value: string | undefined): string | undefined => {\n if (!value) {\n return \"Application ID is required\";\n }\n\n if (!isValidApplicationId(value)) {\n return \"Application ID must be reverse domain notation (e.g., com.example.myapp)\";\n }\n\n return undefined;\n};\n\nconst fail = (message: string): never => {\n p.log.error(message);\n throw new ScaffoldAbortedError(message);\n};\n\nconst validateTarget = (value: string | undefined): string | undefined => {\n if (!value) {\n return \"Project directory is required\";\n }\n\n return validateProjectName(deriveProjectName(formatTargetDir(value)));\n};\n\nconst promptTarget = async (): Promise<string> =>\n guardCancellation(\n await p.text({\n message: \"Project directory\",\n placeholder: \"my-app\",\n validate: validateTarget,\n }),\n );\n\nconst promptApplicationId = async (name: string): Promise<string> => {\n const defaultApplicationId = suggestApplicationId(name);\n\n return guardCancellation(\n await p.text({\n message: \"Application ID\",\n placeholder: defaultApplicationId,\n initialValue: defaultApplicationId,\n validate: validateApplicationIdInput,\n }),\n );\n};\n\nconst detectPackageManager = async (cwd: string): Promise<PackageManager | undefined> => {\n const detected = await nypmDetectPackageManager(cwd, { includeParentDirs: true });\n\n if (!detected) {\n return undefined;\n }\n\n return isKnownPackageManager(detected.name) ? detected.name : undefined;\n};\n\nconst packageManagerHint = (\n manager: (typeof PACKAGE_MANAGERS)[number],\n detected: PackageManager | undefined,\n): string | undefined => {\n if (detected === manager.value) {\n return \"detected\";\n }\n\n if (manager.isRecommended) {\n return \"recommended\";\n }\n\n return undefined;\n};\n\nconst packageManagerOption = (manager: (typeof PACKAGE_MANAGERS)[number], detected: PackageManager | undefined) => {\n const hint = packageManagerHint(manager, detected);\n\n return { value: manager.value, label: manager.label, ...(hint !== undefined && { hint }) };\n};\n\nconst detectedPackageManager = async (): Promise<PackageManager | undefined> => {\n try {\n return await detectPackageManager(process.cwd());\n } catch {\n return undefined;\n }\n};\n\nconst promptPackageManager = async (): Promise<PackageManager> => {\n const detected = await detectedPackageManager();\n const initial: PackageManager = detected ?? \"pnpm\";\n\n return guardCancellation(\n await p.select<PackageManager>({\n message: \"Package manager\",\n options: PACKAGE_MANAGERS.map((manager) => packageManagerOption(manager, detected)),\n initialValue: initial,\n }),\n );\n};\n\nconst promptTypeScript = async (): Promise<boolean> =>\n guardCancellation(\n await p.confirm({\n message: \"Use TypeScript?\",\n initialValue: true,\n }),\n );\n\nconst promptTesting = async (): Promise<boolean> =>\n guardCancellation(\n await p.confirm({\n message: \"Include testing setup (Vitest)?\",\n initialValue: true,\n }),\n );\n\nconst emptyDir = (root: string): void => {\n for (const entry of readdirSync(root)) {\n if (entry === \".git\") {\n continue;\n }\n\n rmSync(join(root, entry), { recursive: true, force: true });\n }\n};\n\nconst validateResolvedOptions = (name: string, applicationId: string): void => {\n const nameError = validateProjectName(name);\n\n if (nameError) {\n fail(nameError);\n }\n\n const applicationIdError = validateApplicationIdInput(applicationId);\n\n if (applicationIdError) {\n fail(applicationIdError);\n }\n};\n\nconst confirmOverwrite = async (target: string, options: CreateOptions): Promise<boolean> => {\n if (!options.isInteractive) {\n return options.shouldOverwrite === true;\n }\n\n return guardCancellation(\n await p.confirm({\n message: `Directory \"${target}\" is not empty. Overwrite its contents?`,\n initialValue: false,\n }),\n );\n};\n\nconst handleTargetDirectory = async (root: string, target: string, options: CreateOptions): Promise<void> => {\n if (!existsSync(root) || isDirEmpty(root)) {\n return;\n }\n\n if (await confirmOverwrite(target, options)) {\n emptyDir(root);\n\n return;\n }\n\n fail(`Directory \"${target}\" is not empty`);\n};\n\nconst resolveTarget = async (options: CreateOptions): Promise<string> => {\n if (options.name !== undefined) {\n return formatTargetDir(options.name);\n }\n\n if (!options.isInteractive) {\n return fail(\"Project directory is required\");\n }\n\n return formatTargetDir(await promptTarget());\n};\n\nconst resolveApplicationId = async (options: CreateOptions, name: string): Promise<string> => {\n if (options.applicationId !== undefined) {\n return options.applicationId;\n }\n\n return options.isInteractive ? promptApplicationId(name) : suggestApplicationId(name);\n};\n\nconst resolvePackageManager = async (options: CreateOptions): Promise<PackageManager> => {\n if (options.packageManager !== undefined) {\n return options.packageManager;\n }\n\n if (options.isInteractive) {\n return promptPackageManager();\n }\n\n return (await detectedPackageManager()) ?? \"pnpm\";\n};\n\nconst resolveTypeScript = async (options: CreateOptions): Promise<boolean> => {\n if (options.isTypescript !== undefined) {\n return options.isTypescript;\n }\n\n return options.isInteractive ? promptTypeScript() : true;\n};\n\nconst resolveIncludeTesting = async (options: CreateOptions): Promise<boolean> => {\n if (options.shouldIncludeTesting !== undefined) {\n return options.shouldIncludeTesting;\n }\n\n return options.isInteractive ? promptTesting() : true;\n};\n\nconst resolveOptions = async (options: CreateOptions): Promise<ResolvedOptions> => {\n const target = await resolveTarget(options);\n const name = deriveProjectName(target);\n const applicationId = await resolveApplicationId(options, name);\n validateResolvedOptions(name, applicationId);\n const root = resolve(process.cwd(), target);\n await handleTargetDirectory(root, target, options);\n const packageManager = await resolvePackageManager(options);\n const isTypescript = await resolveTypeScript(options);\n const shouldIncludeTesting = await resolveIncludeTesting(options);\n\n return { target, name, applicationId, packageManager, isTypescript, shouldIncludeTesting };\n};\n\nconst isTemplateIncluded = (templateRelativePath: string, resolved: ResolvedOptions): boolean => {\n if (TESTING_TEMPLATES.has(templateRelativePath)) {\n return resolved.shouldIncludeTesting;\n }\n\n if (TYPESCRIPT_TEMPLATES.has(templateRelativePath)) {\n return resolved.isTypescript;\n }\n\n return true;\n};\n\nconst toDestinationPath = (templateRelativePath: string, isTypescript: boolean): string =>\n isTypescript ? templateRelativePath : templateRelativePath.replace(/\\.tsx$/, \".jsx\").replace(/\\.ts$/, \".js\");\n\nconst addTestScript = (root: string): void => {\n const packageJsonPath = join(root, PACKAGE_JSON_TEMPLATE);\n\n const manifest = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as {\n scripts: Record<string, string>;\n };\n\n manifest.scripts.test = \"vitest\";\n writeFileSync(packageJsonPath, `${JSON.stringify(manifest, null, 4)}\\n`);\n};\n\nconst scaffoldProject = async (root: string, resolved: ResolvedOptions): Promise<void> => {\n const { name, applicationId, isTypescript, shouldIncludeTesting } = resolved;\n\n const context: TemplateContext = {\n name,\n applicationId,\n title: titleFromName(name),\n shouldIncludeTesting,\n isTypescript,\n importExtension: isTypescript ? \".js\" : \".jsx\",\n };\n\n mkdirSync(root, { recursive: true });\n\n for (const template of listTemplates()) {\n if (!isTemplateIncluded(template, resolved)) {\n continue;\n }\n\n const destination = join(root, toDestinationPath(template, isTypescript));\n mkdirSync(dirname(destination), { recursive: true });\n writeFileSync(destination, await renderFile(template, context));\n }\n\n if (shouldIncludeTesting) {\n addTestScript(root);\n }\n};\n\nconst installDependencies = async (options: InstallDependenciesOptions): Promise<void> => {\n const { cwd, packageManager, dependencies, isDev } = options;\n await addDependency(dependencies, { cwd, packageManager, dev: isDev, silent: true });\n};\n\nconst pin = (names: string[]): string[] => names.map((dependency) => pinGtkxDependency(dependency, selfVersion));\n\nconst installAllDependencies = async (options: InstallAllOptions): Promise<void> => {\n const { root, target, packageManager, devDependencies } = options;\n const spinner = p.spinner();\n spinner.start(\"Installing dependencies...\");\n\n try {\n await installDependencies({ cwd: root, packageManager, dependencies: pin(DEPENDENCIES), isDev: false });\n await installDependencies({ cwd: root, packageManager, dependencies: pin(devDependencies), isDev: true });\n spinner.stop(\"Dependencies installed\");\n } catch (error) {\n spinner.stop(\"Failed to install dependencies\");\n p.log.error(`Failed to install dependencies: ${errorMessage(error)}`);\n p.log.info(`Install them manually by running:\\n cd ${target}\\n ${getInstallCommand(packageManager)}`);\n throw new ScaffoldAbortedError(\"Failed to install dependencies\");\n }\n};\n\nconst writeInitialEnvModule = (root: string): void => {\n const storeDir = join(root, \"node_modules\", \".gtkx\");\n mkdirSync(storeDir, { recursive: true });\n writeFileSync(join(storeDir, \"env.d.ts\"), `${GTKX_ENV_MODULE_HEADER}\\n`);\n};\n\nconst initializeGitRepo = async (root: string): Promise<void> => {\n const spinner = p.spinner();\n spinner.start(\"Initializing git repository...\");\n\n try {\n const opts = { nodeOptions: { cwd: root }, throwOnError: true } as const;\n await x(\"git\", [\"init\"], opts);\n await x(\"git\", [\"add\", \"-A\"], opts);\n await x(\"git\", [\"commit\", \"-m\", \"Initial commit\"], opts);\n spinner.stop(\"Git repository initialized\");\n } catch {\n spinner.stop(\"Failed to initialize git repository\");\n }\n};\n\nconst printNextSteps = (resolved: ResolvedOptions): void => {\n const devCmd = getDevCommand(resolved.packageManager);\n const cdStep = resolved.target === \".\" ? \"\" : `cd ${resolved.target}\\n`;\n const testingNote = resolved.shouldIncludeTesting ? HEADLESS_COMPOSITOR_NOTE : \"\";\n p.note(`${cdStep}${devCmd}${testingNote}`, \"Next steps\");\n};\n\nconst scaffold = async (options: CreateOptions = {}): Promise<void> => {\n p.intro(\"Create GTKX App\");\n const resolved = await resolveOptions(options);\n const root = resolve(process.cwd(), resolved.target);\n const devDeps = getDevDependencies(resolved);\n const projectSpinner = p.spinner();\n projectSpinner.start(\"Creating project structure...\");\n await scaffoldProject(root, resolved);\n projectSpinner.stop(\"Project structure created\");\n\n await installAllDependencies({\n root,\n target: resolved.target,\n packageManager: resolved.packageManager,\n devDependencies: devDeps,\n });\n\n if (resolved.isTypescript) {\n writeInitialEnvModule(root);\n }\n\n await initializeGitRepo(root);\n printNextSteps(resolved);\n};\n\nexport { scaffold, type CreateOptions };\n"]}
|
|
1
|
+
{"version":3,"file":"scaffolder.js","sourceRoot":"","sources":["../src/scaffolder.ts"],"names":[],"mappings":"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","sourcesContent":["import * as p from \"@clack/prompts\";\nimport { isValidApplicationId } from \"@gtkx/config/internal\";\nimport { errorMessage, packageVersion, upperFirst } from \"@gtkx/utils\";\nimport { existsSync, mkdirSync, readdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { addDependency, detectPackageManager as nypmDetectPackageManager } from \"nypm\";\nimport { x } from \"tinyexec\";\nimport { writeBuildAllowance } from \"./build-allowance.js\";\nimport { OperationCanceledError, ScaffoldAbortedError } from \"./errors.js\";\nimport { getInstallHint } from \"./install-hints.js\";\nimport { updateManifest } from \"./manifest.js\";\nimport { isKnownPackageManager, PACKAGE_MANAGERS, type PackageManager } from \"./package-managers.js\";\nimport { isValidProjectName } from \"./project-name.js\";\nimport { listTemplates, renderFile, type TemplateContext } from \"./templates.js\";\n\ntype CreateOptions = {\n name?: string | undefined;\n applicationId?: string | undefined;\n packageManager?: PackageManager | undefined;\n isTypescript?: boolean | undefined;\n shouldIncludeTesting?: boolean | undefined;\n isInteractive?: boolean | undefined;\n shouldOverwrite?: boolean | undefined;\n};\n\ntype ResolvedOptions = {\n target: string;\n name: string;\n applicationId: string;\n packageManager: PackageManager;\n isTypescript: boolean;\n shouldIncludeTesting: boolean;\n};\n\ntype InstallDependenciesOptions = {\n cwd: string;\n packageManager: PackageManager;\n dependencies: string[];\n isDev: boolean;\n};\n\ntype InstallAllOptions = {\n root: string;\n target: string;\n packageManager: PackageManager;\n devDependencies: string[];\n};\n\ntype InstallFailureOptions = {\n error: unknown;\n target: string;\n packageManager: PackageManager;\n devDependencies: string[];\n};\n\nconst selfVersion = packageVersion(import.meta.url, \"../package.json\");\n\nconst GTKX_ENV_MODULE_HEADER = `/**\n * Generated by \\`gtkx codegen\\`, \\`gtkx dev\\`, and \\`gtkx build\\`; do not edit.\n */`;\n\nconst DEPENDENCIES = [\"@gtkx/css\", \"@gtkx/runtime\", \"@gtkx/react\", \"react\"];\nconst DEV_DEPENDENCIES = [\"@gtkx/cli\", \"@gtkx/config\", \"@gtkx/mcp\", \"vite\"];\nconst TYPESCRIPT_DEV_DEPENDENCIES = [\"@types/node\", \"@types/react\", \"typescript\"];\nconst TESTING_DEV_DEPENDENCIES = [\"@gtkx/testing\", \"vitest\"];\n\nconst DEV_COMMAND: Record<PackageManager, string> = Object.fromEntries(\n PACKAGE_MANAGERS.map((manager) => [manager.value, manager.devCommand]),\n) as Record<PackageManager, string>;\n\nconst ADD_COMMAND: Record<PackageManager, string> = Object.fromEntries(\n PACKAGE_MANAGERS.map((manager) => [manager.value, manager.addCommand]),\n) as Record<PackageManager, string>;\n\nconst INHERITED_SCRIPT_POLICY_VARS = [\"npm_config_allow_scripts\", \"npm_config_allow-scripts\"];\nconst TESTING_TEMPLATES = new Set([\"vitest.config.ts\", \"tests/app.test.tsx\"]);\nconst TYPESCRIPT_TEMPLATES = new Set([\"tsconfig.json\", \"src/gtkx-env.d.ts\"]);\n\nconst HEADLESS_COMPOSITOR_NOTE = `\n\nTo run tests, you need a headless Wayland compositor installed:\n Fedora: sudo dnf install sway\n Ubuntu: sudo apt install sway`;\n\nconst RECOVERY_HEADING = \"Finish the setup by adding the dependencies again, which is safe to repeat:\";\n\nconst pinGtkxDependency = (name: string, version: string): string =>\n name.startsWith(\"@gtkx/\") ? `${name}@^${version}` : name;\n\nconst getDevCommand = (packageManager: PackageManager): string => DEV_COMMAND[packageManager];\nconst getAddCommand = (packageManager: PackageManager): string => ADD_COMMAND[packageManager];\nconst titleFromName = (name: string): string => name.split(\"-\").map((part) => upperFirst(part)).join(\" \");\nconst suggestApplicationId = (name: string): string => `com.${name.replaceAll(\"-\", \"\")}.app`;\n\nconst stripTrailingSlashes = (value: string): string => {\n let end = value.length;\n\n while (end > 0 && value[end - 1] === \"/\") {\n end--;\n }\n\n return value.slice(0, end);\n};\n\nconst formatTargetDir = (target: string): string => stripTrailingSlashes(target.trim().replaceAll(/[<>:\"\\\\|?*]/g, \"\"));\nconst deriveProjectName = (target: string): string => basename(resolve(process.cwd(), target));\n\nconst isDirEmpty = (dir: string): boolean => {\n const entries = readdirSync(dir);\n\n return entries.length === 0 || (entries.length === 1 && entries[0] === \".git\");\n};\n\nconst getDevDependencies = ({\n isTypescript,\n shouldIncludeTesting,\n}: Pick<ResolvedOptions, \"isTypescript\" | \"shouldIncludeTesting\">): string[] => {\n const devDeps = [...DEV_DEPENDENCIES];\n\n if (isTypescript) {\n devDeps.push(...TYPESCRIPT_DEV_DEPENDENCIES);\n }\n\n if (shouldIncludeTesting) {\n devDeps.push(...TESTING_DEV_DEPENDENCIES);\n }\n\n return devDeps;\n};\n\nconst guardCancellation = <T>(value: T | symbol): T => {\n if (p.isCancel(value)) {\n p.cancel(\"Operation canceled\");\n throw new OperationCanceledError();\n }\n\n return value;\n};\n\nconst validateProjectName = (value: string | undefined): string | undefined => {\n if (!value) {\n return \"Project name is required\";\n }\n\n if (!isValidProjectName(value)) {\n return \"Project name must be lowercase letters, numbers, and hyphens only\";\n }\n\n return undefined;\n};\n\nconst validateApplicationIdInput = (value: string | undefined): string | undefined => {\n if (!value) {\n return \"Application ID is required\";\n }\n\n if (!isValidApplicationId(value)) {\n return \"Application ID must be reverse domain notation (e.g., com.example.myapp)\";\n }\n\n return undefined;\n};\n\nconst fail = (message: string): never => {\n p.log.error(message);\n throw new ScaffoldAbortedError(message);\n};\n\nconst validateTarget = (value: string | undefined): string | undefined => {\n if (!value) {\n return \"Project directory is required\";\n }\n\n return validateProjectName(deriveProjectName(formatTargetDir(value)));\n};\n\nconst promptTarget = async (): Promise<string> =>\n guardCancellation(\n await p.text({\n message: \"Project directory\",\n placeholder: \"my-app\",\n validate: validateTarget,\n }),\n );\n\nconst promptApplicationId = async (name: string): Promise<string> => {\n const defaultApplicationId = suggestApplicationId(name);\n\n return guardCancellation(\n await p.text({\n message: \"Application ID\",\n placeholder: defaultApplicationId,\n initialValue: defaultApplicationId,\n validate: validateApplicationIdInput,\n }),\n );\n};\n\nconst detectPackageManager = async (cwd: string): Promise<PackageManager | undefined> => {\n const detected = await nypmDetectPackageManager(cwd, { includeParentDirs: true });\n\n if (!detected) {\n return undefined;\n }\n\n return isKnownPackageManager(detected.name) ? detected.name : undefined;\n};\n\nconst packageManagerHint = (\n manager: (typeof PACKAGE_MANAGERS)[number],\n detected: PackageManager | undefined,\n): string | undefined => {\n if (detected === manager.value) {\n return \"detected\";\n }\n\n if (manager.isRecommended) {\n return \"recommended\";\n }\n\n return undefined;\n};\n\nconst packageManagerOption = (manager: (typeof PACKAGE_MANAGERS)[number], detected: PackageManager | undefined) => {\n const hint = packageManagerHint(manager, detected);\n\n return { value: manager.value, label: manager.label, ...(hint !== undefined && { hint }) };\n};\n\nconst detectedPackageManager = async (): Promise<PackageManager | undefined> => {\n try {\n return await detectPackageManager(process.cwd());\n } catch {\n return undefined;\n }\n};\n\nconst promptPackageManager = async (): Promise<PackageManager> => {\n const detected = await detectedPackageManager();\n const initial: PackageManager = detected ?? \"pnpm\";\n\n return guardCancellation(\n await p.select<PackageManager>({\n message: \"Package manager\",\n options: PACKAGE_MANAGERS.map((manager) => packageManagerOption(manager, detected)),\n initialValue: initial,\n }),\n );\n};\n\nconst shouldUseTypeScript = async (): Promise<boolean> =>\n guardCancellation(\n await p.confirm({\n message: \"Use TypeScript?\",\n initialValue: true,\n }),\n );\n\nconst shouldSetUpTesting = async (): Promise<boolean> =>\n guardCancellation(\n await p.confirm({\n message: \"Include testing setup (Vitest)?\",\n initialValue: true,\n }),\n );\n\nconst emptyDir = (root: string): void => {\n for (const entry of readdirSync(root)) {\n if (entry === \".git\") {\n continue;\n }\n\n rmSync(join(root, entry), { recursive: true, force: true });\n }\n};\n\nconst validateResolvedOptions = (name: string, applicationId: string): void => {\n const nameError = validateProjectName(name);\n\n if (nameError) {\n fail(nameError);\n }\n\n const applicationIdError = validateApplicationIdInput(applicationId);\n\n if (applicationIdError) {\n fail(applicationIdError);\n }\n};\n\nconst shouldOverwriteDirectory = async (target: string, options: CreateOptions): Promise<boolean> => {\n if (!options.isInteractive) {\n return options.shouldOverwrite === true;\n }\n\n return guardCancellation(\n await p.confirm({\n message: `Directory \"${target}\" is not empty. Overwrite its contents?`,\n initialValue: false,\n }),\n );\n};\n\nconst handleTargetDirectory = async (root: string, target: string, options: CreateOptions): Promise<void> => {\n if (!existsSync(root) || isDirEmpty(root)) {\n return;\n }\n\n if (await shouldOverwriteDirectory(target, options)) {\n emptyDir(root);\n\n return;\n }\n\n fail(`Directory \"${target}\" is not empty`);\n};\n\nconst resolveTarget = async (options: CreateOptions): Promise<string> => {\n if (options.name !== undefined) {\n return formatTargetDir(options.name);\n }\n\n if (!options.isInteractive) {\n return fail(\"Project directory is required\");\n }\n\n return formatTargetDir(await promptTarget());\n};\n\nconst resolveApplicationId = async (options: CreateOptions, name: string): Promise<string> => {\n if (options.applicationId !== undefined) {\n return options.applicationId;\n }\n\n return options.isInteractive ? promptApplicationId(name) : suggestApplicationId(name);\n};\n\nconst resolvePackageManager = async (options: CreateOptions): Promise<PackageManager> => {\n if (options.packageManager !== undefined) {\n return options.packageManager;\n }\n\n if (options.isInteractive) {\n return promptPackageManager();\n }\n\n return (await detectedPackageManager()) ?? \"pnpm\";\n};\n\nconst isTypescriptSelected = async (options: CreateOptions): Promise<boolean> => {\n if (options.isTypescript !== undefined) {\n return options.isTypescript;\n }\n\n return options.isInteractive ? shouldUseTypeScript() : true;\n};\n\nconst isTestingIncluded = async (options: CreateOptions): Promise<boolean> => {\n if (options.shouldIncludeTesting !== undefined) {\n return options.shouldIncludeTesting;\n }\n\n return options.isInteractive ? shouldSetUpTesting() : true;\n};\n\nconst resolveOptions = async (options: CreateOptions): Promise<ResolvedOptions> => {\n const target = await resolveTarget(options);\n const name = deriveProjectName(target);\n const applicationId = await resolveApplicationId(options, name);\n validateResolvedOptions(name, applicationId);\n const root = resolve(process.cwd(), target);\n await handleTargetDirectory(root, target, options);\n const packageManager = await resolvePackageManager(options);\n const isTypescript = await isTypescriptSelected(options);\n const shouldIncludeTesting = await isTestingIncluded(options);\n\n return { target, name, applicationId, packageManager, isTypescript, shouldIncludeTesting };\n};\n\nconst isTemplateIncluded = (templateRelativePath: string, resolved: ResolvedOptions): boolean => {\n if (TESTING_TEMPLATES.has(templateRelativePath)) {\n return resolved.shouldIncludeTesting;\n }\n\n if (TYPESCRIPT_TEMPLATES.has(templateRelativePath)) {\n return resolved.isTypescript;\n }\n\n return true;\n};\n\nconst toDestinationPath = (templateRelativePath: string, isTypescript: boolean): string =>\n isTypescript ? templateRelativePath : templateRelativePath.replace(/\\.tsx$/, \".jsx\").replace(/\\.ts$/, \".js\");\n\nconst addTestScript = (root: string): void => {\n updateManifest(root, (manifest) => {\n (manifest.scripts as Record<string, string>).test = \"vitest run\";\n });\n};\n\nconst scaffoldProject = async (root: string, resolved: ResolvedOptions): Promise<void> => {\n const { name, applicationId, isTypescript, shouldIncludeTesting } = resolved;\n\n const context: TemplateContext = {\n name,\n applicationId,\n title: titleFromName(name),\n shouldIncludeTesting,\n isTypescript,\n importExtension: isTypescript ? \".js\" : \".jsx\",\n };\n\n mkdirSync(root, { recursive: true });\n\n for (const template of listTemplates()) {\n if (!isTemplateIncluded(template, resolved)) {\n continue;\n }\n\n const destination = join(root, toDestinationPath(template, isTypescript));\n mkdirSync(dirname(destination), { recursive: true });\n writeFileSync(destination, await renderFile(template, context));\n }\n\n if (shouldIncludeTesting) {\n addTestScript(root);\n }\n};\n\nconst withoutInheritedScriptPolicy = async (run: () => Promise<void>): Promise<void> => {\n const saved = INHERITED_SCRIPT_POLICY_VARS.map((key) => [key, process.env[key]] as const);\n\n for (const [key] of saved) {\n Reflect.deleteProperty(process.env, key);\n }\n\n try {\n await run();\n } finally {\n for (const [key, value] of saved) {\n if (value !== undefined) {\n process.env[key] = value;\n }\n }\n }\n};\n\nconst installDependencies = async (options: InstallDependenciesOptions): Promise<void> => {\n const { cwd, packageManager, dependencies, isDev } = options;\n\n await withoutInheritedScriptPolicy(async () => {\n await addDependency(dependencies, { cwd, packageManager, dev: isDev, silent: true });\n });\n};\n\nconst pin = (names: string[]): string[] => names.map((dependency) => pinGtkxDependency(dependency, selfVersion));\n\nconst formatRecovery = ({ target, packageManager, devDependencies }: InstallFailureOptions): string => {\n const add = getAddCommand(packageManager);\n\n const steps = [\n ...(target === \".\" ? [] : [`cd ${target}`]),\n `${add} ${pin(DEPENDENCIES).join(\" \")}`,\n `${add} -D ${pin(devDependencies).join(\" \")}`,\n ];\n\n const indented = steps.map((step) => ` ${step}`).join(\"\\n\");\n\n return `${RECOVERY_HEADING}\\n${indented}`;\n};\n\nconst reportInstallFailure = (options: InstallFailureOptions): void => {\n const message = errorMessage(options.error);\n p.log.error(`Failed to install dependencies: ${message}`);\n const hint = getInstallHint(message);\n\n if (hint !== undefined) {\n p.log.warn(hint);\n }\n\n p.log.info(formatRecovery(options));\n};\n\nconst installAllDependencies = async (options: InstallAllOptions): Promise<void> => {\n const { root, target, packageManager, devDependencies } = options;\n const spinner = p.spinner();\n spinner.start(\"Installing dependencies...\");\n\n try {\n await installDependencies({ cwd: root, packageManager, dependencies: pin(DEPENDENCIES), isDev: false });\n await installDependencies({ cwd: root, packageManager, dependencies: pin(devDependencies), isDev: true });\n spinner.stop(\"Dependencies installed\");\n } catch (error) {\n spinner.stop(\"Failed to install dependencies\");\n reportInstallFailure({ error, target, packageManager, devDependencies });\n throw new ScaffoldAbortedError(\"Failed to install dependencies\");\n }\n};\n\nconst writeInitialEnvModule = (root: string): void => {\n const storeDir = join(root, \"node_modules\", \".gtkx\");\n mkdirSync(storeDir, { recursive: true });\n writeFileSync(join(storeDir, \"env.d.ts\"), `${GTKX_ENV_MODULE_HEADER}\\n`);\n};\n\nconst initializeGitRepo = async (root: string): Promise<void> => {\n const spinner = p.spinner();\n spinner.start(\"Initializing git repository...\");\n\n try {\n const opts = { nodeOptions: { cwd: root }, throwOnError: true } as const;\n await x(\"git\", [\"init\"], opts);\n await x(\"git\", [\"add\", \"-A\"], opts);\n await x(\"git\", [\"commit\", \"-m\", \"Initial commit\"], opts);\n spinner.stop(\"Git repository initialized\");\n } catch {\n spinner.stop(\"Failed to initialize git repository\");\n }\n};\n\nconst printNextSteps = (resolved: ResolvedOptions): void => {\n const devCmd = getDevCommand(resolved.packageManager);\n const cdStep = resolved.target === \".\" ? \"\" : `cd ${resolved.target}\\n`;\n const testingNote = resolved.shouldIncludeTesting ? HEADLESS_COMPOSITOR_NOTE : \"\";\n p.note(`${cdStep}${devCmd}${testingNote}`, \"Next steps\");\n};\n\nconst scaffold = async (options: CreateOptions = {}): Promise<void> => {\n p.intro(\"Create GTKX App\");\n const resolved = await resolveOptions(options);\n const root = resolve(process.cwd(), resolved.target);\n const devDeps = getDevDependencies(resolved);\n const projectSpinner = p.spinner();\n projectSpinner.start(\"Creating project structure...\");\n await scaffoldProject(root, resolved);\n writeBuildAllowance(root, resolved.packageManager);\n projectSpinner.stop(\"Project structure created\");\n\n await installAllDependencies({\n root,\n target: resolved.target,\n packageManager: resolved.packageManager,\n devDependencies: devDeps,\n });\n\n if (resolved.isTypescript) {\n writeInitialEnvModule(root);\n }\n\n await initializeGitRepo(root);\n printNextSteps(resolved);\n};\n\nexport { scaffold, type CreateOptions };\n"]}
|
|
@@ -11,12 +11,8 @@
|
|
|
11
11
|
"build": "gtkx build",
|
|
12
12
|
"codegen": "gtkx codegen",
|
|
13
13
|
<% if (isTypescript) { -%>
|
|
14
|
-
"typecheck": "gtkx codegen && tsc
|
|
14
|
+
"typecheck": "gtkx codegen && tsc",
|
|
15
15
|
<% } -%>
|
|
16
16
|
"start": "node dist/bundle.js"
|
|
17
|
-
},
|
|
18
|
-
"allowScripts": {
|
|
19
|
-
"esbuild": true,
|
|
20
|
-
"@swc/core": true
|
|
21
17
|
}
|
|
22
18
|
}
|
|
@@ -9,8 +9,11 @@
|
|
|
9
9
|
"resolveJsonModule": true,
|
|
10
10
|
"lib": ["esnext"],
|
|
11
11
|
"types": ["node", "react"],
|
|
12
|
-
"
|
|
13
|
-
"rootDir": "src"
|
|
12
|
+
"noEmit": true
|
|
14
13
|
},
|
|
14
|
+
<% if (shouldIncludeTesting) { -%>
|
|
15
|
+
"include": ["src/**/*", "tests/**/*"]
|
|
16
|
+
<% } else { -%>
|
|
15
17
|
"include": ["src/**/*"]
|
|
18
|
+
<% } -%>
|
|
16
19
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-gtkx",
|
|
3
|
-
"version": "1.0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Scaffold a new native GTK4 + React desktop application with GTKX",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gtkx",
|
|
@@ -50,14 +50,14 @@
|
|
|
50
50
|
"ejs": "^6.0.1",
|
|
51
51
|
"citty": "^0.2.2",
|
|
52
52
|
"nypm": "^0.6.9",
|
|
53
|
-
"tinyexec": "^1.
|
|
54
|
-
"@gtkx/config": "1.0.0
|
|
55
|
-
"@gtkx/utils": "1.0.0
|
|
53
|
+
"tinyexec": "^1.3.0",
|
|
54
|
+
"@gtkx/config": "1.0.0",
|
|
55
|
+
"@gtkx/utils": "1.0.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@types/ejs": "^3.1.5",
|
|
59
|
-
"@types/node": "^26.
|
|
60
|
-
"memfs": "^4.
|
|
59
|
+
"@types/node": "^26.2.0",
|
|
60
|
+
"memfs": "^4.68.0",
|
|
61
61
|
"typescript": "^6.0.3",
|
|
62
62
|
"vitest": "^4.1.10"
|
|
63
63
|
},
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import type { PackageManager } from "./package-managers.js";
|
|
4
|
+
import { updateManifest } from "./manifest.js";
|
|
5
|
+
|
|
6
|
+
const BUILT_DEPENDENCIES = ["@swc/core", "esbuild"];
|
|
7
|
+
const PNPM_WORKSPACE_FILE = "pnpm-workspace.yaml";
|
|
8
|
+
const SAFE_YAML_KEY = /^[A-Za-z][A-Za-z0-9-]*$/;
|
|
9
|
+
const PNPM_PACKAGES_BLOCK = "packages:\n - '.'\n";
|
|
10
|
+
|
|
11
|
+
const quoteYamlKey = (name: string): string => (SAFE_YAML_KEY.test(name) ? name : `'${name}'`);
|
|
12
|
+
|
|
13
|
+
const writePnpmAllowance = (root: string): void => {
|
|
14
|
+
const entries = BUILT_DEPENDENCIES.map((name) => ` ${quoteYamlKey(name)}: true`).join("\n");
|
|
15
|
+
writeFileSync(join(root, PNPM_WORKSPACE_FILE), `${PNPM_PACKAGES_BLOCK}allowBuilds:\n${entries}\n`);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const writeNpmAllowance = (root: string): void => {
|
|
19
|
+
updateManifest(root, (manifest) => {
|
|
20
|
+
manifest.allowScripts = Object.fromEntries(BUILT_DEPENDENCIES.map((name) => [name, true]));
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const writeYarnAllowance = (root: string): void => {
|
|
25
|
+
updateManifest(root, (manifest) => {
|
|
26
|
+
manifest.dependenciesMeta = Object.fromEntries(BUILT_DEPENDENCIES.map((name) => [name, { built: true }]));
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const writeBuildAllowance = (root: string, packageManager: PackageManager): void => {
|
|
31
|
+
if (packageManager === "pnpm") {
|
|
32
|
+
writePnpmAllowance(root);
|
|
33
|
+
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (packageManager === "yarn") {
|
|
38
|
+
writeYarnAllowance(root);
|
|
39
|
+
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
writeNpmAllowance(root);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { writeBuildAllowance };
|
package/src/cli.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { packageVersion } from "@gtkx/utils";
|
|
|
2
2
|
import { defineCommand, runMain } from "citty";
|
|
3
3
|
import { scaffoldCommand } from "./command.js";
|
|
4
4
|
|
|
5
|
-
const version = packageVersion(import.meta.url);
|
|
5
|
+
const version = packageVersion(import.meta.url, "../package.json");
|
|
6
6
|
|
|
7
7
|
const main = defineCommand({
|
|
8
8
|
...scaffoldCommand,
|
package/src/command.ts
CHANGED
|
@@ -14,12 +14,6 @@ type CreateCommandArgs = {
|
|
|
14
14
|
overwrite?: boolean | undefined;
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
/**
|
|
18
|
-
* Citty command definition for the CLI `create` subcommand. It declares the
|
|
19
|
-
* scaffolder's arguments (target name, application ID, package manager,
|
|
20
|
-
* TypeScript and Vitest toggles, prompt behavior, and overwrite) and runs the
|
|
21
|
-
* scaffolder to generate a new GTKX application.
|
|
22
|
-
*/
|
|
23
17
|
const scaffoldCommand = defineCommand({
|
|
24
18
|
meta: {
|
|
25
19
|
name: "create",
|
|
@@ -114,4 +108,4 @@ const runCreate = async (args: CreateCommandArgs): Promise<void> => {
|
|
|
114
108
|
}
|
|
115
109
|
};
|
|
116
110
|
|
|
117
|
-
export { scaffoldCommand, runCreate
|
|
111
|
+
export { scaffoldCommand, runCreate };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const RELEASE_AGE_PATTERN = /ERR_PNPM_(?:MINIMUM_RELEASE_AGE_VIOLATION|NO_MATURE_MATCHING_VERSION)/;
|
|
2
|
+
const BLOCKED_VERSION_PATTERN = /^[ \t]*(\S+) was published at .+ within the minimumReleaseAge cutoff/gm;
|
|
3
|
+
|
|
4
|
+
const RELEASE_AGE_POLICY =
|
|
5
|
+
"pnpm refused the install under its minimumReleaseAge policy, which by default holds back every package " +
|
|
6
|
+
"published in the last 24 hours so a compromised release has time to be caught and pulled. Nothing is wrong " +
|
|
7
|
+
"with these versions other than their age.";
|
|
8
|
+
|
|
9
|
+
const RELEASE_AGE_REMEDY =
|
|
10
|
+
"Wait for them to clear that window and install again, or allow the versions pnpm named. They belong at the " +
|
|
11
|
+
"top level of pnpm-workspace.yaml, as a sibling of packages: and allowBuilds: rather than nested inside " +
|
|
12
|
+
"either of them:";
|
|
13
|
+
|
|
14
|
+
const RELEASE_AGE_REMEDY_WITHOUT_VERSIONS =
|
|
15
|
+
"Wait for them to clear that window and install again, or list the versions pnpm reported under a top-level " +
|
|
16
|
+
"minimumReleaseAgeExclude key in pnpm-workspace.yaml.";
|
|
17
|
+
|
|
18
|
+
const RELEASE_AGE_PARTIAL_LIST =
|
|
19
|
+
"pnpm reports only the versions the command it stopped on had to resolve, so a later install can name more. " +
|
|
20
|
+
"Add each one to the same list.";
|
|
21
|
+
|
|
22
|
+
const RELEASE_AGE_OPT_OUT =
|
|
23
|
+
'Listing exact versions keeps the policy on for every other package. Setting "minimumReleaseAge: 0" in the ' +
|
|
24
|
+
"same file turns it off for all of them, so prefer the list above. npm and yarn apply no such policy.";
|
|
25
|
+
|
|
26
|
+
const getBlockedVersions = (message: string): string[] => {
|
|
27
|
+
const matches = Array.from(message.matchAll(BLOCKED_VERSION_PATTERN), (match) => match[1] ?? "");
|
|
28
|
+
|
|
29
|
+
return [...new Set(matches.filter(Boolean))];
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const formatExcludeBlock = (versions: string[]): string =>
|
|
33
|
+
["minimumReleaseAgeExclude:", ...versions.map((version) => ` - '${version}'`)].join("\n");
|
|
34
|
+
|
|
35
|
+
const describeReleaseAge = (message: string): string => {
|
|
36
|
+
const versions = getBlockedVersions(message);
|
|
37
|
+
|
|
38
|
+
if (versions.length === 0) {
|
|
39
|
+
return [RELEASE_AGE_POLICY, RELEASE_AGE_REMEDY_WITHOUT_VERSIONS].join("\n\n");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return [
|
|
43
|
+
RELEASE_AGE_POLICY,
|
|
44
|
+
RELEASE_AGE_REMEDY,
|
|
45
|
+
formatExcludeBlock(versions),
|
|
46
|
+
RELEASE_AGE_PARTIAL_LIST,
|
|
47
|
+
RELEASE_AGE_OPT_OUT,
|
|
48
|
+
].join("\n\n");
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const getInstallHint = (message: string): string | undefined =>
|
|
52
|
+
RELEASE_AGE_PATTERN.test(message) ? describeReleaseAge(message) : undefined;
|
|
53
|
+
|
|
54
|
+
export { getInstallHint };
|
package/src/manifest.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
const PACKAGE_JSON_FILE = "package.json";
|
|
5
|
+
|
|
6
|
+
const updateManifest = (root: string, mutate: (manifest: Record<string, unknown>) => void): void => {
|
|
7
|
+
const manifestPath = join(root, PACKAGE_JSON_FILE);
|
|
8
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf8")) as Record<string, unknown>;
|
|
9
|
+
mutate(manifest);
|
|
10
|
+
const pendingPath = `${manifestPath}.pending`;
|
|
11
|
+
writeFileSync(pendingPath, `${JSON.stringify(manifest, null, 4)}\n`);
|
|
12
|
+
renameSync(pendingPath, manifestPath);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export { updateManifest };
|
package/src/package-managers.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
type PackageManager = (typeof PACKAGE_MANAGERS)[number]["value"];
|
|
2
2
|
|
|
3
3
|
const PACKAGE_MANAGERS = [
|
|
4
|
-
{ value: "pnpm", label: "pnpm", devCommand: "pnpm dev",
|
|
5
|
-
{ value: "npm", label: "npm", devCommand: "npm run dev",
|
|
6
|
-
{ value: "yarn", label: "yarn", devCommand: "yarn dev",
|
|
4
|
+
{ value: "pnpm", label: "pnpm", devCommand: "pnpm dev", addCommand: "pnpm add", isRecommended: true },
|
|
5
|
+
{ value: "npm", label: "npm", devCommand: "npm run dev", addCommand: "npm install", isRecommended: false },
|
|
6
|
+
{ value: "yarn", label: "yarn", devCommand: "yarn dev", addCommand: "yarn add", isRecommended: false },
|
|
7
7
|
] as const;
|
|
8
8
|
|
|
9
9
|
const PACKAGE_MANAGER_VALUES: PackageManager[] = PACKAGE_MANAGERS.map((manager) => manager.value);
|
package/src/scaffolder.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
2
|
import { isValidApplicationId } from "@gtkx/config/internal";
|
|
3
3
|
import { errorMessage, packageVersion, upperFirst } from "@gtkx/utils";
|
|
4
|
-
import { existsSync, mkdirSync, readdirSync,
|
|
4
|
+
import { existsSync, mkdirSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { basename, dirname, join, resolve } from "node:path";
|
|
6
6
|
import { addDependency, detectPackageManager as nypmDetectPackageManager } from "nypm";
|
|
7
7
|
import { x } from "tinyexec";
|
|
8
|
+
import { writeBuildAllowance } from "./build-allowance.js";
|
|
8
9
|
import { OperationCanceledError, ScaffoldAbortedError } from "./errors.js";
|
|
10
|
+
import { getInstallHint } from "./install-hints.js";
|
|
11
|
+
import { updateManifest } from "./manifest.js";
|
|
9
12
|
import { isKnownPackageManager, PACKAGE_MANAGERS, type PackageManager } from "./package-managers.js";
|
|
10
13
|
import { isValidProjectName } from "./project-name.js";
|
|
11
14
|
import { listTemplates, renderFile, type TemplateContext } from "./templates.js";
|
|
@@ -43,14 +46,21 @@ type InstallAllOptions = {
|
|
|
43
46
|
devDependencies: string[];
|
|
44
47
|
};
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
type InstallFailureOptions = {
|
|
50
|
+
error: unknown;
|
|
51
|
+
target: string;
|
|
52
|
+
packageManager: PackageManager;
|
|
53
|
+
devDependencies: string[];
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const selfVersion = packageVersion(import.meta.url, "../package.json");
|
|
47
57
|
|
|
48
58
|
const GTKX_ENV_MODULE_HEADER = `/**
|
|
49
59
|
* Generated by \`gtkx codegen\`, \`gtkx dev\`, and \`gtkx build\`; do not edit.
|
|
50
60
|
*/`;
|
|
51
61
|
|
|
52
62
|
const DEPENDENCIES = ["@gtkx/css", "@gtkx/runtime", "@gtkx/react", "react"];
|
|
53
|
-
const DEV_DEPENDENCIES = ["@gtkx/cli", "@gtkx/config", "vite"];
|
|
63
|
+
const DEV_DEPENDENCIES = ["@gtkx/cli", "@gtkx/config", "@gtkx/mcp", "vite"];
|
|
54
64
|
const TYPESCRIPT_DEV_DEPENDENCIES = ["@types/node", "@types/react", "typescript"];
|
|
55
65
|
const TESTING_DEV_DEPENDENCIES = ["@gtkx/testing", "vitest"];
|
|
56
66
|
|
|
@@ -58,13 +68,13 @@ const DEV_COMMAND: Record<PackageManager, string> = Object.fromEntries(
|
|
|
58
68
|
PACKAGE_MANAGERS.map((manager) => [manager.value, manager.devCommand]),
|
|
59
69
|
) as Record<PackageManager, string>;
|
|
60
70
|
|
|
61
|
-
const
|
|
62
|
-
PACKAGE_MANAGERS.map((manager) => [manager.value, manager.
|
|
71
|
+
const ADD_COMMAND: Record<PackageManager, string> = Object.fromEntries(
|
|
72
|
+
PACKAGE_MANAGERS.map((manager) => [manager.value, manager.addCommand]),
|
|
63
73
|
) as Record<PackageManager, string>;
|
|
64
74
|
|
|
75
|
+
const INHERITED_SCRIPT_POLICY_VARS = ["npm_config_allow_scripts", "npm_config_allow-scripts"];
|
|
65
76
|
const TESTING_TEMPLATES = new Set(["vitest.config.ts", "tests/app.test.tsx"]);
|
|
66
77
|
const TYPESCRIPT_TEMPLATES = new Set(["tsconfig.json", "src/gtkx-env.d.ts"]);
|
|
67
|
-
const PACKAGE_JSON_TEMPLATE = "package.json";
|
|
68
78
|
|
|
69
79
|
const HEADLESS_COMPOSITOR_NOTE = `
|
|
70
80
|
|
|
@@ -72,11 +82,13 @@ To run tests, you need a headless Wayland compositor installed:
|
|
|
72
82
|
Fedora: sudo dnf install sway
|
|
73
83
|
Ubuntu: sudo apt install sway`;
|
|
74
84
|
|
|
85
|
+
const RECOVERY_HEADING = "Finish the setup by adding the dependencies again, which is safe to repeat:";
|
|
86
|
+
|
|
75
87
|
const pinGtkxDependency = (name: string, version: string): string =>
|
|
76
88
|
name.startsWith("@gtkx/") ? `${name}@^${version}` : name;
|
|
77
89
|
|
|
78
90
|
const getDevCommand = (packageManager: PackageManager): string => DEV_COMMAND[packageManager];
|
|
79
|
-
const
|
|
91
|
+
const getAddCommand = (packageManager: PackageManager): string => ADD_COMMAND[packageManager];
|
|
80
92
|
const titleFromName = (name: string): string => name.split("-").map((part) => upperFirst(part)).join(" ");
|
|
81
93
|
const suggestApplicationId = (name: string): string => `com.${name.replaceAll("-", "")}.app`;
|
|
82
94
|
|
|
@@ -236,7 +248,7 @@ const promptPackageManager = async (): Promise<PackageManager> => {
|
|
|
236
248
|
);
|
|
237
249
|
};
|
|
238
250
|
|
|
239
|
-
const
|
|
251
|
+
const shouldUseTypeScript = async (): Promise<boolean> =>
|
|
240
252
|
guardCancellation(
|
|
241
253
|
await p.confirm({
|
|
242
254
|
message: "Use TypeScript?",
|
|
@@ -244,7 +256,7 @@ const promptTypeScript = async (): Promise<boolean> =>
|
|
|
244
256
|
}),
|
|
245
257
|
);
|
|
246
258
|
|
|
247
|
-
const
|
|
259
|
+
const shouldSetUpTesting = async (): Promise<boolean> =>
|
|
248
260
|
guardCancellation(
|
|
249
261
|
await p.confirm({
|
|
250
262
|
message: "Include testing setup (Vitest)?",
|
|
@@ -276,7 +288,7 @@ const validateResolvedOptions = (name: string, applicationId: string): void => {
|
|
|
276
288
|
}
|
|
277
289
|
};
|
|
278
290
|
|
|
279
|
-
const
|
|
291
|
+
const shouldOverwriteDirectory = async (target: string, options: CreateOptions): Promise<boolean> => {
|
|
280
292
|
if (!options.isInteractive) {
|
|
281
293
|
return options.shouldOverwrite === true;
|
|
282
294
|
}
|
|
@@ -294,7 +306,7 @@ const handleTargetDirectory = async (root: string, target: string, options: Crea
|
|
|
294
306
|
return;
|
|
295
307
|
}
|
|
296
308
|
|
|
297
|
-
if (await
|
|
309
|
+
if (await shouldOverwriteDirectory(target, options)) {
|
|
298
310
|
emptyDir(root);
|
|
299
311
|
|
|
300
312
|
return;
|
|
@@ -335,20 +347,20 @@ const resolvePackageManager = async (options: CreateOptions): Promise<PackageMan
|
|
|
335
347
|
return (await detectedPackageManager()) ?? "pnpm";
|
|
336
348
|
};
|
|
337
349
|
|
|
338
|
-
const
|
|
350
|
+
const isTypescriptSelected = async (options: CreateOptions): Promise<boolean> => {
|
|
339
351
|
if (options.isTypescript !== undefined) {
|
|
340
352
|
return options.isTypescript;
|
|
341
353
|
}
|
|
342
354
|
|
|
343
|
-
return options.isInteractive ?
|
|
355
|
+
return options.isInteractive ? shouldUseTypeScript() : true;
|
|
344
356
|
};
|
|
345
357
|
|
|
346
|
-
const
|
|
358
|
+
const isTestingIncluded = async (options: CreateOptions): Promise<boolean> => {
|
|
347
359
|
if (options.shouldIncludeTesting !== undefined) {
|
|
348
360
|
return options.shouldIncludeTesting;
|
|
349
361
|
}
|
|
350
362
|
|
|
351
|
-
return options.isInteractive ?
|
|
363
|
+
return options.isInteractive ? shouldSetUpTesting() : true;
|
|
352
364
|
};
|
|
353
365
|
|
|
354
366
|
const resolveOptions = async (options: CreateOptions): Promise<ResolvedOptions> => {
|
|
@@ -359,8 +371,8 @@ const resolveOptions = async (options: CreateOptions): Promise<ResolvedOptions>
|
|
|
359
371
|
const root = resolve(process.cwd(), target);
|
|
360
372
|
await handleTargetDirectory(root, target, options);
|
|
361
373
|
const packageManager = await resolvePackageManager(options);
|
|
362
|
-
const isTypescript = await
|
|
363
|
-
const shouldIncludeTesting = await
|
|
374
|
+
const isTypescript = await isTypescriptSelected(options);
|
|
375
|
+
const shouldIncludeTesting = await isTestingIncluded(options);
|
|
364
376
|
|
|
365
377
|
return { target, name, applicationId, packageManager, isTypescript, shouldIncludeTesting };
|
|
366
378
|
};
|
|
@@ -381,14 +393,9 @@ const toDestinationPath = (templateRelativePath: string, isTypescript: boolean):
|
|
|
381
393
|
isTypescript ? templateRelativePath : templateRelativePath.replace(/\.tsx$/, ".jsx").replace(/\.ts$/, ".js");
|
|
382
394
|
|
|
383
395
|
const addTestScript = (root: string): void => {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
scripts: Record<string, string>;
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
manifest.scripts.test = "vitest";
|
|
391
|
-
writeFileSync(packageJsonPath, `${JSON.stringify(manifest, null, 4)}\n`);
|
|
396
|
+
updateManifest(root, (manifest) => {
|
|
397
|
+
(manifest.scripts as Record<string, string>).test = "vitest run";
|
|
398
|
+
});
|
|
392
399
|
};
|
|
393
400
|
|
|
394
401
|
const scaffoldProject = async (root: string, resolved: ResolvedOptions): Promise<void> => {
|
|
@@ -420,13 +427,60 @@ const scaffoldProject = async (root: string, resolved: ResolvedOptions): Promise
|
|
|
420
427
|
}
|
|
421
428
|
};
|
|
422
429
|
|
|
430
|
+
const withoutInheritedScriptPolicy = async (run: () => Promise<void>): Promise<void> => {
|
|
431
|
+
const saved = INHERITED_SCRIPT_POLICY_VARS.map((key) => [key, process.env[key]] as const);
|
|
432
|
+
|
|
433
|
+
for (const [key] of saved) {
|
|
434
|
+
Reflect.deleteProperty(process.env, key);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
try {
|
|
438
|
+
await run();
|
|
439
|
+
} finally {
|
|
440
|
+
for (const [key, value] of saved) {
|
|
441
|
+
if (value !== undefined) {
|
|
442
|
+
process.env[key] = value;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
|
|
423
448
|
const installDependencies = async (options: InstallDependenciesOptions): Promise<void> => {
|
|
424
449
|
const { cwd, packageManager, dependencies, isDev } = options;
|
|
425
|
-
|
|
450
|
+
|
|
451
|
+
await withoutInheritedScriptPolicy(async () => {
|
|
452
|
+
await addDependency(dependencies, { cwd, packageManager, dev: isDev, silent: true });
|
|
453
|
+
});
|
|
426
454
|
};
|
|
427
455
|
|
|
428
456
|
const pin = (names: string[]): string[] => names.map((dependency) => pinGtkxDependency(dependency, selfVersion));
|
|
429
457
|
|
|
458
|
+
const formatRecovery = ({ target, packageManager, devDependencies }: InstallFailureOptions): string => {
|
|
459
|
+
const add = getAddCommand(packageManager);
|
|
460
|
+
|
|
461
|
+
const steps = [
|
|
462
|
+
...(target === "." ? [] : [`cd ${target}`]),
|
|
463
|
+
`${add} ${pin(DEPENDENCIES).join(" ")}`,
|
|
464
|
+
`${add} -D ${pin(devDependencies).join(" ")}`,
|
|
465
|
+
];
|
|
466
|
+
|
|
467
|
+
const indented = steps.map((step) => ` ${step}`).join("\n");
|
|
468
|
+
|
|
469
|
+
return `${RECOVERY_HEADING}\n${indented}`;
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
const reportInstallFailure = (options: InstallFailureOptions): void => {
|
|
473
|
+
const message = errorMessage(options.error);
|
|
474
|
+
p.log.error(`Failed to install dependencies: ${message}`);
|
|
475
|
+
const hint = getInstallHint(message);
|
|
476
|
+
|
|
477
|
+
if (hint !== undefined) {
|
|
478
|
+
p.log.warn(hint);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
p.log.info(formatRecovery(options));
|
|
482
|
+
};
|
|
483
|
+
|
|
430
484
|
const installAllDependencies = async (options: InstallAllOptions): Promise<void> => {
|
|
431
485
|
const { root, target, packageManager, devDependencies } = options;
|
|
432
486
|
const spinner = p.spinner();
|
|
@@ -438,8 +492,7 @@ const installAllDependencies = async (options: InstallAllOptions): Promise<void>
|
|
|
438
492
|
spinner.stop("Dependencies installed");
|
|
439
493
|
} catch (error) {
|
|
440
494
|
spinner.stop("Failed to install dependencies");
|
|
441
|
-
|
|
442
|
-
p.log.info(`Install them manually by running:\n cd ${target}\n ${getInstallCommand(packageManager)}`);
|
|
495
|
+
reportInstallFailure({ error, target, packageManager, devDependencies });
|
|
443
496
|
throw new ScaffoldAbortedError("Failed to install dependencies");
|
|
444
497
|
}
|
|
445
498
|
};
|
|
@@ -480,6 +533,7 @@ const scaffold = async (options: CreateOptions = {}): Promise<void> => {
|
|
|
480
533
|
const projectSpinner = p.spinner();
|
|
481
534
|
projectSpinner.start("Creating project structure...");
|
|
482
535
|
await scaffoldProject(root, resolved);
|
|
536
|
+
writeBuildAllowance(root, resolved.packageManager);
|
|
483
537
|
projectSpinner.stop("Project structure created");
|
|
484
538
|
|
|
485
539
|
await installAllDependencies({
|
|
@@ -11,12 +11,8 @@
|
|
|
11
11
|
"build": "gtkx build",
|
|
12
12
|
"codegen": "gtkx codegen",
|
|
13
13
|
<% if (isTypescript) { -%>
|
|
14
|
-
"typecheck": "gtkx codegen && tsc
|
|
14
|
+
"typecheck": "gtkx codegen && tsc",
|
|
15
15
|
<% } -%>
|
|
16
16
|
"start": "node dist/bundle.js"
|
|
17
|
-
},
|
|
18
|
-
"allowScripts": {
|
|
19
|
-
"esbuild": true,
|
|
20
|
-
"@swc/core": true
|
|
21
17
|
}
|
|
22
18
|
}
|
|
@@ -9,8 +9,11 @@
|
|
|
9
9
|
"resolveJsonModule": true,
|
|
10
10
|
"lib": ["esnext"],
|
|
11
11
|
"types": ["node", "react"],
|
|
12
|
-
"
|
|
13
|
-
"rootDir": "src"
|
|
12
|
+
"noEmit": true
|
|
14
13
|
},
|
|
14
|
+
<% if (shouldIncludeTesting) { -%>
|
|
15
|
+
"include": ["src/**/*", "tests/**/*"]
|
|
16
|
+
<% } else { -%>
|
|
15
17
|
"include": ["src/**/*"]
|
|
18
|
+
<% } -%>
|
|
16
19
|
}
|