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 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 the comparison in full.
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@rc
124
+ npm create gtkx
125
125
  ```
126
126
 
127
- The same command works with other package managers: `pnpm create gtkx@rc` or `yarn create gtkx@rc`.
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), and GLib development libraries
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 at the release candidate stage.
164
+ GTKX 1.0 is released.
165
165
 
166
166
  ## Contributing
167
167
 
@@ -0,0 +1,4 @@
1
+ import type { PackageManager } from "./package-managers.js";
2
+ declare const writeBuildAllowance: (root: string, packageManager: PackageManager) => void;
3
+ export { writeBuildAllowance };
4
+ //# sourceMappingURL=build-allowance.d.ts.map
@@ -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;AAEhD,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);\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"]}
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, type CreateCommandArgs };
51
+ export { scaffoldCommand, runCreate };
58
52
  //# sourceMappingURL=command.d.ts.map
@@ -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;;;;;GAKG;AACH,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,KAAK,iBAAiB,EAAE,CAAC"}
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",
@@ -1 +1 @@
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\n/**\n * Citty command definition for the CLI `create` subcommand. It declares the\n * scaffolder's arguments (target name, application ID, package manager,\n * TypeScript and Vitest toggles, prompt behavior, and overwrite) and runs the\n * scaffolder to generate a new GTKX application.\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, type CreateCommandArgs };\n"]}
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,3 @@
1
+ declare const getInstallHint: (message: string) => string | undefined;
2
+ export { getInstallHint };
3
+ //# sourceMappingURL=install-hints.d.ts.map
@@ -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,3 @@
1
+ declare const updateManifest: (root: string, mutate: (manifest: Record<string, unknown>) => void) => void;
2
+ export { updateManifest };
3
+ //# sourceMappingURL=manifest.d.ts.map
@@ -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"}
@@ -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 installCommand: "pnpm install";
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 installCommand: "npm install";
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 installCommand: "yarn install";
18
+ readonly addCommand: "yarn add";
19
19
  readonly isRecommended: false;
20
20
  }];
21
21
  declare const PACKAGE_MANAGER_FLAG_DESCRIPTION: string;
@@ -1,7 +1,7 @@
1
1
  const PACKAGE_MANAGERS = [
2
- { value: "pnpm", label: "pnpm", devCommand: "pnpm dev", installCommand: "pnpm install", isRecommended: true },
3
- { value: "npm", label: "npm", devCommand: "npm run dev", installCommand: "npm install", isRecommended: false },
4
- { value: "yarn", label: "yarn", devCommand: "yarn dev", installCommand: "yarn install", isRecommended: false },
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,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,IAAI,EAAE;IAC7G,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,EAAE;IAC9G,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,KAAK,EAAE;CACxG,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\", installCommand: \"pnpm install\", isRecommended: true },\n { value: \"npm\", label: \"npm\", devCommand: \"npm run dev\", installCommand: \"npm install\", isRecommended: false },\n { value: \"yarn\", label: \"yarn\", devCommand: \"yarn dev\", installCommand: \"yarn install\", 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"]}
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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"scaffolder.d.ts","sourceRoot":"","sources":["../src/scaffolder.ts"],"names":[],"mappings":"AAQA,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;AAscF,QAAA,MAAM,QAAQ,GAAU,UAAS,aAAkB,KAAG,OAAO,CAAC,IAAI,CAuBjE,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,CAAC"}
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"}
@@ -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, readFileSync, rmSync, writeFileSync } from "node:fs";
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 INSTALL_COMMAND = Object.fromEntries(PACKAGE_MANAGERS.map((manager) => [manager.value, manager.installCommand]));
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 getInstallCommand = (packageManager) => INSTALL_COMMAND[packageManager];
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 promptTypeScript = async () => guardCancellation(await p.confirm({
148
+ const shouldUseTypeScript = async () => guardCancellation(await p.confirm({
145
149
  message: "Use TypeScript?",
146
150
  initialValue: true,
147
151
  }));
148
- const promptTesting = async () => guardCancellation(await p.confirm({
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 confirmOverwrite = async (target, options) => {
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 confirmOverwrite(target, options)) {
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 resolveTypeScript = async (options) => {
217
+ const isTypescriptSelected = async (options) => {
214
218
  if (options.isTypescript !== undefined) {
215
219
  return options.isTypescript;
216
220
  }
217
- return options.isInteractive ? promptTypeScript() : true;
221
+ return options.isInteractive ? shouldUseTypeScript() : true;
218
222
  };
219
- const resolveIncludeTesting = async (options) => {
223
+ const isTestingIncluded = async (options) => {
220
224
  if (options.shouldIncludeTesting !== undefined) {
221
225
  return options.shouldIncludeTesting;
222
226
  }
223
- return options.isInteractive ? promptTesting() : true;
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 resolveTypeScript(options);
234
- const shouldIncludeTesting = await resolveIncludeTesting(options);
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
- const packageJsonPath = join(root, PACKAGE_JSON_TEMPLATE);
249
- const manifest = JSON.parse(readFileSync(packageJsonPath, "utf8"));
250
- manifest.scripts.test = "vitest";
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 addDependency(dependencies, { cwd, packageManager, dev: isDev, silent: true });
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
- p.log.error(`Failed to install dependencies: ${errorMessage(error)}`);
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,
@@ -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":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACpF,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,oBAAoB,IAAI,wBAAwB,EAAE,MAAM,MAAM,CAAC;AACvF,OAAO,EAAE,CAAC,EAAE,MAAM,UAAU,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAuB,MAAM,uBAAuB,CAAC;AACrG,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAwB,MAAM,gBAAgB,CAAC;AA0CjF,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;AAEvE,MAAM,sBAAsB,GAAG;;IAE3B,CAAC;AAEL,MAAM,YAAY,GAAG,CAAC,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;AAC5E,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;AAC5E,MAAM,2BAA2B,GAAG,CAAC,aAAa,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC;AAClF,MAAM,wBAAwB,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;AAE7D,MAAM,WAAW,GAAmC,MAAM,CAAC,WAAW,CAClE,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CACvC,CAAC;AAEpC,MAAM,WAAW,GAAmC,MAAM,CAAC,WAAW,CAClE,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CACvC,CAAC;AAEpC,MAAM,4BAA4B,GAAG,CAAC,0BAA0B,EAAE,0BAA0B,CAAC,CAAC;AAC9F,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,kBAAkB,EAAE,oBAAoB,CAAC,CAAC,CAAC;AAC9E,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAE7E,MAAM,wBAAwB,GAAG;;;;gCAID,CAAC;AAEjC,MAAM,gBAAgB,GAAG,6EAA6E,CAAC;AAEvG,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAE,OAAe,EAAU,EAAE,CAChE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAE7D,MAAM,aAAa,GAAG,CAAC,cAA8B,EAAU,EAAE,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;AAC9F,MAAM,aAAa,GAAG,CAAC,cAA8B,EAAU,EAAE,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;AAC9F,MAAM,aAAa,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC1G,MAAM,oBAAoB,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC;AAE7F,MAAM,oBAAoB,GAAG,CAAC,KAAa,EAAU,EAAE;IACnD,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC;IAEvB,OAAO,GAAG,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;QACvC,GAAG,EAAE,CAAC;IACV,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,MAAc,EAAU,EAAE,CAAC,oBAAoB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC;AACvH,MAAM,iBAAiB,GAAG,CAAC,MAAc,EAAU,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;AAE/F,MAAM,UAAU,GAAG,CAAC,GAAW,EAAW,EAAE;IACxC,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAEjC,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;AACnF,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,EACxB,YAAY,EACZ,oBAAoB,GACyC,EAAY,EAAE;IAC3E,MAAM,OAAO,GAAG,CAAC,GAAG,gBAAgB,CAAC,CAAC;IAEtC,IAAI,YAAY,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,GAAG,2BAA2B,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,oBAAoB,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,GAAG,wBAAwB,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAI,KAAiB,EAAK,EAAE;IAClD,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,CAAC,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAC/B,MAAM,IAAI,sBAAsB,EAAE,CAAC;IACvC,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,KAAyB,EAAsB,EAAE;IAC1E,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,OAAO,0BAA0B,CAAC;IACtC,CAAC;IAED,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,mEAAmE,CAAC;IAC/E,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,0BAA0B,GAAG,CAAC,KAAyB,EAAsB,EAAE;IACjF,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,OAAO,4BAA4B,CAAC;IACxC,CAAC;IAED,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,0EAA0E,CAAC;IACtF,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,IAAI,GAAG,CAAC,OAAe,EAAS,EAAE;IACpC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACrB,MAAM,IAAI,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,KAAyB,EAAsB,EAAE;IACrE,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,OAAO,+BAA+B,CAAC;IAC3C,CAAC;IAED,OAAO,mBAAmB,CAAC,iBAAiB,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC1E,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,KAAK,IAAqB,EAAE,CAC7C,iBAAiB,CACb,MAAM,CAAC,CAAC,IAAI,CAAC;IACT,OAAO,EAAE,mBAAmB;IAC5B,WAAW,EAAE,QAAQ;IACrB,QAAQ,EAAE,cAAc;CAC3B,CAAC,CACL,CAAC;AAEN,MAAM,mBAAmB,GAAG,KAAK,EAAE,IAAY,EAAmB,EAAE;IAChE,MAAM,oBAAoB,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAExD,OAAO,iBAAiB,CACpB,MAAM,CAAC,CAAC,IAAI,CAAC;QACT,OAAO,EAAE,gBAAgB;QACzB,WAAW,EAAE,oBAAoB;QACjC,YAAY,EAAE,oBAAoB;QAClC,QAAQ,EAAE,0BAA0B;KACvC,CAAC,CACL,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,KAAK,EAAE,GAAW,EAAuC,EAAE;IACpF,MAAM,QAAQ,GAAG,MAAM,wBAAwB,CAAC,GAAG,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC;IAElF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACZ,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,OAAO,qBAAqB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5E,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CACvB,OAA0C,EAC1C,QAAoC,EAClB,EAAE;IACpB,IAAI,QAAQ,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;QAC7B,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QACxB,OAAO,aAAa,CAAC;IACzB,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,OAA0C,EAAE,QAAoC,EAAE,EAAE;IAC9G,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAEnD,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAC/F,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,KAAK,IAAyC,EAAE;IAC3E,IAAI,CAAC;QACD,OAAO,MAAM,oBAAoB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,SAAS,CAAC;IACrB,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,KAAK,IAA6B,EAAE;IAC7D,MAAM,QAAQ,GAAG,MAAM,sBAAsB,EAAE,CAAC;IAChD,MAAM,OAAO,GAAmB,QAAQ,IAAI,MAAM,CAAC;IAEnD,OAAO,iBAAiB,CACpB,MAAM,CAAC,CAAC,MAAM,CAAiB;QAC3B,OAAO,EAAE,iBAAiB;QAC1B,OAAO,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,oBAAoB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACnF,YAAY,EAAE,OAAO;KACxB,CAAC,CACL,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,KAAK,IAAsB,EAAE,CACrD,iBAAiB,CACb,MAAM,CAAC,CAAC,OAAO,CAAC;IACZ,OAAO,EAAE,iBAAiB;IAC1B,YAAY,EAAE,IAAI;CACrB,CAAC,CACL,CAAC;AAEN,MAAM,kBAAkB,GAAG,KAAK,IAAsB,EAAE,CACpD,iBAAiB,CACb,MAAM,CAAC,CAAC,OAAO,CAAC;IACZ,OAAO,EAAE,iCAAiC;IAC1C,YAAY,EAAE,IAAI;CACrB,CAAC,CACL,CAAC;AAEN,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAQ,EAAE;IACpC,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YACnB,SAAS;QACb,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAG,CAAC,IAAY,EAAE,aAAqB,EAAQ,EAAE;IAC1E,MAAM,SAAS,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAE5C,IAAI,SAAS,EAAE,CAAC;QACZ,IAAI,CAAC,SAAS,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,kBAAkB,GAAG,0BAA0B,CAAC,aAAa,CAAC,CAAC;IAErE,IAAI,kBAAkB,EAAE,CAAC;QACrB,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC7B,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,wBAAwB,GAAG,KAAK,EAAE,MAAc,EAAE,OAAsB,EAAoB,EAAE;IAChG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC,eAAe,KAAK,IAAI,CAAC;IAC5C,CAAC;IAED,OAAO,iBAAiB,CACpB,MAAM,CAAC,CAAC,OAAO,CAAC;QACZ,OAAO,EAAE,cAAc,MAAM,yCAAyC;QACtE,YAAY,EAAE,KAAK;KACtB,CAAC,CACL,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,KAAK,EAAE,IAAY,EAAE,MAAc,EAAE,OAAsB,EAAiB,EAAE;IACxG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,OAAO;IACX,CAAC;IAED,IAAI,MAAM,wBAAwB,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;QAClD,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEf,OAAO;IACX,CAAC;IAED,IAAI,CAAC,cAAc,MAAM,gBAAgB,CAAC,CAAC;AAC/C,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,KAAK,EAAE,OAAsB,EAAmB,EAAE;IACpE,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,+BAA+B,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,eAAe,CAAC,MAAM,YAAY,EAAE,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,KAAK,EAAE,OAAsB,EAAE,IAAY,EAAmB,EAAE;IACzF,IAAI,OAAO,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO,OAAO,CAAC,aAAa,CAAC;IACjC,CAAC;IAED,OAAO,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;AAC1F,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,KAAK,EAAE,OAAsB,EAA2B,EAAE;IACpF,IAAI,OAAO,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;QACvC,OAAO,OAAO,CAAC,cAAc,CAAC;IAClC,CAAC;IAED,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QACxB,OAAO,oBAAoB,EAAE,CAAC;IAClC,CAAC;IAED,OAAO,CAAC,MAAM,sBAAsB,EAAE,CAAC,IAAI,MAAM,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,KAAK,EAAE,OAAsB,EAAoB,EAAE;IAC5E,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QACrC,OAAO,OAAO,CAAC,YAAY,CAAC;IAChC,CAAC;IAED,OAAO,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAChE,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,KAAK,EAAE,OAAsB,EAAoB,EAAE;IACzE,IAAI,OAAO,CAAC,oBAAoB,KAAK,SAAS,EAAE,CAAC;QAC7C,OAAO,OAAO,CAAC,oBAAoB,CAAC;IACxC,CAAC;IAED,OAAO,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/D,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,KAAK,EAAE,OAAsB,EAA4B,EAAE;IAC9E,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAChE,uBAAuB,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;IAC5C,MAAM,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACnD,MAAM,cAAc,GAAG,MAAM,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC5D,MAAM,YAAY,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACzD,MAAM,oBAAoB,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAE9D,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,oBAAoB,EAAE,CAAC;AAC/F,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,oBAA4B,EAAE,QAAyB,EAAW,EAAE;IAC5F,IAAI,iBAAiB,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,CAAC;QAC9C,OAAO,QAAQ,CAAC,oBAAoB,CAAC;IACzC,CAAC;IAED,IAAI,oBAAoB,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,CAAC;QACjD,OAAO,QAAQ,CAAC,YAAY,CAAC;IACjC,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,oBAA4B,EAAE,YAAqB,EAAU,EAAE,CACtF,YAAY,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAEjH,MAAM,aAAa,GAAG,CAAC,IAAY,EAAQ,EAAE;IACzC,cAAc,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,EAAE;QAC7B,QAAQ,CAAC,OAAkC,CAAC,IAAI,GAAG,YAAY,CAAC;IACrE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,KAAK,EAAE,IAAY,EAAE,QAAyB,EAAiB,EAAE;IACrF,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,YAAY,EAAE,oBAAoB,EAAE,GAAG,QAAQ,CAAC;IAE7E,MAAM,OAAO,GAAoB;QAC7B,IAAI;QACJ,aAAa;QACb,KAAK,EAAE,aAAa,CAAC,IAAI,CAAC;QAC1B,oBAAoB;QACpB,YAAY;QACZ,eAAe,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM;KACjD,CAAC;IAEF,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAErC,KAAK,MAAM,QAAQ,IAAI,aAAa,EAAE,EAAE,CAAC;QACrC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;YAC1C,SAAS;QACb,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC;QAC1E,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,aAAa,CAAC,WAAW,EAAE,MAAM,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,oBAAoB,EAAE,CAAC;QACvB,aAAa,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,4BAA4B,GAAG,KAAK,EAAE,GAAwB,EAAiB,EAAE;IACnF,MAAM,KAAK,GAAG,4BAA4B,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAU,CAAC,CAAC;IAE1F,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,CAAC;QACD,MAAM,GAAG,EAAE,CAAC;IAChB,CAAC;YAAS,CAAC;QACP,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;YAC/B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACtB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YAC7B,CAAC;QACL,CAAC;IACL,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,KAAK,EAAE,OAAmC,EAAiB,EAAE;IACrF,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAE7D,MAAM,4BAA4B,CAAC,KAAK,IAAI,EAAE;QAC1C,MAAM,aAAa,CAAC,YAAY,EAAE,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,GAAG,GAAG,CAAC,KAAe,EAAY,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,iBAAiB,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;AAEjH,MAAM,cAAc,GAAG,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAyB,EAAU,EAAE;IAClG,MAAM,GAAG,GAAG,aAAa,CAAC,cAAc,CAAC,CAAC;IAE1C,MAAM,KAAK,GAAG;QACV,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC;QAC3C,GAAG,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QACvC,GAAG,GAAG,OAAO,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;KAChD,CAAC;IAEF,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE7D,OAAO,GAAG,gBAAgB,KAAK,QAAQ,EAAE,CAAC;AAC9C,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,OAA8B,EAAQ,EAAE;IAClE,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,mCAAmC,OAAO,EAAE,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAErC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACrB,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAED,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;AACxC,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,KAAK,EAAE,OAA0B,EAAiB,EAAE;IAC/E,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC;IAClE,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAC5B,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAE5C,IAAI,CAAC;QACD,MAAM,mBAAmB,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,GAAG,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACxG,MAAM,mBAAmB,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,GAAG,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1G,OAAO,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAC/C,oBAAoB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,CAAC,CAAC;QACzE,MAAM,IAAI,oBAAoB,CAAC,gCAAgC,CAAC,CAAC;IACrE,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAAQ,EAAE;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;IACrD,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,GAAG,sBAAsB,IAAI,CAAC,CAAC;AAC7E,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,KAAK,EAAE,IAAY,EAAiB,EAAE;IAC5D,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAC5B,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAEhD,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,YAAY,EAAE,IAAI,EAAW,CAAC;QACzE,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,gBAAgB,CAAC,EAAE,IAAI,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;IACxD,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,QAAyB,EAAQ,EAAE;IACvD,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,MAAM,IAAI,CAAC;IACxE,MAAM,WAAW,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,CAAC,CAAC,IAAI,CAAC,GAAG,MAAM,GAAG,MAAM,GAAG,WAAW,EAAE,EAAE,YAAY,CAAC,CAAC;AAC7D,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,KAAK,EAAE,UAAyB,EAAE,EAAiB,EAAE;IAClE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC3B,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,cAAc,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IACnC,cAAc,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACtD,MAAM,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACtC,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IACnD,cAAc,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAEjD,MAAM,sBAAsB,CAAC;QACzB,IAAI;QACJ,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,cAAc,EAAE,QAAQ,CAAC,cAAc;QACvC,eAAe,EAAE,OAAO;KAC3B,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;QACxB,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC9B,cAAc,CAAC,QAAQ,CAAC,CAAC;AAC7B,CAAC,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAsB,CAAC","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 --noEmit",
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
- "outDir": "out-tsc",
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-rc.4",
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.2.4",
54
- "@gtkx/config": "1.0.0-rc.4",
55
- "@gtkx/utils": "1.0.0-rc.4"
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.1.2",
60
- "memfs": "^4.64.0",
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, type CreateCommandArgs };
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 };
@@ -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 };
@@ -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", installCommand: "pnpm install", isRecommended: true },
5
- { value: "npm", label: "npm", devCommand: "npm run dev", installCommand: "npm install", isRecommended: false },
6
- { value: "yarn", label: "yarn", devCommand: "yarn dev", installCommand: "yarn install", isRecommended: false },
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, readFileSync, rmSync, writeFileSync } from "node:fs";
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
- const selfVersion = packageVersion(import.meta.url);
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 INSTALL_COMMAND: Record<PackageManager, string> = Object.fromEntries(
62
- PACKAGE_MANAGERS.map((manager) => [manager.value, manager.installCommand]),
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 getInstallCommand = (packageManager: PackageManager): string => INSTALL_COMMAND[packageManager];
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 promptTypeScript = async (): Promise<boolean> =>
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 promptTesting = async (): Promise<boolean> =>
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 confirmOverwrite = async (target: string, options: CreateOptions): Promise<boolean> => {
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 confirmOverwrite(target, options)) {
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 resolveTypeScript = async (options: CreateOptions): Promise<boolean> => {
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 ? promptTypeScript() : true;
355
+ return options.isInteractive ? shouldUseTypeScript() : true;
344
356
  };
345
357
 
346
- const resolveIncludeTesting = async (options: CreateOptions): Promise<boolean> => {
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 ? promptTesting() : true;
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 resolveTypeScript(options);
363
- const shouldIncludeTesting = await resolveIncludeTesting(options);
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
- const packageJsonPath = join(root, PACKAGE_JSON_TEMPLATE);
385
-
386
- const manifest = JSON.parse(readFileSync(packageJsonPath, "utf8")) as {
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
- await addDependency(dependencies, { cwd, packageManager, dev: isDev, silent: true });
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
- p.log.error(`Failed to install dependencies: ${errorMessage(error)}`);
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 --noEmit",
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
- "outDir": "out-tsc",
13
- "rootDir": "src"
12
+ "noEmit": true
14
13
  },
14
+ <% if (shouldIncludeTesting) { -%>
15
+ "include": ["src/**/*", "tests/**/*"]
16
+ <% } else { -%>
15
17
  "include": ["src/**/*"]
18
+ <% } -%>
16
19
  }