@craft-ts/cli 0.7.0-beta.15

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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -0
  3. package/package.json +53 -0
  4. package/src/bin/craft-ts.d.ts +3 -0
  5. package/src/bin/craft-ts.d.ts.map +1 -0
  6. package/src/bin/craft-ts.js +9 -0
  7. package/src/bin/craft-ts.js.map +1 -0
  8. package/src/index.d.ts +10 -0
  9. package/src/index.d.ts.map +1 -0
  10. package/src/index.js +6 -0
  11. package/src/index.js.map +1 -0
  12. package/src/lib/args.d.ts +21 -0
  13. package/src/lib/args.d.ts.map +1 -0
  14. package/src/lib/args.js +37 -0
  15. package/src/lib/args.js.map +1 -0
  16. package/src/lib/commands/check.d.ts +8 -0
  17. package/src/lib/commands/check.d.ts.map +1 -0
  18. package/src/lib/commands/check.js +79 -0
  19. package/src/lib/commands/check.js.map +1 -0
  20. package/src/lib/commands/deploy.d.ts +10 -0
  21. package/src/lib/commands/deploy.d.ts.map +1 -0
  22. package/src/lib/commands/deploy.js +199 -0
  23. package/src/lib/commands/deploy.js.map +1 -0
  24. package/src/lib/commands/manifest.d.ts +10 -0
  25. package/src/lib/commands/manifest.d.ts.map +1 -0
  26. package/src/lib/commands/manifest.js +67 -0
  27. package/src/lib/commands/manifest.js.map +1 -0
  28. package/src/lib/commands/providers.d.ts +9 -0
  29. package/src/lib/commands/providers.d.ts.map +1 -0
  30. package/src/lib/commands/providers.js +42 -0
  31. package/src/lib/commands/providers.js.map +1 -0
  32. package/src/lib/io.d.ts +7 -0
  33. package/src/lib/io.d.ts.map +1 -0
  34. package/src/lib/io.js +12 -0
  35. package/src/lib/io.js.map +1 -0
  36. package/src/lib/load-config.d.ts +22 -0
  37. package/src/lib/load-config.d.ts.map +1 -0
  38. package/src/lib/load-config.js +158 -0
  39. package/src/lib/load-config.js.map +1 -0
  40. package/src/lib/load-provider.d.ts +25 -0
  41. package/src/lib/load-provider.d.ts.map +1 -0
  42. package/src/lib/load-provider.js +92 -0
  43. package/src/lib/load-provider.js.map +1 -0
  44. package/src/lib/run.d.ts +8 -0
  45. package/src/lib/run.d.ts.map +1 -0
  46. package/src/lib/run.js +48 -0
  47. package/src/lib/run.js.map +1 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Romain Geffrault
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # @craft-ts/cli
2
+
3
+ Deployment CLI of CraftTS.
4
+
5
+ > **Experimental.** The command surface is not settled. `check`, `manifest`,
6
+ > `providers`, `deploy preview` and `deploy` exist today; `init`, `build` and
7
+ > `deploy init` do not yet.
8
+
9
+ ```bash
10
+ npx craft-ts check --provider docker
11
+ npx craft-ts manifest --out dist/apps/demo-ssr/craft-deployment-manifest.json
12
+ npx craft-ts providers
13
+ ```
14
+
15
+ `check` validates the manifest, the declared paths, the runtime/platform pair,
16
+ the provider capabilities and the module graph of the runtime entry — before
17
+ any build has run. `manifest` resolves the manifest to the provider-neutral
18
+ artefact form. `providers` prints the capability matrix.
19
+
20
+ The CLI never creates a secret and never mutates an infrastructure: publishing
21
+ and provisioning belong to a provider package.
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@craft-ts/cli",
3
+ "version": "0.7.0-beta.15",
4
+ "description": "CraftTS deployment CLI: check a deployment manifest and resolve it to its artefact form",
5
+ "author": "Romain Geffrault",
6
+ "license": "MIT",
7
+ "homepage": "https://craft-ts.github.io/craft/",
8
+ "bugs": {
9
+ "url": "https://github.com/craft-ts/craft-ts/issues"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/craft-ts/craft-ts.git"
14
+ },
15
+ "keywords": [
16
+ "craft-ts",
17
+ "cli",
18
+ "deployment",
19
+ "manifest",
20
+ "typescript"
21
+ ],
22
+ "engines": {
23
+ "node": ">=20.19.0"
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "type": "module",
29
+ "main": "./src/index.js",
30
+ "types": "./src/index.d.ts",
31
+ "exports": {
32
+ "./package.json": "./package.json",
33
+ ".": {
34
+ "types": "./src/index.d.ts",
35
+ "default": "./src/index.js"
36
+ }
37
+ },
38
+ "bin": {
39
+ "craft-ts": "./src/bin/craft-ts.js"
40
+ },
41
+ "dependencies": {
42
+ "@craft-ts/deploy": "^0.7.0-beta.0"
43
+ },
44
+ "peerDependencies": {
45
+ "typescript": ">=5.4.0"
46
+ },
47
+ "peerDependenciesMeta": {
48
+ "typescript": {
49
+ "optional": true
50
+ }
51
+ },
52
+ "module": "./src/index.js"
53
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=craft-ts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"craft-ts.d.ts","sourceRoot":"","sources":["../../../../../libs/cli/src/bin/craft-ts.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ import { runCraftCli } from '../lib/run.js';
3
+ runCraftCli(process.argv.slice(2)).then((code) => {
4
+ process.exitCode = code;
5
+ }, (error) => {
6
+ process.stderr.write(`${error instanceof Error ? error.stack : String(error)}\n`);
7
+ process.exitCode = 1;
8
+ });
9
+ //# sourceMappingURL=craft-ts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"craft-ts.js","sourceRoot":"","sources":["../../../../../libs/cli/src/bin/craft-ts.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CACrC,CAAC,IAAI,EAAE,EAAE;IACP,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;AAC1B,CAAC,EACD,CAAC,KAAc,EAAE,EAAE;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAC5D,CAAC;IACF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CACF,CAAC","sourcesContent":["#!/usr/bin/env node\n\nimport { runCraftCli } from '../lib/run.js';\n\nrunCraftCli(process.argv.slice(2)).then(\n (code) => {\n process.exitCode = code;\n },\n (error: unknown) => {\n process.stderr.write(\n `${error instanceof Error ? error.stack : String(error)}\\n`,\n );\n process.exitCode = 1;\n },\n);\n"]}
package/src/index.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ export { CRAFT_CLI_HELP, runCraftCli } from './lib/run.js';
2
+ export { processIo } from './lib/io.js';
3
+ export type { CraftCliIo } from './lib/io.js';
4
+ export { CRAFT_DEPLOYMENT_CONFIG_FILES, loadCraftDeploymentConfig, } from './lib/load-config.js';
5
+ export type { LoadCraftDeploymentConfigOptions, LoadedCraftDeploymentConfig, } from './lib/load-config.js';
6
+ export { loadCraftDeploymentProvider } from './lib/load-provider.js';
7
+ export type { LoadCraftDeploymentProviderOptions, LoadedCraftDeploymentProvider, } from './lib/load-provider.js';
8
+ export { parseArguments } from './lib/args.js';
9
+ export type { OptionSpec, ParsedArguments } from './lib/args.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../libs/cli/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,6BAA6B,EAC7B,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,gCAAgC,EAChC,2BAA2B,GAC5B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AACrE,YAAY,EACV,kCAAkC,EAClC,6BAA6B,GAC9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
package/src/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { CRAFT_CLI_HELP, runCraftCli } from './lib/run.js';
2
+ export { processIo } from './lib/io.js';
3
+ export { CRAFT_DEPLOYMENT_CONFIG_FILES, loadCraftDeploymentConfig, } from './lib/load-config.js';
4
+ export { loadCraftDeploymentProvider } from './lib/load-provider.js';
5
+ export { parseArguments } from './lib/args.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/cli/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EACL,6BAA6B,EAC7B,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAK9B,OAAO,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAKrE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC","sourcesContent":["export { CRAFT_CLI_HELP, runCraftCli } from './lib/run.js';\nexport { processIo } from './lib/io.js';\nexport type { CraftCliIo } from './lib/io.js';\nexport {\n CRAFT_DEPLOYMENT_CONFIG_FILES,\n loadCraftDeploymentConfig,\n} from './lib/load-config.js';\nexport type {\n LoadCraftDeploymentConfigOptions,\n LoadedCraftDeploymentConfig,\n} from './lib/load-config.js';\nexport { loadCraftDeploymentProvider } from './lib/load-provider.js';\nexport type {\n LoadCraftDeploymentProviderOptions,\n LoadedCraftDeploymentProvider,\n} from './lib/load-provider.js';\nexport { parseArguments } from './lib/args.js';\nexport type { OptionSpec, ParsedArguments } from './lib/args.js';\n"]}
@@ -0,0 +1,21 @@
1
+ export type ParsedArguments = Readonly<{
2
+ command: string | null;
3
+ values: Readonly<Record<string, string>>;
4
+ flags: ReadonlySet<string>;
5
+ /** Options the command does not know about. */
6
+ unknown: readonly string[];
7
+ }>;
8
+ export type OptionSpec = Readonly<{
9
+ /** Options taking a value, e.g. `--config <path>`. */
10
+ values: readonly string[];
11
+ /** Options used as switches, e.g. `--json`. */
12
+ flags: readonly string[];
13
+ }>;
14
+ /**
15
+ * Minimal option parser.
16
+ *
17
+ * Unknown options are collected instead of ignored: a typo in a deployment
18
+ * command must fail loudly rather than silently check something else.
19
+ */
20
+ export declare function parseArguments(argv: readonly string[], spec: OptionSpec): ParsedArguments;
21
+ //# sourceMappingURL=args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../../../../libs/cli/src/lib/args.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,+CAA+C;IAC/C,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B,CAAC,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,sDAAsD;IACtD,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,+CAA+C;IAC/C,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B,CAAC,CAAC;AAEH;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,IAAI,EAAE,UAAU,GACf,eAAe,CA+BjB"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Minimal option parser.
3
+ *
4
+ * Unknown options are collected instead of ignored: a typo in a deployment
5
+ * command must fail loudly rather than silently check something else.
6
+ */
7
+ export function parseArguments(argv, spec) {
8
+ const values = {};
9
+ const flags = new Set();
10
+ const unknown = [];
11
+ let command = null;
12
+ for (let index = 0; index < argv.length; index += 1) {
13
+ const argument = argv[index];
14
+ if (!argument.startsWith('-')) {
15
+ command ??= argument;
16
+ continue;
17
+ }
18
+ const name = argument.replace(/^--?/, '');
19
+ if (spec.flags.includes(name)) {
20
+ flags.add(name);
21
+ continue;
22
+ }
23
+ if (spec.values.includes(name)) {
24
+ const next = argv[index + 1];
25
+ if (next === undefined || next.startsWith('-')) {
26
+ unknown.push(`${argument} (missing value)`);
27
+ continue;
28
+ }
29
+ values[name] = next;
30
+ index += 1;
31
+ continue;
32
+ }
33
+ unknown.push(argument);
34
+ }
35
+ return { command, values, flags, unknown };
36
+ }
37
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../../../../libs/cli/src/lib/args.ts"],"names":[],"mappings":"AAeA;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAuB,EACvB,IAAgB;IAEhB,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,OAAO,GAAkB,IAAI,CAAC;IAElC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAW,CAAC;QACvC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9B,OAAO,KAAK,QAAQ,CAAC;YACrB,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC1C,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAChB,SAAS;QACX,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YAC7B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/C,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,kBAAkB,CAAC,CAAC;gBAC5C,SAAS;YACX,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YACpB,KAAK,IAAI,CAAC,CAAC;YACX,SAAS;QACX,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC7C,CAAC","sourcesContent":["export type ParsedArguments = Readonly<{\n command: string | null;\n values: Readonly<Record<string, string>>;\n flags: ReadonlySet<string>;\n /** Options the command does not know about. */\n unknown: readonly string[];\n}>;\n\nexport type OptionSpec = Readonly<{\n /** Options taking a value, e.g. `--config <path>`. */\n values: readonly string[];\n /** Options used as switches, e.g. `--json`. */\n flags: readonly string[];\n}>;\n\n/**\n * Minimal option parser.\n *\n * Unknown options are collected instead of ignored: a typo in a deployment\n * command must fail loudly rather than silently check something else.\n */\nexport function parseArguments(\n argv: readonly string[],\n spec: OptionSpec,\n): ParsedArguments {\n const values: Record<string, string> = {};\n const flags = new Set<string>();\n const unknown: string[] = [];\n let command: string | null = null;\n\n for (let index = 0; index < argv.length; index += 1) {\n const argument = argv[index] as string;\n if (!argument.startsWith('-')) {\n command ??= argument;\n continue;\n }\n const name = argument.replace(/^--?/, '');\n if (spec.flags.includes(name)) {\n flags.add(name);\n continue;\n }\n if (spec.values.includes(name)) {\n const next = argv[index + 1];\n if (next === undefined || next.startsWith('-')) {\n unknown.push(`${argument} (missing value)`);\n continue;\n }\n values[name] = next;\n index += 1;\n continue;\n }\n unknown.push(argument);\n }\n\n return { command, values, flags, unknown };\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import type { CraftCliIo } from '../io.js';
2
+ export declare const CHECK_HELP = "craft-ts check \u2014 validate a deployment manifest before building\n\nOptions:\n --config <path> Manifest to read (default: craft.deploy.* in the root)\n --root <dir> Directory the manifest paths are relative to\n --runtime <name> Assert the manifest declares this runtime\n --platform <name> Assert the manifest declares this platform\n --provider <name> Check the provider capabilities against the manifest\n --artifact Also inspect the built artefact\n --json Emit a machine-readable report";
3
+ /**
4
+ * Validates a manifest and reports what has to change before a deployment is
5
+ * attempted. Nothing is written and no provider is contacted.
6
+ */
7
+ export declare function runCheckCommand(argv: readonly string[], io: CraftCliIo): Promise<number>;
8
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/commands/check.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAQ3C,eAAO,MAAM,UAAU,0iBAS+B,CAAC;AAEvD;;;GAGG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,EAAE,EAAE,UAAU,GACb,OAAO,CAAC,MAAM,CAAC,CAoCjB"}
@@ -0,0 +1,79 @@
1
+ import { resolve } from 'node:path';
2
+ import { checkCraftDeployment, formatCraftDeploymentDiagnostic, } from '@craft-ts/deploy';
3
+ import { parseArguments } from '../args.js';
4
+ import { loadCraftDeploymentConfig } from '../load-config.js';
5
+ const SPEC = {
6
+ values: ['config', 'root', 'runtime', 'platform', 'provider'],
7
+ flags: ['artifact', 'json', 'help'],
8
+ };
9
+ export const CHECK_HELP = `craft-ts check — validate a deployment manifest before building
10
+
11
+ Options:
12
+ --config <path> Manifest to read (default: craft.deploy.* in the root)
13
+ --root <dir> Directory the manifest paths are relative to
14
+ --runtime <name> Assert the manifest declares this runtime
15
+ --platform <name> Assert the manifest declares this platform
16
+ --provider <name> Check the provider capabilities against the manifest
17
+ --artifact Also inspect the built artefact
18
+ --json Emit a machine-readable report`;
19
+ /**
20
+ * Validates a manifest and reports what has to change before a deployment is
21
+ * attempted. Nothing is written and no provider is contacted.
22
+ */
23
+ export async function runCheckCommand(argv, io) {
24
+ const parsed = parseArguments(argv, SPEC);
25
+ if (parsed.flags.has('help')) {
26
+ io.write(CHECK_HELP);
27
+ return 0;
28
+ }
29
+ if (parsed.unknown.length > 0) {
30
+ io.writeError(`Unknown option(s): ${parsed.unknown.join(', ')}`);
31
+ io.writeError(CHECK_HELP);
32
+ return 1;
33
+ }
34
+ const rootDir = resolve(io.cwd, parsed.values['root'] ?? '.');
35
+ const loaded = await loadCraftDeploymentConfig({
36
+ rootDir,
37
+ config: parsed.values['config'],
38
+ });
39
+ const json = parsed.flags.has('json');
40
+ if (loaded.definition === null) {
41
+ return report(io, json, loaded.file, null, loaded.diagnostics);
42
+ }
43
+ const result = checkCraftDeployment({
44
+ rootDir,
45
+ definition: loaded.definition,
46
+ provider: parsed.values['provider'],
47
+ runtime: parsed.values['runtime'],
48
+ platform: parsed.values['platform'],
49
+ artifact: parsed.flags.has('artifact'),
50
+ });
51
+ return report(io, json, loaded.file, result.manifest, [
52
+ ...loaded.diagnostics,
53
+ ...result.diagnostics,
54
+ ]);
55
+ }
56
+ function report(io, json, file, manifest, diagnostics) {
57
+ const errors = diagnostics.filter((diagnostic) => diagnostic.severity === 'error').length;
58
+ const warnings = diagnostics.length - errors;
59
+ if (json) {
60
+ io.write(JSON.stringify({ passed: errors === 0, manifest: manifest ?? null, diagnostics }, null, 2));
61
+ return errors === 0 ? 0 : 1;
62
+ }
63
+ if (file)
64
+ io.write(`manifest: ${file}`);
65
+ for (const diagnostic of diagnostics) {
66
+ const text = formatCraftDeploymentDiagnostic(diagnostic);
67
+ if (diagnostic.severity === 'error')
68
+ io.writeError(text);
69
+ else
70
+ io.write(text);
71
+ }
72
+ if (errors === 0) {
73
+ io.write(`Deployment check passed${warnings > 0 ? ` with ${warnings} warning(s)` : ''}.`);
74
+ return 0;
75
+ }
76
+ io.writeError(`Deployment check failed with ${errors} error(s)${warnings > 0 ? ` and ${warnings} warning(s)` : ''}.`);
77
+ return 1;
78
+ }
79
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/commands/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,oBAAoB,EACpB,+BAA+B,GAEhC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,MAAM,IAAI,GAAG;IACX,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,CAAC;IAC7D,KAAK,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEX,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;sDAS4B,CAAC;AAEvD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAuB,EACvB,EAAc;IAEd,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC1C,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACrB,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,EAAE,CAAC,UAAU,CAAC,sBAAsB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjE,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAC1B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,MAAM,yBAAyB,CAAC;QAC7C,OAAO;QACP,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;KAChC,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAEtC,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,MAAM,GAAG,oBAAoB,CAAC;QAClC,OAAO;QACP,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;QACnC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC;QACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;QACnC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;KACvC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE;QACpD,GAAG,MAAM,CAAC,WAAW;QACrB,GAAG,MAAM,CAAC,WAAW;KACtB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,MAAM,CACb,EAAc,EACd,IAAa,EACb,IAAmB,EACnB,QAAiB,EACjB,WAAiD;IAEjD,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAC/B,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,KAAK,OAAO,CAChD,CAAC,MAAM,CAAC;IACT,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC;IAE7C,IAAI,IAAI,EAAE,CAAC;QACT,EAAE,CAAC,KAAK,CACN,IAAI,CAAC,SAAS,CACZ,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,EAAE,WAAW,EAAE,EACjE,IAAI,EACJ,CAAC,CACF,CACF,CAAC;QACF,OAAO,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,IAAI;QAAE,EAAE,CAAC,KAAK,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;IACxC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,+BAA+B,CAAC,UAAU,CAAC,CAAC;QACzD,IAAI,UAAU,CAAC,QAAQ,KAAK,OAAO;YAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;;YACpD,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;QACjB,EAAE,CAAC,KAAK,CACN,0BAA0B,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,QAAQ,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,CAChF,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IACD,EAAE,CAAC,UAAU,CACX,gCAAgC,MAAM,YAAY,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,QAAQ,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,CACvG,CAAC;IACF,OAAO,CAAC,CAAC;AACX,CAAC","sourcesContent":["import { resolve } from 'node:path';\nimport {\n checkCraftDeployment,\n formatCraftDeploymentDiagnostic,\n type CraftDeploymentDiagnostic,\n} from '@craft-ts/deploy';\nimport { parseArguments } from '../args.js';\nimport type { CraftCliIo } from '../io.js';\nimport { loadCraftDeploymentConfig } from '../load-config.js';\n\nconst SPEC = {\n values: ['config', 'root', 'runtime', 'platform', 'provider'],\n flags: ['artifact', 'json', 'help'],\n} as const;\n\nexport const CHECK_HELP = `craft-ts check — validate a deployment manifest before building\n\nOptions:\n --config <path> Manifest to read (default: craft.deploy.* in the root)\n --root <dir> Directory the manifest paths are relative to\n --runtime <name> Assert the manifest declares this runtime\n --platform <name> Assert the manifest declares this platform\n --provider <name> Check the provider capabilities against the manifest\n --artifact Also inspect the built artefact\n --json Emit a machine-readable report`;\n\n/**\n * Validates a manifest and reports what has to change before a deployment is\n * attempted. Nothing is written and no provider is contacted.\n */\nexport async function runCheckCommand(\n argv: readonly string[],\n io: CraftCliIo,\n): Promise<number> {\n const parsed = parseArguments(argv, SPEC);\n if (parsed.flags.has('help')) {\n io.write(CHECK_HELP);\n return 0;\n }\n if (parsed.unknown.length > 0) {\n io.writeError(`Unknown option(s): ${parsed.unknown.join(', ')}`);\n io.writeError(CHECK_HELP);\n return 1;\n }\n\n const rootDir = resolve(io.cwd, parsed.values['root'] ?? '.');\n const loaded = await loadCraftDeploymentConfig({\n rootDir,\n config: parsed.values['config'],\n });\n const json = parsed.flags.has('json');\n\n if (loaded.definition === null) {\n return report(io, json, loaded.file, null, loaded.diagnostics);\n }\n\n const result = checkCraftDeployment({\n rootDir,\n definition: loaded.definition,\n provider: parsed.values['provider'],\n runtime: parsed.values['runtime'],\n platform: parsed.values['platform'],\n artifact: parsed.flags.has('artifact'),\n });\n\n return report(io, json, loaded.file, result.manifest, [\n ...loaded.diagnostics,\n ...result.diagnostics,\n ]);\n}\n\nfunction report(\n io: CraftCliIo,\n json: boolean,\n file: string | null,\n manifest: unknown,\n diagnostics: readonly CraftDeploymentDiagnostic[],\n): number {\n const errors = diagnostics.filter(\n (diagnostic) => diagnostic.severity === 'error',\n ).length;\n const warnings = diagnostics.length - errors;\n\n if (json) {\n io.write(\n JSON.stringify(\n { passed: errors === 0, manifest: manifest ?? null, diagnostics },\n null,\n 2,\n ),\n );\n return errors === 0 ? 0 : 1;\n }\n\n if (file) io.write(`manifest: ${file}`);\n for (const diagnostic of diagnostics) {\n const text = formatCraftDeploymentDiagnostic(diagnostic);\n if (diagnostic.severity === 'error') io.writeError(text);\n else io.write(text);\n }\n\n if (errors === 0) {\n io.write(\n `Deployment check passed${warnings > 0 ? ` with ${warnings} warning(s)` : ''}.`,\n );\n return 0;\n }\n io.writeError(\n `Deployment check failed with ${errors} error(s)${warnings > 0 ? ` and ${warnings} warning(s)` : ''}.`,\n );\n return 1;\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import type { CraftCliIo } from '../io.js';
2
+ export declare const DEPLOY_HELP = "craft-ts deploy \u2014 hand the checked manifest to a deployment provider\n\nUsage:\n craft-ts deploy preview --provider <name>\n craft-ts deploy --provider <name> --yes\n\nOptions:\n --provider <name> Provider to delegate to, resolved from @craft-ts/deploy-<name>\n --provider-module <spec> Import the provider from this module instead\n --stage <name> Target stage (default: the manifest environment)\n --config <path> Manifest to read (default: craft.deploy.* in the root)\n --root <dir> Directory the manifest paths are relative to\n --json Emit a machine-readable report\n --yes Apply the plan; without it, deploy stops after the preview\n\n`preview` never mutates anything. `deploy` runs the same checks and the same\npreview first, and refuses to apply until `--yes` approves the plan.";
3
+ /**
4
+ * Runs the deployment pipeline: check, provider check, preview, then apply.
5
+ *
6
+ * No step is skippable, and applying is the only step that needs consent: a
7
+ * plan an operator has not seen is never executed.
8
+ */
9
+ export declare function runDeployCommand(argv: readonly string[], io: CraftCliIo): Promise<number>;
10
+ //# sourceMappingURL=deploy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/commands/deploy.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAS3C,eAAO,MAAM,WAAW,i3BAgB+C,CAAC;AAExE;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,EAAE,EAAE,UAAU,GACb,OAAO,CAAC,MAAM,CAAC,CAgIjB"}
@@ -0,0 +1,199 @@
1
+ import { resolve } from 'node:path';
2
+ import { checkCraftDeployment, formatCraftDeploymentDiagnostic, formatCraftDeploymentPlan, requiredCapability, } from '@craft-ts/deploy';
3
+ import { parseArguments } from '../args.js';
4
+ import { loadCraftDeploymentConfig } from '../load-config.js';
5
+ import { loadCraftDeploymentProvider } from '../load-provider.js';
6
+ const SPEC = {
7
+ values: ['config', 'root', 'provider', 'provider-module', 'stage'],
8
+ flags: ['json', 'yes', 'help'],
9
+ };
10
+ export const DEPLOY_HELP = `craft-ts deploy — hand the checked manifest to a deployment provider
11
+
12
+ Usage:
13
+ craft-ts deploy preview --provider <name>
14
+ craft-ts deploy --provider <name> --yes
15
+
16
+ Options:
17
+ --provider <name> Provider to delegate to, resolved from @craft-ts/deploy-<name>
18
+ --provider-module <spec> Import the provider from this module instead
19
+ --stage <name> Target stage (default: the manifest environment)
20
+ --config <path> Manifest to read (default: craft.deploy.* in the root)
21
+ --root <dir> Directory the manifest paths are relative to
22
+ --json Emit a machine-readable report
23
+ --yes Apply the plan; without it, deploy stops after the preview
24
+
25
+ \`preview\` never mutates anything. \`deploy\` runs the same checks and the same
26
+ preview first, and refuses to apply until \`--yes\` approves the plan.`;
27
+ /**
28
+ * Runs the deployment pipeline: check, provider check, preview, then apply.
29
+ *
30
+ * No step is skippable, and applying is the only step that needs consent: a
31
+ * plan an operator has not seen is never executed.
32
+ */
33
+ export async function runDeployCommand(argv, io) {
34
+ const parsed = parseArguments(argv, SPEC);
35
+ if (parsed.flags.has('help')) {
36
+ io.write(DEPLOY_HELP);
37
+ return 0;
38
+ }
39
+ if (parsed.unknown.length > 0) {
40
+ io.writeError(`Unknown option(s): ${parsed.unknown.join(', ')}`);
41
+ io.writeError(DEPLOY_HELP);
42
+ return 1;
43
+ }
44
+ const mode = parsed.command === 'preview' ? 'preview' : 'deploy';
45
+ if (parsed.command !== null && parsed.command !== 'preview') {
46
+ io.writeError(`Unknown deploy subcommand: ${parsed.command}`);
47
+ io.writeError(DEPLOY_HELP);
48
+ return 1;
49
+ }
50
+ const providerName = parsed.values['provider'];
51
+ const providerModule = parsed.values['provider-module'];
52
+ if (!providerName) {
53
+ io.writeError('`--provider` is required: a deployment is always delegated.');
54
+ io.writeError(DEPLOY_HELP);
55
+ return 1;
56
+ }
57
+ const json = parsed.flags.has('json');
58
+ const rootDir = resolve(io.cwd, parsed.values['root'] ?? '.');
59
+ const report = createReporter(io, json);
60
+ const loaded = await loadCraftDeploymentConfig({
61
+ rootDir,
62
+ config: parsed.values['config'],
63
+ });
64
+ if (loaded.definition === null) {
65
+ return report.fail(loaded.diagnostics);
66
+ }
67
+ // The manifest is checked on its own here: the authority on what a provider
68
+ // can do is the provider itself, loaded just below, not the documented
69
+ // matrix — which is what lets a project deploy with a provider CraftTS does
70
+ // not ship.
71
+ const checked = checkCraftDeployment({
72
+ rootDir,
73
+ definition: loaded.definition,
74
+ });
75
+ if (!checked.passed || checked.manifest === null) {
76
+ return report.fail([...loaded.diagnostics, ...checked.diagnostics]);
77
+ }
78
+ report.warnings(checked.diagnostics);
79
+ const provider = await loadCraftDeploymentProvider({
80
+ name: providerName,
81
+ rootDir,
82
+ module: providerModule,
83
+ });
84
+ if (!provider.provider) {
85
+ return report.fail(provider.diagnostics);
86
+ }
87
+ report.warnings(provider.diagnostics);
88
+ const capability = requiredCapability(checked.manifest.runtime, checked.manifest.runtime === 'static'
89
+ ? checked.manifest.static.mode
90
+ : undefined);
91
+ if (!provider.provider.capabilities.includes(capability)) {
92
+ return report.fail([
93
+ {
94
+ code: 'CRAFT_DEPLOY_PROVIDER_CAPABILITY_MISSING',
95
+ severity: 'error',
96
+ provider: provider.provider.name,
97
+ runtime: checked.manifest.runtime,
98
+ message: `\`${provider.provider.name}\` declares ${provider.provider.capabilities.join(', ') || 'no capability'} and this manifest needs \`${capability}\`.`,
99
+ fix: `Choose a provider declaring \`${capability}\`, or change the runtime or the static mode.`,
100
+ },
101
+ ]);
102
+ }
103
+ const request = {
104
+ manifest: checked.manifest,
105
+ rootDir,
106
+ stage: parsed.values['stage'] ?? checked.manifest.environment,
107
+ };
108
+ try {
109
+ const providerDiagnostics = (await provider.provider.check?.(request)) ?? [];
110
+ if (providerDiagnostics.some((d) => d.severity === 'error')) {
111
+ return report.fail(providerDiagnostics);
112
+ }
113
+ report.warnings(providerDiagnostics);
114
+ const plan = await provider.provider.preview(request);
115
+ report.plan(plan);
116
+ if (mode === 'preview')
117
+ return report.done(plan, null);
118
+ if (!parsed.flags.has('yes')) {
119
+ return report.fail([
120
+ {
121
+ code: 'CRAFT_DEPLOY_DEPLOY_NOT_CONFIRMED',
122
+ severity: 'error',
123
+ provider: providerName,
124
+ message: `The plan above would change ${mutating(plan)} resource(s) on stage \`${request.stage}\`.`,
125
+ fix: 'Re-run with `--yes` once the plan is approved.',
126
+ },
127
+ ]);
128
+ }
129
+ return report.done(plan, await provider.provider.deploy(request));
130
+ }
131
+ catch (error) {
132
+ return report.fail([
133
+ {
134
+ code: 'CRAFT_DEPLOY_PROVIDER_TOOLCHAIN_MISSING',
135
+ severity: 'error',
136
+ provider: providerName,
137
+ message: `\`${providerName}\` failed: ${error instanceof Error ? error.message : String(error)}`,
138
+ fix: 'Read the provider error above; nothing was recorded by CraftTS.',
139
+ },
140
+ ]);
141
+ }
142
+ }
143
+ function mutating(plan) {
144
+ return plan.resources.filter((resource) => resource.action !== 'unchanged')
145
+ .length;
146
+ }
147
+ function createReporter(io, json) {
148
+ const collected = [];
149
+ return {
150
+ warnings(diagnostics) {
151
+ collected.push(...diagnostics);
152
+ if (json)
153
+ return;
154
+ for (const diagnostic of diagnostics) {
155
+ io.write(formatCraftDeploymentDiagnostic(diagnostic));
156
+ }
157
+ },
158
+ plan(plan) {
159
+ if (json)
160
+ return;
161
+ io.write(formatCraftDeploymentPlan(plan));
162
+ },
163
+ fail(diagnostics) {
164
+ const all = [...collected, ...diagnostics];
165
+ if (json) {
166
+ io.write(JSON.stringify({ applied: false, plan: null, result: null, diagnostics: all }, null, 2));
167
+ return 1;
168
+ }
169
+ for (const diagnostic of diagnostics) {
170
+ io.writeError(formatCraftDeploymentDiagnostic(diagnostic));
171
+ }
172
+ io.writeError(`Deployment stopped with ${all.filter((d) => d.severity === 'error').length} error(s).`);
173
+ return 1;
174
+ },
175
+ done(plan, result) {
176
+ if (json) {
177
+ io.write(JSON.stringify({
178
+ applied: result !== null,
179
+ plan,
180
+ result,
181
+ diagnostics: collected,
182
+ }, null, 2));
183
+ return 0;
184
+ }
185
+ if (!result) {
186
+ io.write('Preview only: nothing was created, updated or deleted.');
187
+ return 0;
188
+ }
189
+ if (result.url)
190
+ io.write(`url: ${result.url}`);
191
+ for (const [key, value] of Object.entries(result.outputs)) {
192
+ io.write(`output ${key}: ${value}`);
193
+ }
194
+ io.write(`Deployed to stage \`${result.stage}\` with ${result.provider}.`);
195
+ return 0;
196
+ },
197
+ };
198
+ }
199
+ //# sourceMappingURL=deploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/commands/deploy.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolve } from 'node:path';\nimport {\n checkCraftDeployment,\n formatCraftDeploymentDiagnostic,\n formatCraftDeploymentPlan,\n requiredCapability,\n type CraftDeploymentDiagnostic,\n type CraftDeploymentPlan,\n type CraftDeploymentRequest,\n type CraftDeploymentResult,\n} from '@craft-ts/deploy';\nimport { parseArguments } from '../args.js';\nimport type { CraftCliIo } from '../io.js';\nimport { loadCraftDeploymentConfig } from '../load-config.js';\nimport { loadCraftDeploymentProvider } from '../load-provider.js';\n\nconst SPEC = {\n values: ['config', 'root', 'provider', 'provider-module', 'stage'],\n flags: ['json', 'yes', 'help'],\n} as const;\n\nexport const DEPLOY_HELP = `craft-ts deploy — hand the checked manifest to a deployment provider\n\nUsage:\n craft-ts deploy preview --provider <name>\n craft-ts deploy --provider <name> --yes\n\nOptions:\n --provider <name> Provider to delegate to, resolved from @craft-ts/deploy-<name>\n --provider-module <spec> Import the provider from this module instead\n --stage <name> Target stage (default: the manifest environment)\n --config <path> Manifest to read (default: craft.deploy.* in the root)\n --root <dir> Directory the manifest paths are relative to\n --json Emit a machine-readable report\n --yes Apply the plan; without it, deploy stops after the preview\n\n\\`preview\\` never mutates anything. \\`deploy\\` runs the same checks and the same\npreview first, and refuses to apply until \\`--yes\\` approves the plan.`;\n\n/**\n * Runs the deployment pipeline: check, provider check, preview, then apply.\n *\n * No step is skippable, and applying is the only step that needs consent: a\n * plan an operator has not seen is never executed.\n */\nexport async function runDeployCommand(\n argv: readonly string[],\n io: CraftCliIo,\n): Promise<number> {\n const parsed = parseArguments(argv, SPEC);\n if (parsed.flags.has('help')) {\n io.write(DEPLOY_HELP);\n return 0;\n }\n if (parsed.unknown.length > 0) {\n io.writeError(`Unknown option(s): ${parsed.unknown.join(', ')}`);\n io.writeError(DEPLOY_HELP);\n return 1;\n }\n\n const mode = parsed.command === 'preview' ? 'preview' : 'deploy';\n if (parsed.command !== null && parsed.command !== 'preview') {\n io.writeError(`Unknown deploy subcommand: ${parsed.command}`);\n io.writeError(DEPLOY_HELP);\n return 1;\n }\n\n const providerName = parsed.values['provider'];\n const providerModule = parsed.values['provider-module'];\n if (!providerName) {\n io.writeError(\n '`--provider` is required: a deployment is always delegated.',\n );\n io.writeError(DEPLOY_HELP);\n return 1;\n }\n\n const json = parsed.flags.has('json');\n const rootDir = resolve(io.cwd, parsed.values['root'] ?? '.');\n const report = createReporter(io, json);\n\n const loaded = await loadCraftDeploymentConfig({\n rootDir,\n config: parsed.values['config'],\n });\n if (loaded.definition === null) {\n return report.fail(loaded.diagnostics);\n }\n\n // The manifest is checked on its own here: the authority on what a provider\n // can do is the provider itself, loaded just below, not the documented\n // matrix — which is what lets a project deploy with a provider CraftTS does\n // not ship.\n const checked = checkCraftDeployment({\n rootDir,\n definition: loaded.definition,\n });\n if (!checked.passed || checked.manifest === null) {\n return report.fail([...loaded.diagnostics, ...checked.diagnostics]);\n }\n report.warnings(checked.diagnostics);\n\n const provider = await loadCraftDeploymentProvider({\n name: providerName,\n rootDir,\n module: providerModule,\n });\n if (!provider.provider) {\n return report.fail(provider.diagnostics);\n }\n report.warnings(provider.diagnostics);\n\n const capability = requiredCapability(\n checked.manifest.runtime,\n checked.manifest.runtime === 'static'\n ? checked.manifest.static.mode\n : undefined,\n );\n if (!provider.provider.capabilities.includes(capability)) {\n return report.fail([\n {\n code: 'CRAFT_DEPLOY_PROVIDER_CAPABILITY_MISSING',\n severity: 'error',\n provider: provider.provider.name,\n runtime: checked.manifest.runtime,\n message: `\\`${provider.provider.name}\\` declares ${provider.provider.capabilities.join(', ') || 'no capability'} and this manifest needs \\`${capability}\\`.`,\n fix: `Choose a provider declaring \\`${capability}\\`, or change the runtime or the static mode.`,\n },\n ]);\n }\n\n const request: CraftDeploymentRequest = {\n manifest: checked.manifest,\n rootDir,\n stage: parsed.values['stage'] ?? checked.manifest.environment,\n };\n\n try {\n const providerDiagnostics =\n (await provider.provider.check?.(request)) ?? [];\n if (providerDiagnostics.some((d) => d.severity === 'error')) {\n return report.fail(providerDiagnostics);\n }\n report.warnings(providerDiagnostics);\n\n const plan = await provider.provider.preview(request);\n report.plan(plan);\n\n if (mode === 'preview') return report.done(plan, null);\n\n if (!parsed.flags.has('yes')) {\n return report.fail([\n {\n code: 'CRAFT_DEPLOY_DEPLOY_NOT_CONFIRMED',\n severity: 'error',\n provider: providerName,\n message: `The plan above would change ${mutating(plan)} resource(s) on stage \\`${request.stage}\\`.`,\n fix: 'Re-run with `--yes` once the plan is approved.',\n },\n ]);\n }\n\n return report.done(plan, await provider.provider.deploy(request));\n } catch (error) {\n return report.fail([\n {\n code: 'CRAFT_DEPLOY_PROVIDER_TOOLCHAIN_MISSING',\n severity: 'error',\n provider: providerName,\n message: `\\`${providerName}\\` failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n fix: 'Read the provider error above; nothing was recorded by CraftTS.',\n },\n ]);\n }\n}\n\nfunction mutating(plan: CraftDeploymentPlan): number {\n return plan.resources.filter((resource) => resource.action !== 'unchanged')\n .length;\n}\n\ntype Reporter = Readonly<{\n warnings(diagnostics: readonly CraftDeploymentDiagnostic[]): void;\n plan(plan: CraftDeploymentPlan): void;\n fail(diagnostics: readonly CraftDeploymentDiagnostic[]): number;\n done(plan: CraftDeploymentPlan, result: CraftDeploymentResult | null): number;\n}>;\n\nfunction createReporter(io: CraftCliIo, json: boolean): Reporter {\n const collected: CraftDeploymentDiagnostic[] = [];\n\n return {\n warnings(diagnostics) {\n collected.push(...diagnostics);\n if (json) return;\n for (const diagnostic of diagnostics) {\n io.write(formatCraftDeploymentDiagnostic(diagnostic));\n }\n },\n plan(plan) {\n if (json) return;\n io.write(formatCraftDeploymentPlan(plan));\n },\n fail(diagnostics) {\n const all = [...collected, ...diagnostics];\n if (json) {\n io.write(\n JSON.stringify(\n { applied: false, plan: null, result: null, diagnostics: all },\n null,\n 2,\n ),\n );\n return 1;\n }\n for (const diagnostic of diagnostics) {\n io.writeError(formatCraftDeploymentDiagnostic(diagnostic));\n }\n io.writeError(\n `Deployment stopped with ${\n all.filter((d) => d.severity === 'error').length\n } error(s).`,\n );\n return 1;\n },\n done(plan, result) {\n if (json) {\n io.write(\n JSON.stringify(\n {\n applied: result !== null,\n plan,\n result,\n diagnostics: collected,\n },\n null,\n 2,\n ),\n );\n return 0;\n }\n if (!result) {\n io.write('Preview only: nothing was created, updated or deleted.');\n return 0;\n }\n if (result.url) io.write(`url: ${result.url}`);\n for (const [key, value] of Object.entries(result.outputs)) {\n io.write(`output ${key}: ${value}`);\n }\n io.write(\n `Deployed to stage \\`${result.stage}\\` with ${result.provider}.`,\n );\n return 0;\n },\n };\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import type { CraftCliIo } from '../io.js';
2
+ export declare const MANIFEST_HELP = "craft-ts manifest \u2014 resolve the deployment manifest to its artefact form\n\nOptions:\n --config <path> Manifest to read (default: craft.deploy.* in the root)\n --root <dir> Directory the manifest paths are relative to\n --out <file> Write the resolved manifest instead of printing it";
3
+ /**
4
+ * Emits the resolved, provider-neutral manifest.
5
+ *
6
+ * Resolution applies every default of the tooling, so the file a provider
7
+ * consumes never depends on the CraftTS version that produced it.
8
+ */
9
+ export declare function runManifestCommand(argv: readonly string[], io: CraftCliIo): Promise<number>;
10
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/commands/manifest.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAQ3C,eAAO,MAAM,aAAa,6TAKgD,CAAC;AAE3E;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,EAAE,EAAE,UAAU,GACb,OAAO,CAAC,MAAM,CAAC,CA8CjB"}
@@ -0,0 +1,67 @@
1
+ import { mkdirSync, writeFileSync } from 'node:fs';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { formatCraftDeploymentDiagnostic, resolveCraftDeploymentManifest, serializeCraftDeploymentManifest, validateCraftDeploymentDefinition, } from '@craft-ts/deploy';
4
+ import { parseArguments } from '../args.js';
5
+ import { loadCraftDeploymentConfig } from '../load-config.js';
6
+ const SPEC = {
7
+ values: ['config', 'root', 'out'],
8
+ flags: ['help'],
9
+ };
10
+ export const MANIFEST_HELP = `craft-ts manifest — resolve the deployment manifest to its artefact form
11
+
12
+ Options:
13
+ --config <path> Manifest to read (default: craft.deploy.* in the root)
14
+ --root <dir> Directory the manifest paths are relative to
15
+ --out <file> Write the resolved manifest instead of printing it`;
16
+ /**
17
+ * Emits the resolved, provider-neutral manifest.
18
+ *
19
+ * Resolution applies every default of the tooling, so the file a provider
20
+ * consumes never depends on the CraftTS version that produced it.
21
+ */
22
+ export async function runManifestCommand(argv, io) {
23
+ const parsed = parseArguments(argv, SPEC);
24
+ if (parsed.flags.has('help')) {
25
+ io.write(MANIFEST_HELP);
26
+ return 0;
27
+ }
28
+ if (parsed.unknown.length > 0) {
29
+ io.writeError(`Unknown option(s): ${parsed.unknown.join(', ')}`);
30
+ io.writeError(MANIFEST_HELP);
31
+ return 1;
32
+ }
33
+ const rootDir = resolve(io.cwd, parsed.values['root'] ?? '.');
34
+ const loaded = await loadCraftDeploymentConfig({
35
+ rootDir,
36
+ config: parsed.values['config'],
37
+ });
38
+ for (const diagnostic of loaded.diagnostics) {
39
+ io.writeError(formatCraftDeploymentDiagnostic(diagnostic));
40
+ }
41
+ if (loaded.definition === null)
42
+ return 1;
43
+ const validation = validateCraftDeploymentDefinition(loaded.definition);
44
+ for (const diagnostic of validation.diagnostics) {
45
+ const text = formatCraftDeploymentDiagnostic(diagnostic);
46
+ if (diagnostic.severity === 'error')
47
+ io.writeError(text);
48
+ else
49
+ io.write(text);
50
+ }
51
+ if (!validation.definition)
52
+ return 1;
53
+ if (validation.diagnostics.some((d) => d.severity === 'error'))
54
+ return 1;
55
+ const serialized = serializeCraftDeploymentManifest(resolveCraftDeploymentManifest(validation.definition));
56
+ const out = parsed.values['out'];
57
+ if (!out) {
58
+ io.write(serialized.trimEnd());
59
+ return 0;
60
+ }
61
+ const target = resolve(rootDir, out);
62
+ mkdirSync(dirname(target), { recursive: true });
63
+ writeFileSync(target, serialized, 'utf8');
64
+ io.write(`Wrote ${out}`);
65
+ return 0;
66
+ }
67
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/commands/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport {\n formatCraftDeploymentDiagnostic,\n resolveCraftDeploymentManifest,\n serializeCraftDeploymentManifest,\n validateCraftDeploymentDefinition,\n} from '@craft-ts/deploy';\nimport { parseArguments } from '../args.js';\nimport type { CraftCliIo } from '../io.js';\nimport { loadCraftDeploymentConfig } from '../load-config.js';\n\nconst SPEC = {\n values: ['config', 'root', 'out'],\n flags: ['help'],\n} as const;\n\nexport const MANIFEST_HELP = `craft-ts manifest — resolve the deployment manifest to its artefact form\n\nOptions:\n --config <path> Manifest to read (default: craft.deploy.* in the root)\n --root <dir> Directory the manifest paths are relative to\n --out <file> Write the resolved manifest instead of printing it`;\n\n/**\n * Emits the resolved, provider-neutral manifest.\n *\n * Resolution applies every default of the tooling, so the file a provider\n * consumes never depends on the CraftTS version that produced it.\n */\nexport async function runManifestCommand(\n argv: readonly string[],\n io: CraftCliIo,\n): Promise<number> {\n const parsed = parseArguments(argv, SPEC);\n if (parsed.flags.has('help')) {\n io.write(MANIFEST_HELP);\n return 0;\n }\n if (parsed.unknown.length > 0) {\n io.writeError(`Unknown option(s): ${parsed.unknown.join(', ')}`);\n io.writeError(MANIFEST_HELP);\n return 1;\n }\n\n const rootDir = resolve(io.cwd, parsed.values['root'] ?? '.');\n const loaded = await loadCraftDeploymentConfig({\n rootDir,\n config: parsed.values['config'],\n });\n for (const diagnostic of loaded.diagnostics) {\n io.writeError(formatCraftDeploymentDiagnostic(diagnostic));\n }\n if (loaded.definition === null) return 1;\n\n const validation = validateCraftDeploymentDefinition(loaded.definition);\n for (const diagnostic of validation.diagnostics) {\n const text = formatCraftDeploymentDiagnostic(diagnostic);\n if (diagnostic.severity === 'error') io.writeError(text);\n else io.write(text);\n }\n if (!validation.definition) return 1;\n if (validation.diagnostics.some((d) => d.severity === 'error')) return 1;\n\n const serialized = serializeCraftDeploymentManifest(\n resolveCraftDeploymentManifest(validation.definition),\n );\n\n const out = parsed.values['out'];\n if (!out) {\n io.write(serialized.trimEnd());\n return 0;\n }\n\n const target = resolve(rootDir, out);\n mkdirSync(dirname(target), { recursive: true });\n writeFileSync(target, serialized, 'utf8');\n io.write(`Wrote ${out}`);\n return 0;\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import type { CraftCliIo } from '../io.js';
2
+ export declare const PROVIDERS_HELP = "craft-ts providers \u2014 list the deployment providers and their capabilities\n\nOptions:\n --json Emit the capability matrix as JSON";
3
+ /**
4
+ * Prints the capability matrix. A provider listed here is documented, not
5
+ * necessarily implemented: the CLI delegates every mutation to a provider
6
+ * package installed separately.
7
+ */
8
+ export declare function runProvidersCommand(argv: readonly string[], io: CraftCliIo): number;
9
+ //# sourceMappingURL=providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/commands/providers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAI3C,eAAO,MAAM,cAAc,0JAG+B,CAAC;AAE3D;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,EAAE,EAAE,UAAU,GACb,MAAM,CA8BR"}
@@ -0,0 +1,42 @@
1
+ import { CRAFT_DEPLOYMENT_PROVIDERS } from '@craft-ts/deploy';
2
+ import { parseArguments } from '../args.js';
3
+ const SPEC = { values: [], flags: ['json', 'help'] };
4
+ export const PROVIDERS_HELP = `craft-ts providers — list the deployment providers and their capabilities
5
+
6
+ Options:
7
+ --json Emit the capability matrix as JSON`;
8
+ /**
9
+ * Prints the capability matrix. A provider listed here is documented, not
10
+ * necessarily implemented: the CLI delegates every mutation to a provider
11
+ * package installed separately.
12
+ */
13
+ export function runProvidersCommand(argv, io) {
14
+ const parsed = parseArguments(argv, SPEC);
15
+ if (parsed.flags.has('help')) {
16
+ io.write(PROVIDERS_HELP);
17
+ return 0;
18
+ }
19
+ if (parsed.unknown.length > 0) {
20
+ io.writeError(`Unknown option(s): ${parsed.unknown.join(', ')}`);
21
+ io.writeError(PROVIDERS_HELP);
22
+ return 1;
23
+ }
24
+ if (parsed.flags.has('json')) {
25
+ io.write(JSON.stringify(CRAFT_DEPLOYMENT_PROVIDERS, null, 2));
26
+ return 0;
27
+ }
28
+ for (const provider of CRAFT_DEPLOYMENT_PROVIDERS) {
29
+ io.write(provider.name);
30
+ io.write(` capabilities: ${provider.capabilities.join(', ')}`);
31
+ io.write(` platforms: ${provider.platforms.join(', ')}`);
32
+ io.write(` artifact: ${provider.artifact}`);
33
+ io.write(` preview: ${provider.previewCommand ?? 'none'}`);
34
+ io.write(` credentials: ${provider.credentials}`);
35
+ for (const limit of provider.limits) {
36
+ io.write(` limit: ${limit}`);
37
+ }
38
+ io.write('');
39
+ }
40
+ return 0;
41
+ }
42
+ //# sourceMappingURL=providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/commands/providers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,MAAM,IAAI,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAW,CAAC;AAE9D,MAAM,CAAC,MAAM,cAAc,GAAG;;;0DAG4B,CAAC;AAE3D;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAuB,EACvB,EAAc;IAEd,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC1C,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACzB,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,EAAE,CAAC,UAAU,CAAC,sBAAsB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjE,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QAC9B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,0BAA0B,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9D,OAAO,CAAC,CAAC;IACX,CAAC;IAED,KAAK,MAAM,QAAQ,IAAI,0BAA0B,EAAE,CAAC;QAClD,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACxB,EAAE,CAAC,KAAK,CAAC,mBAAmB,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChE,EAAE,CAAC,KAAK,CAAC,mBAAmB,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7D,EAAE,CAAC,KAAK,CAAC,mBAAmB,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjD,EAAE,CAAC,KAAK,CAAC,mBAAmB,QAAQ,CAAC,cAAc,IAAI,MAAM,EAAE,CAAC,CAAC;QACjE,EAAE,CAAC,KAAK,CAAC,mBAAmB,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;QACpD,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YACpC,EAAE,CAAC,KAAK,CAAC,mBAAmB,KAAK,EAAE,CAAC,CAAC;QACvC,CAAC;QACD,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACf,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC","sourcesContent":["import { CRAFT_DEPLOYMENT_PROVIDERS } from '@craft-ts/deploy';\nimport { parseArguments } from '../args.js';\nimport type { CraftCliIo } from '../io.js';\n\nconst SPEC = { values: [], flags: ['json', 'help'] } as const;\n\nexport const PROVIDERS_HELP = `craft-ts providers — list the deployment providers and their capabilities\n\nOptions:\n --json Emit the capability matrix as JSON`;\n\n/**\n * Prints the capability matrix. A provider listed here is documented, not\n * necessarily implemented: the CLI delegates every mutation to a provider\n * package installed separately.\n */\nexport function runProvidersCommand(\n argv: readonly string[],\n io: CraftCliIo,\n): number {\n const parsed = parseArguments(argv, SPEC);\n if (parsed.flags.has('help')) {\n io.write(PROVIDERS_HELP);\n return 0;\n }\n if (parsed.unknown.length > 0) {\n io.writeError(`Unknown option(s): ${parsed.unknown.join(', ')}`);\n io.writeError(PROVIDERS_HELP);\n return 1;\n }\n\n if (parsed.flags.has('json')) {\n io.write(JSON.stringify(CRAFT_DEPLOYMENT_PROVIDERS, null, 2));\n return 0;\n }\n\n for (const provider of CRAFT_DEPLOYMENT_PROVIDERS) {\n io.write(provider.name);\n io.write(` capabilities: ${provider.capabilities.join(', ')}`);\n io.write(` platforms: ${provider.platforms.join(', ')}`);\n io.write(` artifact: ${provider.artifact}`);\n io.write(` preview: ${provider.previewCommand ?? 'none'}`);\n io.write(` credentials: ${provider.credentials}`);\n for (const limit of provider.limits) {\n io.write(` limit: ${limit}`);\n }\n io.write('');\n }\n return 0;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ export type CraftCliIo = Readonly<{
2
+ cwd: string;
3
+ write(text: string): void;
4
+ writeError(text: string): void;
5
+ }>;
6
+ export declare function processIo(): CraftCliIo;
7
+ //# sourceMappingURL=io.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../../../../../libs/cli/src/lib/io.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC,CAAC;AAEH,wBAAgB,SAAS,IAAI,UAAU,CAUtC"}
package/src/lib/io.js ADDED
@@ -0,0 +1,12 @@
1
+ export function processIo() {
2
+ return {
3
+ cwd: process.cwd(),
4
+ write: (text) => {
5
+ process.stdout.write(`${text}\n`);
6
+ },
7
+ writeError: (text) => {
8
+ process.stderr.write(`${text}\n`);
9
+ },
10
+ };
11
+ }
12
+ //# sourceMappingURL=io.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"io.js","sourceRoot":"","sources":["../../../../../libs/cli/src/lib/io.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,SAAS;IACvB,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;QAClB,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;QACpC,CAAC;QACD,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE;YACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;QACpC,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["export type CraftCliIo = Readonly<{\n cwd: string;\n write(text: string): void;\n writeError(text: string): void;\n}>;\n\nexport function processIo(): CraftCliIo {\n return {\n cwd: process.cwd(),\n write: (text) => {\n process.stdout.write(`${text}\\n`);\n },\n writeError: (text) => {\n process.stderr.write(`${text}\\n`);\n },\n };\n}\n"]}
@@ -0,0 +1,22 @@
1
+ import type { CraftDeploymentDiagnostic } from '@craft-ts/deploy';
2
+ /** Manifest file names looked up, in priority order. */
3
+ export declare const CRAFT_DEPLOYMENT_CONFIG_FILES: readonly ["craft.deploy.ts", "craft.deploy.mts", "craft.deploy.mjs", "craft.deploy.js", "craft.deploy.json"];
4
+ export type LoadedCraftDeploymentConfig = Readonly<{
5
+ /** Path relative to the root, or `null` when nothing was loaded. */
6
+ file: string | null;
7
+ definition: unknown;
8
+ diagnostics: readonly CraftDeploymentDiagnostic[];
9
+ }>;
10
+ export type LoadCraftDeploymentConfigOptions = Readonly<{
11
+ rootDir: string;
12
+ /** Explicit manifest path, relative to the root or absolute. */
13
+ config?: string;
14
+ }>;
15
+ /**
16
+ * Finds and loads the deployment manifest.
17
+ *
18
+ * Loading is a separate step from checking so a provider, a test or a build
19
+ * can hand a manifest object over without ever touching a config file.
20
+ */
21
+ export declare function loadCraftDeploymentConfig(options: LoadCraftDeploymentConfigOptions): Promise<LoadedCraftDeploymentConfig>;
22
+ //# sourceMappingURL=load-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-config.d.ts","sourceRoot":"","sources":["../../../../../libs/cli/src/lib/load-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAElE,wDAAwD;AACxD,eAAO,MAAM,6BAA6B,8GAMhC,CAAC;AAEX,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IACjD,oEAAoE;IACpE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,SAAS,yBAAyB,EAAE,CAAC;CACnD,CAAC,CAAC;AAEH,MAAM,MAAM,gCAAgC,GAAG,QAAQ,CAAC;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAEH;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,gCAAgC,GACxC,OAAO,CAAC,2BAA2B,CAAC,CAyDtC"}
@@ -0,0 +1,158 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
10
+ import { createRequire } from 'node:module';
11
+ import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
12
+ import { pathToFileURL } from 'node:url';
13
+ /** Manifest file names looked up, in priority order. */
14
+ export const CRAFT_DEPLOYMENT_CONFIG_FILES = [
15
+ 'craft.deploy.ts',
16
+ 'craft.deploy.mts',
17
+ 'craft.deploy.mjs',
18
+ 'craft.deploy.js',
19
+ 'craft.deploy.json',
20
+ ];
21
+ /**
22
+ * Finds and loads the deployment manifest.
23
+ *
24
+ * Loading is a separate step from checking so a provider, a test or a build
25
+ * can hand a manifest object over without ever touching a config file.
26
+ */
27
+ export async function loadCraftDeploymentConfig(options) {
28
+ const rootDir = resolve(options.rootDir);
29
+ const file = locate(rootDir, options.config);
30
+ if (!file) {
31
+ return {
32
+ file: null,
33
+ definition: null,
34
+ diagnostics: [
35
+ {
36
+ code: 'CRAFT_DEPLOY_CONFIG_NOT_FOUND',
37
+ severity: 'error',
38
+ message: options.config
39
+ ? `\`${options.config}\` does not exist.`
40
+ : `No deployment manifest was found in \`${rootDir}\`.`,
41
+ fix: `Create one of ${CRAFT_DEPLOYMENT_CONFIG_FILES.join(', ')}, or pass \`--config\`.`,
42
+ },
43
+ ],
44
+ };
45
+ }
46
+ const relativeFile = relative(rootDir, file) || file;
47
+ if (file.endsWith('.json')) {
48
+ try {
49
+ return {
50
+ file: relativeFile,
51
+ definition: JSON.parse(readFileSync(file, 'utf8')),
52
+ diagnostics: [],
53
+ };
54
+ }
55
+ catch (error) {
56
+ return loadFailure(relativeFile, error);
57
+ }
58
+ }
59
+ try {
60
+ const module = await importModule(file);
61
+ const definition = module.default;
62
+ if (definition === undefined) {
63
+ return {
64
+ file: relativeFile,
65
+ definition: null,
66
+ diagnostics: [
67
+ {
68
+ code: 'CRAFT_DEPLOY_CONFIG_NO_DEFAULT_EXPORT',
69
+ severity: 'error',
70
+ file: relativeFile,
71
+ message: `\`${relativeFile}\` exports no default.`,
72
+ fix: 'Add `export default defineCraftDeployment({ ... })`.',
73
+ },
74
+ ],
75
+ };
76
+ }
77
+ return { file: relativeFile, definition, diagnostics: [] };
78
+ }
79
+ catch (error) {
80
+ return loadFailure(relativeFile, error);
81
+ }
82
+ }
83
+ function loadFailure(file, error) {
84
+ return {
85
+ file,
86
+ definition: null,
87
+ diagnostics: [
88
+ {
89
+ code: 'CRAFT_DEPLOY_CONFIG_LOAD_FAILED',
90
+ severity: 'error',
91
+ file,
92
+ message: `\`${file}\` could not be loaded: ${error instanceof Error ? error.message : String(error)}`,
93
+ fix: 'Fix the reported error, run the CLI under a TypeScript loader, or commit a `craft.deploy.json`.',
94
+ },
95
+ ],
96
+ };
97
+ }
98
+ function locate(rootDir, config) {
99
+ if (config) {
100
+ const path = isAbsolute(config) ? config : resolve(rootDir, config);
101
+ return existsSync(path) ? path : null;
102
+ }
103
+ for (const name of CRAFT_DEPLOYMENT_CONFIG_FILES) {
104
+ const path = join(rootDir, name);
105
+ if (existsSync(path))
106
+ return path;
107
+ }
108
+ return null;
109
+ }
110
+ async function importModule(file) {
111
+ if (!/\.m?ts$/.test(file)) {
112
+ return await import(__rewriteRelativeImportExtension(pathToFileURL(file).href));
113
+ }
114
+ try {
115
+ // Recent Node versions strip types themselves, and a TypeScript loader
116
+ // such as tsx makes this branch the only one ever taken.
117
+ return await import(__rewriteRelativeImportExtension(pathToFileURL(file).href));
118
+ }
119
+ catch (error) {
120
+ if (!isTypeStrippingFailure(error))
121
+ throw error;
122
+ return await importTranspiled(file);
123
+ }
124
+ }
125
+ function isTypeStrippingFailure(error) {
126
+ if (!(error instanceof Error))
127
+ return false;
128
+ const code = error.code;
129
+ return (code === 'ERR_UNKNOWN_FILE_EXTENSION' ||
130
+ code === 'ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING' ||
131
+ /Unknown file extension|Unsupported file extension|TypeScript/i.test(error.message));
132
+ }
133
+ /**
134
+ * Transpiles the manifest with the TypeScript installed next to it and imports
135
+ * the result from a sibling file, so relative imports and package resolution
136
+ * keep working exactly as they do for the original.
137
+ */
138
+ async function importTranspiled(file) {
139
+ const requireFromConfig = createRequire(file);
140
+ const typescript = requireFromConfig('typescript');
141
+ const { outputText } = typescript.transpileModule(readFileSync(file, 'utf8'), {
142
+ fileName: file,
143
+ compilerOptions: {
144
+ module: typescript.ModuleKind['ESNext'],
145
+ target: typescript.ScriptTarget['ES2022'],
146
+ verbatimModuleSyntax: false,
147
+ },
148
+ });
149
+ const temporary = join(dirname(file), `.craft-deploy.${process.pid}.${Date.now()}.mjs`);
150
+ writeFileSync(temporary, outputText, 'utf8');
151
+ try {
152
+ return await import(__rewriteRelativeImportExtension(pathToFileURL(temporary).href));
153
+ }
154
+ finally {
155
+ rmSync(temporary, { force: true });
156
+ }
157
+ }
158
+ //# sourceMappingURL=load-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-config.js","sourceRoot":"","sources":["../../../../../libs/cli/src/lib/load-config.ts"],"names":[],"mappings":";;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,wDAAwD;AACxD,MAAM,CAAC,MAAM,6BAA6B,GAAG;IAC3C,iBAAiB;IACjB,kBAAkB;IAClB,kBAAkB;IAClB,iBAAiB;IACjB,mBAAmB;CACX,CAAC;AAeX;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,OAAyC;IAEzC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAE7C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO;YACL,IAAI,EAAE,IAAI;YACV,UAAU,EAAE,IAAI;YAChB,WAAW,EAAE;gBACX;oBACE,IAAI,EAAE,+BAA+B;oBACrC,QAAQ,EAAE,OAAO;oBACjB,OAAO,EAAE,OAAO,CAAC,MAAM;wBACrB,CAAC,CAAC,KAAK,OAAO,CAAC,MAAM,oBAAoB;wBACzC,CAAC,CAAC,yCAAyC,OAAO,KAAK;oBACzD,GAAG,EAAE,iBAAiB,6BAA6B,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB;iBACxF;aACF;SACF,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC;IAErD,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,OAAO;gBACL,IAAI,EAAE,YAAY;gBAClB,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAClD,WAAW,EAAE,EAAE;aAChB,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,WAAW,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,UAAU,GAAI,MAAgC,CAAC,OAAO,CAAC;QAC7D,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,OAAO;gBACL,IAAI,EAAE,YAAY;gBAClB,UAAU,EAAE,IAAI;gBAChB,WAAW,EAAE;oBACX;wBACE,IAAI,EAAE,uCAAuC;wBAC7C,QAAQ,EAAE,OAAO;wBACjB,IAAI,EAAE,YAAY;wBAClB,OAAO,EAAE,KAAK,YAAY,wBAAwB;wBAClD,GAAG,EAAE,sDAAsD;qBAC5D;iBACF;aACF,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;IAC7D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,WAAW,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IAC1C,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAClB,IAAY,EACZ,KAAc;IAEd,OAAO;QACL,IAAI;QACJ,UAAU,EAAE,IAAI;QAChB,WAAW,EAAE;YACX;gBACE,IAAI,EAAE,iCAAiC;gBACvC,QAAQ,EAAE,OAAO;gBACjB,IAAI;gBACJ,OAAO,EAAE,KAAK,IAAI,2BAChB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE;gBACF,GAAG,EAAE,iGAAiG;aACvG;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CAAC,OAAe,EAAE,MAAe;IAC9C,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACpE,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACxC,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,6BAA6B,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACjC,IAAI,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACpC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAcD,KAAK,UAAU,YAAY,CAAC,IAAY;IACtC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,MAAM,MAAM,kCAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,EAAC,CAAC;IAChD,CAAC;IACD,IAAI,CAAC;QACH,uEAAuE;QACvE,yDAAyD;QACzD,OAAO,MAAM,MAAM,kCAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,EAAC,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC;YAAE,MAAM,KAAK,CAAC;QAChD,OAAO,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAc;IAC5C,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,IAAI,GAAI,KAA2B,CAAC,IAAI,CAAC;IAC/C,OAAO,CACL,IAAI,KAAK,4BAA4B;QACrC,IAAI,KAAK,6CAA6C;QACtD,+DAA+D,CAAC,IAAI,CAClE,KAAK,CAAC,OAAO,CACd,CACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,gBAAgB,CAAC,IAAY;IAC1C,MAAM,iBAAiB,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,iBAAiB,CAAC,YAAY,CAAqB,CAAC;IACvE,MAAM,EAAE,UAAU,EAAE,GAAG,UAAU,CAAC,eAAe,CAC/C,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,EAC1B;QACE,QAAQ,EAAE,IAAI;QACd,eAAe,EAAE;YACf,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC;YACvC,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,QAAQ,CAAC;YACzC,oBAAoB,EAAE,KAAK;SAC5B;KACF,CACF,CAAC;IAEF,MAAM,SAAS,GAAG,IAAI,CACpB,OAAO,CAAC,IAAI,CAAC,EACb,iBAAiB,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,MAAM,CACjD,CAAC;IACF,aAAa,CAAC,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAC7C,IAAI,CAAC;QACH,OAAO,MAAM,MAAM,kCAAC,aAAa,CAAC,SAAS,CAAC,CAAC,IAAI,EAAC,CAAC;IACrD,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;AACH,CAAC","sourcesContent":["import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, isAbsolute, join, relative, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { CraftDeploymentDiagnostic } from '@craft-ts/deploy';\n\n/** Manifest file names looked up, in priority order. */\nexport const CRAFT_DEPLOYMENT_CONFIG_FILES = [\n 'craft.deploy.ts',\n 'craft.deploy.mts',\n 'craft.deploy.mjs',\n 'craft.deploy.js',\n 'craft.deploy.json',\n] as const;\n\nexport type LoadedCraftDeploymentConfig = Readonly<{\n /** Path relative to the root, or `null` when nothing was loaded. */\n file: string | null;\n definition: unknown;\n diagnostics: readonly CraftDeploymentDiagnostic[];\n}>;\n\nexport type LoadCraftDeploymentConfigOptions = Readonly<{\n rootDir: string;\n /** Explicit manifest path, relative to the root or absolute. */\n config?: string;\n}>;\n\n/**\n * Finds and loads the deployment manifest.\n *\n * Loading is a separate step from checking so a provider, a test or a build\n * can hand a manifest object over without ever touching a config file.\n */\nexport async function loadCraftDeploymentConfig(\n options: LoadCraftDeploymentConfigOptions,\n): Promise<LoadedCraftDeploymentConfig> {\n const rootDir = resolve(options.rootDir);\n const file = locate(rootDir, options.config);\n\n if (!file) {\n return {\n file: null,\n definition: null,\n diagnostics: [\n {\n code: 'CRAFT_DEPLOY_CONFIG_NOT_FOUND',\n severity: 'error',\n message: options.config\n ? `\\`${options.config}\\` does not exist.`\n : `No deployment manifest was found in \\`${rootDir}\\`.`,\n fix: `Create one of ${CRAFT_DEPLOYMENT_CONFIG_FILES.join(', ')}, or pass \\`--config\\`.`,\n },\n ],\n };\n }\n\n const relativeFile = relative(rootDir, file) || file;\n\n if (file.endsWith('.json')) {\n try {\n return {\n file: relativeFile,\n definition: JSON.parse(readFileSync(file, 'utf8')),\n diagnostics: [],\n };\n } catch (error) {\n return loadFailure(relativeFile, error);\n }\n }\n\n try {\n const module = await importModule(file);\n const definition = (module as { default?: unknown }).default;\n if (definition === undefined) {\n return {\n file: relativeFile,\n definition: null,\n diagnostics: [\n {\n code: 'CRAFT_DEPLOY_CONFIG_NO_DEFAULT_EXPORT',\n severity: 'error',\n file: relativeFile,\n message: `\\`${relativeFile}\\` exports no default.`,\n fix: 'Add `export default defineCraftDeployment({ ... })`.',\n },\n ],\n };\n }\n return { file: relativeFile, definition, diagnostics: [] };\n } catch (error) {\n return loadFailure(relativeFile, error);\n }\n}\n\nfunction loadFailure(\n file: string,\n error: unknown,\n): LoadedCraftDeploymentConfig {\n return {\n file,\n definition: null,\n diagnostics: [\n {\n code: 'CRAFT_DEPLOY_CONFIG_LOAD_FAILED',\n severity: 'error',\n file,\n message: `\\`${file}\\` could not be loaded: ${\n error instanceof Error ? error.message : String(error)\n }`,\n fix: 'Fix the reported error, run the CLI under a TypeScript loader, or commit a `craft.deploy.json`.',\n },\n ],\n };\n}\n\nfunction locate(rootDir: string, config?: string): string | null {\n if (config) {\n const path = isAbsolute(config) ? config : resolve(rootDir, config);\n return existsSync(path) ? path : null;\n }\n for (const name of CRAFT_DEPLOYMENT_CONFIG_FILES) {\n const path = join(rootDir, name);\n if (existsSync(path)) return path;\n }\n return null;\n}\n\ntype TypeScriptModule = Readonly<{\n ModuleKind: Readonly<Record<string, number>>;\n ScriptTarget: Readonly<Record<string, number>>;\n transpileModule(\n input: string,\n options: {\n compilerOptions: Record<string, unknown>;\n fileName?: string;\n },\n ): { outputText: string };\n}>;\n\nasync function importModule(file: string): Promise<unknown> {\n if (!/\\.m?ts$/.test(file)) {\n return await import(pathToFileURL(file).href);\n }\n try {\n // Recent Node versions strip types themselves, and a TypeScript loader\n // such as tsx makes this branch the only one ever taken.\n return await import(pathToFileURL(file).href);\n } catch (error) {\n if (!isTypeStrippingFailure(error)) throw error;\n return await importTranspiled(file);\n }\n}\n\nfunction isTypeStrippingFailure(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n const code = (error as { code?: string }).code;\n return (\n code === 'ERR_UNKNOWN_FILE_EXTENSION' ||\n code === 'ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING' ||\n /Unknown file extension|Unsupported file extension|TypeScript/i.test(\n error.message,\n )\n );\n}\n\n/**\n * Transpiles the manifest with the TypeScript installed next to it and imports\n * the result from a sibling file, so relative imports and package resolution\n * keep working exactly as they do for the original.\n */\nasync function importTranspiled(file: string): Promise<unknown> {\n const requireFromConfig = createRequire(file);\n const typescript = requireFromConfig('typescript') as TypeScriptModule;\n const { outputText } = typescript.transpileModule(\n readFileSync(file, 'utf8'),\n {\n fileName: file,\n compilerOptions: {\n module: typescript.ModuleKind['ESNext'],\n target: typescript.ScriptTarget['ES2022'],\n verbatimModuleSyntax: false,\n },\n },\n );\n\n const temporary = join(\n dirname(file),\n `.craft-deploy.${process.pid}.${Date.now()}.mjs`,\n );\n writeFileSync(temporary, outputText, 'utf8');\n try {\n return await import(pathToFileURL(temporary).href);\n } finally {\n rmSync(temporary, { force: true });\n }\n}\n"]}
@@ -0,0 +1,25 @@
1
+ import { type CraftDeploymentDiagnostic, type CraftDeploymentProvider } from '@craft-ts/deploy';
2
+ export type LoadedCraftDeploymentProvider = Readonly<{
3
+ provider: CraftDeploymentProvider | null;
4
+ /** Module specifier that was resolved, for diagnostics. */
5
+ specifier: string;
6
+ diagnostics: readonly CraftDeploymentDiagnostic[];
7
+ }>;
8
+ export type LoadCraftDeploymentProviderOptions = Readonly<{
9
+ name: string;
10
+ /** Project the provider is resolved from. */
11
+ rootDir: string;
12
+ /** Explicit module specifier, overriding `@craft-ts/deploy-<name>`. */
13
+ module?: string;
14
+ /** Options handed to the provider factory. */
15
+ providerOptions?: Readonly<Record<string, unknown>>;
16
+ }>;
17
+ /**
18
+ * Resolves a provider package at run time.
19
+ *
20
+ * The CLI has no dependency on any provider: it imports
21
+ * `@craft-ts/deploy-<name>` from the project being deployed and reads the one
22
+ * factory the contract defines. Adding a provider never means changing the CLI.
23
+ */
24
+ export declare function loadCraftDeploymentProvider(options: LoadCraftDeploymentProviderOptions): Promise<LoadedCraftDeploymentProvider>;
25
+ //# sourceMappingURL=load-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-provider.d.ts","sourceRoot":"","sources":["../../../../../libs/cli/src/lib/load-provider.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,EAC7B,MAAM,kBAAkB,CAAC;AAE1B,MAAM,MAAM,6BAA6B,GAAG,QAAQ,CAAC;IACnD,QAAQ,EAAE,uBAAuB,GAAG,IAAI,CAAC;IACzC,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,SAAS,yBAAyB,EAAE,CAAC;CACnD,CAAC,CAAC;AAEH,MAAM,MAAM,kCAAkC,GAAG,QAAQ,CAAC;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACrD,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,kCAAkC,GAC1C,OAAO,CAAC,6BAA6B,CAAC,CA2DxC"}
@@ -0,0 +1,92 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ import { createRequire } from 'node:module';
10
+ import { join } from 'node:path';
11
+ import { pathToFileURL } from 'node:url';
12
+ import { isCraftDeploymentProviderModule, } from '@craft-ts/deploy';
13
+ /**
14
+ * Resolves a provider package at run time.
15
+ *
16
+ * The CLI has no dependency on any provider: it imports
17
+ * `@craft-ts/deploy-<name>` from the project being deployed and reads the one
18
+ * factory the contract defines. Adding a provider never means changing the CLI.
19
+ */
20
+ export async function loadCraftDeploymentProvider(options) {
21
+ const specifier = options.module ?? `@craft-ts/deploy-${options.name}`;
22
+ let module;
23
+ try {
24
+ module = await importFromProject(specifier, options.rootDir);
25
+ }
26
+ catch (error) {
27
+ return {
28
+ provider: null,
29
+ specifier,
30
+ diagnostics: [
31
+ {
32
+ code: 'CRAFT_DEPLOY_PROVIDER_NOT_INSTALLED',
33
+ severity: 'error',
34
+ provider: options.name,
35
+ message: `\`${specifier}\` could not be imported: ${messageOf(error)}`,
36
+ fix: `Install \`${specifier}\`, or pass \`--provider-module\` with the module that exports the provider.`,
37
+ },
38
+ ],
39
+ };
40
+ }
41
+ if (!isCraftDeploymentProviderModule(module)) {
42
+ return {
43
+ provider: null,
44
+ specifier,
45
+ diagnostics: [
46
+ {
47
+ code: 'CRAFT_DEPLOY_PROVIDER_INVALID_MODULE',
48
+ severity: 'error',
49
+ provider: options.name,
50
+ message: `\`${specifier}\` exports no \`createCraftDeploymentProvider\` factory.`,
51
+ fix: 'Export `createCraftDeploymentProvider(options?)` returning a `CraftDeploymentProvider`.',
52
+ },
53
+ ],
54
+ };
55
+ }
56
+ const provider = module.createCraftDeploymentProvider(options.providerOptions ?? {});
57
+ if (provider.name !== options.name && options.module === undefined) {
58
+ return {
59
+ provider,
60
+ specifier,
61
+ diagnostics: [
62
+ {
63
+ code: 'CRAFT_DEPLOY_PROVIDER_INVALID_MODULE',
64
+ severity: 'warning',
65
+ provider: options.name,
66
+ message: `\`${specifier}\` provides \`${provider.name}\`, not \`${options.name}\`.`,
67
+ fix: 'Use the provider name the package declares, or pass `--provider-module` explicitly.',
68
+ },
69
+ ],
70
+ };
71
+ }
72
+ return { provider, specifier, diagnostics: [] };
73
+ }
74
+ /**
75
+ * Resolves from the deployed project, not from wherever the CLI is installed:
76
+ * a globally installed `craft-ts` must still find the provider a project
77
+ * declares in its own dependencies.
78
+ */
79
+ async function importFromProject(specifier, rootDir) {
80
+ try {
81
+ const requireFromProject = createRequire(join(rootDir, 'package.json'));
82
+ const resolved = requireFromProject.resolve(specifier);
83
+ return await import(__rewriteRelativeImportExtension(pathToFileURL(resolved).href));
84
+ }
85
+ catch {
86
+ return await import(__rewriteRelativeImportExtension(specifier));
87
+ }
88
+ }
89
+ function messageOf(error) {
90
+ return error instanceof Error ? error.message : String(error);
91
+ }
92
+ //# sourceMappingURL=load-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-provider.js","sourceRoot":"","sources":["../../../../../libs/cli/src/lib/load-provider.ts"],"names":[],"mappings":";;;;;;;;AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,+BAA+B,GAGhC,MAAM,kBAAkB,CAAC;AAmB1B;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,OAA2C;IAE3C,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,IAAI,oBAAoB,OAAO,CAAC,IAAI,EAAE,CAAC;IAEvE,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,iBAAiB,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,QAAQ,EAAE,IAAI;YACd,SAAS;YACT,WAAW,EAAE;gBACX;oBACE,IAAI,EAAE,qCAAqC;oBAC3C,QAAQ,EAAE,OAAO;oBACjB,QAAQ,EAAE,OAAO,CAAC,IAAI;oBACtB,OAAO,EAAE,KAAK,SAAS,6BAA6B,SAAS,CAAC,KAAK,CAAC,EAAE;oBACtE,GAAG,EAAE,aAAa,SAAS,8EAA8E;iBAC1G;aACF;SACF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,+BAA+B,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7C,OAAO;YACL,QAAQ,EAAE,IAAI;YACd,SAAS;YACT,WAAW,EAAE;gBACX;oBACE,IAAI,EAAE,sCAAsC;oBAC5C,QAAQ,EAAE,OAAO;oBACjB,QAAQ,EAAE,OAAO,CAAC,IAAI;oBACtB,OAAO,EAAE,KAAK,SAAS,0DAA0D;oBACjF,GAAG,EAAE,yFAAyF;iBAC/F;aACF;SACF,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,6BAA6B,CACnD,OAAO,CAAC,eAAe,IAAI,EAAE,CAC9B,CAAC;IAEF,IAAI,QAAQ,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACnE,OAAO;YACL,QAAQ;YACR,SAAS;YACT,WAAW,EAAE;gBACX;oBACE,IAAI,EAAE,sCAAsC;oBAC5C,QAAQ,EAAE,SAAS;oBACnB,QAAQ,EAAE,OAAO,CAAC,IAAI;oBACtB,OAAO,EAAE,KAAK,SAAS,iBAAiB,QAAQ,CAAC,IAAI,aAAa,OAAO,CAAC,IAAI,KAAK;oBACnF,GAAG,EAAE,qFAAqF;iBAC3F;aACF;SACF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,iBAAiB,CAC9B,SAAiB,EACjB,OAAe;IAEf,IAAI,CAAC;QACH,MAAM,kBAAkB,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;QACxE,MAAM,QAAQ,GAAG,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACvD,OAAO,MAAM,MAAM,kCAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,MAAM,kCAAC,SAAS,EAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC","sourcesContent":["import { createRequire } from 'node:module';\nimport { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport {\n isCraftDeploymentProviderModule,\n type CraftDeploymentDiagnostic,\n type CraftDeploymentProvider,\n} from '@craft-ts/deploy';\n\nexport type LoadedCraftDeploymentProvider = Readonly<{\n provider: CraftDeploymentProvider | null;\n /** Module specifier that was resolved, for diagnostics. */\n specifier: string;\n diagnostics: readonly CraftDeploymentDiagnostic[];\n}>;\n\nexport type LoadCraftDeploymentProviderOptions = Readonly<{\n name: string;\n /** Project the provider is resolved from. */\n rootDir: string;\n /** Explicit module specifier, overriding `@craft-ts/deploy-<name>`. */\n module?: string;\n /** Options handed to the provider factory. */\n providerOptions?: Readonly<Record<string, unknown>>;\n}>;\n\n/**\n * Resolves a provider package at run time.\n *\n * The CLI has no dependency on any provider: it imports\n * `@craft-ts/deploy-<name>` from the project being deployed and reads the one\n * factory the contract defines. Adding a provider never means changing the CLI.\n */\nexport async function loadCraftDeploymentProvider(\n options: LoadCraftDeploymentProviderOptions,\n): Promise<LoadedCraftDeploymentProvider> {\n const specifier = options.module ?? `@craft-ts/deploy-${options.name}`;\n\n let module: unknown;\n try {\n module = await importFromProject(specifier, options.rootDir);\n } catch (error) {\n return {\n provider: null,\n specifier,\n diagnostics: [\n {\n code: 'CRAFT_DEPLOY_PROVIDER_NOT_INSTALLED',\n severity: 'error',\n provider: options.name,\n message: `\\`${specifier}\\` could not be imported: ${messageOf(error)}`,\n fix: `Install \\`${specifier}\\`, or pass \\`--provider-module\\` with the module that exports the provider.`,\n },\n ],\n };\n }\n\n if (!isCraftDeploymentProviderModule(module)) {\n return {\n provider: null,\n specifier,\n diagnostics: [\n {\n code: 'CRAFT_DEPLOY_PROVIDER_INVALID_MODULE',\n severity: 'error',\n provider: options.name,\n message: `\\`${specifier}\\` exports no \\`createCraftDeploymentProvider\\` factory.`,\n fix: 'Export `createCraftDeploymentProvider(options?)` returning a `CraftDeploymentProvider`.',\n },\n ],\n };\n }\n\n const provider = module.createCraftDeploymentProvider(\n options.providerOptions ?? {},\n );\n\n if (provider.name !== options.name && options.module === undefined) {\n return {\n provider,\n specifier,\n diagnostics: [\n {\n code: 'CRAFT_DEPLOY_PROVIDER_INVALID_MODULE',\n severity: 'warning',\n provider: options.name,\n message: `\\`${specifier}\\` provides \\`${provider.name}\\`, not \\`${options.name}\\`.`,\n fix: 'Use the provider name the package declares, or pass `--provider-module` explicitly.',\n },\n ],\n };\n }\n\n return { provider, specifier, diagnostics: [] };\n}\n\n/**\n * Resolves from the deployed project, not from wherever the CLI is installed:\n * a globally installed `craft-ts` must still find the provider a project\n * declares in its own dependencies.\n */\nasync function importFromProject(\n specifier: string,\n rootDir: string,\n): Promise<unknown> {\n try {\n const requireFromProject = createRequire(join(rootDir, 'package.json'));\n const resolved = requireFromProject.resolve(specifier);\n return await import(pathToFileURL(resolved).href);\n } catch {\n return await import(specifier);\n }\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import { type CraftCliIo } from './io.js';
2
+ export declare const CRAFT_CLI_HELP = "craft-ts \u2014 deployment tooling for CraftTS applications\n\nExperimental: the command surface, the manifest fields and the diagnostic codes\ncan still change between minor versions. Pin the version in a pipeline.\n\nUsage: craft-ts <command> [options]\n\nCommands:\n check Validate a deployment manifest before building\n manifest Resolve the manifest to its provider-neutral artefact form\n providers List the deployment providers and their capabilities\n deploy preview Show what a provider would change, without changing it\n deploy Apply that plan, once `--yes` approves it\n\nRun `craft-ts <command> --help` for the options of a command.\n\nDeployment vocabulary:\n runtime Execution shape of the bundle: static, node, worker, lambda\n platform Technical platform executing it: cloudflare, aws, docker, \u2026\n provider Integration that builds, publishes or provisions it";
3
+ /**
4
+ * Entry point of the CLI, kept free of `process` so tests drive it with a
5
+ * captured `io` and an arbitrary working directory.
6
+ */
7
+ export declare function runCraftCli(argv: readonly string[], io?: CraftCliIo): Promise<number>;
8
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../../../libs/cli/src/lib/run.ts"],"names":[],"mappings":"AAIA,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAErD,eAAO,MAAM,cAAc,49BAmBgD,CAAC;AAE5E;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,EAAE,GAAE,UAAwB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
package/src/lib/run.js ADDED
@@ -0,0 +1,48 @@
1
+ import { runCheckCommand } from './commands/check.js';
2
+ import { runDeployCommand } from './commands/deploy.js';
3
+ import { runManifestCommand } from './commands/manifest.js';
4
+ import { runProvidersCommand } from './commands/providers.js';
5
+ import { processIo } from './io.js';
6
+ export const CRAFT_CLI_HELP = `craft-ts — deployment tooling for CraftTS applications
7
+
8
+ Experimental: the command surface, the manifest fields and the diagnostic codes
9
+ can still change between minor versions. Pin the version in a pipeline.
10
+
11
+ Usage: craft-ts <command> [options]
12
+
13
+ Commands:
14
+ check Validate a deployment manifest before building
15
+ manifest Resolve the manifest to its provider-neutral artefact form
16
+ providers List the deployment providers and their capabilities
17
+ deploy preview Show what a provider would change, without changing it
18
+ deploy Apply that plan, once \`--yes\` approves it
19
+
20
+ Run \`craft-ts <command> --help\` for the options of a command.
21
+
22
+ Deployment vocabulary:
23
+ runtime Execution shape of the bundle: static, node, worker, lambda
24
+ platform Technical platform executing it: cloudflare, aws, docker, …
25
+ provider Integration that builds, publishes or provisions it`;
26
+ /**
27
+ * Entry point of the CLI, kept free of `process` so tests drive it with a
28
+ * captured `io` and an arbitrary working directory.
29
+ */
30
+ export async function runCraftCli(argv, io = processIo()) {
31
+ const [command, ...rest] = argv;
32
+ if (command === undefined || command === 'help' || command === '--help') {
33
+ io.write(CRAFT_CLI_HELP);
34
+ return command === undefined ? 1 : 0;
35
+ }
36
+ if (command === 'check')
37
+ return await runCheckCommand(rest, io);
38
+ if (command === 'manifest')
39
+ return await runManifestCommand(rest, io);
40
+ if (command === 'providers')
41
+ return runProvidersCommand(rest, io);
42
+ if (command === 'deploy')
43
+ return await runDeployCommand(rest, io);
44
+ io.writeError(`Unknown command: ${command}`);
45
+ io.writeError(CRAFT_CLI_HELP);
46
+ return 1;
47
+ }
48
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../../../libs/cli/src/lib/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAmB,MAAM,SAAS,CAAC;AAErD,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;2EAmB6C,CAAC;AAE5E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAuB,EACvB,KAAiB,SAAS,EAAE;IAE5B,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAEhC,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACxE,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACzB,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,OAAO,KAAK,OAAO;QAAE,OAAO,MAAM,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAChE,IAAI,OAAO,KAAK,UAAU;QAAE,OAAO,MAAM,kBAAkB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACtE,IAAI,OAAO,KAAK,WAAW;QAAE,OAAO,mBAAmB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAClE,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO,MAAM,gBAAgB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAElE,EAAE,CAAC,UAAU,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;IAC7C,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC;AACX,CAAC","sourcesContent":["import { runCheckCommand } from './commands/check.js';\nimport { runDeployCommand } from './commands/deploy.js';\nimport { runManifestCommand } from './commands/manifest.js';\nimport { runProvidersCommand } from './commands/providers.js';\nimport { processIo, type CraftCliIo } from './io.js';\n\nexport const CRAFT_CLI_HELP = `craft-ts — deployment tooling for CraftTS applications\n\nExperimental: the command surface, the manifest fields and the diagnostic codes\ncan still change between minor versions. Pin the version in a pipeline.\n\nUsage: craft-ts <command> [options]\n\nCommands:\n check Validate a deployment manifest before building\n manifest Resolve the manifest to its provider-neutral artefact form\n providers List the deployment providers and their capabilities\n deploy preview Show what a provider would change, without changing it\n deploy Apply that plan, once \\`--yes\\` approves it\n\nRun \\`craft-ts <command> --help\\` for the options of a command.\n\nDeployment vocabulary:\n runtime Execution shape of the bundle: static, node, worker, lambda\n platform Technical platform executing it: cloudflare, aws, docker, …\n provider Integration that builds, publishes or provisions it`;\n\n/**\n * Entry point of the CLI, kept free of `process` so tests drive it with a\n * captured `io` and an arbitrary working directory.\n */\nexport async function runCraftCli(\n argv: readonly string[],\n io: CraftCliIo = processIo(),\n): Promise<number> {\n const [command, ...rest] = argv;\n\n if (command === undefined || command === 'help' || command === '--help') {\n io.write(CRAFT_CLI_HELP);\n return command === undefined ? 1 : 0;\n }\n\n if (command === 'check') return await runCheckCommand(rest, io);\n if (command === 'manifest') return await runManifestCommand(rest, io);\n if (command === 'providers') return runProvidersCommand(rest, io);\n if (command === 'deploy') return await runDeployCommand(rest, io);\n\n io.writeError(`Unknown command: ${command}`);\n io.writeError(CRAFT_CLI_HELP);\n return 1;\n}\n"]}