@craft-ts/deploy 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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +41 -0
  3. package/package.json +42 -0
  4. package/src/index.d.ts +18 -0
  5. package/src/index.d.ts.map +1 -0
  6. package/src/index.js +10 -0
  7. package/src/index.js.map +1 -0
  8. package/src/lib/artifact.d.ts +18 -0
  9. package/src/lib/artifact.d.ts.map +1 -0
  10. package/src/lib/artifact.js +121 -0
  11. package/src/lib/artifact.js.map +1 -0
  12. package/src/lib/check.d.ts +31 -0
  13. package/src/lib/check.d.ts.map +1 -0
  14. package/src/lib/check.js +278 -0
  15. package/src/lib/check.js.map +1 -0
  16. package/src/lib/diagnostics.d.ts +38 -0
  17. package/src/lib/diagnostics.d.ts.map +1 -0
  18. package/src/lib/diagnostics.js +297 -0
  19. package/src/lib/diagnostics.js.map +1 -0
  20. package/src/lib/format.d.ts +17 -0
  21. package/src/lib/format.d.ts.map +1 -0
  22. package/src/lib/format.js +42 -0
  23. package/src/lib/format.js.map +1 -0
  24. package/src/lib/manifest.d.ts +236 -0
  25. package/src/lib/manifest.d.ts.map +1 -0
  26. package/src/lib/manifest.js +47 -0
  27. package/src/lib/manifest.js.map +1 -0
  28. package/src/lib/protocol.d.ts +22 -0
  29. package/src/lib/protocol.d.ts.map +1 -0
  30. package/src/lib/protocol.js +182 -0
  31. package/src/lib/protocol.js.map +1 -0
  32. package/src/lib/providers.d.ts +111 -0
  33. package/src/lib/providers.d.ts.map +1 -0
  34. package/src/lib/providers.js +156 -0
  35. package/src/lib/providers.js.map +1 -0
  36. package/src/lib/sources.d.ts +31 -0
  37. package/src/lib/sources.d.ts.map +1 -0
  38. package/src/lib/sources.js +155 -0
  39. package/src/lib/sources.js.map +1 -0
  40. package/src/lib/validate.d.ts +16 -0
  41. package/src/lib/validate.d.ts.map +1 -0
  42. package/src/lib/validate.js +361 -0
  43. package/src/lib/validate.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,41 @@
1
+ # @craft-ts/deploy
2
+
3
+ Provider-neutral deployment contract for CraftTS applications.
4
+
5
+ > **Experimental.** Manifest fields, diagnostic codes and the provider contract
6
+ > can still change between minor versions. The serialised manifest carries
7
+ > `protocolVersion: '1'`, and one produced by another protocol is refused rather
8
+ > than reinterpreted, so a change breaks loudly at the check. Pin the version if
9
+ > you build a pipeline on it.
10
+
11
+ The package holds the typed manifest an application writes in
12
+ `craft.deploy.ts`, the checks that run before a build, and the capability
13
+ matrix of the deployment providers. It never deploys anything: publishing and
14
+ provisioning belong to a provider package.
15
+
16
+ ```ts
17
+ import { defineCraftDeployment } from '@craft-ts/deploy';
18
+
19
+ export default defineCraftDeployment({
20
+ name: 'demo-ssr',
21
+ runtime: 'node',
22
+ platform: 'docker',
23
+ server: {
24
+ entry: 'dist/apps/demo-ssr/server/server.js',
25
+ source: 'apps/demo-ssr/src/production-server.ts',
26
+ healthPath: '/health',
27
+ readyPath: '/ready',
28
+ },
29
+ });
30
+ ```
31
+
32
+ Three notions stay distinct everywhere:
33
+
34
+ | Notion | Question it answers | Examples |
35
+ | ---------- | ------------------------------------------------ | ------------------------------------ |
36
+ | `runtime` | What shape does the bundle execute in? | `static`, `node`, `worker`, `lambda` |
37
+ | `platform` | Which technical platform runs it? | `cloudflare`, `aws`, `docker` |
38
+ | provider | Which integration builds, publishes, provisions? | `alchemy`, `vercel`, `docker` |
39
+
40
+ See the [deployment guide](../../apps/docs/guide/deployment/index.md) for the
41
+ manifest reference, the diagnostics and the provider matrix.
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@craft-ts/deploy",
3
+ "version": "0.7.0-beta.15",
4
+ "description": "Provider-neutral deployment contract for CraftTS: manifest, validation and capability matrix",
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
+ "deployment",
18
+ "manifest",
19
+ "worker",
20
+ "lambda",
21
+ "ssr",
22
+ "typescript"
23
+ ],
24
+ "engines": {
25
+ "node": ">=20.19.0"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "sideEffects": false,
31
+ "type": "module",
32
+ "main": "./src/index.js",
33
+ "types": "./src/index.d.ts",
34
+ "exports": {
35
+ "./package.json": "./package.json",
36
+ ".": {
37
+ "types": "./src/index.d.ts",
38
+ "default": "./src/index.js"
39
+ }
40
+ },
41
+ "module": "./src/index.js"
42
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ export { CRAFT_DEPLOYMENT_PLATFORMS, CRAFT_DEPLOYMENT_PROTOCOL_VERSION, CRAFT_DEPLOYMENT_RUNTIMES, CRAFT_SOURCE_MAP_POLICIES, CRAFT_STATIC_MODES, defineCraftDeployment, } from './lib/manifest.js';
2
+ export type { CraftDeploymentArtifact, CraftDeploymentArtifactInput, CraftDeploymentBinding, CraftDeploymentClient, CraftDeploymentDefinition, CraftDeploymentEnvironmentVariable, CraftDeploymentFunctions, CraftDeploymentFunctionsInput, CraftDeploymentLambda, CraftDeploymentLambdaInput, CraftDeploymentManifest, CraftDeploymentPlatform, CraftDeploymentRuntime, CraftDeploymentServer, CraftDeploymentServerInput, CraftDeploymentStatic, CraftDeploymentStaticInput, CraftDeploymentWorker, CraftDeploymentWorkerInput, CraftLambdaDeploymentDefinition, CraftLambdaDeploymentManifest, CraftNodeDeploymentDefinition, CraftNodeDeploymentManifest, CraftSourceMapPolicy, CraftStaticDeploymentDefinition, CraftStaticDeploymentManifest, CraftStaticMode, CraftWorkerDeploymentDefinition, CraftWorkerDeploymentManifest, } from './lib/manifest.js';
3
+ export { CRAFT_DEPLOYMENT_DIAGNOSTIC_CODES, CRAFT_DEPLOYMENT_DIAGNOSTICS, } from './lib/diagnostics.js';
4
+ export type { CraftDeploymentDiagnostic, CraftDeploymentDiagnosticCode, CraftDeploymentDiagnosticDescription, CraftDeploymentSeverity, } from './lib/diagnostics.js';
5
+ export { formatCraftDeploymentDiagnostic, formatCraftDeploymentPlan, } from './lib/format.js';
6
+ export { parseCraftDeploymentManifest, resolveCraftDeploymentManifest, serializeCraftDeploymentManifest, } from './lib/protocol.js';
7
+ export type { CraftDeploymentParseResult } from './lib/protocol.js';
8
+ export { validateCraftDeploymentDefinition } from './lib/validate.js';
9
+ export type { CraftDeploymentValidation } from './lib/validate.js';
10
+ export { CRAFT_DEPLOYMENT_CAPABILITIES, CRAFT_DEPLOYMENT_PROVIDERS, CRAFT_DEPLOYMENT_RESOURCE_ACTIONS, CRAFT_RUNTIME_PLATFORMS, findCraftDeploymentProvider, isCraftDeploymentProviderModule, isRuntimeSupportedByPlatform, requiredCapability, } from './lib/providers.js';
11
+ export type { CraftDeploymentCapability, CraftDeploymentPlan, CraftDeploymentPlannedResource, CraftDeploymentProvider, CraftDeploymentProviderDescriptor, CraftDeploymentProviderModule, CraftDeploymentRequest, CraftDeploymentResourceAction, CraftDeploymentResult, } from './lib/providers.js';
12
+ export { checkCraftDeployment } from './lib/check.js';
13
+ export type { CraftDeploymentCheckOptions, CraftDeploymentCheckResult, } from './lib/check.js';
14
+ export { checkCraftDeploymentArtifact } from './lib/artifact.js';
15
+ export type { CraftArtifactCheckOptions } from './lib/artifact.js';
16
+ export { collectEnvironmentReads, isNodeBuiltin, readCraftModuleGraph, } from './lib/sources.js';
17
+ export type { CraftModuleGraph, CraftModuleImport } from './lib/sources.js';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../libs/deploy/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,iCAAiC,EACjC,yBAAyB,EACzB,yBAAyB,EACzB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,uBAAuB,EACvB,4BAA4B,EAC5B,sBAAsB,EACtB,qBAAqB,EACrB,yBAAyB,EACzB,kCAAkC,EAClC,wBAAwB,EACxB,6BAA6B,EAC7B,qBAAqB,EACrB,0BAA0B,EAC1B,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,EACrB,0BAA0B,EAC1B,+BAA+B,EAC/B,6BAA6B,EAC7B,6BAA6B,EAC7B,2BAA2B,EAC3B,oBAAoB,EACpB,+BAA+B,EAC/B,6BAA6B,EAC7B,eAAe,EACf,+BAA+B,EAC/B,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,iCAAiC,EACjC,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,yBAAyB,EACzB,6BAA6B,EAC7B,oCAAoC,EACpC,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,+BAA+B,EAC/B,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,4BAA4B,EAC5B,8BAA8B,EAC9B,gCAAgC,GACjC,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,EAAE,iCAAiC,EAAE,MAAM,mBAAmB,CAAC;AACtE,YAAY,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EACL,6BAA6B,EAC7B,0BAA0B,EAC1B,iCAAiC,EACjC,uBAAuB,EACvB,2BAA2B,EAC3B,+BAA+B,EAC/B,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,yBAAyB,EACzB,mBAAmB,EACnB,8BAA8B,EAC9B,uBAAuB,EACvB,iCAAiC,EACjC,6BAA6B,EAC7B,sBAAsB,EACtB,6BAA6B,EAC7B,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,YAAY,EACV,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AACjE,YAAY,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EACL,uBAAuB,EACvB,aAAa,EACb,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC"}
package/src/index.js ADDED
@@ -0,0 +1,10 @@
1
+ export { CRAFT_DEPLOYMENT_PLATFORMS, CRAFT_DEPLOYMENT_PROTOCOL_VERSION, CRAFT_DEPLOYMENT_RUNTIMES, CRAFT_SOURCE_MAP_POLICIES, CRAFT_STATIC_MODES, defineCraftDeployment, } from './lib/manifest.js';
2
+ export { CRAFT_DEPLOYMENT_DIAGNOSTIC_CODES, CRAFT_DEPLOYMENT_DIAGNOSTICS, } from './lib/diagnostics.js';
3
+ export { formatCraftDeploymentDiagnostic, formatCraftDeploymentPlan, } from './lib/format.js';
4
+ export { parseCraftDeploymentManifest, resolveCraftDeploymentManifest, serializeCraftDeploymentManifest, } from './lib/protocol.js';
5
+ export { validateCraftDeploymentDefinition } from './lib/validate.js';
6
+ export { CRAFT_DEPLOYMENT_CAPABILITIES, CRAFT_DEPLOYMENT_PROVIDERS, CRAFT_DEPLOYMENT_RESOURCE_ACTIONS, CRAFT_RUNTIME_PLATFORMS, findCraftDeploymentProvider, isCraftDeploymentProviderModule, isRuntimeSupportedByPlatform, requiredCapability, } from './lib/providers.js';
7
+ export { checkCraftDeployment } from './lib/check.js';
8
+ export { checkCraftDeploymentArtifact } from './lib/artifact.js';
9
+ export { collectEnvironmentReads, isNodeBuiltin, readCraftModuleGraph, } from './lib/sources.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/deploy/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,iCAAiC,EACjC,yBAAyB,EACzB,yBAAyB,EACzB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAiC3B,OAAO,EACL,iCAAiC,EACjC,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAQ9B,OAAO,EACL,+BAA+B,EAC/B,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,4BAA4B,EAC5B,8BAA8B,EAC9B,gCAAgC,GACjC,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,iCAAiC,EAAE,MAAM,mBAAmB,CAAC;AAGtE,OAAO,EACL,6BAA6B,EAC7B,0BAA0B,EAC1B,iCAAiC,EACjC,uBAAuB,EACvB,2BAA2B,EAC3B,+BAA+B,EAC/B,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAa5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAMtD,OAAO,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AAGjE,OAAO,EACL,uBAAuB,EACvB,aAAa,EACb,oBAAoB,GACrB,MAAM,kBAAkB,CAAC","sourcesContent":["export {\n CRAFT_DEPLOYMENT_PLATFORMS,\n CRAFT_DEPLOYMENT_PROTOCOL_VERSION,\n CRAFT_DEPLOYMENT_RUNTIMES,\n CRAFT_SOURCE_MAP_POLICIES,\n CRAFT_STATIC_MODES,\n defineCraftDeployment,\n} from './lib/manifest.js';\nexport type {\n CraftDeploymentArtifact,\n CraftDeploymentArtifactInput,\n CraftDeploymentBinding,\n CraftDeploymentClient,\n CraftDeploymentDefinition,\n CraftDeploymentEnvironmentVariable,\n CraftDeploymentFunctions,\n CraftDeploymentFunctionsInput,\n CraftDeploymentLambda,\n CraftDeploymentLambdaInput,\n CraftDeploymentManifest,\n CraftDeploymentPlatform,\n CraftDeploymentRuntime,\n CraftDeploymentServer,\n CraftDeploymentServerInput,\n CraftDeploymentStatic,\n CraftDeploymentStaticInput,\n CraftDeploymentWorker,\n CraftDeploymentWorkerInput,\n CraftLambdaDeploymentDefinition,\n CraftLambdaDeploymentManifest,\n CraftNodeDeploymentDefinition,\n CraftNodeDeploymentManifest,\n CraftSourceMapPolicy,\n CraftStaticDeploymentDefinition,\n CraftStaticDeploymentManifest,\n CraftStaticMode,\n CraftWorkerDeploymentDefinition,\n CraftWorkerDeploymentManifest,\n} from './lib/manifest.js';\n\nexport {\n CRAFT_DEPLOYMENT_DIAGNOSTIC_CODES,\n CRAFT_DEPLOYMENT_DIAGNOSTICS,\n} from './lib/diagnostics.js';\nexport type {\n CraftDeploymentDiagnostic,\n CraftDeploymentDiagnosticCode,\n CraftDeploymentDiagnosticDescription,\n CraftDeploymentSeverity,\n} from './lib/diagnostics.js';\n\nexport {\n formatCraftDeploymentDiagnostic,\n formatCraftDeploymentPlan,\n} from './lib/format.js';\n\nexport {\n parseCraftDeploymentManifest,\n resolveCraftDeploymentManifest,\n serializeCraftDeploymentManifest,\n} from './lib/protocol.js';\nexport type { CraftDeploymentParseResult } from './lib/protocol.js';\n\nexport { validateCraftDeploymentDefinition } from './lib/validate.js';\nexport type { CraftDeploymentValidation } from './lib/validate.js';\n\nexport {\n CRAFT_DEPLOYMENT_CAPABILITIES,\n CRAFT_DEPLOYMENT_PROVIDERS,\n CRAFT_DEPLOYMENT_RESOURCE_ACTIONS,\n CRAFT_RUNTIME_PLATFORMS,\n findCraftDeploymentProvider,\n isCraftDeploymentProviderModule,\n isRuntimeSupportedByPlatform,\n requiredCapability,\n} from './lib/providers.js';\nexport type {\n CraftDeploymentCapability,\n CraftDeploymentPlan,\n CraftDeploymentPlannedResource,\n CraftDeploymentProvider,\n CraftDeploymentProviderDescriptor,\n CraftDeploymentProviderModule,\n CraftDeploymentRequest,\n CraftDeploymentResourceAction,\n CraftDeploymentResult,\n} from './lib/providers.js';\n\nexport { checkCraftDeployment } from './lib/check.js';\nexport type {\n CraftDeploymentCheckOptions,\n CraftDeploymentCheckResult,\n} from './lib/check.js';\n\nexport { checkCraftDeploymentArtifact } from './lib/artifact.js';\nexport type { CraftArtifactCheckOptions } from './lib/artifact.js';\n\nexport {\n collectEnvironmentReads,\n isNodeBuiltin,\n readCraftModuleGraph,\n} from './lib/sources.js';\nexport type { CraftModuleGraph, CraftModuleImport } from './lib/sources.js';\n"]}
@@ -0,0 +1,18 @@
1
+ import type { CraftDeploymentDiagnostic } from './diagnostics.js';
2
+ import type { CraftDeploymentManifest } from './manifest.js';
3
+ export type CraftArtifactCheckOptions = Readonly<{
4
+ /** Directory the manifest paths are relative to. */
5
+ rootDir?: string;
6
+ manifest: CraftDeploymentManifest;
7
+ }>;
8
+ /**
9
+ * Inspects the produced artefact rather than the sources.
10
+ *
11
+ * This is the stable API behind the `production:check` smoke: a build can only
12
+ * be published once the directory a provider would upload holds an entry
13
+ * point, executable JavaScript and nothing the source map policy forbids.
14
+ */
15
+ export declare function checkCraftDeploymentArtifact(options: CraftArtifactCheckOptions): readonly CraftDeploymentDiagnostic[];
16
+ /** A route is rendered as `<route>.html` or as `<route>/index.html`. */
17
+ export declare function hasPrerenderedDocument(publicDir: string, route: string): boolean;
18
+ //# sourceMappingURL=artifact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact.d.ts","sourceRoot":"","sources":["../../../../../libs/deploy/src/lib/artifact.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAE7D,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAAC;IAC/C,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,uBAAuB,CAAC;CACnC,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,yBAAyB,GACjC,SAAS,yBAAyB,EAAE,CAiGtC;AAED,wEAAwE;AACxE,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAKT"}
@@ -0,0 +1,121 @@
1
+ import { existsSync, readdirSync, statSync } from 'node:fs';
2
+ import { join, relative, resolve } from 'node:path';
3
+ /**
4
+ * Inspects the produced artefact rather than the sources.
5
+ *
6
+ * This is the stable API behind the `production:check` smoke: a build can only
7
+ * be published once the directory a provider would upload holds an entry
8
+ * point, executable JavaScript and nothing the source map policy forbids.
9
+ */
10
+ export function checkCraftDeploymentArtifact(options) {
11
+ const rootDir = resolve(options.rootDir ?? process.cwd());
12
+ const manifest = options.manifest;
13
+ const publicDir = manifest.artifact.publicDir;
14
+ const diagnostics = [];
15
+ if (!publicDir)
16
+ return diagnostics;
17
+ const absolutePublicDir = resolve(rootDir, publicDir);
18
+ if (!existsSync(absolutePublicDir)) {
19
+ return [
20
+ {
21
+ code: 'CRAFT_DEPLOY_ARTIFACT_MISSING',
22
+ severity: 'error',
23
+ path: 'artifact.publicDir',
24
+ file: publicDir,
25
+ runtime: manifest.runtime,
26
+ platform: manifest.platform,
27
+ message: `The artefact directory \`${publicDir}\` does not exist.`,
28
+ fix: 'Run the declared build command before checking the artefact.',
29
+ },
30
+ ];
31
+ }
32
+ const files = listFiles(absolutePublicDir);
33
+ const relativeFiles = files.map((file) => relative(rootDir, file));
34
+ if (!existsSync(join(absolutePublicDir, 'index.html'))) {
35
+ diagnostics.push({
36
+ code: 'CRAFT_DEPLOY_ARTIFACT_NO_ENTRY',
37
+ severity: 'error',
38
+ path: 'artifact.publicDir',
39
+ file: join(publicDir, 'index.html'),
40
+ runtime: manifest.runtime,
41
+ message: `\`${publicDir}\` contains no \`index.html\`.`,
42
+ fix: 'Check the build output directory declared in `client.outDir`.',
43
+ });
44
+ }
45
+ if (!files.some((file) => /\.m?js$/.test(file))) {
46
+ diagnostics.push({
47
+ code: 'CRAFT_DEPLOY_ARTIFACT_NO_JAVASCRIPT',
48
+ severity: 'error',
49
+ path: 'artifact.publicDir',
50
+ file: publicDir,
51
+ runtime: manifest.runtime,
52
+ message: `\`${publicDir}\` contains no JavaScript file.`,
53
+ fix: 'Check the build command and its output directory.',
54
+ });
55
+ }
56
+ if (manifest.artifact.sourceMaps === 'forbidden') {
57
+ for (const file of relativeFiles.filter((name) => name.endsWith('.map'))) {
58
+ diagnostics.push({
59
+ code: 'CRAFT_DEPLOY_ARTIFACT_SOURCE_MAP',
60
+ severity: 'error',
61
+ path: 'artifact.sourceMaps',
62
+ file,
63
+ runtime: manifest.runtime,
64
+ message: `\`${file}\` is a source map and the policy is \`forbidden\`.`,
65
+ fix: 'Disable source maps in the production build, or relax `artifact.sourceMaps`.',
66
+ });
67
+ }
68
+ }
69
+ if (manifest.runtime === 'static') {
70
+ if (manifest.static.mode === 'spa') {
71
+ const fallback = join(publicDir, manifest.static.fallback);
72
+ if (!existsSync(resolve(rootDir, fallback))) {
73
+ diagnostics.push({
74
+ code: 'CRAFT_DEPLOY_SPA_FALLBACK_MISSING',
75
+ severity: 'error',
76
+ path: 'static.fallback',
77
+ file: fallback,
78
+ runtime: 'static',
79
+ message: `The SPA fallback \`${fallback}\` is missing from the artefact.`,
80
+ fix: 'Build the client, or correct `static.fallback`.',
81
+ });
82
+ }
83
+ }
84
+ else {
85
+ for (const [index, route] of manifest.static.routes.entries()) {
86
+ if (!hasPrerenderedDocument(absolutePublicDir, route)) {
87
+ diagnostics.push({
88
+ code: 'CRAFT_DEPLOY_SSG_ROUTE_NOT_RENDERED',
89
+ severity: 'error',
90
+ path: `static.routes[${index}]`,
91
+ file: publicDir,
92
+ runtime: 'static',
93
+ message: `No pre-rendered document was found for \`${route}\`.`,
94
+ fix: 'Run the pre-render step for that route, or remove it from `static.routes`.',
95
+ });
96
+ }
97
+ }
98
+ }
99
+ }
100
+ return diagnostics;
101
+ }
102
+ /** A route is rendered as `<route>.html` or as `<route>/index.html`. */
103
+ export function hasPrerenderedDocument(publicDir, route) {
104
+ const segments = route.split('/').filter((segment) => segment.length > 0);
105
+ if (segments.length === 0)
106
+ return existsSync(join(publicDir, 'index.html'));
107
+ const base = join(publicDir, ...segments);
108
+ return existsSync(`${base}.html`) || existsSync(join(base, 'index.html'));
109
+ }
110
+ function listFiles(directory) {
111
+ const files = [];
112
+ for (const entry of readdirSync(directory)) {
113
+ const path = join(directory, entry);
114
+ if (statSync(path).isDirectory())
115
+ files.push(...listFiles(path));
116
+ else
117
+ files.push(path);
118
+ }
119
+ return files;
120
+ }
121
+ //# sourceMappingURL=artifact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact.js","sourceRoot":"","sources":["../../../../../libs/deploy/src/lib/artifact.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative, resolve } from 'node:path';\nimport type { CraftDeploymentDiagnostic } from './diagnostics.js';\nimport type { CraftDeploymentManifest } from './manifest.js';\n\nexport type CraftArtifactCheckOptions = Readonly<{\n /** Directory the manifest paths are relative to. */\n rootDir?: string;\n manifest: CraftDeploymentManifest;\n}>;\n\n/**\n * Inspects the produced artefact rather than the sources.\n *\n * This is the stable API behind the `production:check` smoke: a build can only\n * be published once the directory a provider would upload holds an entry\n * point, executable JavaScript and nothing the source map policy forbids.\n */\nexport function checkCraftDeploymentArtifact(\n options: CraftArtifactCheckOptions,\n): readonly CraftDeploymentDiagnostic[] {\n const rootDir = resolve(options.rootDir ?? process.cwd());\n const manifest = options.manifest;\n const publicDir = manifest.artifact.publicDir;\n const diagnostics: CraftDeploymentDiagnostic[] = [];\n\n if (!publicDir) return diagnostics;\n\n const absolutePublicDir = resolve(rootDir, publicDir);\n if (!existsSync(absolutePublicDir)) {\n return [\n {\n code: 'CRAFT_DEPLOY_ARTIFACT_MISSING',\n severity: 'error',\n path: 'artifact.publicDir',\n file: publicDir,\n runtime: manifest.runtime,\n platform: manifest.platform,\n message: `The artefact directory \\`${publicDir}\\` does not exist.`,\n fix: 'Run the declared build command before checking the artefact.',\n },\n ];\n }\n\n const files = listFiles(absolutePublicDir);\n const relativeFiles = files.map((file) => relative(rootDir, file));\n\n if (!existsSync(join(absolutePublicDir, 'index.html'))) {\n diagnostics.push({\n code: 'CRAFT_DEPLOY_ARTIFACT_NO_ENTRY',\n severity: 'error',\n path: 'artifact.publicDir',\n file: join(publicDir, 'index.html'),\n runtime: manifest.runtime,\n message: `\\`${publicDir}\\` contains no \\`index.html\\`.`,\n fix: 'Check the build output directory declared in `client.outDir`.',\n });\n }\n\n if (!files.some((file) => /\\.m?js$/.test(file))) {\n diagnostics.push({\n code: 'CRAFT_DEPLOY_ARTIFACT_NO_JAVASCRIPT',\n severity: 'error',\n path: 'artifact.publicDir',\n file: publicDir,\n runtime: manifest.runtime,\n message: `\\`${publicDir}\\` contains no JavaScript file.`,\n fix: 'Check the build command and its output directory.',\n });\n }\n\n if (manifest.artifact.sourceMaps === 'forbidden') {\n for (const file of relativeFiles.filter((name) => name.endsWith('.map'))) {\n diagnostics.push({\n code: 'CRAFT_DEPLOY_ARTIFACT_SOURCE_MAP',\n severity: 'error',\n path: 'artifact.sourceMaps',\n file,\n runtime: manifest.runtime,\n message: `\\`${file}\\` is a source map and the policy is \\`forbidden\\`.`,\n fix: 'Disable source maps in the production build, or relax `artifact.sourceMaps`.',\n });\n }\n }\n\n if (manifest.runtime === 'static') {\n if (manifest.static.mode === 'spa') {\n const fallback = join(publicDir, manifest.static.fallback);\n if (!existsSync(resolve(rootDir, fallback))) {\n diagnostics.push({\n code: 'CRAFT_DEPLOY_SPA_FALLBACK_MISSING',\n severity: 'error',\n path: 'static.fallback',\n file: fallback,\n runtime: 'static',\n message: `The SPA fallback \\`${fallback}\\` is missing from the artefact.`,\n fix: 'Build the client, or correct `static.fallback`.',\n });\n }\n } else {\n for (const [index, route] of manifest.static.routes.entries()) {\n if (!hasPrerenderedDocument(absolutePublicDir, route)) {\n diagnostics.push({\n code: 'CRAFT_DEPLOY_SSG_ROUTE_NOT_RENDERED',\n severity: 'error',\n path: `static.routes[${index}]`,\n file: publicDir,\n runtime: 'static',\n message: `No pre-rendered document was found for \\`${route}\\`.`,\n fix: 'Run the pre-render step for that route, or remove it from `static.routes`.',\n });\n }\n }\n }\n }\n\n return diagnostics;\n}\n\n/** A route is rendered as `<route>.html` or as `<route>/index.html`. */\nexport function hasPrerenderedDocument(\n publicDir: string,\n route: string,\n): boolean {\n const segments = route.split('/').filter((segment) => segment.length > 0);\n if (segments.length === 0) return existsSync(join(publicDir, 'index.html'));\n const base = join(publicDir, ...segments);\n return existsSync(`${base}.html`) || existsSync(join(base, 'index.html'));\n}\n\nfunction listFiles(directory: string): readonly string[] {\n const files: string[] = [];\n for (const entry of readdirSync(directory)) {\n const path = join(directory, entry);\n if (statSync(path).isDirectory()) files.push(...listFiles(path));\n else files.push(path);\n }\n return files;\n}\n"]}
@@ -0,0 +1,31 @@
1
+ import type { CraftDeploymentDiagnostic } from './diagnostics.js';
2
+ import { type CraftDeploymentManifest } from './manifest.js';
3
+ export type CraftDeploymentCheckOptions = Readonly<{
4
+ /** Directory the manifest paths are relative to. Defaults to `cwd`. */
5
+ rootDir?: string;
6
+ /** Raw manifest, typically the default export of `craft.deploy.ts`. */
7
+ definition: unknown;
8
+ /** Provider the deployment targets, checked against the capability matrix. */
9
+ provider?: string;
10
+ /** Asserts the manifest declares this runtime. */
11
+ runtime?: string;
12
+ /** Asserts the manifest declares this platform. */
13
+ platform?: string;
14
+ /** Also inspect the produced artefact, which requires a completed build. */
15
+ artifact?: boolean;
16
+ }>;
17
+ export type CraftDeploymentCheckResult = Readonly<{
18
+ passed: boolean;
19
+ /** `null` when the manifest could not be resolved. */
20
+ manifest: CraftDeploymentManifest | null;
21
+ diagnostics: readonly CraftDeploymentDiagnostic[];
22
+ }>;
23
+ /**
24
+ * Runs every deployment check that does not need a provider account.
25
+ *
26
+ * The order matters: nothing filesystem-related runs while the manifest itself
27
+ * is unusable, so an author never reads a page of path errors caused by a
28
+ * single missing field.
29
+ */
30
+ export declare function checkCraftDeployment(options: CraftDeploymentCheckOptions): CraftDeploymentCheckResult;
31
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../../../libs/deploy/src/lib/check.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,yBAAyB,EAE1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAGL,KAAK,uBAAuB,EAC7B,MAAM,eAAe,CAAC;AAcvB,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IACjD,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,UAAU,EAAE,OAAO,CAAC;IACpB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC,CAAC;AAEH,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IAChD,MAAM,EAAE,OAAO,CAAC;IAChB,sDAAsD;IACtD,QAAQ,EAAE,uBAAuB,GAAG,IAAI,CAAC;IACzC,WAAW,EAAE,SAAS,yBAAyB,EAAE,CAAC;CACnD,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,2BAA2B,GACnC,0BAA0B,CAyB5B"}
@@ -0,0 +1,278 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { relative, resolve } from 'node:path';
3
+ import { checkCraftDeploymentArtifact } from './artifact.js';
4
+ import { CRAFT_DEPLOYMENT_PLATFORMS, CRAFT_DEPLOYMENT_RUNTIMES, } from './manifest.js';
5
+ import { findCraftDeploymentProvider, requiredCapability, } from './providers.js';
6
+ import { resolveCraftDeploymentManifest } from './protocol.js';
7
+ import { collectEnvironmentReads, isNodeBuiltin, readCraftModuleGraph, } from './sources.js';
8
+ import { validateCraftDeploymentDefinition } from './validate.js';
9
+ /**
10
+ * Runs every deployment check that does not need a provider account.
11
+ *
12
+ * The order matters: nothing filesystem-related runs while the manifest itself
13
+ * is unusable, so an author never reads a page of path errors caused by a
14
+ * single missing field.
15
+ */
16
+ export function checkCraftDeployment(options) {
17
+ const rootDir = resolve(options.rootDir ?? process.cwd());
18
+ const validation = validateCraftDeploymentDefinition(options.definition);
19
+ const diagnostics = [...validation.diagnostics];
20
+ if (!validation.definition) {
21
+ return { passed: false, manifest: null, diagnostics };
22
+ }
23
+ const manifest = resolveCraftDeploymentManifest(validation.definition);
24
+ checkRequestedTarget(options, manifest, diagnostics);
25
+ checkProvider(options.provider, manifest, diagnostics);
26
+ checkDeclaredPaths(rootDir, manifest, options.artifact === true, diagnostics);
27
+ checkModuleGraphs(rootDir, manifest, diagnostics);
28
+ if (options.artifact === true) {
29
+ diagnostics.push(...checkCraftDeploymentArtifact({ rootDir, manifest }));
30
+ }
31
+ return {
32
+ passed: diagnostics.every((diagnostic) => diagnostic.severity !== 'error'),
33
+ manifest,
34
+ diagnostics,
35
+ };
36
+ }
37
+ function checkRequestedTarget(options, manifest, diagnostics) {
38
+ if (options.runtime !== undefined && options.runtime !== manifest.runtime) {
39
+ diagnostics.push({
40
+ code: 'CRAFT_DEPLOY_RUNTIME_MISMATCH',
41
+ severity: 'error',
42
+ path: 'runtime',
43
+ runtime: manifest.runtime,
44
+ message: `The check requested the \`${options.runtime}\` runtime and the manifest declares \`${manifest.runtime}\`.`,
45
+ fix: CRAFT_DEPLOYMENT_RUNTIMES.includes(options.runtime)
46
+ ? 'Drop `--runtime`, or change `runtime` in the manifest.'
47
+ : `Use one of ${CRAFT_DEPLOYMENT_RUNTIMES.join(', ')}.`,
48
+ });
49
+ }
50
+ if (options.platform !== undefined &&
51
+ options.platform !== manifest.platform) {
52
+ diagnostics.push({
53
+ code: 'CRAFT_DEPLOY_PLATFORM_MISMATCH',
54
+ severity: 'error',
55
+ path: 'platform',
56
+ platform: manifest.platform,
57
+ message: `The check requested the \`${options.platform}\` platform and the manifest declares \`${manifest.platform}\`.`,
58
+ fix: CRAFT_DEPLOYMENT_PLATFORMS.includes(options.platform)
59
+ ? 'Drop `--platform`, or change `platform` in the manifest.'
60
+ : `Use one of ${CRAFT_DEPLOYMENT_PLATFORMS.join(', ')}.`,
61
+ });
62
+ }
63
+ }
64
+ function checkProvider(provider, manifest, diagnostics) {
65
+ if (provider === undefined)
66
+ return;
67
+ const descriptor = findCraftDeploymentProvider(provider);
68
+ if (!descriptor) {
69
+ diagnostics.push({
70
+ code: 'CRAFT_DEPLOY_PROVIDER_UNKNOWN',
71
+ severity: 'error',
72
+ provider,
73
+ message: `\`${provider}\` is not in the provider capability matrix.`,
74
+ fix: 'Use a documented provider name, or register the provider before checking.',
75
+ });
76
+ return;
77
+ }
78
+ const capability = requiredCapability(manifest.runtime, manifest.runtime === 'static' ? manifest.static.mode : undefined);
79
+ if (!descriptor.capabilities.includes(capability)) {
80
+ diagnostics.push({
81
+ code: 'CRAFT_DEPLOY_PROVIDER_CAPABILITY_MISSING',
82
+ severity: 'error',
83
+ provider,
84
+ runtime: manifest.runtime,
85
+ message: `\`${provider}\` does not declare the \`${capability}\` capability.`,
86
+ fix: `Choose a provider declaring \`${capability}\`, or change the runtime or the static mode.`,
87
+ });
88
+ }
89
+ if (!descriptor.platforms.includes(manifest.platform)) {
90
+ diagnostics.push({
91
+ code: 'CRAFT_DEPLOY_PROVIDER_PLATFORM_UNSUPPORTED',
92
+ severity: 'error',
93
+ provider,
94
+ platform: manifest.platform,
95
+ message: `\`${provider}\` does not deploy to \`${manifest.platform}\`.`,
96
+ fix: `Use one of ${descriptor.platforms.join(', ')}, or change the platform.`,
97
+ });
98
+ }
99
+ }
100
+ function declaredPaths(manifest) {
101
+ const paths = [];
102
+ const runtimeSection = manifest.runtime === 'node'
103
+ ? { key: 'server', section: manifest.server }
104
+ : manifest.runtime === 'worker'
105
+ ? { key: 'worker', section: manifest.worker }
106
+ : manifest.runtime === 'lambda'
107
+ ? { key: 'lambda', section: manifest.lambda }
108
+ : null;
109
+ if (runtimeSection) {
110
+ paths.push({
111
+ path: `${runtimeSection.key}.entry`,
112
+ value: runtimeSection.section.entry,
113
+ kind: 'output',
114
+ });
115
+ if (runtimeSection.section.source) {
116
+ paths.push({
117
+ path: `${runtimeSection.key}.source`,
118
+ value: runtimeSection.section.source,
119
+ kind: 'source',
120
+ });
121
+ }
122
+ }
123
+ if (manifest.functions) {
124
+ paths.push({
125
+ path: 'functions.entry',
126
+ value: manifest.functions.entry,
127
+ kind: 'source',
128
+ });
129
+ }
130
+ if (manifest.client) {
131
+ paths.push({
132
+ path: 'client.outDir',
133
+ value: manifest.client.outDir,
134
+ kind: 'output',
135
+ });
136
+ }
137
+ for (const [index, file] of manifest.artifact.configFiles.entries()) {
138
+ paths.push({
139
+ path: `artifact.configFiles[${index}]`,
140
+ value: file,
141
+ kind: 'source',
142
+ });
143
+ }
144
+ return paths;
145
+ }
146
+ function checkDeclaredPaths(rootDir, manifest, artifactMode, diagnostics) {
147
+ for (const declared of declaredPaths(manifest)) {
148
+ if (existsSync(resolve(rootDir, declared.value)))
149
+ continue;
150
+ // Before the build, a missing output is expected; it only becomes an
151
+ // error once the check claims to inspect the artefact.
152
+ const severity = declared.kind === 'source' || artifactMode ? 'error' : 'warning';
153
+ diagnostics.push({
154
+ code: 'CRAFT_DEPLOY_PATH_MISSING',
155
+ severity,
156
+ path: declared.path,
157
+ file: declared.value,
158
+ runtime: manifest.runtime,
159
+ message: `\`${declared.value}\` does not exist.`,
160
+ fix: declared.kind === 'output'
161
+ ? 'Run the declared build command, or correct the path in the manifest.'
162
+ : 'Correct the path in the manifest.',
163
+ });
164
+ }
165
+ }
166
+ function checkModuleGraphs(rootDir, manifest, diagnostics) {
167
+ const runtimeEntry = analysisEntry(manifest);
168
+ if (runtimeEntry !== null) {
169
+ const graph = readCraftModuleGraph(resolve(rootDir, runtimeEntry));
170
+ if (graph.missingEntry === null) {
171
+ if (manifest.runtime === 'worker' || manifest.runtime === 'lambda') {
172
+ checkNodeBuiltins(rootDir, manifest, graph, diagnostics);
173
+ }
174
+ if (manifest.runtime === 'node') {
175
+ checkHealthRoutes(manifest, graph, diagnostics);
176
+ }
177
+ checkEnvironment(manifest, graph, runtimeEntry, diagnostics);
178
+ }
179
+ }
180
+ checkFunctionIds(rootDir, manifest, diagnostics);
181
+ }
182
+ /** Module the static analysis reads: the source when declared, else the build output. */
183
+ function analysisEntry(manifest) {
184
+ if (manifest.runtime === 'node') {
185
+ return manifest.server.source ?? manifest.server.entry;
186
+ }
187
+ if (manifest.runtime === 'worker') {
188
+ return manifest.worker.source ?? manifest.worker.entry;
189
+ }
190
+ if (manifest.runtime === 'lambda') {
191
+ return manifest.lambda.source ?? manifest.lambda.entry;
192
+ }
193
+ return null;
194
+ }
195
+ function checkNodeBuiltins(rootDir, manifest, graph, diagnostics) {
196
+ for (const moduleImport of graph.imports) {
197
+ if (!isNodeBuiltin(moduleImport.specifier))
198
+ continue;
199
+ diagnostics.push({
200
+ code: 'CRAFT_DEPLOY_NODE_BUILTIN_IMPORT',
201
+ severity: 'error',
202
+ file: relative(rootDir, moduleImport.file),
203
+ line: moduleImport.line,
204
+ runtime: manifest.runtime,
205
+ platform: manifest.platform,
206
+ message: `\`${moduleImport.specifier}\` is a Node built-in and the \`${manifest.runtime}\` runtime does not provide it.`,
207
+ fix: 'Replace it with a Web API, or move the code behind an adapter this entry does not import.',
208
+ });
209
+ }
210
+ }
211
+ function checkHealthRoutes(manifest, graph, diagnostics) {
212
+ const routes = [
213
+ {
214
+ code: 'CRAFT_DEPLOY_HEALTH_PATH_MISSING',
215
+ path: 'server.healthPath',
216
+ value: manifest.server.healthPath,
217
+ },
218
+ {
219
+ code: 'CRAFT_DEPLOY_READY_PATH_MISSING',
220
+ path: 'server.readyPath',
221
+ value: manifest.server.readyPath,
222
+ },
223
+ ];
224
+ for (const route of routes) {
225
+ if (graph.source.includes(`'${route.value}'`))
226
+ continue;
227
+ if (graph.source.includes(`"${route.value}"`))
228
+ continue;
229
+ if (graph.source.includes(`\`${route.value}\``))
230
+ continue;
231
+ diagnostics.push({
232
+ code: route.code,
233
+ severity: 'error',
234
+ path: route.path,
235
+ runtime: 'node',
236
+ message: `The SSR entry never mentions \`${route.value}\`.`,
237
+ fix: 'Serve the declared path, or align the manifest with the path the server exposes.',
238
+ });
239
+ }
240
+ }
241
+ function checkEnvironment(manifest, graph, entry, diagnostics) {
242
+ const declared = new Set(manifest.env.map((variable) => variable.name));
243
+ for (const name of collectEnvironmentReads(graph.source)) {
244
+ if (declared.has(name))
245
+ continue;
246
+ diagnostics.push({
247
+ code: 'CRAFT_DEPLOY_ENV_UNDECLARED',
248
+ severity: 'warning',
249
+ path: 'env',
250
+ file: entry,
251
+ runtime: manifest.runtime,
252
+ message: `\`${name}\` is read by the runtime entry and is not declared in \`env\`.`,
253
+ fix: `Add \`{ name: '${name}', required: … }\` to \`env\`, or stop reading it from the entry.`,
254
+ });
255
+ }
256
+ }
257
+ function checkFunctionIds(rootDir, manifest, diagnostics) {
258
+ const functions = manifest.functions;
259
+ if (!functions || functions.ids.length === 0)
260
+ return;
261
+ const graph = readCraftModuleGraph(resolve(rootDir, functions.entry));
262
+ if (graph.missingEntry !== null)
263
+ return;
264
+ for (const [index, id] of functions.ids.entries()) {
265
+ if (graph.source.includes(id))
266
+ continue;
267
+ diagnostics.push({
268
+ code: 'CRAFT_DEPLOY_FUNCTION_ID_UNKNOWN',
269
+ severity: 'warning',
270
+ path: `functions.ids[${index}]`,
271
+ file: functions.entry,
272
+ runtime: manifest.runtime,
273
+ message: `\`${id}\` does not appear in the module graph of \`${functions.entry}\`.`,
274
+ fix: 'Register the function in the entry, or remove the identifier from the manifest.',
275
+ });
276
+ }
277
+ }
278
+ //# sourceMappingURL=check.js.map