@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.
- package/LICENSE +21 -0
- package/README.md +21 -0
- package/package.json +53 -0
- package/src/bin/craft-ts.d.ts +3 -0
- package/src/bin/craft-ts.d.ts.map +1 -0
- package/src/bin/craft-ts.js +9 -0
- package/src/bin/craft-ts.js.map +1 -0
- package/src/index.d.ts +10 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js +6 -0
- package/src/index.js.map +1 -0
- package/src/lib/args.d.ts +21 -0
- package/src/lib/args.d.ts.map +1 -0
- package/src/lib/args.js +37 -0
- package/src/lib/args.js.map +1 -0
- package/src/lib/commands/check.d.ts +8 -0
- package/src/lib/commands/check.d.ts.map +1 -0
- package/src/lib/commands/check.js +79 -0
- package/src/lib/commands/check.js.map +1 -0
- package/src/lib/commands/deploy.d.ts +10 -0
- package/src/lib/commands/deploy.d.ts.map +1 -0
- package/src/lib/commands/deploy.js +199 -0
- package/src/lib/commands/deploy.js.map +1 -0
- package/src/lib/commands/manifest.d.ts +10 -0
- package/src/lib/commands/manifest.d.ts.map +1 -0
- package/src/lib/commands/manifest.js +67 -0
- package/src/lib/commands/manifest.js.map +1 -0
- package/src/lib/commands/providers.d.ts +9 -0
- package/src/lib/commands/providers.d.ts.map +1 -0
- package/src/lib/commands/providers.js +42 -0
- package/src/lib/commands/providers.js.map +1 -0
- package/src/lib/io.d.ts +7 -0
- package/src/lib/io.d.ts.map +1 -0
- package/src/lib/io.js +12 -0
- package/src/lib/io.js.map +1 -0
- package/src/lib/load-config.d.ts +22 -0
- package/src/lib/load-config.d.ts.map +1 -0
- package/src/lib/load-config.js +158 -0
- package/src/lib/load-config.js.map +1 -0
- package/src/lib/load-provider.d.ts +25 -0
- package/src/lib/load-provider.d.ts.map +1 -0
- package/src/lib/load-provider.js +92 -0
- package/src/lib/load-provider.js.map +1 -0
- package/src/lib/run.d.ts +8 -0
- package/src/lib/run.d.ts.map +1 -0
- package/src/lib/run.js +48 -0
- 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 @@
|
|
|
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
|
package/src/index.js.map
ADDED
|
@@ -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"}
|
package/src/lib/args.js
ADDED
|
@@ -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":"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","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"]}
|
package/src/lib/io.d.ts
ADDED
|
@@ -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 @@
|
|
|
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":"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","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"]}
|
package/src/lib/run.d.ts
ADDED
|
@@ -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"]}
|