@telorun/kernel 0.58.0 → 0.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/bundle/files-integrity.d.ts +21 -12
  2. package/dist/bundle/files-integrity.d.ts.map +1 -1
  3. package/dist/bundle/files-integrity.js +27 -14
  4. package/dist/bundle/files-integrity.js.map +1 -1
  5. package/dist/bundle/module-artifact.d.ts +134 -0
  6. package/dist/bundle/module-artifact.d.ts.map +1 -0
  7. package/dist/bundle/module-artifact.js +300 -0
  8. package/dist/bundle/module-artifact.js.map +1 -0
  9. package/dist/bundle/module-manifest.d.ts +12 -4
  10. package/dist/bundle/module-manifest.d.ts.map +1 -1
  11. package/dist/bundle/module-manifest.js +8 -4
  12. package/dist/bundle/module-manifest.js.map +1 -1
  13. package/dist/controller-loader.d.ts +3 -2
  14. package/dist/controller-loader.d.ts.map +1 -1
  15. package/dist/controller-loader.js +8 -8
  16. package/dist/controller-loader.js.map +1 -1
  17. package/dist/controller-loaders/bundle-loader.d.ts +8 -6
  18. package/dist/controller-loaders/bundle-loader.d.ts.map +1 -1
  19. package/dist/controller-loaders/bundle-loader.js +52 -13
  20. package/dist/controller-loaders/bundle-loader.js.map +1 -1
  21. package/dist/controller-loaders/npm-loader.d.ts +0 -18
  22. package/dist/controller-loaders/npm-loader.d.ts.map +1 -1
  23. package/dist/controller-loaders/npm-loader.js +3 -190
  24. package/dist/controller-loaders/npm-loader.js.map +1 -1
  25. package/dist/controllers/resource-definition/resource-definition-controller.d.ts.map +1 -1
  26. package/dist/controllers/resource-definition/resource-definition-controller.js +6 -1
  27. package/dist/controllers/resource-definition/resource-definition-controller.js.map +1 -1
  28. package/dist/directory-lock.d.ts +27 -0
  29. package/dist/directory-lock.d.ts.map +1 -0
  30. package/dist/directory-lock.js +205 -0
  31. package/dist/directory-lock.js.map +1 -0
  32. package/dist/evaluation-context.d.ts.map +1 -1
  33. package/dist/evaluation-context.js +20 -6
  34. package/dist/evaluation-context.js.map +1 -1
  35. package/dist/index.d.ts +4 -2
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +3 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/kernel.d.ts +32 -0
  40. package/dist/kernel.d.ts.map +1 -1
  41. package/dist/kernel.js +55 -1
  42. package/dist/kernel.js.map +1 -1
  43. package/dist/manifest-sources/local-manifest-cache-source.d.ts +1 -1
  44. package/dist/manifest-sources/local-manifest-cache-source.d.ts.map +1 -1
  45. package/dist/manifest-sources/local-manifest-cache-source.js +1 -1
  46. package/dist/manifest-sources/local-manifest-cache-source.js.map +1 -1
  47. package/dist/resource-context.d.ts +18 -0
  48. package/dist/resource-context.d.ts.map +1 -1
  49. package/dist/resource-context.js +72 -1
  50. package/dist/resource-context.js.map +1 -1
  51. package/dist/transports/oci/oci-client.d.ts +28 -1
  52. package/dist/transports/oci/oci-client.d.ts.map +1 -1
  53. package/dist/transports/oci/oci-client.js +24 -1
  54. package/dist/transports/oci/oci-client.js.map +1 -1
  55. package/dist/transports/oci/oci-transport.d.ts +20 -14
  56. package/dist/transports/oci/oci-transport.d.ts.map +1 -1
  57. package/dist/transports/oci/oci-transport.js +105 -46
  58. package/dist/transports/oci/oci-transport.js.map +1 -1
  59. package/dist/transports/registry-transport.d.ts +7 -2
  60. package/dist/transports/registry-transport.d.ts.map +1 -1
  61. package/dist/transports/registry-transport.js +8 -33
  62. package/dist/transports/registry-transport.js.map +1 -1
  63. package/dist/transports/transport-registry.d.ts +5 -4
  64. package/dist/transports/transport-registry.d.ts.map +1 -1
  65. package/dist/transports/transport-registry.js +4 -4
  66. package/dist/transports/transport-registry.js.map +1 -1
  67. package/dist/transports/transport.d.ts +27 -19
  68. package/dist/transports/transport.d.ts.map +1 -1
  69. package/package.json +3 -3
  70. package/src/bundle/files-integrity.ts +34 -14
  71. package/src/bundle/module-artifact.ts +375 -0
  72. package/src/bundle/module-manifest.ts +22 -6
  73. package/src/controller-loader.ts +9 -4
  74. package/src/controller-loaders/bundle-loader.ts +57 -11
  75. package/src/controller-loaders/npm-loader.ts +3 -209
  76. package/src/controllers/resource-definition/resource-definition-controller.ts +19 -0
  77. package/src/directory-lock.ts +225 -0
  78. package/src/evaluation-context.ts +17 -7
  79. package/src/index.ts +10 -2
  80. package/src/kernel.ts +66 -0
  81. package/src/manifest-sources/local-manifest-cache-source.ts +1 -1
  82. package/src/resource-context.ts +78 -1
  83. package/src/transports/oci/oci-client.ts +32 -1
  84. package/src/transports/oci/oci-transport.ts +122 -51
  85. package/src/transports/registry-transport.ts +10 -38
  86. package/src/transports/transport-registry.ts +5 -5
  87. package/src/transports/transport.ts +32 -19
@@ -1,25 +1,34 @@
1
+ import { type ArtifactLayer } from "@telorun/analyzer";
1
2
  export interface PayloadFile {
2
3
  /** POSIX-relative path inside the bundle. */
3
4
  name: string;
4
5
  content: Buffer | Uint8Array;
5
6
  }
6
7
  /**
7
- * Canonical per-file content digest of a module's `files:` payload — the value
8
- * of `filesIntegrity` in a bundle's `telo.yaml`. SHA-256 over the sorted
9
- * `<path>\0<sha256(content)>` lines of every payload file, `telo.yaml`
10
- * excluded (the importer's `#sha256-...` hash already covers the manifest, and
11
- * excluding it breaks the self-reference the manifest embeds this value).
8
+ * Canonical per-file content digest of one **layer**'s files — the `integrity`
9
+ * value of that layer's entry in the published `layers:` index. SHA-256 over the
10
+ * sorted `<path>\0<sha256(content)>` lines of every file in the layer,
11
+ * `telo.yaml` excluded (it is the manifest layer, which carries the index and so
12
+ * cannot hash itself; the importer's `#sha256-...` pin covers it instead).
12
13
  *
13
14
  * Hashing file *contents* rather than the tar/gzip bytes makes the digest
14
15
  * independent of archive framing, so publisher and client compute the same
15
16
  * value from the same file set, and it can be re-derived from the extracted
16
- * files on disk. Returns `sha256-<base64url>`.
17
+ * files on disk which is what makes a per-layer cache marker checkable without
18
+ * re-tarring. Distinct from the layer's `blob` digest, which covers the pushed
19
+ * bytes and addresses the layer. Returns `sha256-<base64url>`.
17
20
  */
18
21
  export declare function computeFilesIntegrity(files: PayloadFile[]): Promise<string>;
19
- /** Write `filesIntegrity` onto the manifest's owner doc so the published
20
- * `telo.yaml` pins its payload transitively covered by importers'
21
- * `#sha256-...` hash. The digest excludes `telo.yaml`, so injecting it does
22
- * not change the digest. Returns the manifest unchanged when it has no owner
23
- * doc. */
24
- export declare function injectFilesIntegrity(manifest: string, hash: string): string;
22
+ /**
23
+ * Write the `layers:` index onto the manifest's owner doc so the published
24
+ * `telo.yaml` pins and addresses every payload layer transitively covered by
25
+ * importers' `#sha256-...` hash over this manifest.
26
+ *
27
+ * Called after the payload blobs are pushed and before the manifest blob is,
28
+ * which is what keeps the index non-circular: it names only layers other than
29
+ * the one carrying it. Each layer's own digest excludes `telo.yaml`, so
30
+ * injecting the index does not invalidate any of them. Returns the manifest
31
+ * unchanged when it has no owner doc.
32
+ */
33
+ export declare function injectLayerIndex(manifest: string, layers: readonly ArtifactLayer[]): string;
25
34
  //# sourceMappingURL=files-integrity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"files-integrity.d.ts","sourceRoot":"","sources":["../../src/bundle/files-integrity.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;CAC9B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAUjF;AAED;;;;WAIW;AACX,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAM3E"}
1
+ {"version":3,"file":"files-integrity.d.ts","sourceRoot":"","sources":["../../src/bundle/files-integrity.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,mBAAmB,CAAC;AAI3B,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;CAC9B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAUjF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAc3F"}
@@ -1,16 +1,18 @@
1
- import { DEFAULT_MANIFEST_FILENAME, sha256Base64Url } from "@telorun/analyzer";
1
+ import { DEFAULT_MANIFEST_FILENAME, sha256Base64Url, } from "@telorun/analyzer";
2
2
  import { findOwnerDoc, parseManifestDocs } from "./module-manifest.js";
3
3
  /**
4
- * Canonical per-file content digest of a module's `files:` payload — the value
5
- * of `filesIntegrity` in a bundle's `telo.yaml`. SHA-256 over the sorted
6
- * `<path>\0<sha256(content)>` lines of every payload file, `telo.yaml`
7
- * excluded (the importer's `#sha256-...` hash already covers the manifest, and
8
- * excluding it breaks the self-reference the manifest embeds this value).
4
+ * Canonical per-file content digest of one **layer**'s files — the `integrity`
5
+ * value of that layer's entry in the published `layers:` index. SHA-256 over the
6
+ * sorted `<path>\0<sha256(content)>` lines of every file in the layer,
7
+ * `telo.yaml` excluded (it is the manifest layer, which carries the index and so
8
+ * cannot hash itself; the importer's `#sha256-...` pin covers it instead).
9
9
  *
10
10
  * Hashing file *contents* rather than the tar/gzip bytes makes the digest
11
11
  * independent of archive framing, so publisher and client compute the same
12
12
  * value from the same file set, and it can be re-derived from the extracted
13
- * files on disk. Returns `sha256-<base64url>`.
13
+ * files on disk which is what makes a per-layer cache marker checkable without
14
+ * re-tarring. Distinct from the layer's `blob` digest, which covers the pushed
15
+ * bytes and addresses the layer. Returns `sha256-<base64url>`.
14
16
  */
15
17
  export async function computeFilesIntegrity(files) {
16
18
  const lines = [];
@@ -24,17 +26,28 @@ export async function computeFilesIntegrity(files) {
24
26
  const canonical = new TextEncoder().encode(lines.join("\n"));
25
27
  return `sha256-${await sha256Base64Url(canonical)}`;
26
28
  }
27
- /** Write `filesIntegrity` onto the manifest's owner doc so the published
28
- * `telo.yaml` pins its payload transitively covered by importers'
29
- * `#sha256-...` hash. The digest excludes `telo.yaml`, so injecting it does
30
- * not change the digest. Returns the manifest unchanged when it has no owner
31
- * doc. */
32
- export function injectFilesIntegrity(manifest, hash) {
29
+ /**
30
+ * Write the `layers:` index onto the manifest's owner doc so the published
31
+ * `telo.yaml` pins and addresses every payload layer transitively covered by
32
+ * importers' `#sha256-...` hash over this manifest.
33
+ *
34
+ * Called after the payload blobs are pushed and before the manifest blob is,
35
+ * which is what keeps the index non-circular: it names only layers other than
36
+ * the one carrying it. Each layer's own digest excludes `telo.yaml`, so
37
+ * injecting the index does not invalidate any of them. Returns the manifest
38
+ * unchanged when it has no owner doc.
39
+ */
40
+ export function injectLayerIndex(manifest, layers) {
33
41
  const docs = parseManifestDocs(manifest);
34
42
  const owner = findOwnerDoc(docs);
35
43
  if (!owner)
36
44
  return manifest;
37
- owner.set("filesIntegrity", hash);
45
+ owner.set("layers", layers.map((layer) => ({
46
+ role: layer.role,
47
+ ...(layer.selector ? { selector: { ...layer.selector } } : {}),
48
+ blob: layer.blob,
49
+ integrity: layer.integrity,
50
+ })));
38
51
  return docs.map((d) => d.toString()).join("---\n");
39
52
  }
40
53
  //# sourceMappingURL=files-integrity.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"files-integrity.js","sourceRoot":"","sources":["../../src/bundle/files-integrity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE/E,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAQvE;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAAoB;IAC9D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,yBAAyB;YAAE,SAAS;QACtD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,YAAY,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/F,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,KAAK,MAAM,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,KAAK,CAAC,IAAI,EAAE,CAAC;IACb,MAAM,SAAS,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7D,OAAO,UAAU,MAAM,eAAe,CAAC,SAAS,CAAC,EAAE,CAAC;AACtD,CAAC;AAED;;;;WAIW;AACX,MAAM,UAAU,oBAAoB,CAAC,QAAgB,EAAE,IAAY;IACjE,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC;IAC5B,KAAK,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IAClC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACrD,CAAC"}
1
+ {"version":3,"file":"files-integrity.js","sourceRoot":"","sources":["../../src/bundle/files-integrity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,eAAe,GAEhB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAQvE;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAAoB;IAC9D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,yBAAyB;YAAE,SAAS;QACtD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,YAAY,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/F,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,KAAK,MAAM,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,KAAK,CAAC,IAAI,EAAE,CAAC;IACb,MAAM,SAAS,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7D,OAAO,UAAU,MAAM,eAAe,CAAC,SAAS,CAAC,EAAE,CAAC;AACtD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,MAAgC;IACjF,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC;IAC5B,KAAK,CAAC,GAAG,CACP,QAAQ,EACR,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACrB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,SAAS,EAAE,KAAK,CAAC,SAAS;KAC3B,CAAC,CAAC,CACJ,CAAC;IACF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,134 @@
1
+ import { type ArtifactLayer, type ArtifactSelector, type PlatformTarget } from "@telorun/analyzer";
2
+ import { type Logger } from "@telorun/sdk";
3
+ import type { TransportRegistry } from "../transports/transport-registry.js";
4
+ /** A materialized layer: the directory its files were extracted into (the
5
+ * module's cache directory) and the manifest-relative paths it wrote. */
6
+ export interface MaterializedLayer {
7
+ dir: string;
8
+ files: string[];
9
+ }
10
+ export declare function hostPlatformTarget(): PlatformTarget;
11
+ /**
12
+ * A module's artifact, scoped to one loaded module.
13
+ *
14
+ * Built during module load, where the **pinned** import ref and the
15
+ * already-verified manifest are both in hand — which is the whole reason this
16
+ * exists as its own object rather than as logic inside a controller loader. A
17
+ * loader is handed only the canonical base URI, which carries no `#sha256-`, so
18
+ * a loader that fetched for itself would have to re-read the layer index off the
19
+ * cache directory: verification silently downgraded from "anchored at the
20
+ * importer's pin" to "trust whatever is already on disk".
21
+ *
22
+ * Materialization is per layer, memoized in-process, and guarded by the shared
23
+ * cross-process directory lock — oauth-client alone has seventeen definitions
24
+ * resolving concurrently against one controller layer, and several kernels may
25
+ * populate one cache directory at once.
26
+ *
27
+ * Verification runs before extraction: the transport checks the transfer against
28
+ * the layer's `blob` digest, and the extracted file set is checked against its
29
+ * `integrity` content digest here. A per-layer marker keyed by the blob digest
30
+ * records success, so a republish to different bytes re-extracts rather than
31
+ * being mistaken for an already-populated layer.
32
+ */
33
+ export declare class ModuleArtifact {
34
+ /** The importer's pinned ref — what the transport verifies the manifest layer
35
+ * against, and what keeps the Merkle chain anchored. */
36
+ private readonly pinnedRef;
37
+ private readonly layers;
38
+ private readonly dir;
39
+ private readonly transports;
40
+ private readonly log;
41
+ /** In-flight / completed materializations, keyed by blob digest. Rejections
42
+ * are dropped so a transient fetch failure retries on the next ask. */
43
+ private readonly inFlight;
44
+ constructor(opts: {
45
+ pinnedRef: string;
46
+ layers: readonly ArtifactLayer[];
47
+ dir: string;
48
+ transports: TransportRegistry;
49
+ log?: Logger;
50
+ });
51
+ /** The module's local directory — where every materialized layer lands, and
52
+ * what a module-relative path resolves against. */
53
+ get directory(): string;
54
+ /**
55
+ * Materialize the layer carrying `selector` exactly, plus the `common` layer.
56
+ *
57
+ * Looked up by exact selector key rather than by re-matching the host: the
58
+ * candidate being resolved already *is* one selector, and it is by construction
59
+ * the key of the layer that carries it. Re-matching would take the first layer
60
+ * in declaration order that the host satisfies, so a module shipping both a
61
+ * platform-neutral and a platform-constrained layer of one format would fetch
62
+ * whichever came first regardless of which candidate asked — materializing the
63
+ * wrong layer and then reporting "bundle not found".
64
+ *
65
+ * The `common` layer rides along because it is the sink for files no candidate
66
+ * claimed — an undeclared sidecar an entry point loads at runtime. Pulling it
67
+ * with any controller layer is what makes a forgotten declaration cost bytes
68
+ * instead of a module-not-found at import.
69
+ *
70
+ * Returns `undefined` when the artifact ships no layer for this selector, which
71
+ * is how a loader learns to fall through to the next candidate.
72
+ */
73
+ materializeController(selector: ArtifactSelector): Promise<MaterializedLayer | undefined>;
74
+ /**
75
+ * Materialize everything a module-relative file read could need: the `assets`
76
+ * layer **and** the `common` layer.
77
+ *
78
+ * Both, because `common` is where the sink rule puts a file the author did not
79
+ * claim via `assets:` — and a module that ships static files but has no bundled
80
+ * controller has no other path to its own payload. Assets alone would leave such
81
+ * a module's `Http.Static` root resolving into an empty directory, which is the
82
+ * exact silent failure this design promises not to have.
83
+ */
84
+ materializeModuleFiles(): Promise<void>;
85
+ /** Materialize the lazily-fetched `assets` layer, if the module ships one. */
86
+ materializeAssets(): Promise<MaterializedLayer | undefined>;
87
+ /** Materialize the `common` layer, if the module ships one. */
88
+ materializeCommon(): Promise<MaterializedLayer | undefined>;
89
+ /**
90
+ * Materialize every layer a `target` platform could need — both singletons and
91
+ * each controller layer matching it. `telo install`'s make-this-offline pass,
92
+ * where being exhaustive for one platform is the point.
93
+ */
94
+ materializeAll(target: PlatformTarget): Promise<MaterializedLayer[]>;
95
+ /** Human-facing description of what this artifact ships, for diagnostics that
96
+ * have to explain why no layer matched. */
97
+ describeLayers(): string;
98
+ private materialize;
99
+ private markerPath;
100
+ private materializeUncached;
101
+ private extract;
102
+ }
103
+ /**
104
+ * The directory a module's layers live in.
105
+ *
106
+ * Derived from the **pinned** `requestedUrl`, not the canonical `source`, because
107
+ * those diverge exactly when the manifest cache is warm: a cache hit is served as
108
+ * a `file://` URL into `.telo/manifests/`, which no transport claims, so a
109
+ * `source`-derived path is `null` on every run after the first. The pinned ref is
110
+ * what the importer wrote and survives the hit, so it places the module
111
+ * identically cold and warm. A genuinely local `source` (development, or a module
112
+ * loaded straight off disk) resolves to its own directory.
113
+ *
114
+ * Returns `null` when neither route yields a directory — a `memory://` module, or
115
+ * a ref this cache has no coordinates for.
116
+ */
117
+ export declare function moduleDirectoryFor(requestedUrl: string, source: string, entryDir: string, registryUrl: string | undefined, manifestsDir: string | undefined): string | null;
118
+ /**
119
+ * Build the artifact handle for a loaded module, or `undefined` when the module
120
+ * has no payload to materialize.
121
+ *
122
+ * The trigger is the presence of a `layers:` index — a module that ships nothing
123
+ * needs no handle. `pinnedRef` is the ref **as the importer wrote it**, integrity
124
+ * fragment included, which is what keeps verification anchored to the importer's
125
+ * pin; `moduleDir` is where its layers extract to (see {@link moduleDirectoryFor}).
126
+ */
127
+ export declare function moduleArtifactFor(opts: {
128
+ pinnedRef: string;
129
+ layers: readonly ArtifactLayer[] | undefined;
130
+ moduleDir: string | null;
131
+ transports: TransportRegistry;
132
+ log?: Logger;
133
+ }): ModuleArtifact | undefined;
134
+ //# sourceMappingURL=module-artifact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-artifact.d.ts","sourceRoot":"","sources":["../../src/bundle/module-artifact.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAA6B,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAQtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAG7E;0EAC0E;AAC1E,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AA2DD,wBAAgB,kBAAkB,IAAI,cAAc,CAOnD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,cAAc;IACzB;6DACyD;IACzD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;IAClD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B;4EACwE;IACxE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiD;gBAE9D,IAAI,EAAE;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;QACjC,GAAG,EAAE,MAAM,CAAC;QACZ,UAAU,EAAE,iBAAiB,CAAC;QAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;KACd;IAQD;wDACoD;IACpD,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACG,qBAAqB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;IAU/F;;;;;;;;;OASG;IACG,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7C,8EAA8E;IACxE,iBAAiB,IAAI,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;IAKjE,+DAA+D;IACzD,iBAAiB,IAAI,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;IAKjE;;;;OAIG;IACG,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAW1E;gDAC4C;IAC5C,cAAc,IAAI,MAAM;IAOxB,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,UAAU;YAQJ,mBAAmB;YA0CnB,OAAO;CAkBtB;AAOD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,YAAY,EAAE,MAAM,GAAG,SAAS,GAC/B,MAAM,GAAG,IAAI,CAWf;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,SAAS,CAAC;IAC7C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,cAAc,GAAG,SAAS,CAU7B"}
@@ -0,0 +1,300 @@
1
+ import { matchControllerLayers, selectorKey, singletonLayer, splitIntegrity, describeSelector, } from "@telorun/analyzer";
2
+ import { NOOP_LOGGER, RuntimeError } from "@telorun/sdk";
3
+ import { existsSync } from "fs";
4
+ import * as fs from "fs/promises";
5
+ import * as path from "path";
6
+ import { fileURLToPath } from "url";
7
+ import { withDirectoryLock } from "../directory-lock.js";
8
+ import { cachePathForCanonical } from "../manifest-sources/local-manifest-cache-source.js";
9
+ import { computeFilesIntegrity } from "./files-integrity.js";
10
+ /**
11
+ * Map Node's platform vocabulary onto the canonical OCI/GOOS names selectors are
12
+ * published with. Node says `win32`/`x64`; OCI descriptors say
13
+ * `windows`/`amd64`, and the published artifact is what has to be matched.
14
+ */
15
+ const NODE_OS_TO_OCI = {
16
+ win32: "windows",
17
+ darwin: "darwin",
18
+ linux: "linux",
19
+ freebsd: "freebsd",
20
+ openbsd: "openbsd",
21
+ sunos: "solaris",
22
+ aix: "aix",
23
+ };
24
+ const NODE_ARCH_TO_OCI = {
25
+ x64: "amd64",
26
+ ia32: "386",
27
+ arm64: "arm64",
28
+ arm: "arm",
29
+ ppc64: "ppc64le",
30
+ s390x: "s390x",
31
+ riscv64: "riscv64",
32
+ loong64: "loong64",
33
+ };
34
+ /**
35
+ * Which libc this process is linked against, or `undefined` when it cannot be
36
+ * determined. Undetermined is deliberately *not* guessed: a selector that
37
+ * constrains `libc` then matches nothing, so a glibc binary is never handed to
38
+ * an Alpine host on the assumption it will run. Node reports
39
+ * `glibcVersionRuntime` in its process report only on a glibc build, which makes
40
+ * its absence on Linux the musl signal.
41
+ */
42
+ function detectLibc() {
43
+ if (process.platform !== "linux")
44
+ return undefined;
45
+ try {
46
+ const report = process.report?.getReport();
47
+ return report?.header?.glibcVersionRuntime ? "gnu" : "musl";
48
+ }
49
+ catch {
50
+ return undefined;
51
+ }
52
+ }
53
+ /**
54
+ * The platform this kernel is running on, in the published vocabulary. An axis
55
+ * Node cannot name is left absent rather than guessed.
56
+ *
57
+ * Computed once: the host cannot change mid-process, and `detectLibc` generates a
58
+ * full Node diagnostic report (a heap and stack walk costing tens of milliseconds).
59
+ * The controller loader asks per candidate per definition — oauth-client alone has
60
+ * seventeen — so recomputing would put that squarely inside the init loop.
61
+ */
62
+ let cachedHostTarget;
63
+ export function hostPlatformTarget() {
64
+ cachedHostTarget ?? (cachedHostTarget = {
65
+ os: NODE_OS_TO_OCI[process.platform],
66
+ arch: NODE_ARCH_TO_OCI[process.arch],
67
+ libc: detectLibc(),
68
+ });
69
+ return cachedHostTarget;
70
+ }
71
+ /**
72
+ * A module's artifact, scoped to one loaded module.
73
+ *
74
+ * Built during module load, where the **pinned** import ref and the
75
+ * already-verified manifest are both in hand — which is the whole reason this
76
+ * exists as its own object rather than as logic inside a controller loader. A
77
+ * loader is handed only the canonical base URI, which carries no `#sha256-`, so
78
+ * a loader that fetched for itself would have to re-read the layer index off the
79
+ * cache directory: verification silently downgraded from "anchored at the
80
+ * importer's pin" to "trust whatever is already on disk".
81
+ *
82
+ * Materialization is per layer, memoized in-process, and guarded by the shared
83
+ * cross-process directory lock — oauth-client alone has seventeen definitions
84
+ * resolving concurrently against one controller layer, and several kernels may
85
+ * populate one cache directory at once.
86
+ *
87
+ * Verification runs before extraction: the transport checks the transfer against
88
+ * the layer's `blob` digest, and the extracted file set is checked against its
89
+ * `integrity` content digest here. A per-layer marker keyed by the blob digest
90
+ * records success, so a republish to different bytes re-extracts rather than
91
+ * being mistaken for an already-populated layer.
92
+ */
93
+ export class ModuleArtifact {
94
+ constructor(opts) {
95
+ /** In-flight / completed materializations, keyed by blob digest. Rejections
96
+ * are dropped so a transient fetch failure retries on the next ask. */
97
+ this.inFlight = new Map();
98
+ this.pinnedRef = opts.pinnedRef;
99
+ this.layers = opts.layers;
100
+ this.dir = opts.dir;
101
+ this.transports = opts.transports;
102
+ this.log = opts.log ?? NOOP_LOGGER;
103
+ }
104
+ /** The module's local directory — where every materialized layer lands, and
105
+ * what a module-relative path resolves against. */
106
+ get directory() {
107
+ return this.dir;
108
+ }
109
+ /**
110
+ * Materialize the layer carrying `selector` exactly, plus the `common` layer.
111
+ *
112
+ * Looked up by exact selector key rather than by re-matching the host: the
113
+ * candidate being resolved already *is* one selector, and it is by construction
114
+ * the key of the layer that carries it. Re-matching would take the first layer
115
+ * in declaration order that the host satisfies, so a module shipping both a
116
+ * platform-neutral and a platform-constrained layer of one format would fetch
117
+ * whichever came first regardless of which candidate asked — materializing the
118
+ * wrong layer and then reporting "bundle not found".
119
+ *
120
+ * The `common` layer rides along because it is the sink for files no candidate
121
+ * claimed — an undeclared sidecar an entry point loads at runtime. Pulling it
122
+ * with any controller layer is what makes a forgotten declaration cost bytes
123
+ * instead of a module-not-found at import.
124
+ *
125
+ * Returns `undefined` when the artifact ships no layer for this selector, which
126
+ * is how a loader learns to fall through to the next candidate.
127
+ */
128
+ async materializeController(selector) {
129
+ const key = selectorKey(selector);
130
+ const layer = this.layers.find((l) => l.role === "controller" && l.selector !== undefined && selectorKey(l.selector) === key);
131
+ if (!layer)
132
+ return undefined;
133
+ await this.materializeCommon();
134
+ return this.materialize(layer);
135
+ }
136
+ /**
137
+ * Materialize everything a module-relative file read could need: the `assets`
138
+ * layer **and** the `common` layer.
139
+ *
140
+ * Both, because `common` is where the sink rule puts a file the author did not
141
+ * claim via `assets:` — and a module that ships static files but has no bundled
142
+ * controller has no other path to its own payload. Assets alone would leave such
143
+ * a module's `Http.Static` root resolving into an empty directory, which is the
144
+ * exact silent failure this design promises not to have.
145
+ */
146
+ async materializeModuleFiles() {
147
+ await Promise.all([this.materializeAssets(), this.materializeCommon()]);
148
+ }
149
+ /** Materialize the lazily-fetched `assets` layer, if the module ships one. */
150
+ async materializeAssets() {
151
+ const layer = singletonLayer(this.layers, "assets");
152
+ return layer ? this.materialize(layer) : undefined;
153
+ }
154
+ /** Materialize the `common` layer, if the module ships one. */
155
+ async materializeCommon() {
156
+ const layer = singletonLayer(this.layers, "common");
157
+ return layer ? this.materialize(layer) : undefined;
158
+ }
159
+ /**
160
+ * Materialize every layer a `target` platform could need — both singletons and
161
+ * each controller layer matching it. `telo install`'s make-this-offline pass,
162
+ * where being exhaustive for one platform is the point.
163
+ */
164
+ async materializeAll(target) {
165
+ const wanted = [
166
+ ...matchControllerLayers(this.layers, target),
167
+ singletonLayer(this.layers, "assets"),
168
+ singletonLayer(this.layers, "common"),
169
+ ].filter((l) => l !== undefined);
170
+ const out = [];
171
+ for (const layer of wanted)
172
+ out.push(await this.materialize(layer));
173
+ return out;
174
+ }
175
+ /** Human-facing description of what this artifact ships, for diagnostics that
176
+ * have to explain why no layer matched. */
177
+ describeLayers() {
178
+ if (this.layers.length === 0)
179
+ return "(no payload layers)";
180
+ return this.layers
181
+ .map((l) => (l.selector ? `${l.role} ${describeSelector(l.selector)}` : l.role))
182
+ .join(", ");
183
+ }
184
+ materialize(layer) {
185
+ const pending = this.inFlight.get(layer.blob);
186
+ if (pending)
187
+ return pending;
188
+ const work = this.materializeUncached(layer).catch((err) => {
189
+ // Drop the rejection so a transient fetch failure is retried rather than
190
+ // cached for the lifetime of the module.
191
+ this.inFlight.delete(layer.blob);
192
+ throw err;
193
+ });
194
+ this.inFlight.set(layer.blob, work);
195
+ return work;
196
+ }
197
+ markerPath(layer) {
198
+ // Keyed by the blob digest, so a republish to different bytes gets a new
199
+ // marker and re-extracts instead of being read as already-populated. The
200
+ // role is in the name purely so a human can tell the markers apart.
201
+ const short = layer.blob.replace(/^sha256:/, "").slice(0, 16);
202
+ return path.join(this.dir, `.telo-layer-${layer.role}-${short}`);
203
+ }
204
+ async materializeUncached(layer) {
205
+ const marker = this.markerPath(layer);
206
+ if (existsSync(marker)) {
207
+ return { dir: this.dir, files: await readMarker(marker) };
208
+ }
209
+ return withDirectoryLock(this.dir, "module layer", async () => {
210
+ // Re-check inside the lock: a peer may have extracted this layer between
211
+ // the fast-path miss and our acquisition.
212
+ if (existsSync(marker)) {
213
+ return { dir: this.dir, files: await readMarker(marker) };
214
+ }
215
+ const files = await this.transports.fetchLayer(this.pinnedRef, layer.blob);
216
+ const actual = await computeFilesIntegrity(files);
217
+ if (actual !== layer.integrity) {
218
+ throw new RuntimeError("ERR_MODULE_LAYER_INTEGRITY", `Integrity check failed for the ${layer.role} layer of ${this.pinnedRef}: ` +
219
+ `expected ${layer.integrity}, got ${actual}. The layer's contents do not match ` +
220
+ `the digest recorded in the module's pinned telo.yaml — it may have been ` +
221
+ `tampered with or republished.`);
222
+ }
223
+ const written = await this.extract(files, layer);
224
+ // Marker last, so a partial extraction leaves none and re-runs.
225
+ await fs.writeFile(marker, `${written.join("\n")}\n`, "utf-8");
226
+ this.log.debug("materialized module layer", {
227
+ "telo.module.ref": this.pinnedRef,
228
+ "telo.layer.role": layer.role,
229
+ "telo.layer.files": written.length,
230
+ });
231
+ return { dir: this.dir, files: written };
232
+ }, this.log);
233
+ }
234
+ async extract(files, layer) {
235
+ const root = path.resolve(this.dir) + path.sep;
236
+ const written = [];
237
+ for (const entry of files) {
238
+ const dest = path.resolve(this.dir, entry.name);
239
+ if (!dest.startsWith(root)) {
240
+ throw new RuntimeError("ERR_MODULE_LAYER_INVALID", `The ${layer.role} layer of ${this.pinnedRef} contains entry '${entry.name}', which ` +
241
+ `resolves outside the module's cache directory.`);
242
+ }
243
+ await fs.mkdir(path.dirname(dest), { recursive: true });
244
+ await fs.writeFile(dest, entry.content);
245
+ written.push(entry.name);
246
+ }
247
+ return written.sort();
248
+ }
249
+ }
250
+ async function readMarker(marker) {
251
+ const text = await fs.readFile(marker, "utf-8");
252
+ return text.split("\n").filter((line) => line !== "");
253
+ }
254
+ /**
255
+ * The directory a module's layers live in.
256
+ *
257
+ * Derived from the **pinned** `requestedUrl`, not the canonical `source`, because
258
+ * those diverge exactly when the manifest cache is warm: a cache hit is served as
259
+ * a `file://` URL into `.telo/manifests/`, which no transport claims, so a
260
+ * `source`-derived path is `null` on every run after the first. The pinned ref is
261
+ * what the importer wrote and survives the hit, so it places the module
262
+ * identically cold and warm. A genuinely local `source` (development, or a module
263
+ * loaded straight off disk) resolves to its own directory.
264
+ *
265
+ * Returns `null` when neither route yields a directory — a `memory://` module, or
266
+ * a ref this cache has no coordinates for.
267
+ */
268
+ export function moduleDirectoryFor(requestedUrl, source, entryDir, registryUrl, manifestsDir) {
269
+ const cacheFile = cachePathForCanonical(splitIntegrity(requestedUrl).base, entryDir, registryUrl, manifestsDir);
270
+ if (cacheFile)
271
+ return path.dirname(cacheFile);
272
+ if (source.startsWith("file://"))
273
+ return path.dirname(fileURLToPath(source));
274
+ if (path.isAbsolute(source))
275
+ return path.dirname(source);
276
+ return null;
277
+ }
278
+ /**
279
+ * Build the artifact handle for a loaded module, or `undefined` when the module
280
+ * has no payload to materialize.
281
+ *
282
+ * The trigger is the presence of a `layers:` index — a module that ships nothing
283
+ * needs no handle. `pinnedRef` is the ref **as the importer wrote it**, integrity
284
+ * fragment included, which is what keeps verification anchored to the importer's
285
+ * pin; `moduleDir` is where its layers extract to (see {@link moduleDirectoryFor}).
286
+ */
287
+ export function moduleArtifactFor(opts) {
288
+ if (!opts.layers || opts.layers.length === 0)
289
+ return undefined;
290
+ if (!opts.moduleDir)
291
+ return undefined;
292
+ return new ModuleArtifact({
293
+ pinnedRef: opts.pinnedRef,
294
+ layers: opts.layers,
295
+ dir: opts.moduleDir,
296
+ transports: opts.transports,
297
+ log: opts.log,
298
+ });
299
+ }
300
+ //# sourceMappingURL=module-artifact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-artifact.js","sourceRoot":"","sources":["../../src/bundle/module-artifact.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,24 @@
1
+ import { type ArtifactLayer } from "@telorun/analyzer";
1
2
  import { type Document } from "yaml";
2
3
  /** Parse a manifest's YAML documents, tolerating its `!cel` / `!ref` tags. */
3
4
  export declare function parseManifestDocs(text: string): Document[];
4
5
  /** The owner document of a manifest — the single `Telo.Application` /
5
- * `Telo.Library` doc that carries its identity, `files:`, and `filesIntegrity`.
6
- * The one place that selects it, shared by every reader/writer. */
6
+ * `Telo.Library` doc that carries its identity, `files:` / `assets:`, and the
7
+ * published `layers:` index. The one place that selects it, shared by every
8
+ * reader/writer. */
7
9
  export declare function findOwnerDoc(docs: Document[]): Document | undefined;
8
10
  /** The owner-doc fields the transports read: identity for the publish location,
9
11
  * and payload markers for artifact fetch. */
10
12
  export interface OwnerManifest {
11
13
  name?: string;
12
14
  version?: string;
13
- filesIntegrity?: string;
15
+ /** The published layer index, absent on an unpublished manifest. Parsed and
16
+ * validated through the analyzer's shared model, so a malformed index is a
17
+ * hard `LayerIndexError` rather than a silently ignored field. */
18
+ layers?: ArtifactLayer[];
19
+ /** Ordered `.gitignore`-style patterns the author claimed as the lazily
20
+ * materialized `assets` layer. */
21
+ assetPatterns: string[];
14
22
  /** True when the owner doc declares a non-empty `files:` list. */
15
23
  declaresFiles: boolean;
16
24
  /** Descriptive provenance a transport projects into its backend's metadata
@@ -22,6 +30,6 @@ export interface OwnerManifest {
22
30
  }
23
31
  /** Read the owner doc's identity + payload fields from a manifest, parsing once
24
32
  * (never regex-scraping). The single source both transports call for the
25
- * module's name and version, `filesIntegrity`, and payload detection. */
33
+ * module's name and version, its layer index, and payload detection. */
26
34
  export declare function readOwnerManifest(text: string): OwnerManifest;
27
35
  //# sourceMappingURL=module-manifest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"module-manifest.d.ts","sourceRoot":"","sources":["../../src/bundle/module-manifest.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,QAAQ,EAAE,MAAM,MAAM,CAAC;AAIxD,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,CAE1D;AAED;;oEAEoE;AACpE,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,QAAQ,GAAG,SAAS,CAKnE;AAED;8CAC8C;AAC9C,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,aAAa,EAAE,OAAO,CAAC;IACvB;iEAC6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;0EAE0E;AAC1E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAiB7D"}
1
+ {"version":3,"file":"module-manifest.d.ts","sourceRoot":"","sources":["../../src/bundle/module-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAExE,OAAO,EAAqB,KAAK,QAAQ,EAAE,MAAM,MAAM,CAAC;AAIxD,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,CAE1D;AAED;;;qBAGqB;AACrB,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,QAAQ,GAAG,SAAS,CAKnE;AAED;8CAC8C;AAC9C,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;uEAEmE;IACnE,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC;IACzB;uCACmC;IACnC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,kEAAkE;IAClE,aAAa,EAAE,OAAO,CAAC;IACvB;iEAC6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;yEAEyE;AACzE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAyB7D"}