@loaders.gl/tile-converter 4.5.3 → 5.0.0-alpha.10

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 (125) hide show
  1. package/LICENSE +14 -3
  2. package/README.md +464 -0
  3. package/dist/converter.min.cjs +199 -260
  4. package/dist/i3s-server/bin/i3s-server.min.cjs +106 -341
  5. package/dist/index.cjs +38482 -0
  6. package/dist/index.js +38453 -0
  7. package/dist/v5/adapters.cjs +1992 -0
  8. package/dist/v5/adapters.d.ts +22 -0
  9. package/dist/v5/adapters.js +1972 -0
  10. package/dist/v5/browser-sink.d.ts +37 -0
  11. package/dist/v5/browser-source.d.ts +38 -0
  12. package/dist/v5/browser-tileset-source.d.ts +70 -0
  13. package/dist/v5/browser.cjs +64 -0
  14. package/dist/v5/browser.d.ts +34 -0
  15. package/dist/v5/browser.js +57 -0
  16. package/dist/v5/conversion-api.d.ts +122 -0
  17. package/dist/v5/conversion-archive.d.ts +32 -0
  18. package/dist/v5/core.cjs +863 -0
  19. package/dist/v5/core.d.ts +16 -0
  20. package/dist/v5/core.js +845 -0
  21. package/dist/v5/feature-arrow.d.ts +36 -0
  22. package/dist/v5/i3s-mesh-conversion.d.ts +26 -0
  23. package/dist/v5/index.cjs +63 -0
  24. package/dist/v5/index.d.ts +32 -0
  25. package/dist/v5/index.js +59 -0
  26. package/dist/v5/mesh-conversion.d.ts +62 -0
  27. package/dist/v5/mesh-draco.d.ts +8 -0
  28. package/dist/v5/mesh-source-features.d.ts +21 -0
  29. package/dist/v5/mesh-source-texture.d.ts +4 -0
  30. package/dist/v5/mesh-source.d.ts +34 -0
  31. package/dist/v5/mesh-tileset-archive.d.ts +18 -0
  32. package/dist/v5/mesh-tileset-sink.d.ts +51 -0
  33. package/dist/v5/mesh.d.ts +81 -0
  34. package/dist/v5/point-cloud-conversion.d.ts +31 -0
  35. package/dist/v5/point-cloud-source-encoder.d.ts +49 -0
  36. package/dist/v5/point-cloud-source.d.ts +25 -0
  37. package/dist/v5/point-cloud.d.ts +24 -0
  38. package/dist/v5/resource-manifest.d.ts +58 -0
  39. package/dist/v5/spatial-conversion.d.ts +59 -0
  40. package/dist/v5/tileset-source.d.ts +21 -0
  41. package/package.json +53 -27
  42. package/src/common/README.md +5 -0
  43. package/src/index.ts +1 -2
  44. package/src/{3d-tiles-converter → v4/3d-tiles-converter}/3d-tiles-converter.ts +14 -3
  45. package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/3d-tiles-content-converter.ts +2 -2
  46. package/src/v4/3d-tiles-converter/helpers/validate-i3s-spatial-reference.ts +124 -0
  47. package/src/{3d-tiles-converter → v4/3d-tiles-converter}/json-templates/tileset.ts +4 -4
  48. package/src/{converter-cli.ts → v4/converter-cli.ts} +4 -4
  49. package/src/{deps-installer → v4/deps-installer}/deps-installer.ts +10 -7
  50. package/src/{i3s-converter → v4/i3s-converter}/helpers/attribute-metadata-info.ts +1 -1
  51. package/src/{i3s-converter → v4/i3s-converter}/helpers/batch-ids-extensions.ts +1 -1
  52. package/src/v4/i3s-converter/helpers/encode-string-attribute.ts +23 -0
  53. package/src/{i3s-converter → v4/i3s-converter}/helpers/geometry-attributes.ts +1 -1
  54. package/src/{i3s-converter → v4/i3s-converter}/helpers/geometry-converter.ts +34 -59
  55. package/src/{i3s-converter → v4/i3s-converter}/helpers/gltf-attributes.ts +7 -6
  56. package/src/{i3s-converter → v4/i3s-converter}/helpers/load-3d-tiles.ts +5 -9
  57. package/src/{i3s-converter → v4/i3s-converter}/helpers/node-debug.ts +5 -6
  58. package/src/{i3s-converter → v4/i3s-converter}/i3s-converter.ts +16 -19
  59. package/src/{i3s-converter → v4/i3s-converter}/json-templates/geometry-definitions.ts +4 -4
  60. package/src/{i3s-converter → v4/i3s-converter}/json-templates/layers.ts +6 -6
  61. package/src/{i3s-converter → v4/i3s-converter}/json-templates/node.ts +1 -1
  62. package/src/{i3s-converter → v4/i3s-converter}/json-templates/scene-server.ts +1 -1
  63. package/src/{i3s-converter → v4/i3s-converter}/json-templates/shared-resources.ts +1 -1
  64. package/src/{i3s-converter → v4/i3s-converter}/json-templates/store.ts +1 -1
  65. package/src/{i3s-server → v4/i3s-server}/README.md +2 -2
  66. package/src/{i3s-server → v4/i3s-server}/controllers/slpk-controller.ts +1 -1
  67. package/src/{i3s-server → v4/i3s-server}/routes/slpk-router.ts +2 -1
  68. package/src/v4/index.ts +2 -0
  69. package/src/{lib → v4/lib}/utils/compress-util.ts +8 -7
  70. package/src/{lib → v4/lib}/utils/conversion-dump.ts +4 -4
  71. package/src/{lib → v4/lib}/utils/file-utils.ts +2 -2
  72. package/src/{lib → v4/lib}/utils/lod-conversion-utils.ts +2 -4
  73. package/src/v5/adapters.ts +56 -0
  74. package/src/v5/browser-sink.ts +130 -0
  75. package/src/v5/browser-source.ts +155 -0
  76. package/src/v5/browser-tileset-source.ts +328 -0
  77. package/src/v5/browser.ts +105 -0
  78. package/src/v5/conversion-api.ts +287 -0
  79. package/src/v5/conversion-archive.ts +85 -0
  80. package/src/v5/core.ts +61 -0
  81. package/src/v5/feature-arrow.ts +429 -0
  82. package/src/v5/i3s-mesh-conversion.ts +152 -0
  83. package/src/v5/index.ts +99 -0
  84. package/src/v5/mesh-conversion.ts +200 -0
  85. package/src/v5/mesh-draco.ts +138 -0
  86. package/src/v5/mesh-source-features.ts +232 -0
  87. package/src/v5/mesh-source-texture.ts +122 -0
  88. package/src/v5/mesh-source.ts +360 -0
  89. package/src/v5/mesh-tileset-archive.ts +50 -0
  90. package/src/v5/mesh-tileset-sink.ts +324 -0
  91. package/src/v5/mesh.ts +517 -0
  92. package/src/v5/point-cloud-conversion.ts +80 -0
  93. package/src/v5/point-cloud-source-encoder.ts +105 -0
  94. package/src/v5/point-cloud-source.ts +84 -0
  95. package/src/v5/point-cloud.ts +271 -0
  96. package/src/v5/resource-manifest.ts +213 -0
  97. package/src/v5/spatial-conversion.ts +305 -0
  98. package/src/v5/tileset-source.ts +54 -0
  99. /package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/i3s-obb-to-3d-tiles-obb.ts +0 -0
  100. /package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/load-i3s.ts +0 -0
  101. /package/src/{3d-tiles-converter → v4/3d-tiles-converter}/helpers/texture-atlas.ts +0 -0
  102. /package/src/{constants.ts → v4/constants.ts} +0 -0
  103. /package/src/{i3s-converter → v4/i3s-converter}/helpers/coordinate-converter.ts +0 -0
  104. /package/src/{i3s-converter → v4/i3s-converter}/helpers/create-scene-server-path.ts +0 -0
  105. /package/src/{i3s-converter → v4/i3s-converter}/helpers/feature-attributes.ts +0 -0
  106. /package/src/{i3s-converter → v4/i3s-converter}/helpers/node-index-document.ts +0 -0
  107. /package/src/{i3s-converter → v4/i3s-converter}/helpers/node-pages.ts +0 -0
  108. /package/src/{i3s-converter → v4/i3s-converter}/helpers/preprocess-3d-tiles.ts +0 -0
  109. /package/src/{i3s-converter → v4/i3s-converter}/helpers/progress.ts +0 -0
  110. /package/src/{i3s-converter → v4/i3s-converter}/helpers/tileset-traversal.ts +0 -0
  111. /package/src/{i3s-converter → v4/i3s-converter}/json-templates/metadata.ts +0 -0
  112. /package/src/{i3s-converter → v4/i3s-converter}/types.ts +0 -0
  113. /package/src/{i3s-server → v4/i3s-server}/app.ts +0 -0
  114. /package/src/{i3s-server → v4/i3s-server}/bin/www.ts +0 -0
  115. /package/src/{i3s-server → v4/i3s-server}/certs/cert.pem +0 -0
  116. /package/src/{i3s-server → v4/i3s-server}/certs/key.pem +0 -0
  117. /package/src/{i3s-server → v4/i3s-server}/utils/create-scene-server.ts +0 -0
  118. /package/src/{i3s-server → v4/i3s-server}/utils/server-utils.ts +0 -0
  119. /package/src/{lib → v4/lib}/json-schemas/conversion-dump-json-schema.ts +0 -0
  120. /package/src/{lib → v4/lib}/utils/cli-utils.ts +0 -0
  121. /package/src/{lib → v4/lib}/utils/geometry-utils.ts +0 -0
  122. /package/src/{lib → v4/lib}/utils/queue.ts +0 -0
  123. /package/src/{lib → v4/lib}/utils/statistic-utils.ts +0 -0
  124. /package/src/{lib → v4/lib}/utils/write-queue.ts +0 -0
  125. /package/src/{pgm-loader.ts → v4/pgm-loader.ts} +0 -0
@@ -0,0 +1,287 @@
1
+ /** A diagnostic produced while inspecting, converting, or validating tiles. */
2
+ export interface TileConversionDiagnostic {
3
+ /** Stable machine-readable diagnostic code. */
4
+ readonly code: string;
5
+ /** Human-readable explanation of the diagnostic. */
6
+ readonly message: string;
7
+ /** Severity used by callers to decide whether the result is acceptable. */
8
+ readonly severity: 'info' | 'warning' | 'error';
9
+ /** Optional resource that produced the diagnostic. */
10
+ readonly resourceId?: string;
11
+ }
12
+
13
+ /** Typed failure raised when a conversion policy or validation gate rejects a resource. */
14
+ export class TileConversionError extends Error {
15
+ /** Stable machine-readable failure code. */
16
+ readonly code: string;
17
+ /** Diagnostics associated with this failure. */
18
+ readonly diagnostics: readonly TileConversionDiagnostic[];
19
+
20
+ /** Creates a typed conversion failure. */
21
+ constructor(
22
+ code: string,
23
+ message: string,
24
+ diagnostics: readonly TileConversionDiagnostic[] = []
25
+ ) {
26
+ super(message);
27
+ this.name = 'TileConversionError';
28
+ this.code = code;
29
+ this.diagnostics = diagnostics;
30
+ }
31
+ }
32
+
33
+ /** Progress reported by the portable conversion core. */
34
+ export interface TileConversionProgress {
35
+ /** Current conversion phase. */
36
+ readonly phase: 'inspect' | 'convert' | 'validate' | 'finalize';
37
+ /** Number of input resources consumed so far. */
38
+ readonly inputResources: number;
39
+ /** Number of output resources written so far. */
40
+ readonly outputResources: number;
41
+ /** Number of input bytes consumed so far. */
42
+ readonly inputBytes: number;
43
+ /** Number of output bytes written so far. */
44
+ readonly outputBytes: number;
45
+ }
46
+
47
+ /** Summary returned after a tileset conversion completes. */
48
+ export interface TileConversionReport {
49
+ /** Completed conversion state. Failed conversions reject with their cause. */
50
+ readonly state: 'completed';
51
+ /** Number of input resources consumed. */
52
+ readonly inputResources: number;
53
+ /** Number of output resources written. */
54
+ readonly outputResources: number;
55
+ /** Number of input bytes consumed. */
56
+ readonly inputBytes: number;
57
+ /** Number of output bytes written. */
58
+ readonly outputBytes: number;
59
+ /** Largest output resource written. */
60
+ readonly largestOutputResourceBytes: number;
61
+ /** Diagnostics reported during conversion and validation. */
62
+ readonly diagnostics: readonly TileConversionDiagnostic[];
63
+ }
64
+
65
+ /** Portable source adapter that resolves and reads a tileset. */
66
+ export interface TileConversionSource<TInspection, TInput> {
67
+ /** Inspect the source and return its profile-specific metadata. */
68
+ inspect(signal?: AbortSignal): Promise<TInspection>;
69
+ /** Stream input resources in deterministic traversal order. */
70
+ read(inspection: TInspection, signal?: AbortSignal): AsyncIterable<TInput>;
71
+ }
72
+
73
+ /** Output adapter whose awaited writes apply backpressure to conversion. */
74
+ export interface TileConversionSink<TOutput> {
75
+ /** Write one completed output resource and resolve when it can be released. */
76
+ write(resource: TOutput, signal?: AbortSignal): Promise<void>;
77
+ /** Finalize the destination after every resource has been written. */
78
+ finalize(report: TileConversionReport): Promise<void>;
79
+ /** Abort and clean up a partial destination after a failure. */
80
+ abort(reason: unknown): Promise<void>;
81
+ }
82
+
83
+ /** Codec adapter used to convert one input resource into streamed outputs. */
84
+ export interface TileConversionCodec<TInspection, TInput, TOutput> {
85
+ /** Convert one input resource into zero or more output resources. */
86
+ convert(
87
+ resource: TInput,
88
+ inspection: TInspection,
89
+ signal?: AbortSignal
90
+ ): AsyncIterable<TOutput> | Promise<AsyncIterable<TOutput>>;
91
+ /** Optionally validate each output resource before it is written. */
92
+ validateOutput?(
93
+ resource: TOutput,
94
+ signal?: AbortSignal
95
+ ): Promise<readonly TileConversionDiagnostic[]>;
96
+ }
97
+
98
+ /** Options for the portable `convertTileset` operation. */
99
+ export interface ConvertTilesetOptions<TInspection, TInput, TOutput> {
100
+ /** Injected input resolver and resource reader. */
101
+ readonly source: TileConversionSource<TInspection, TInput>;
102
+ /** Injected output codec. */
103
+ readonly codec: TileConversionCodec<TInspection, TInput, TOutput>;
104
+ /** Injected destination writer. */
105
+ readonly sink: TileConversionSink<TOutput>;
106
+ /** Return the decoded input byte size as a nonnegative safe integer. */
107
+ readonly measureInputBytes: (resource: TInput) => number;
108
+ /** Return the byte size of an output resource. */
109
+ readonly measureOutputBytes: (resource: TOutput) => number;
110
+ /** Reject a decoded input resource above this byte limit before encoding. Defaults to no limit. */
111
+ readonly maxInputResourceBytes?: number;
112
+ /** Reject any output resource larger than this configured byte limit. */
113
+ readonly maxOutputResourceBytes?: number;
114
+ /** Cancel inspection, conversion, validation, or writes. */
115
+ readonly signal?: AbortSignal;
116
+ /** Receive progress updates after each resource transition. */
117
+ readonly onProgress?: (progress: TileConversionProgress) => void;
118
+ }
119
+
120
+ /** Options for a standalone tileset validation pass. */
121
+ export interface ValidateTilesetOptions<TTileset> {
122
+ /** Tileset or conversion result to validate. */
123
+ readonly tileset: TTileset;
124
+ /** Injected profile-specific validator. */
125
+ readonly validate: (
126
+ tileset: TTileset,
127
+ signal?: AbortSignal
128
+ ) => Promise<readonly TileConversionDiagnostic[]>;
129
+ /** Cancel validation. */
130
+ readonly signal?: AbortSignal;
131
+ }
132
+
133
+ /** Result of validating a tileset. */
134
+ export interface TileValidationReport {
135
+ /** False when at least one error diagnostic was reported. */
136
+ readonly valid: boolean;
137
+ /** Diagnostics returned by the injected validator. */
138
+ readonly diagnostics: readonly TileConversionDiagnostic[];
139
+ }
140
+
141
+ /** Inspects a tileset with an injected, platform-specific source adapter. */
142
+ export async function inspectTileset<TInspection, TInput>(
143
+ source: TileConversionSource<TInspection, TInput>,
144
+ signal?: AbortSignal
145
+ ): Promise<TInspection> {
146
+ throwIfAborted(signal);
147
+ const inspection = await source.inspect(signal);
148
+ throwIfAborted(signal);
149
+ return inspection;
150
+ }
151
+
152
+ /**
153
+ * Converts a stream of tileset resources through injected source, codec, and sink adapters.
154
+ * Decoded inputs are measured and checked against `maxInputResourceBytes` before encoding.
155
+ * This does not limit source decoding allocations or content retained by a source.
156
+ * Writes are awaited one resource at a time, keeping queued output bytes bounded by the
157
+ * largest emitted resource and the configured `maxOutputResourceBytes` limit.
158
+ */
159
+ export async function convertTileset<TInspection, TInput, TOutput>(
160
+ options: ConvertTilesetOptions<TInspection, TInput, TOutput>
161
+ ): Promise<TileConversionReport> {
162
+ const {
163
+ source,
164
+ codec,
165
+ sink,
166
+ measureInputBytes,
167
+ measureOutputBytes,
168
+ maxInputResourceBytes = Number.POSITIVE_INFINITY,
169
+ maxOutputResourceBytes = Number.POSITIVE_INFINITY,
170
+ signal,
171
+ onProgress
172
+ } = options;
173
+ let inputResources = 0;
174
+ let outputResources = 0;
175
+ let inputBytes = 0;
176
+ let outputBytes = 0;
177
+ let largestOutputResourceBytes = 0;
178
+ const diagnostics: TileConversionDiagnostic[] = [];
179
+ const reportProgress = (phase: TileConversionProgress['phase']): void => {
180
+ onProgress?.({phase, inputResources, outputResources, inputBytes, outputBytes});
181
+ };
182
+
183
+ try {
184
+ if (
185
+ maxInputResourceBytes !== Number.POSITIVE_INFINITY &&
186
+ (!Number.isSafeInteger(maxInputResourceBytes) || maxInputResourceBytes < 0)
187
+ ) {
188
+ throw new TileConversionError(
189
+ 'INVALID_INPUT_RESOURCE_LIMIT',
190
+ 'maxInputResourceBytes must be a nonnegative safe integer or Infinity'
191
+ );
192
+ }
193
+ reportProgress('inspect');
194
+ const inspection = await inspectTileset(source, signal);
195
+ for await (const inputResource of source.read(inspection, signal)) {
196
+ throwIfAborted(signal);
197
+ const inputResourceBytes = measureInputBytes(inputResource);
198
+ if (!Number.isSafeInteger(inputResourceBytes) || inputResourceBytes < 0) {
199
+ throw new TileConversionError(
200
+ 'INVALID_INPUT_RESOURCE_SIZE',
201
+ 'measureInputBytes must return a nonnegative safe integer'
202
+ );
203
+ }
204
+ if (inputResourceBytes > maxInputResourceBytes) {
205
+ throw new TileConversionError(
206
+ 'INPUT_RESOURCE_TOO_LARGE',
207
+ `Input resource is ${inputResourceBytes} bytes, exceeding the configured limit of ${maxInputResourceBytes} bytes`
208
+ );
209
+ }
210
+ inputResources++;
211
+ inputBytes += inputResourceBytes;
212
+ reportProgress('convert');
213
+ const convertedResources = await codec.convert(inputResource, inspection, signal);
214
+ for await (const outputResource of convertedResources) {
215
+ throwIfAborted(signal);
216
+ reportProgress('validate');
217
+ const resourceDiagnostics = (await codec.validateOutput?.(outputResource, signal)) || [];
218
+ diagnostics.push(...resourceDiagnostics);
219
+ const outputResourceBytes = measureOutputBytes(outputResource);
220
+ largestOutputResourceBytes = Math.max(largestOutputResourceBytes, outputResourceBytes);
221
+ if (outputResourceBytes > maxOutputResourceBytes) {
222
+ throw new TileConversionError(
223
+ 'OUTPUT_RESOURCE_TOO_LARGE',
224
+ `Output resource is ${outputResourceBytes} bytes, exceeding the configured limit of ${maxOutputResourceBytes} bytes`
225
+ );
226
+ }
227
+ if (resourceDiagnostics.some(diagnostic => diagnostic.severity === 'error')) {
228
+ throw new TileConversionError(
229
+ 'OUTPUT_VALIDATION_FAILED',
230
+ 'Output resource validation failed',
231
+ resourceDiagnostics
232
+ );
233
+ }
234
+ throwIfAborted(signal);
235
+ await sink.write(outputResource, signal);
236
+ throwIfAborted(signal);
237
+ outputResources++;
238
+ outputBytes += outputResourceBytes;
239
+ reportProgress('convert');
240
+ }
241
+ }
242
+
243
+ const report: TileConversionReport = {
244
+ state: 'completed',
245
+ inputResources,
246
+ outputResources,
247
+ inputBytes,
248
+ outputBytes,
249
+ largestOutputResourceBytes,
250
+ diagnostics
251
+ };
252
+ throwIfAborted(signal);
253
+ reportProgress('finalize');
254
+ await sink.finalize(report);
255
+ return report;
256
+ } catch (error) {
257
+ try {
258
+ await sink.abort(error);
259
+ } catch (abortError) {
260
+ throw new AggregateError(
261
+ [error, abortError],
262
+ 'Conversion failed and the destination could not abort'
263
+ );
264
+ }
265
+ throw error;
266
+ }
267
+ }
268
+
269
+ /** Validates a tileset through an injected profile-specific validator. */
270
+ export async function validateTileset<TTileset>(
271
+ options: ValidateTilesetOptions<TTileset>
272
+ ): Promise<TileValidationReport> {
273
+ throwIfAborted(options.signal);
274
+ const diagnostics = await options.validate(options.tileset, options.signal);
275
+ throwIfAborted(options.signal);
276
+ return {
277
+ valid: !diagnostics.some(diagnostic => diagnostic.severity === 'error'),
278
+ diagnostics
279
+ };
280
+ }
281
+
282
+ /** Throws the signal reason when a conversion operation has been cancelled. */
283
+ function throwIfAborted(signal?: AbortSignal): void {
284
+ if (signal?.aborted) {
285
+ throw signal.reason ?? new DOMException('The operation was aborted', 'AbortError');
286
+ }
287
+ }
@@ -0,0 +1,85 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import {
6
+ Tiles3DArchiveWriter,
7
+ encodeTiles3DArchiveInBatches
8
+ } from '@loaders.gl/3d-tiles/3d-tiles-archive-writer';
9
+ import {SLPKWriter, encodeSLPKArchiveInBatches} from '@loaders.gl/i3s/i3s-slpk-writer';
10
+ import {TileConversionError} from '@loaders.gl/tile-converter/v5/core';
11
+ import type {BrowserTileConversionFile} from '@loaders.gl/tile-converter/v5/core';
12
+
13
+ /** Output profile and required budget for packaging finalized conversion resources. */
14
+ export interface TileConversionArchiveOptions {
15
+ /** Archive format; resources must already use the selected format's layout and encoding. */
16
+ readonly format: '3tz' | 'slpk';
17
+ /** Maximum final archive bytes, including headers/index; not peak serialization memory. */
18
+ readonly maxArchiveBytes: number;
19
+ /** Cooperative packaging cancellation; active block reads and header encodes finish first. */
20
+ readonly signal?: AbortSignal;
21
+ }
22
+
23
+ /**
24
+ * Packages finalized, already-authored resources as a bounded 3TZ or SLPK Blob.
25
+ * 3TZ requires tileset.json; SLPK requires 3dSceneLayer.json.gz and precompressed I3S resources.
26
+ * Selecting an archive format does not convert geometry, metadata, or coordinate systems.
27
+ * Applications own input qualification, object URLs, and downloads. Inputs must remain unchanged.
28
+ * @param files - Unmodified files from a successfully finalized browser sink.
29
+ * @param options - Archive format and complete output-size budget.
30
+ * @returns Archive Blob to save using the selected .3tz or .slpk extension.
31
+ */
32
+ export async function createTileConversionArchive(
33
+ files: readonly BrowserTileConversionFile[],
34
+ options: TileConversionArchiveOptions
35
+ ): Promise<Blob> {
36
+ const {resources, format, maxArchiveBytes, signal} = prepareArchiveInput(files, options);
37
+ const writer = format === '3tz' ? Tiles3DArchiveWriter : SLPKWriter;
38
+ const archive = await writer.encode(resources, {[format]: {maxArchiveBytes, signal}});
39
+ return new Blob([archive], {type: writer.mimeTypes[0]});
40
+ }
41
+
42
+ /**
43
+ * Streams finalized resources as a bounded 3TZ or SLPK archive without a complete output buffer.
44
+ * Checks declarations and the full budget on first pull, before output. Await each chunk write
45
+ * for backpressure; callers finalize storage only after successful completion and discard partial
46
+ * output on failure, cancellation, or early exit. Resource inputs remain caller-owned and immutable.
47
+ * Uses payload blocks of at most 64 KiB and retains index/directory metadata and caller inputs.
48
+ * Each resource is read once for its checksum, then again for output; this is not a total heap guarantee.
49
+ * @param files - Files from a successfully finalized browser conversion sink.
50
+ * @param options - Format, complete archive-size budget, and optional cancellation signal.
51
+ * @returns Uint8Array views to write to application-owned storage, respecting their byte ranges.
52
+ */
53
+ export async function* encodeTileConversionArchiveInBatches(
54
+ files: readonly BrowserTileConversionFile[],
55
+ options: TileConversionArchiveOptions
56
+ ): AsyncIterable<Uint8Array<ArrayBuffer>> {
57
+ const {resources, format, maxArchiveBytes, signal} = prepareArchiveInput(files, options);
58
+ const encode = format === '3tz' ? encodeTiles3DArchiveInBatches : encodeSLPKArchiveInBatches;
59
+ yield* encode(resources, {[format]: {maxArchiveBytes, signal}});
60
+ }
61
+
62
+ /** Captures archive resources/options and preserves the converter's typed input diagnostics. */
63
+ function prepareArchiveInput(
64
+ files: readonly BrowserTileConversionFile[],
65
+ options: TileConversionArchiveOptions
66
+ ) {
67
+ const {format, maxArchiveBytes, signal} = options;
68
+ if (!Number.isSafeInteger(maxArchiveBytes) || maxArchiveBytes < 0) {
69
+ throw new TileConversionError(
70
+ 'INVALID_ARCHIVE_BYTE_LIMIT',
71
+ 'Archive byte limit must be a non-negative safe integer'
72
+ );
73
+ }
74
+ if (format !== '3tz' && format !== 'slpk') {
75
+ throw new TileConversionError('INVALID_ARCHIVE_FORMAT', 'Expected 3tz or slpk archive format');
76
+ }
77
+ const resources = Object.fromEntries(files.map(file => [file.resourceId, file.blob]));
78
+ if (Object.keys(resources).length !== files.length) {
79
+ throw new TileConversionError(
80
+ 'DUPLICATE_ARCHIVE_RESOURCE',
81
+ 'Archive resource identifiers must be unique'
82
+ );
83
+ }
84
+ return {resources, format, maxArchiveBytes, signal};
85
+ }
package/src/v5/core.ts ADDED
@@ -0,0 +1,61 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ // Portable orchestration and adapters using the existing tiles and math dependencies.
6
+ export {
7
+ TileConversionError,
8
+ inspectTileset,
9
+ convertTileset,
10
+ validateTileset
11
+ } from './conversion-api.js';
12
+ export type {
13
+ TileConversionDiagnostic,
14
+ TileConversionProgress,
15
+ TileConversionReport,
16
+ TileConversionSource,
17
+ TileConversionSink,
18
+ TileConversionCodec,
19
+ ConvertTilesetOptions,
20
+ ValidateTilesetOptions,
21
+ TileValidationReport
22
+ } from './conversion-api.js';
23
+ export {createBrowserTileConversionSource} from './browser-source.js';
24
+ export type {
25
+ BrowserTileConversionInspection,
26
+ BrowserTileConversionInputResource,
27
+ BrowserTileConversionSourceOptions
28
+ } from './browser-source.js';
29
+ export {traversePointCloudSource} from './point-cloud-source.js';
30
+ export type {PointCloudSourceTile, TraversePointCloudSourceOptions} from './point-cloud-source.js';
31
+ export {
32
+ createTiles3DConversionSpatialContext,
33
+ createI3SConversionSpatialContext
34
+ } from './spatial-conversion.js';
35
+ export type {
36
+ Tiles3DConversionSpatialContext,
37
+ I3SConversionSpatialContext
38
+ } from './spatial-conversion.js';
39
+ export {createTilesetConversionSource} from './tileset-source.js';
40
+ export type {TilesetConversionSourceOptions} from './tileset-source.js';
41
+ export {createManifestBackedTileConversionSink} from './resource-manifest.js';
42
+ export type {
43
+ TileResourceManifestEntry,
44
+ TileResourceManifest,
45
+ TileResourceManifestStore,
46
+ ManifestBackedTileConversionSinkOptions
47
+ } from './resource-manifest.js';
48
+ export {createBoundedMemoryTileConversionSink} from './browser-sink.js';
49
+ export type {
50
+ BrowserTileConversionResource,
51
+ BrowserTileConversionFile,
52
+ BoundedMemoryTileConversionSinkOptions,
53
+ BoundedMemoryTileConversionSink
54
+ } from './browser-sink.js';
55
+ export {createBrowserTilesetConversionSource} from './browser-tileset-source.js';
56
+ export type {
57
+ BrowserTilesetConversionSourceOptions,
58
+ BrowserTilesetConversionInspection,
59
+ BrowserTilesetResourceDescriptor,
60
+ BrowserTilesetConversionInputResource
61
+ } from './browser-tileset-source.js';