@forgeax/engine-import 0.0.0-dev.8d955ade1c79

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 (118) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +227 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/__tests__/decode-image-owner.test-d.d.ts +2 -0
  5. package/dist/__tests__/decode-image-owner.test-d.d.ts.map +1 -0
  6. package/dist/__tests__/import-contract-migration.test.d.ts +2 -0
  7. package/dist/__tests__/import-contract-migration.test.d.ts.map +1 -0
  8. package/dist/__tests__/import-dependencies.test.d.ts +2 -0
  9. package/dist/__tests__/import-dependencies.test.d.ts.map +1 -0
  10. package/dist/__tests__/import-finalizer-digest-retry.test.d.ts +2 -0
  11. package/dist/__tests__/import-finalizer-digest-retry.test.d.ts.map +1 -0
  12. package/dist/__tests__/import-local-artifacts.test.d.ts +2 -0
  13. package/dist/__tests__/import-local-artifacts.test.d.ts.map +1 -0
  14. package/dist/__tests__/import.unit.test.d.ts +2 -0
  15. package/dist/__tests__/import.unit.test.d.ts.map +1 -0
  16. package/dist/__tests__/mesh-bin-contract.test.d.ts +2 -0
  17. package/dist/__tests__/mesh-bin-contract.test.d.ts.map +1 -0
  18. package/dist/__tests__/mesh-bin-morph-v3.test.d.ts +2 -0
  19. package/dist/__tests__/mesh-bin-morph-v3.test.d.ts.map +1 -0
  20. package/dist/__tests__/mesh-bin.test.d.ts +2 -0
  21. package/dist/__tests__/mesh-bin.test.d.ts.map +1 -0
  22. package/dist/__tests__/owner-chain.integration.test.d.ts +2 -0
  23. package/dist/__tests__/owner-chain.integration.test.d.ts.map +1 -0
  24. package/dist/__tests__/scriptable-pack-host.unit.test.d.ts +2 -0
  25. package/dist/__tests__/scriptable-pack-host.unit.test.d.ts.map +1 -0
  26. package/dist/__tests__/scriptable-pack-output-producers.unit.test.d.ts +2 -0
  27. package/dist/__tests__/scriptable-pack-output-producers.unit.test.d.ts.map +1 -0
  28. package/dist/__tests__/scriptable-pack-product.contract.test.d.ts +2 -0
  29. package/dist/__tests__/scriptable-pack-product.contract.test.d.ts.map +1 -0
  30. package/dist/__tests__/scriptable-pack-production-producers.unit.test.d.ts +2 -0
  31. package/dist/__tests__/scriptable-pack-production-producers.unit.test.d.ts.map +1 -0
  32. package/dist/__tests__/scriptable-pack-staged-snapshot.unit.test.d.ts +2 -0
  33. package/dist/__tests__/scriptable-pack-staged-snapshot.unit.test.d.ts.map +1 -0
  34. package/dist/__tests__/scriptable-pack.integration.test.d.ts +2 -0
  35. package/dist/__tests__/scriptable-pack.integration.test.d.ts.map +1 -0
  36. package/dist/__tests__/source-overrides-import-context.unit.test.d.ts +2 -0
  37. package/dist/__tests__/source-overrides-import-context.unit.test.d.ts.map +1 -0
  38. package/dist/__tests__/source-package-publication.integration.test.d.ts +2 -0
  39. package/dist/__tests__/source-package-publication.integration.test.d.ts.map +1 -0
  40. package/dist/browser.d.ts +5 -0
  41. package/dist/browser.d.ts.map +1 -0
  42. package/dist/browser.mjs +782 -0
  43. package/dist/browser.mjs.map +1 -0
  44. package/dist/build-production.d.ts +48 -0
  45. package/dist/build-production.d.ts.map +1 -0
  46. package/dist/catalog-importer-policy.d.ts +13 -0
  47. package/dist/catalog-importer-policy.d.ts.map +1 -0
  48. package/dist/catalog-inventory.d.ts +4 -0
  49. package/dist/catalog-inventory.d.ts.map +1 -0
  50. package/dist/import-product.d.ts +27 -0
  51. package/dist/import-product.d.ts.map +1 -0
  52. package/dist/import-runner.d.ts +136 -0
  53. package/dist/import-runner.d.ts.map +1 -0
  54. package/dist/importer-registry.d.ts +48 -0
  55. package/dist/importer-registry.d.ts.map +1 -0
  56. package/dist/index.d.ts +19 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.mjs +2849 -0
  59. package/dist/index.mjs.map +1 -0
  60. package/dist/mesh-bin.d.ts +19 -0
  61. package/dist/mesh-bin.d.ts.map +1 -0
  62. package/dist/mesh-bin.mjs +182 -0
  63. package/dist/mesh-bin.mjs.map +1 -0
  64. package/dist/pack-projection.d.ts +5 -0
  65. package/dist/pack-projection.d.ts.map +1 -0
  66. package/dist/scriptable-pack-host.d.ts +72 -0
  67. package/dist/scriptable-pack-host.d.ts.map +1 -0
  68. package/dist/scriptable-pack-output-producers.d.ts +7 -0
  69. package/dist/scriptable-pack-output-producers.d.ts.map +1 -0
  70. package/dist/scriptable-pack-staged-snapshot.d.ts +21 -0
  71. package/dist/scriptable-pack-staged-snapshot.d.ts.map +1 -0
  72. package/dist/scriptable-pack.d.ts +141 -0
  73. package/dist/scriptable-pack.d.ts.map +1 -0
  74. package/dist/scriptable-source-package.d.ts +14 -0
  75. package/dist/scriptable-source-package.d.ts.map +1 -0
  76. package/dist/source-package-errors.d.ts +52 -0
  77. package/dist/source-package-errors.d.ts.map +1 -0
  78. package/dist/source-package-publication.d.ts +63 -0
  79. package/dist/source-package-publication.d.ts.map +1 -0
  80. package/dist/source-package.d.ts +60 -0
  81. package/dist/source-package.d.ts.map +1 -0
  82. package/package.json +69 -0
  83. package/src/__tests__/decode-image-owner.test-d.ts +53 -0
  84. package/src/__tests__/import-contract-migration.test.ts +223 -0
  85. package/src/__tests__/import-dependencies.test.ts +65 -0
  86. package/src/__tests__/import-finalizer-digest-retry.test.ts +113 -0
  87. package/src/__tests__/import-local-artifacts.test.ts +102 -0
  88. package/src/__tests__/import.unit.test.ts +429 -0
  89. package/src/__tests__/mesh-bin-contract.test.ts +95 -0
  90. package/src/__tests__/mesh-bin-morph-v3.test.ts +44 -0
  91. package/src/__tests__/mesh-bin.test.ts +102 -0
  92. package/src/__tests__/owner-chain.integration.test.ts +37 -0
  93. package/src/__tests__/scriptable-pack-host.unit.test.ts +86 -0
  94. package/src/__tests__/scriptable-pack-output-producers.unit.test.ts +190 -0
  95. package/src/__tests__/scriptable-pack-product.contract.test.ts +47 -0
  96. package/src/__tests__/scriptable-pack-production-producers.unit.test.ts +488 -0
  97. package/src/__tests__/scriptable-pack-staged-snapshot.unit.test.ts +290 -0
  98. package/src/__tests__/scriptable-pack.integration.test.ts +435 -0
  99. package/src/__tests__/source-overrides-import-context.unit.test.ts +92 -0
  100. package/src/__tests__/source-package-publication.integration.test.ts +75 -0
  101. package/src/browser.ts +14 -0
  102. package/src/build-production.ts +493 -0
  103. package/src/catalog-importer-policy.ts +58 -0
  104. package/src/catalog-inventory.ts +24 -0
  105. package/src/import-product.ts +163 -0
  106. package/src/import-runner.ts +749 -0
  107. package/src/importer-registry.ts +103 -0
  108. package/src/index.ts +175 -0
  109. package/src/mesh-bin.ts +229 -0
  110. package/src/pack-projection.ts +21 -0
  111. package/src/scriptable-pack-host.ts +544 -0
  112. package/src/scriptable-pack-output-producers.ts +456 -0
  113. package/src/scriptable-pack-staged-snapshot.ts +172 -0
  114. package/src/scriptable-pack.ts +626 -0
  115. package/src/scriptable-source-package.ts +88 -0
  116. package/src/source-package-errors.ts +201 -0
  117. package/src/source-package-publication.ts +326 -0
  118. package/src/source-package.ts +187 -0
@@ -0,0 +1,187 @@
1
+ import type {
2
+ ImportErrorDetail,
3
+ ImportedAsset,
4
+ ImportProduct,
5
+ ImportProductFinalizeOptions,
6
+ ImportProductFinalizeResult,
7
+ Result,
8
+ } from '@forgeax/engine-types';
9
+ import { err, ok } from '@forgeax/engine-types';
10
+ import type { ImportRunnerFs, RunImportMeta } from './import-runner.js';
11
+ import { runImport } from './import-runner.js';
12
+ import type { ImporterRegistry } from './importer-registry.js';
13
+
14
+ export type ProducerReadiness = 'before-consume' | 'on-demand';
15
+
16
+ export interface ProducerReadinessError {
17
+ readonly code: 'producer-readiness-invalid';
18
+ readonly expected: "'before-consume' or 'on-demand'";
19
+ readonly hint: 'set producerReadiness to before-consume or on-demand';
20
+ readonly detail: { readonly value: unknown };
21
+ }
22
+
23
+ export type ProducerReadinessResult =
24
+ | { readonly ok: true; readonly value: ProducerReadiness }
25
+ | { readonly ok: false; readonly error: ProducerReadinessError };
26
+
27
+ export function parseProducerReadiness(value: unknown): ProducerReadinessResult {
28
+ if (value === undefined || value === 'before-consume' || value === 'on-demand') {
29
+ return { ok: true, value: value ?? 'before-consume' };
30
+ }
31
+ return {
32
+ ok: false,
33
+ error: {
34
+ code: 'producer-readiness-invalid',
35
+ expected: "'before-consume' or 'on-demand'",
36
+ hint: 'set producerReadiness to before-consume or on-demand',
37
+ detail: { value },
38
+ },
39
+ };
40
+ }
41
+
42
+ export interface SourcePackageProducerInput {
43
+ readonly meta: RunImportMeta;
44
+ readonly registry: ImporterRegistry;
45
+ readonly fs: ImportRunnerFs;
46
+ }
47
+
48
+ export interface SourcePackageClosureDetail {
49
+ readonly stage: 'closure';
50
+ readonly declaredGuids: readonly string[];
51
+ readonly producedGuids: readonly string[];
52
+ readonly missingGuids: readonly string[];
53
+ readonly unexpectedGuids: readonly string[];
54
+ readonly duplicateGuids: readonly string[];
55
+ }
56
+
57
+ export interface SourcePackageClosureError {
58
+ readonly code: 'source-package-guid-closure-mismatch';
59
+ readonly expected: string;
60
+ readonly hint: string;
61
+ readonly detail: SourcePackageClosureDetail;
62
+ }
63
+
64
+ export interface SourcePackageProduct {
65
+ readonly anchorGuid: string;
66
+ readonly declaredGuids: readonly string[];
67
+ readonly product: ImportProduct<unknown>;
68
+ }
69
+
70
+ type SourcePackageFinalizeError = Extract<
71
+ ImportProductFinalizeResult,
72
+ { readonly ok: false }
73
+ >['error'];
74
+
75
+ /** Apply an importer-owned transport finalizer without teaching the adapter its kind. */
76
+ export function finalizeSourcePackage(
77
+ product: ImportProduct<unknown>,
78
+ finalizer:
79
+ | ((
80
+ product: ImportProduct<unknown>,
81
+ options: ImportProductFinalizeOptions,
82
+ ) => ImportProductFinalizeResult)
83
+ | undefined,
84
+ artifactUrl: ImportProductFinalizeOptions['artifactUrl'],
85
+ ): Result<ImportProduct<unknown>, SourcePackageFinalizeError> {
86
+ if (finalizer === undefined) return ok(product);
87
+ const result = finalizer(product, { artifactUrl });
88
+ if (!result.ok) return err(result.error);
89
+ return ok({
90
+ ...product,
91
+ assets: product.assets.map((asset, index) =>
92
+ index === 0 ? { ...asset, payload: result.value.asset } : asset,
93
+ ),
94
+ });
95
+ }
96
+
97
+ export type SourcePackageProducerResult =
98
+ | { readonly ok: true; readonly value: SourcePackageProduct }
99
+ | { readonly ok: false; readonly error: SourcePackageClosureError };
100
+
101
+ function closureError(
102
+ declaredGuids: readonly string[],
103
+ producedGuids: readonly string[],
104
+ ): SourcePackageClosureError {
105
+ const declared = new Set(declaredGuids.map((guid) => guid.toLowerCase()));
106
+ const produced = new Set(producedGuids.map((guid) => guid.toLowerCase()));
107
+ const counts = new Map<string, number>();
108
+ for (const guid of producedGuids) {
109
+ const key = guid.toLowerCase();
110
+ counts.set(key, (counts.get(key) ?? 0) + 1);
111
+ }
112
+ const duplicateGuids = [...counts.entries()]
113
+ .filter(([, count]) => count > 1)
114
+ .map(([guid]) => guid);
115
+ return {
116
+ code: 'source-package-guid-closure-mismatch',
117
+ expected: 'the importer to return exactly one asset for every declared Meta GUID',
118
+ hint: 'repair the Meta declaration or importer output, then rebuild the whole source package',
119
+ detail: {
120
+ stage: 'closure',
121
+ declaredGuids,
122
+ producedGuids,
123
+ missingGuids: declaredGuids.filter((guid) => !produced.has(guid.toLowerCase())),
124
+ unexpectedGuids: producedGuids.filter((guid) => !declared.has(guid.toLowerCase())),
125
+ duplicateGuids,
126
+ },
127
+ };
128
+ }
129
+
130
+ function producedGuidsFromImportFailure(
131
+ declaredGuids: readonly string[],
132
+ detail: ImportErrorDetail,
133
+ ): readonly string[] {
134
+ if ('missingGuids' in detail) {
135
+ return declaredGuids.filter((guid) => !detail.missingGuids.includes(guid));
136
+ }
137
+ if ('unexpectedGuids' in detail) return [...declaredGuids, ...detail.unexpectedGuids];
138
+ return [];
139
+ }
140
+
141
+ export async function produceSourcePackage(
142
+ input: SourcePackageProducerInput,
143
+ ): Promise<SourcePackageProducerResult> {
144
+ const declaredGuids = input.meta.subAssets.map((asset) => asset.guid);
145
+ const result = await runImport(input.meta, input.registry, input.fs);
146
+ if (!result.ok) {
147
+ const producedGuids = producedGuidsFromImportFailure(declaredGuids, result.error.detail);
148
+ return {
149
+ ok: false,
150
+ error: closureError(declaredGuids, producedGuids),
151
+ };
152
+ }
153
+ if ('skipped' in result.value) {
154
+ return { ok: false, error: closureError(declaredGuids, []) };
155
+ }
156
+
157
+ const producedGuids = result.value.product.assets.map((asset) => asset.guid);
158
+ const declaredSet = new Set(declaredGuids.map((guid) => guid.toLowerCase()));
159
+ const producedSet = new Set(producedGuids.map((guid) => guid.toLowerCase()));
160
+ const hasDuplicate =
161
+ new Set(producedGuids.map((guid) => guid.toLowerCase())).size !== producedGuids.length;
162
+ const complete =
163
+ !hasDuplicate &&
164
+ declaredGuids.length === producedGuids.length &&
165
+ declaredGuids.every((guid) => producedSet.has(guid.toLowerCase())) &&
166
+ producedGuids.every((guid) => declaredSet.has(guid.toLowerCase()));
167
+ if (!complete) return { ok: false, error: closureError(declaredGuids, producedGuids) };
168
+
169
+ const product = result.value.product;
170
+ const anchorGuid = [...declaredGuids].sort((left, right) => left.localeCompare(right))[0];
171
+ if (anchorGuid === undefined)
172
+ return { ok: false, error: closureError(declaredGuids, producedGuids) };
173
+ return {
174
+ ok: true,
175
+ value: {
176
+ anchorGuid,
177
+ declaredGuids,
178
+ product,
179
+ },
180
+ };
181
+ }
182
+
183
+ export function sourcePackageAssetsByGuid(
184
+ source: SourcePackageProduct,
185
+ ): ReadonlyMap<string, ImportedAsset<unknown>> {
186
+ return new Map(source.product.assets.map((asset) => [asset.guid.toLowerCase(), asset]));
187
+ }