@needle-tools/gltf-build-pipeline 2.14.0 → 2.15.0-next.0c5bc39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cache/cache.d.ts +1 -0
- package/dist/cache/cache.js +4 -4
- package/dist/cli/index.js +0 -0
- package/dist/extensions/NEEDLE_opaque/NEEDLE_opaque.js +48 -30
- package/dist/scripts/pack-gltf.js +12 -3
- package/dist/transforms/needle_progressive.js +26 -9
- package/dist/utils/test-assert.d.ts +8 -0
- package/dist/utils/test-assert.js +18 -0
- package/dist/utils/version.gen.d.ts +1 -1
- package/dist/utils/version.gen.js +1 -1
- package/package.json +16 -4
- package/tsconfig.json +0 -20
package/dist/cache/cache.d.ts
CHANGED
package/dist/cache/cache.js
CHANGED
|
@@ -5,9 +5,9 @@ import path from 'path';
|
|
|
5
5
|
import { getVersion } from "../utils/version.js";
|
|
6
6
|
// import * as CHECKDISCSPACE from 'check-disk-space'
|
|
7
7
|
import xxhash from "xxhash-wasm";
|
|
8
|
-
let
|
|
8
|
+
let xxHashModule = null;
|
|
9
9
|
xxhash().then(module => {
|
|
10
|
-
|
|
10
|
+
xxHashModule = module;
|
|
11
11
|
});
|
|
12
12
|
/**
|
|
13
13
|
* Get the available space on the cache directory in bytes.
|
|
@@ -304,9 +304,9 @@ function hashObject(obj, depth = 0) {
|
|
|
304
304
|
}
|
|
305
305
|
}
|
|
306
306
|
function hashBuffer(buffer, offset, length) {
|
|
307
|
-
if (
|
|
307
|
+
if (xxHashModule) {
|
|
308
308
|
const view = new Uint8Array(buffer, offset, length);
|
|
309
|
-
return
|
|
309
|
+
return xxHashModule.h32Raw(view);
|
|
310
310
|
}
|
|
311
311
|
let hash = 0;
|
|
312
312
|
const view = new Uint8Array(buffer, offset, length);
|
package/dist/cli/index.js
CHANGED
|
File without changes
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Extension, ExtensionProperty, PropertyType, Node, TextureChannel } from '@gltf-transform/core';
|
|
2
2
|
import { getTexture, tryGetInArray, writeExtension } from '../utils.js';
|
|
3
3
|
import { isLightmap } from '../../utils/texture.js';
|
|
4
|
+
import { NEEDLE_progressive_texture_settings } from '../NEEDLE_progressive_texture_settings/index.js';
|
|
5
|
+
import { testAssert } from '../../utils/test-assert.js';
|
|
4
6
|
const ALL_PROPERTY_TYPES = [];
|
|
5
7
|
for (const key in PropertyType) {
|
|
6
8
|
ALL_PROPERTY_TYPES.push(PropertyType[key]);
|
|
@@ -123,8 +125,11 @@ export function createOpaqueExtension(name, types, opts) {
|
|
|
123
125
|
const prop = this.createExtension();
|
|
124
126
|
this.jsonPointerHandler.read(context, texture, ext, prop);
|
|
125
127
|
texture.setExtension(EXTENSION_NAME, prop);
|
|
126
|
-
const handler = new TextureHandler(this.document, textureDefinition, EXTENSION_NAME, ext, debugLog);
|
|
128
|
+
const handler = new TextureHandler(this.document, textureDefinition, EXTENSION_NAME, ext, debugLog, texture);
|
|
127
129
|
prop.add(handler);
|
|
130
|
+
const sourceIndex = textureDefinition.source;
|
|
131
|
+
if (debugLog)
|
|
132
|
+
console.log("Found texture with extension", EXTENSION_NAME, "at index", index, "source image index", sourceIndex, "name", texture.getName() || "<unnamed>");
|
|
128
133
|
});
|
|
129
134
|
break;
|
|
130
135
|
case PropertyType.NODE:
|
|
@@ -188,11 +193,11 @@ export function createOpaqueExtension(name, types, opts) {
|
|
|
188
193
|
const textures = this.document.getRoot().listTextures();
|
|
189
194
|
for (let i = 0; i < textures.length; i++) {
|
|
190
195
|
const tex = textures[i];
|
|
191
|
-
const texDef = textureDefinitions[i];
|
|
192
|
-
const name = texDef?.name;
|
|
193
196
|
if (isLightmap(tex) && tex.getMimeType() !== "image/exr") {
|
|
194
197
|
prop.setReference("lightmapTexture", tex, { channels: TextureChannel.R | TextureChannel.G | TextureChannel.B | TextureChannel.A });
|
|
195
|
-
|
|
198
|
+
const texDef = textureDefinitions[i]; // @TODO: textureDefinitions and textures might not be in the same order - we need to find the texture by source index instead of assuming the order is the same
|
|
199
|
+
const name = tex.getName() || texDef?.name;
|
|
200
|
+
logger.info(`Found lightmap texture \"${name}\" (${tex.getMimeType()}) in ${EXTENSION_NAME}`);
|
|
196
201
|
}
|
|
197
202
|
}
|
|
198
203
|
}
|
|
@@ -389,39 +394,48 @@ class GenericWriter {
|
|
|
389
394
|
class TextureHandler {
|
|
390
395
|
document;
|
|
391
396
|
textureDefinition;
|
|
392
|
-
index;
|
|
393
397
|
key;
|
|
394
398
|
ext;
|
|
395
399
|
debug = false;
|
|
400
|
+
/** Reference to the gltf-transform Texture object, used to resolve the current image index at write time via imageIndexMap */
|
|
401
|
+
textureRef;
|
|
396
402
|
assignTo(obj) {
|
|
397
403
|
Object.assign(obj, this.ext);
|
|
398
404
|
}
|
|
399
|
-
constructor(doc, def, key, ext, debug) {
|
|
405
|
+
constructor(doc, def, key, ext, debug, textureRef) {
|
|
400
406
|
this.document = doc;
|
|
401
407
|
this.textureDefinition = def;
|
|
402
408
|
this.key = key;
|
|
403
409
|
this.ext = ext;
|
|
404
410
|
this.debug = debug;
|
|
405
|
-
this.
|
|
406
|
-
if (debug)
|
|
407
|
-
|
|
411
|
+
this.textureRef = textureRef;
|
|
412
|
+
if (debug) {
|
|
413
|
+
const index = this.tryGetSourceIndex(this.textureDefinition);
|
|
414
|
+
console.log(index, this.textureDefinition);
|
|
415
|
+
}
|
|
408
416
|
}
|
|
409
417
|
write(ctx) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
const imageIndex =
|
|
418
|
+
// Resolve the current image index from the gltf-transform graph reference.
|
|
419
|
+
// This is stable even after dedup/prune operations that re-index images.
|
|
420
|
+
const imageIndex = ctx.imageIndexMap.get(this.textureRef);
|
|
421
|
+
testAssert(imageIndex !== undefined || this.key === "EXT_texture_exr", `imageIndexMap missing texture ref for "${this.key}": ${this.textureRef.getName() || "<unnamed>"}`);
|
|
413
422
|
if (imageIndex === undefined) {
|
|
414
|
-
|
|
423
|
+
if (this.debug) {
|
|
424
|
+
console.warn("WARN: failed to resolve image index for texture via imageIndexMap:", this.key, this.textureRef.getName() || "<unnamed>");
|
|
425
|
+
}
|
|
426
|
+
return;
|
|
415
427
|
}
|
|
428
|
+
let foundTexture = false;
|
|
429
|
+
const textureDefs = ctx.jsonDoc.json.textures || [];
|
|
416
430
|
textureDefs?.forEach((textureDef, i) => {
|
|
417
431
|
if (foundTexture)
|
|
418
432
|
return;
|
|
419
433
|
const textureImageIndex = this.tryGetSourceIndex(textureDef);
|
|
420
434
|
if (imageIndex === textureImageIndex) {
|
|
421
|
-
|
|
422
|
-
|
|
435
|
+
foundTexture = true;
|
|
436
|
+
if (!textureDef.extensions?.[this.key]) {
|
|
437
|
+
// assign texture extension
|
|
423
438
|
textureDef.extensions = textureDef.extensions || {};
|
|
424
|
-
foundTexture = true;
|
|
425
439
|
if (this.debug)
|
|
426
440
|
console.log("Re-Assign extension:", this.key, "at", i);
|
|
427
441
|
const newExt = { ...this.ext };
|
|
@@ -429,20 +443,16 @@ class TextureHandler {
|
|
|
429
443
|
newExt.source = imageIndex;
|
|
430
444
|
textureDef.extensions[this.key] = newExt;
|
|
431
445
|
}
|
|
446
|
+
// else: extension already written by another handler for the same image
|
|
447
|
+
// (happens when gltf-transform dedup merges texture defs that shared the same source)
|
|
432
448
|
}
|
|
433
449
|
});
|
|
450
|
+
testAssert(foundTexture || this.key === "EXT_texture_exr", `failed to match texture for extension "${this.key}", imageIndex=${imageIndex}, textures=${textureDefs.length}, name=${this.textureRef.getName() || "<unnamed>"}, type=${this.textureRef.getMimeType()}`);
|
|
434
451
|
if (foundTexture === false) {
|
|
435
|
-
if (this.
|
|
436
|
-
console.warn("WARN: failed to re-assign extension:", this.key,
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
// .getRoot()
|
|
440
|
-
// .listTextures()
|
|
441
|
-
// .forEach((texture, index) => {
|
|
442
|
-
// if (foundTexture) return;
|
|
443
|
-
// if (!texture.getExtension(this.key)) return;
|
|
444
|
-
// const imageIndex = ctx.imageIndexMap.get(texture);
|
|
445
|
-
// });
|
|
452
|
+
if (this.debug) {
|
|
453
|
+
console.warn("WARN: failed to re-assign extension:", this.key, "imageIndex", imageIndex, textureDefs.length, this.textureRef.getName() || "<unnamed>", this.textureDefinition);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
446
456
|
}
|
|
447
457
|
tryGetSourceIndex(def) {
|
|
448
458
|
let index = def.source;
|
|
@@ -857,7 +867,8 @@ class TextureIndexResolver extends PointerResolver {
|
|
|
857
867
|
resolve(context) {
|
|
858
868
|
const imgIndex = context.imageIndexMap.get(this.inputObject);
|
|
859
869
|
if (imgIndex === undefined) {
|
|
860
|
-
|
|
870
|
+
testAssert(false, `imageIndexMap missing texture: ${this.inputObject.getName() || "<unnamed>"}`);
|
|
871
|
+
console.error("ERR: image is missing");
|
|
861
872
|
return -1;
|
|
862
873
|
}
|
|
863
874
|
// ensure we have a texture array
|
|
@@ -878,11 +889,18 @@ class TextureIndexResolver extends PointerResolver {
|
|
|
878
889
|
// create a new texture def entry
|
|
879
890
|
if (this.debug)
|
|
880
891
|
console.log("Could not find texture, creating a new one: " + this._debugName);
|
|
881
|
-
|
|
892
|
+
// Remove settings-only extensions that are consumed during processing and should not appear in the output.
|
|
893
|
+
let extensions = this.inputDefinition.extensions ? { ...this.inputDefinition.extensions } : undefined;
|
|
894
|
+
if (extensions) {
|
|
895
|
+
delete extensions[NEEDLE_progressive_texture_settings.EXTENSION_NAME];
|
|
896
|
+
if (Object.keys(extensions).length === 0)
|
|
897
|
+
extensions = undefined;
|
|
898
|
+
}
|
|
899
|
+
const hasExtensionWithSource = extensions && Object.keys(extensions).some(key => extensions[key]?.["source"] !== undefined);
|
|
882
900
|
const textureDef = {
|
|
883
901
|
source: hasExtensionWithSource ? undefined : imgIndex,
|
|
884
902
|
sampler: this.findOrCreateSampler(context.jsonDoc.json),
|
|
885
|
-
extensions:
|
|
903
|
+
extensions: extensions,
|
|
886
904
|
extras: this.inputDefinition.extras,
|
|
887
905
|
};
|
|
888
906
|
context.jsonDoc.json.textures.push(textureDef);
|
|
@@ -9,6 +9,7 @@ import { ALL_EXTENSIONS as NEEDLE_EXTENSIONS, NEEDLE_compression_texture, NEEDLE
|
|
|
9
9
|
import { isLOD, isMeshLOD, needle_animation_transform, needle_asset, needle_mesh_transform, needle_texture_transform, } from '../transforms/index.js';
|
|
10
10
|
import { getOutputPath, getVersion, ioTryReadWithMissingResources, writeNodeIO } from "../utils/index.js";
|
|
11
11
|
import { addToCache, getHash, tryGetFromCache, } from "../cache/index.js";
|
|
12
|
+
import { TestAssertionError } from '../utils/test-assert.js';
|
|
12
13
|
/** Compress a glTF file
|
|
13
14
|
*/
|
|
14
15
|
export async function packGLTF(inputFile, outputFile, options) {
|
|
@@ -64,8 +65,13 @@ export async function packGLTF(inputFile, outputFile, options) {
|
|
|
64
65
|
'meshopt.encoder': MeshoptEncoder,
|
|
65
66
|
});
|
|
66
67
|
const document = await ioTryReadWithMissingResources(io, inputFile); // await io.read(inputFile);
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
if (options.logger) {
|
|
69
|
+
document.setLogger(options.logger);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
/** @ts-ignore */
|
|
73
|
+
document.getLogger().verbosity = options.verbose ? Verbosity.DEBUG : options.debug ? Verbosity.INFO : Verbosity.WARN;
|
|
74
|
+
}
|
|
69
75
|
let totalGPUTextureMemory = 0;
|
|
70
76
|
/** @type {Array<import('@gltf-transform/core').Transform>} */
|
|
71
77
|
const transforms = [
|
|
@@ -128,7 +134,10 @@ export async function packGLTF(inputFile, outputFile, options) {
|
|
|
128
134
|
return true;
|
|
129
135
|
}
|
|
130
136
|
catch (err) {
|
|
131
|
-
|
|
137
|
+
if (err instanceof TestAssertionError)
|
|
138
|
+
throw err;
|
|
139
|
+
const shortedStackTrace = err instanceof Error && err.stack ? err.stack.split('\n').slice(0, 2).join('\n') : '';
|
|
140
|
+
logger.error(`Packing of "${path.basename(inputFile)}" using version ${getVersion()} failed with error:\n${err.message}\n${shortedStackTrace}`);
|
|
132
141
|
if (debug)
|
|
133
142
|
throw err;
|
|
134
143
|
return false;
|
|
@@ -13,6 +13,7 @@ import { needle_asset, writeNeedleAsset } from './needle_asset.js';
|
|
|
13
13
|
import { MeshoptDecoder, MeshoptEncoder, MeshoptSimplifier } from 'meshoptimizer';
|
|
14
14
|
import { compressPrimitive, determineMeshCompression } from './needle_mesh_transform.js';
|
|
15
15
|
import { calculateMeshDensity, getMeshInformation } from "../utils/mesh.js";
|
|
16
|
+
import { TestAssertionError } from '../utils/test-assert.js';
|
|
16
17
|
export async function make_progressive(opts) {
|
|
17
18
|
const file = opts.path;
|
|
18
19
|
let success = true;
|
|
@@ -78,9 +79,14 @@ async function onProcess(file, opts) {
|
|
|
78
79
|
});
|
|
79
80
|
let document = await ioTryReadWithMissingResources(io, file); // await io.read(file);
|
|
80
81
|
if (document) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
if (opts.logger) {
|
|
83
|
+
document.setLogger(opts.logger);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
//@ts-ignore
|
|
87
|
+
document.getLogger().verbosity = (opts.debug || opts.verbose) ? Verbosity.DEBUG : Verbosity.WARN;
|
|
88
|
+
}
|
|
89
|
+
const logger = opts.logger || document.getLogger();
|
|
84
90
|
let smallesTextureSize = 128;
|
|
85
91
|
if (opts.config.usecase === "product") {
|
|
86
92
|
smallesTextureSize = 512;
|
|
@@ -120,6 +126,8 @@ async function onProcess(file, opts) {
|
|
|
120
126
|
}
|
|
121
127
|
}
|
|
122
128
|
catch (err) {
|
|
129
|
+
if (err instanceof TestAssertionError)
|
|
130
|
+
throw err;
|
|
123
131
|
console.log("ERR: failed to process file \"" + file + "\", Reason: " + err.message, "\nStack:\n" + err.stack);
|
|
124
132
|
return false;
|
|
125
133
|
}
|
|
@@ -151,6 +159,7 @@ export function make_progressive_textures(filePath, _options = TEXTURE_RESIZE_DE
|
|
|
151
159
|
return Promise.resolve();
|
|
152
160
|
}
|
|
153
161
|
let index = 0;
|
|
162
|
+
const textureHashCache = new Map();
|
|
154
163
|
for (const texture of doc.getRoot().listTextures()) {
|
|
155
164
|
const textureIndex = index++;
|
|
156
165
|
const name = texture.getName();
|
|
@@ -177,8 +186,10 @@ export function make_progressive_textures(filePath, _options = TEXTURE_RESIZE_DE
|
|
|
177
186
|
continue;
|
|
178
187
|
}
|
|
179
188
|
else {
|
|
189
|
+
if (!textureHashCache.has(texture))
|
|
190
|
+
textureHashCache.set(texture, getHash(texture));
|
|
180
191
|
settings = {
|
|
181
|
-
guid: generateGuid(
|
|
192
|
+
guid: generateGuid(textureHashCache.get(texture)),
|
|
182
193
|
maxSize: _options.size[0],
|
|
183
194
|
};
|
|
184
195
|
logger.debug(`[${NAME}] No settings found for texture[${index}] - will use default settings (maxSize: ${settings.maxSize}, guid: ${settings.guid})`);
|
|
@@ -213,7 +224,13 @@ export function make_progressive_textures(filePath, _options = TEXTURE_RESIZE_DE
|
|
|
213
224
|
logger.debug(`[${NAME}] Skipping, texture[${textureIndex}] is already smaller than the requested size: ${currentSize}px <= ${settings.maxSize}px`);
|
|
214
225
|
continue;
|
|
215
226
|
}
|
|
216
|
-
|
|
227
|
+
if (!settings.guid?.length) {
|
|
228
|
+
if (!textureHashCache.has(texture))
|
|
229
|
+
textureHashCache.set(texture, getHash(texture));
|
|
230
|
+
const hash = textureHashCache.get(texture);
|
|
231
|
+
settings.guid = generateGuid(hash);
|
|
232
|
+
}
|
|
233
|
+
const textureGuid = settings.guid;
|
|
217
234
|
/** This is the size of the texture that is embedded in the glTF. No LOD should be smaller than this */
|
|
218
235
|
const maxSize = settings.maxSize;
|
|
219
236
|
const LOD_LEVEL = new Array();
|
|
@@ -360,7 +377,7 @@ async function createTextureLod(args, opts) {
|
|
|
360
377
|
// see https://linear.app/needle/issue/NE-4985
|
|
361
378
|
newMaterial.setAlphaMode("BLEND");
|
|
362
379
|
newMaterial.setBaseColorTexture(newTexture);
|
|
363
|
-
|
|
380
|
+
break;
|
|
364
381
|
}
|
|
365
382
|
if (slot === "specularColorTexture") {
|
|
366
383
|
logger.info("Pass-through KHR_materials_pbrSpecularGlossiness specularColorTexture");
|
|
@@ -368,7 +385,7 @@ async function createTextureLod(args, opts) {
|
|
|
368
385
|
const prob = ext.createSpecular();
|
|
369
386
|
prob.setSpecularColorTexture(newTexture);
|
|
370
387
|
newMaterial.setExtension(KHRMaterialsSpecular.EXTENSION_NAME, prob);
|
|
371
|
-
|
|
388
|
+
break;
|
|
372
389
|
}
|
|
373
390
|
else if (slot === "specularTexture") {
|
|
374
391
|
logger.info("Pass-through KHR_materials_specular specularTexture");
|
|
@@ -376,7 +393,7 @@ async function createTextureLod(args, opts) {
|
|
|
376
393
|
const prob = ext.createSpecular();
|
|
377
394
|
prob.setSpecularTexture(newTexture);
|
|
378
395
|
newMaterial.setExtension(KHRMaterialsSpecular.EXTENSION_NAME, prob);
|
|
379
|
-
|
|
396
|
+
break;
|
|
380
397
|
}
|
|
381
398
|
logger.warn(`WARN: Unknown texture slot: ${slot} for texture ${textureIndex} → can not load progressively (all slots: ${slots.join(", ")})`);
|
|
382
399
|
return null;
|
|
@@ -524,7 +541,7 @@ async function resizeTexture(options, texture, logger, uri, slots) {
|
|
|
524
541
|
}
|
|
525
542
|
dstWidth = Math.floor(dstWidth);
|
|
526
543
|
dstHeight = Math.floor(dstHeight);
|
|
527
|
-
logger.info(`→ Resize texture (${uri || texture.getName() || slots
|
|
544
|
+
logger.info(`→ Resize texture (${uri || texture.getName() || slots?.join(", ")}) from ${srcWidth}x${srcHeight} to ${dstWidth}x${dstHeight}px`);
|
|
528
545
|
// https://sharp.pixelplumbing.com/api-resize
|
|
529
546
|
const buffer = await sharp(texture.getImage())
|
|
530
547
|
.resize(dstWidth, dstHeight, {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare class TestAssertionError extends Error {
|
|
2
|
+
constructor(message: string);
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Lightweight assertion that throws under vitest and is a no-op in production.
|
|
6
|
+
* Use as a one-liner in pipeline code to catch regressions during tests.
|
|
7
|
+
*/
|
|
8
|
+
export declare function testAssert(condition: boolean, message: string): void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const IS_TEST = process.env.VITEST === 'true';
|
|
2
|
+
export class TestAssertionError extends Error {
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = 'TestAssertionError';
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Lightweight assertion that throws under vitest and is a no-op in production.
|
|
10
|
+
* Use as a one-liner in pipeline code to catch regressions during tests.
|
|
11
|
+
*/
|
|
12
|
+
export function testAssert(condition, message) {
|
|
13
|
+
if (condition)
|
|
14
|
+
return;
|
|
15
|
+
if (IS_TEST) {
|
|
16
|
+
throw new TestAssertionError(`Assertion failed: ${message}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "2.
|
|
1
|
+
export declare const version = "2.15.0-next.0c5bc39";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = "2.
|
|
1
|
+
export const version = "2.15.0-next.0c5bc39";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needle-tools/gltf-build-pipeline",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.15.0-next.0c5bc39",
|
|
4
4
|
"description": "Pipeline and tools for optimizing gltf files using gltf-transform and compression settings within glTF extensions",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
"gltf-build-pipeline": "dist/cli/index.js",
|
|
19
19
|
"needle-gltf": "dist/cli/index.js"
|
|
20
20
|
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"scripts",
|
|
24
|
+
"README.md",
|
|
25
|
+
"CHANGELOG.md"
|
|
26
|
+
],
|
|
21
27
|
"imports": {
|
|
22
28
|
"#package.json": "./package.json"
|
|
23
29
|
},
|
|
@@ -33,12 +39,18 @@
|
|
|
33
39
|
"transform:make-progressive": "node scripts/make-progressive.mjs",
|
|
34
40
|
"transform:pack-gltf": "node --no-experimental-fetch scripts/pack-gltf.mjs",
|
|
35
41
|
"pack-gltf": "node --no-experimental-fetch scripts/pack-gltf.mjs",
|
|
36
|
-
"dev:pack-gltf": "npm run compile && node scripts/pack-gltf.mjs"
|
|
42
|
+
"dev:pack-gltf": "npm run compile && node scripts/pack-gltf.mjs",
|
|
43
|
+
"test": "tsx tests/utils/download-fixtures.ts && vitest run",
|
|
44
|
+
"test:watch": "vitest",
|
|
45
|
+
"test:setup": "tsx tests/utils/download-fixtures.ts"
|
|
37
46
|
},
|
|
38
47
|
"devDependencies": {
|
|
39
|
-
"@types/node": "^
|
|
48
|
+
"@types/node": "^22.19.15",
|
|
49
|
+
"gltf-validator": "^2.0.0-dev.3.9",
|
|
40
50
|
"npm-watch": "^0.13.0",
|
|
41
|
-
"
|
|
51
|
+
"tsx": "^4.19.0",
|
|
52
|
+
"typescript": "^4.9.5",
|
|
53
|
+
"vitest": "^3.1.1"
|
|
42
54
|
},
|
|
43
55
|
"optionalDependencies": {
|
|
44
56
|
"@img/sharp-darwin-arm64": "^0.33.4",
|
package/tsconfig.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ESNext",
|
|
4
|
-
"rootDir": "src",
|
|
5
|
-
"outDir": "dist",
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"moduleResolution": "NodeNext",
|
|
8
|
-
"module": "NodeNext",
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"resolveJsonModule": true,
|
|
12
|
-
"lib": [
|
|
13
|
-
"ESNext",
|
|
14
|
-
"DOM"
|
|
15
|
-
],
|
|
16
|
-
},
|
|
17
|
-
"include": [
|
|
18
|
-
"src/index.ts",
|
|
19
|
-
]
|
|
20
|
-
}
|