tiny-essentials 1.29.1 → 1.29.2
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/changelog/1/29/2.md +82 -0
- package/dist/v1/TinyBasicsEs.min.js +1 -1
- package/dist/v1/TinyEssentials.min.js +1 -1
- package/dist/v1/TinyFetchLoader.min.js +1 -0
- package/dist/v1/TinyImageLoader.min.js +1 -0
- package/dist/v1/TinyMediaCache.min.js +1 -0
- package/dist/v1/TinyMediaLoader.min.js +1 -0
- package/dist/v1/basics/index.cjs +5 -0
- package/dist/v1/basics/index.d.mts +2 -1
- package/dist/v1/basics/index.d.mts.map +1 -1
- package/dist/v1/basics/index.mjs +2 -1
- package/dist/v1/basics/media/youtube.cjs +275 -0
- package/dist/v1/basics/media/youtube.d.mts +107 -0
- package/dist/v1/basics/media/youtube.d.mts.map +1 -0
- package/dist/v1/basics/media/youtube.mjs +214 -0
- package/dist/v1/index.cjs +13 -0
- package/dist/v1/index.d.mts +6 -1
- package/dist/v1/index.d.mts.map +1 -1
- package/dist/v1/index.mjs +7 -2
- package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.cjs +0 -1
- package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.d.mts +0 -1
- package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.d.mts.map +1 -1
- package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.mjs +0 -1
- package/dist/v1/libs/fs/plugins/OPFS/index.cjs +0 -8
- package/dist/v1/libs/fs/plugins/OPFS/index.d.mts +0 -8
- package/dist/v1/libs/fs/plugins/OPFS/index.d.mts.map +1 -1
- package/dist/v1/libs/fs/plugins/OPFS/index.mjs +0 -8
- package/dist/v1/libs/html/TinyHtml.cjs +1 -1
- package/dist/v1/libs/html/TinyHtml.d.mts +2 -2
- package/dist/v1/libs/html/TinyHtml.d.mts.map +1 -1
- package/dist/v1/libs/html/TinyHtml.mjs +1 -1
- package/dist/v1/libs/html/loader/TinyMediaLoader.cjs +1999 -0
- package/dist/v1/libs/html/loader/TinyMediaLoader.d.mts +999 -0
- package/dist/v1/libs/html/loader/TinyMediaLoader.d.mts.map +1 -0
- package/dist/v1/libs/html/loader/TinyMediaLoader.mjs +1852 -0
- package/dist/v1/libs/html/loader/beta/formats/TinyAudioLoader.cjs +77 -0
- package/dist/v1/libs/html/loader/beta/formats/TinyAudioLoader.d.mts +103 -0
- package/dist/v1/libs/html/loader/beta/formats/TinyAudioLoader.d.mts.map +1 -0
- package/dist/v1/libs/html/loader/beta/formats/TinyAudioLoader.mjs +67 -0
- package/dist/v1/libs/html/loader/beta/formats/TinyContentLoader.cjs +630 -0
- package/dist/v1/libs/html/loader/beta/formats/TinyContentLoader.d.mts +138 -0
- package/dist/v1/libs/html/loader/beta/formats/TinyContentLoader.d.mts.map +1 -0
- package/dist/v1/libs/html/loader/beta/formats/TinyContentLoader.mjs +576 -0
- package/dist/v1/libs/html/loader/beta/formats/TinyVideoLoader.cjs +70 -0
- package/dist/v1/libs/html/loader/beta/formats/TinyVideoLoader.d.mts +100 -0
- package/dist/v1/libs/html/loader/beta/formats/TinyVideoLoader.d.mts.map +1 -0
- package/dist/v1/libs/html/loader/beta/formats/TinyVideoLoader.mjs +60 -0
- package/dist/v1/libs/html/loader/beta/probe/TinyMediaProbe.cjs +946 -0
- package/dist/v1/libs/html/loader/beta/probe/TinyMediaProbe.d.mts +67 -0
- package/dist/v1/libs/html/loader/beta/probe/TinyMediaProbe.d.mts.map +1 -0
- package/dist/v1/libs/html/loader/beta/probe/TinyMediaProbe.mjs +896 -0
- package/dist/v1/libs/html/loader/formats/TinyFetchLoader.cjs +225 -0
- package/dist/v1/libs/html/loader/formats/TinyFetchLoader.d.mts +149 -0
- package/dist/v1/libs/html/loader/formats/TinyFetchLoader.d.mts.map +1 -0
- package/dist/v1/libs/html/loader/formats/TinyFetchLoader.mjs +197 -0
- package/dist/v1/libs/html/loader/formats/TinyImageLoader.cjs +1454 -0
- package/dist/v1/libs/html/loader/formats/TinyImageLoader.d.mts +200 -0
- package/dist/v1/libs/html/loader/formats/TinyImageLoader.d.mts.map +1 -0
- package/dist/v1/libs/html/loader/formats/TinyImageLoader.mjs +1317 -0
- package/dist/v1/libs/html/loader/probe/TinyImageProbe.cjs +668 -0
- package/dist/v1/libs/html/loader/probe/TinyImageProbe.d.mts +83 -0
- package/dist/v1/libs/html/loader/probe/TinyImageProbe.d.mts.map +1 -0
- package/dist/v1/libs/html/loader/probe/TinyImageProbe.mjs +626 -0
- package/dist/v1/libs/html/loader/utils/TinyBufferReader.cjs +277 -0
- package/dist/v1/libs/html/loader/utils/TinyBufferReader.d.mts +118 -0
- package/dist/v1/libs/html/loader/utils/TinyBufferReader.d.mts.map +1 -0
- package/dist/v1/libs/html/loader/utils/TinyBufferReader.mjs +247 -0
- package/dist/v1/libs/html/loader/utils/TinyIsoBox.cjs +128 -0
- package/dist/v1/libs/html/loader/utils/TinyIsoBox.d.mts +49 -0
- package/dist/v1/libs/html/loader/utils/TinyIsoBox.d.mts.map +1 -0
- package/dist/v1/libs/html/loader/utils/TinyIsoBox.mjs +116 -0
- package/dist/v1/libs/html/loader/utils/TinyMediaCache.cjs +796 -0
- package/dist/v1/libs/html/loader/utils/TinyMediaCache.d.mts +354 -0
- package/dist/v1/libs/html/loader/utils/TinyMediaCache.d.mts.map +1 -0
- package/dist/v1/libs/html/loader/utils/TinyMediaCache.mjs +734 -0
- package/dist/v1/libs/html/loader/utils/TinyMediaMirror.cjs +302 -0
- package/dist/v1/libs/html/loader/utils/TinyMediaMirror.d.mts +256 -0
- package/dist/v1/libs/html/loader/utils/TinyMediaMirror.d.mts.map +1 -0
- package/dist/v1/libs/html/loader/utils/TinyMediaMirror.mjs +280 -0
- package/dist/v1/libs/html/loader/utils/TinyMediaProgress.cjs +194 -0
- package/dist/v1/libs/html/loader/utils/TinyMediaProgress.d.mts +138 -0
- package/dist/v1/libs/html/loader/utils/TinyMediaProgress.d.mts.map +1 -0
- package/dist/v1/libs/html/loader/utils/TinyMediaProgress.mjs +175 -0
- package/dist/v1/libs/tools/TinyPkgExportValidator.cjs +359 -55
- package/dist/v1/libs/tools/TinyPkgExportValidator.d.mts +64 -6
- package/dist/v1/libs/tools/TinyPkgExportValidator.d.mts.map +1 -1
- package/dist/v1/libs/tools/TinyPkgExportValidator.mjs +320 -57
- package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.cjs +0 -1
- package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.d.mts +0 -1
- package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.d.mts.map +1 -1
- package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.mjs +0 -1
- package/dist/v1/webTemplates/bootstrap/5.3/scss/background/_background-grid.scss +15 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/components/buttons/_buttons-contrast.scss +208 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/components/buttons/_buttons-ghost.scss +89 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/components/icon/_cube-icon.scss +65 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/components/icon/_sphere-pulse.scss +39 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_badges.scss +90 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_bootstrap-overrides.scss +495 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_buttons.scss +390 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_colors.scss +213 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_effects.scss +153 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_forms-tones.scss +69 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_forms.scss +323 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_global.scss +31 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_links.scss +47 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_tables.scss +25 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_theme.scss +21 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_tokens.scss +161 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_utilities.scss +81 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_variables.scss +63 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/plugins/_form-tone-mixins.scss +236 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/plugins/_sizing.scss +68 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/plugins/_tone-mixins.scss +392 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/plugins/_typography.scss +112 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/plugins/background/_tiny_gradient_1.scss +131 -0
- package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/plugins/colors/_pink.scss +47 -0
- package/docs/v1/Exports.md +33 -2
- package/docs/v1/README.md +9 -0
- package/docs/v1/basics/youtube.md +204 -0
- package/docs/v1/libs/html/loader/TinyFetchLoader.md +114 -0
- package/docs/v1/libs/html/loader/TinyImageLoader.md +141 -0
- package/docs/v1/libs/html/loader/TinyMediaCache.md +166 -0
- package/docs/v1/libs/html/loader/TinyMediaLoader.md +300 -0
- package/docs/v1/libs/tools/TinyPkgExportValidator.md +55 -0
- package/docs/v1/webTemplates/bootstrap/5.3/DeepStrap.md +177 -0
- package/package.json +244 -8
- /package/dist/v1/webTemplates/bootstrap/5.3/scss/input/{Placeholder-Colors-Fix.scss → _placeholder-colors-fix.scss} +0 -0
- /package/dist/v1/webTemplates/bootstrap/5.3/scss/spacing/{Spacing-Plus.scss → _spacing-plus.scss} +0 -0
|
@@ -23,17 +23,47 @@ var path = require('path');
|
|
|
23
23
|
/**
|
|
24
24
|
* @typedef {Object} DefaultMessages
|
|
25
25
|
* @property {string} header
|
|
26
|
-
* @property {string}
|
|
27
|
-
* @property {string}
|
|
28
|
-
* @property {string}
|
|
29
|
-
* @property {string}
|
|
30
|
-
* @property {string}
|
|
31
|
-
* @property {string}
|
|
32
|
-
* @property {string}
|
|
33
|
-
* @property {string}
|
|
34
|
-
* @property {string}
|
|
35
|
-
* @property {string}
|
|
36
|
-
* @property {string}
|
|
26
|
+
* @property {string} divider
|
|
27
|
+
* @property {string} itemValid
|
|
28
|
+
* @property {string} itemInvalid
|
|
29
|
+
* @property {string} itemMissing
|
|
30
|
+
* @property {string} itemSkipped
|
|
31
|
+
* @property {string} itemPattern
|
|
32
|
+
* @property {string} itemInvalidTarget
|
|
33
|
+
* @property {string} successHeader
|
|
34
|
+
* @property {string} failureHeader
|
|
35
|
+
* @property {string} errorLoad
|
|
36
|
+
* @property {string} noExports
|
|
37
|
+
* @property {string} errorNotFound
|
|
38
|
+
* @property {string} errorParse
|
|
39
|
+
* @property {string} errorUnexpected
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @typedef {Object} LogContext
|
|
44
|
+
* @property {string} [projectName] - The project name injected automatically.
|
|
45
|
+
* @property {string} [path] - The dotted context path of the export.
|
|
46
|
+
* @property {string} [errorPath] - The raw target string from package.json.
|
|
47
|
+
* @property {string} [target] - The invalid target value.
|
|
48
|
+
* @property {string} [reason] - The machine-readable failure reason.
|
|
49
|
+
* @property {string} [pattern] - The wildcard pattern that matched.
|
|
50
|
+
* @property {string} [message] - A generic message payload.
|
|
51
|
+
* @property {number} [errorCount] - The number of failures found.
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The kind of target that was validated.
|
|
56
|
+
* @typedef {'file'|'pattern'|'null'|'invalid'} ExportTargetKind
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The validation result of a single export target.
|
|
61
|
+
* @typedef {Object} ExportTargetResult
|
|
62
|
+
* @property {string} path - The dotted context path (e.g. "exports -> . -> import").
|
|
63
|
+
* @property {boolean} valid - Whether the target resolves to an existing file.
|
|
64
|
+
* @property {ExportTargetKind} [kind] - The kind of target that was validated.
|
|
65
|
+
* @property {string} [errorPath] - The raw target string declared in package.json.
|
|
66
|
+
* @property {string} [reason] - A short machine-readable reason code for failures.
|
|
37
67
|
*/
|
|
38
68
|
|
|
39
69
|
/**
|
|
@@ -47,6 +77,9 @@ const DEFAULT_MESSAGES = {
|
|
|
47
77
|
itemValid: ` [✔] {path}`,
|
|
48
78
|
itemInvalid: ` [✘] {path}`,
|
|
49
79
|
itemMissing: ` Missing: {errorPath}`,
|
|
80
|
+
itemSkipped: ` [-] {path} (excluded by null target)`,
|
|
81
|
+
itemPattern: ` [✔] {path} (pattern: {pattern})`,
|
|
82
|
+
itemInvalidTarget: ` Invalid target: {target} ({reason})`,
|
|
50
83
|
successHeader: `SUCCESS: All exports are correctly mapped.`,
|
|
51
84
|
failureHeader: `FAILURE: {errorCount} export(s) are missing or invalid.`,
|
|
52
85
|
errorLoad: `Error: package.json not loaded in the current directory.`,
|
|
@@ -110,9 +143,10 @@ class TinyPkgExportValidator {
|
|
|
110
143
|
}
|
|
111
144
|
|
|
112
145
|
// 3. Validate that all values are strings
|
|
146
|
+
const colorRecord = /** @type {Record<string, string>} */ (newColors);
|
|
147
|
+
|
|
113
148
|
for (const key of originalKeys) {
|
|
114
|
-
|
|
115
|
-
if (typeof newColors[key] !== 'string') {
|
|
149
|
+
if (typeof colorRecord[key] !== 'string') {
|
|
116
150
|
throw new TypeError(`The value for key "${key}" must be a string.`);
|
|
117
151
|
}
|
|
118
152
|
}
|
|
@@ -132,7 +166,7 @@ class TinyPkgExportValidator {
|
|
|
132
166
|
/** @type {string} */
|
|
133
167
|
#rootDir;
|
|
134
168
|
|
|
135
|
-
/** @type {
|
|
169
|
+
/** @type {ExportTargetResult[]} */
|
|
136
170
|
#results;
|
|
137
171
|
|
|
138
172
|
/** @type {boolean} */
|
|
@@ -231,9 +265,10 @@ class TinyPkgExportValidator {
|
|
|
231
265
|
}
|
|
232
266
|
|
|
233
267
|
// Ensure all required keys from DefaultMessages are present and are strings
|
|
268
|
+
const messages = /** @type {Record<string, unknown>} */ (options.messages);
|
|
269
|
+
|
|
234
270
|
for (const key of MESSAGE_KEYS) {
|
|
235
|
-
|
|
236
|
-
if (typeof options.messages[key] !== 'string') {
|
|
271
|
+
if (typeof messages[key] !== 'string') {
|
|
237
272
|
throw new TypeError(`The "options.messages.${key}" property must be a string.`);
|
|
238
273
|
}
|
|
239
274
|
}
|
|
@@ -242,8 +277,9 @@ class TinyPkgExportValidator {
|
|
|
242
277
|
|
|
243
278
|
/**
|
|
244
279
|
* Internal helper to apply template replacements.
|
|
280
|
+
*
|
|
245
281
|
* @param {string} template - The message template string.
|
|
246
|
-
* @param {
|
|
282
|
+
* @param {LogContext} context - Data for placeholders.
|
|
247
283
|
* @returns {string} The processed string.
|
|
248
284
|
* @throws {TypeError} If template is not a string or context is not an object.
|
|
249
285
|
*/
|
|
@@ -255,17 +291,21 @@ class TinyPkgExportValidator {
|
|
|
255
291
|
throw new TypeError('The context must be a non-null object.');
|
|
256
292
|
}
|
|
257
293
|
|
|
294
|
+
const values = /** @type {Record<string, unknown>} */ (context);
|
|
295
|
+
|
|
258
296
|
return template.replace(/{(\w+)}/g, (match, key) => {
|
|
259
|
-
|
|
260
|
-
return
|
|
297
|
+
const value = values[key];
|
|
298
|
+
return value !== undefined ? String(value) : match;
|
|
261
299
|
});
|
|
262
300
|
}
|
|
263
301
|
|
|
264
302
|
/**
|
|
265
303
|
* Internal helper to handle console output, coloring, and silent mode.
|
|
304
|
+
*
|
|
266
305
|
* @param {'error'|'warning'|'success'|'info'|'dim'|'cyan'} type - The log type.
|
|
267
306
|
* @param {string} templateKey - The key in the messages object.
|
|
268
|
-
* @param {
|
|
307
|
+
* @param {LogContext} [context={}] - Data for the template.
|
|
308
|
+
* @returns {void}
|
|
269
309
|
* @throws {TypeError} If arguments do not match required types or if type is invalid.
|
|
270
310
|
*/
|
|
271
311
|
#log(type, templateKey, context = {}) {
|
|
@@ -285,9 +325,8 @@ class TinyPkgExportValidator {
|
|
|
285
325
|
throw new TypeError('The context must be a non-null object.');
|
|
286
326
|
}
|
|
287
327
|
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
this.#messages[templateKey] || templateKey;
|
|
328
|
+
const messages = /** @type {Record<string, string>} */ (this.#messages);
|
|
329
|
+
const template = messages[templateKey] ?? templateKey;
|
|
291
330
|
const message = this.#applyTemplate(template, { ...context, projectName: this.#projectName });
|
|
292
331
|
|
|
293
332
|
switch (type) {
|
|
@@ -386,24 +425,30 @@ class TinyPkgExportValidator {
|
|
|
386
425
|
|
|
387
426
|
/**
|
|
388
427
|
* Executes the validation process.
|
|
389
|
-
*
|
|
428
|
+
*
|
|
429
|
+
* @returns {Promise<boolean>} True if all paths are valid, false otherwise.
|
|
430
|
+
* @throws {TypeError} If the "exports" field mixes subpath keys with condition keys.
|
|
390
431
|
*/
|
|
391
432
|
async validate() {
|
|
392
433
|
if (!this.#started) {
|
|
393
434
|
this.#log('error', 'errorLoad');
|
|
394
|
-
return
|
|
435
|
+
return false;
|
|
395
436
|
}
|
|
396
437
|
|
|
397
438
|
const exports = this.#packageData.exports;
|
|
398
439
|
|
|
399
|
-
if (
|
|
440
|
+
if (exports === undefined || exports === null) {
|
|
400
441
|
this.#log('warning', 'noExports');
|
|
401
442
|
return true;
|
|
402
443
|
}
|
|
403
444
|
|
|
404
445
|
this.#results = [];
|
|
446
|
+
|
|
405
447
|
try {
|
|
406
|
-
|
|
448
|
+
if (typeof exports === 'object' && !Array.isArray(exports)) {
|
|
449
|
+
this.#assertRootKeys(exports);
|
|
450
|
+
}
|
|
451
|
+
await this.#traverseExports(exports, 'exports', true);
|
|
407
452
|
} catch (error) {
|
|
408
453
|
if (error instanceof Error) {
|
|
409
454
|
if (error instanceof SyntaxError) {
|
|
@@ -416,39 +461,264 @@ class TinyPkgExportValidator {
|
|
|
416
461
|
}
|
|
417
462
|
throw error;
|
|
418
463
|
}
|
|
464
|
+
|
|
419
465
|
return this.#report();
|
|
420
466
|
}
|
|
421
467
|
|
|
422
468
|
/**
|
|
423
|
-
*
|
|
469
|
+
* Ensures the root "exports" object does not mix subpath keys with condition keys.
|
|
470
|
+
*
|
|
471
|
+
* @param {Record<string, unknown>} exportsObject - The root "exports" object.
|
|
472
|
+
* @returns {void}
|
|
473
|
+
* @throws {TypeError} If subpath keys and condition keys are mixed.
|
|
474
|
+
*/
|
|
475
|
+
#assertRootKeys(exportsObject) {
|
|
476
|
+
const keys = Object.keys(exportsObject);
|
|
477
|
+
const subpathCount = keys.filter((key) => key.startsWith('.')).length;
|
|
478
|
+
|
|
479
|
+
if (subpathCount === 0 || subpathCount === keys.length) return;
|
|
480
|
+
|
|
481
|
+
throw new TypeError(
|
|
482
|
+
'The "exports" field cannot mix subpath keys ("./x") with condition keys ("import").',
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Validates a single key of an exports object.
|
|
424
488
|
*
|
|
425
|
-
* @param {
|
|
426
|
-
* @param {
|
|
489
|
+
* @param {string} key - The object key to validate.
|
|
490
|
+
* @param {boolean} isRoot - Whether the key belongs to the root "exports" object.
|
|
491
|
+
* @returns {string|null} A reason code when invalid, or null when the key is valid.
|
|
492
|
+
*/
|
|
493
|
+
#getKeyError(key, isRoot) {
|
|
494
|
+
if (key.length === 0) return 'EMPTY_KEY';
|
|
495
|
+
|
|
496
|
+
const isSubpath = key === '.' || key.startsWith('./');
|
|
497
|
+
|
|
498
|
+
if (isSubpath) {
|
|
499
|
+
if (!isRoot) return 'NESTED_SUBPATH_KEY';
|
|
500
|
+
return null;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (key.startsWith('.')) return 'INVALID_SUBPATH_KEY';
|
|
504
|
+
if (key.includes(',') || key.includes('/') || key.includes('\\')) return 'INVALID_CONDITION';
|
|
505
|
+
|
|
506
|
+
return null;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Recursively traverses the exports tree.
|
|
511
|
+
*
|
|
512
|
+
* @param {unknown} node - The current node of the exports tree.
|
|
513
|
+
* @param {string} currentKey - The dotted context path used for reporting.
|
|
514
|
+
* @param {boolean} [isRoot=false] - Whether this node is the root "exports" value.
|
|
427
515
|
* @returns {Promise<void>}
|
|
428
|
-
* @throws {TypeError} If
|
|
516
|
+
* @throws {TypeError} If currentKey is not a string or node has an unsupported type.
|
|
429
517
|
*/
|
|
430
|
-
async #traverseExports(node, currentKey =
|
|
518
|
+
async #traverseExports(node, currentKey, isRoot = false) {
|
|
431
519
|
if (typeof currentKey !== 'string') {
|
|
432
520
|
throw new TypeError('The "currentKey" argument must be a string.');
|
|
433
521
|
}
|
|
434
522
|
|
|
523
|
+
// Rule: null is a valid target. It excludes a subpath from a broader pattern.
|
|
524
|
+
if (node === null) {
|
|
525
|
+
this.#results.push({ path: currentKey, valid: true, kind: 'null' });
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Rule: a string is a direct file target.
|
|
435
530
|
if (typeof node === 'string') {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
|
|
531
|
+
await this.#checkTarget(node, currentKey);
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Rule: an array is a fallback list of targets.
|
|
536
|
+
if (Array.isArray(node)) {
|
|
537
|
+
if (node.length === 0) {
|
|
538
|
+
this.#results.push({
|
|
539
|
+
path: currentKey,
|
|
540
|
+
valid: false,
|
|
541
|
+
kind: 'invalid',
|
|
542
|
+
reason: 'EMPTY_ARRAY',
|
|
543
|
+
});
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
for (let index = 0; index < node.length; index += 1) {
|
|
548
|
+
await this.#traverseExports(node[index], `${currentKey}[${index}]`);
|
|
549
|
+
}
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Rule: an object holds subpaths (root only) or conditions.
|
|
554
|
+
if (typeof node === 'object') {
|
|
555
|
+
const record = /** @type {Record<string, unknown>} */ (node);
|
|
556
|
+
const keys = Object.keys(record);
|
|
557
|
+
|
|
558
|
+
if (keys.length === 0) {
|
|
559
|
+
this.#results.push({
|
|
560
|
+
path: currentKey,
|
|
561
|
+
valid: false,
|
|
562
|
+
kind: 'invalid',
|
|
563
|
+
reason: 'EMPTY_OBJECT',
|
|
564
|
+
});
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
|
|
441
568
|
for (const key of keys) {
|
|
442
|
-
const
|
|
443
|
-
|
|
569
|
+
const keyError = this.#getKeyError(key, isRoot);
|
|
570
|
+
|
|
571
|
+
if (keyError !== null) {
|
|
572
|
+
this.#results.push({
|
|
573
|
+
path: `${currentKey} -> ${key}`,
|
|
574
|
+
valid: false,
|
|
575
|
+
kind: 'invalid',
|
|
576
|
+
errorPath: key,
|
|
577
|
+
reason: keyError,
|
|
578
|
+
});
|
|
579
|
+
continue;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
await this.#traverseExports(record[key], `${currentKey} -> ${key}`);
|
|
583
|
+
}
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
throw new TypeError('The "node" argument must be a string, an array, or a non-null object.');
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Validates a single string target and dispatches it to the correct checker.
|
|
592
|
+
*
|
|
593
|
+
* @param {string} target - The raw target string from package.json.
|
|
594
|
+
* @param {string} context - The dotted context path used for reporting.
|
|
595
|
+
* @returns {Promise<void>}
|
|
596
|
+
*/
|
|
597
|
+
async #checkTarget(target, context) {
|
|
598
|
+
const targetError = this.#getTargetError(target);
|
|
599
|
+
|
|
600
|
+
if (targetError !== null) {
|
|
601
|
+
this.#results.push({
|
|
602
|
+
path: context,
|
|
603
|
+
valid: false,
|
|
604
|
+
kind: 'invalid',
|
|
605
|
+
errorPath: target,
|
|
606
|
+
reason: targetError,
|
|
607
|
+
});
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
if (target.includes('*')) {
|
|
612
|
+
await this.#checkPatternTarget(target, context);
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
await this.#checkFileExists(target, context);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Applies the path rules documented by Node.js for export targets.
|
|
621
|
+
*
|
|
622
|
+
* @param {string} target - The raw target string from package.json.
|
|
623
|
+
* @returns {string|null} A reason code when invalid, or null when the target is valid.
|
|
624
|
+
*/
|
|
625
|
+
#getTargetError(target) {
|
|
626
|
+
if (target.length === 0) return 'EMPTY_TARGET';
|
|
627
|
+
if (target.includes('\\')) return 'INVALID_SEGMENT';
|
|
628
|
+
if (target.includes('?') || target.includes('#')) return 'INVALID_CHARACTER';
|
|
629
|
+
if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(target)) return 'URL_SCHEME_NOT_ALLOWED';
|
|
630
|
+
if (!target.startsWith('./')) return 'TARGET_NOT_RELATIVE';
|
|
631
|
+
if (target.includes('**')) return 'INVALID_PATTERN';
|
|
632
|
+
|
|
633
|
+
const segments = target.slice(2).split('/');
|
|
634
|
+
|
|
635
|
+
for (const segment of segments) {
|
|
636
|
+
const decoded = this.#safeDecode(segment).toLowerCase();
|
|
637
|
+
|
|
638
|
+
if (decoded.length === 0) return 'INVALID_SEGMENT';
|
|
639
|
+
if (decoded === '.' || decoded === '..' || decoded === 'node_modules') {
|
|
640
|
+
return 'INVALID_SEGMENT';
|
|
444
641
|
}
|
|
445
|
-
} else {
|
|
446
|
-
throw new TypeError('The "node" argument must be a string or a non-null object.');
|
|
447
642
|
}
|
|
643
|
+
|
|
644
|
+
return null;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Decodes a URI component without throwing on malformed input.
|
|
649
|
+
*
|
|
650
|
+
* @param {string} value - The value to decode.
|
|
651
|
+
* @returns {string} The decoded value, or the original value when decoding fails.
|
|
652
|
+
*/
|
|
653
|
+
#safeDecode(value) {
|
|
654
|
+
try {
|
|
655
|
+
return decodeURIComponent(value);
|
|
656
|
+
} catch {
|
|
657
|
+
return value;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Converts a subpath pattern into an anchored regular expression.
|
|
663
|
+
*
|
|
664
|
+
* @param {string} pattern - The file name pattern (e.g. "*.js").
|
|
665
|
+
* @returns {RegExp} The anchored regular expression.
|
|
666
|
+
*/
|
|
667
|
+
#patternToRegExp(pattern) {
|
|
668
|
+
const source = pattern
|
|
669
|
+
.split('*')
|
|
670
|
+
.map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
|
|
671
|
+
.join('.*');
|
|
672
|
+
|
|
673
|
+
return new RegExp(`^${source}$`);
|
|
448
674
|
}
|
|
449
675
|
|
|
450
676
|
/**
|
|
451
|
-
*
|
|
677
|
+
* Expands a wildcard target against the file system.
|
|
678
|
+
*
|
|
679
|
+
* @param {string} target - The raw target containing at least one "*".
|
|
680
|
+
* @param {string} context - The dotted context path used for reporting.
|
|
681
|
+
* @returns {Promise<void>}
|
|
682
|
+
*/
|
|
683
|
+
async #checkPatternTarget(target, context) {
|
|
684
|
+
const lastSlash = target.lastIndexOf('/');
|
|
685
|
+
const directory = lastSlash === 0 ? '.' : target.slice(0, lastSlash);
|
|
686
|
+
const filePattern = target.slice(lastSlash + 1);
|
|
687
|
+
|
|
688
|
+
// When the wildcard lives in a directory segment, fall back to the static prefix.
|
|
689
|
+
const staticDirectory = directory.includes('*')
|
|
690
|
+
? directory.slice(0, directory.indexOf('*')).replace(/\/[^/]*$/, '') || '.'
|
|
691
|
+
: directory;
|
|
692
|
+
|
|
693
|
+
let entries;
|
|
694
|
+
|
|
695
|
+
try {
|
|
696
|
+
entries = await promises.readdir(path.resolve(this.#rootDir, staticDirectory));
|
|
697
|
+
} catch {
|
|
698
|
+
this.#results.push({
|
|
699
|
+
path: context,
|
|
700
|
+
valid: false,
|
|
701
|
+
kind: 'invalid',
|
|
702
|
+
errorPath: target,
|
|
703
|
+
reason: 'DIRECTORY_NOT_FOUND',
|
|
704
|
+
});
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
const matcher = this.#patternToRegExp(filePattern);
|
|
709
|
+
const hasMatch = entries.some((entry) => matcher.test(entry));
|
|
710
|
+
|
|
711
|
+
this.#results.push({
|
|
712
|
+
path: context,
|
|
713
|
+
valid: hasMatch,
|
|
714
|
+
kind: hasMatch ? 'pattern' : 'invalid',
|
|
715
|
+
errorPath: target,
|
|
716
|
+
reason: hasMatch ? undefined : 'PATTERN_NO_MATCH',
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* Checks for the existence of a regular file in the file system.
|
|
452
722
|
*
|
|
453
723
|
* @param {string} relativePath - The relative path defined in package.json.
|
|
454
724
|
* @param {string} context - The key context for reporting purposes.
|
|
@@ -463,15 +733,31 @@ class TinyPkgExportValidator {
|
|
|
463
733
|
throw new TypeError('The "context" argument must be a string.');
|
|
464
734
|
}
|
|
465
735
|
|
|
466
|
-
|
|
467
|
-
const cleanPath = relativePath.replace(/\*/g, '');
|
|
468
|
-
const absolutePath = path.resolve(this.#rootDir, cleanPath);
|
|
736
|
+
const absolutePath = path.resolve(this.#rootDir, relativePath);
|
|
469
737
|
|
|
470
738
|
try {
|
|
471
|
-
await promises.
|
|
472
|
-
|
|
739
|
+
const stats = await promises.stat(absolutePath);
|
|
740
|
+
|
|
741
|
+
if (!stats.isFile()) {
|
|
742
|
+
this.#results.push({
|
|
743
|
+
path: context,
|
|
744
|
+
valid: false,
|
|
745
|
+
kind: 'invalid',
|
|
746
|
+
errorPath: relativePath,
|
|
747
|
+
reason: 'NOT_A_FILE',
|
|
748
|
+
});
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
this.#results.push({ path: context, valid: true, kind: 'file' });
|
|
473
753
|
} catch {
|
|
474
|
-
this.#results.push({
|
|
754
|
+
this.#results.push({
|
|
755
|
+
path: context,
|
|
756
|
+
valid: false,
|
|
757
|
+
kind: 'invalid',
|
|
758
|
+
errorPath: relativePath,
|
|
759
|
+
reason: 'FILE_NOT_FOUND',
|
|
760
|
+
});
|
|
475
761
|
}
|
|
476
762
|
}
|
|
477
763
|
|
|
@@ -486,13 +772,31 @@ class TinyPkgExportValidator {
|
|
|
486
772
|
let errorCount = 0;
|
|
487
773
|
|
|
488
774
|
for (const result of this.#results) {
|
|
775
|
+
if (result.kind === 'null') {
|
|
776
|
+
this.#log('dim', 'itemSkipped', { path: result.path });
|
|
777
|
+
continue;
|
|
778
|
+
}
|
|
779
|
+
|
|
489
780
|
if (result.valid) {
|
|
490
|
-
this.#log('success', '
|
|
491
|
-
|
|
492
|
-
|
|
781
|
+
this.#log('success', result.kind === 'pattern' ? 'itemPattern' : 'itemValid', {
|
|
782
|
+
path: result.path,
|
|
783
|
+
pattern: result.errorPath ?? '',
|
|
784
|
+
});
|
|
785
|
+
continue;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
this.#log('error', 'itemInvalid', { path: result.path });
|
|
789
|
+
|
|
790
|
+
if (result.reason === 'FILE_NOT_FOUND') {
|
|
493
791
|
this.#log('dim', 'itemMissing', { errorPath: result.errorPath });
|
|
494
|
-
|
|
792
|
+
} else {
|
|
793
|
+
this.#log('dim', 'itemInvalidTarget', {
|
|
794
|
+
target: result.errorPath ?? result.path,
|
|
795
|
+
reason: result.reason ?? 'UNKNOWN',
|
|
796
|
+
});
|
|
495
797
|
}
|
|
798
|
+
|
|
799
|
+
errorCount++;
|
|
496
800
|
}
|
|
497
801
|
|
|
498
802
|
this.#log('cyan', 'divider');
|
|
@@ -500,10 +804,10 @@ class TinyPkgExportValidator {
|
|
|
500
804
|
if (errorCount === 0) {
|
|
501
805
|
this.#log('success', 'successHeader');
|
|
502
806
|
return true;
|
|
503
|
-
} else {
|
|
504
|
-
this.#log('error', 'failureHeader', { errorCount });
|
|
505
|
-
return false;
|
|
506
807
|
}
|
|
808
|
+
|
|
809
|
+
this.#log('error', 'failureHeader', { errorCount });
|
|
810
|
+
return false;
|
|
507
811
|
}
|
|
508
812
|
}
|
|
509
813
|
|
|
@@ -44,6 +44,9 @@ export type DefaultMessages = {
|
|
|
44
44
|
itemValid: string;
|
|
45
45
|
itemInvalid: string;
|
|
46
46
|
itemMissing: string;
|
|
47
|
+
itemSkipped: string;
|
|
48
|
+
itemPattern: string;
|
|
49
|
+
itemInvalidTarget: string;
|
|
47
50
|
successHeader: string;
|
|
48
51
|
failureHeader: string;
|
|
49
52
|
errorLoad: string;
|
|
@@ -52,6 +55,63 @@ export type DefaultMessages = {
|
|
|
52
55
|
errorParse: string;
|
|
53
56
|
errorUnexpected: string;
|
|
54
57
|
};
|
|
58
|
+
export type LogContext = {
|
|
59
|
+
/**
|
|
60
|
+
* - The project name injected automatically.
|
|
61
|
+
*/
|
|
62
|
+
projectName?: string;
|
|
63
|
+
/**
|
|
64
|
+
* - The dotted context path of the export.
|
|
65
|
+
*/
|
|
66
|
+
path?: string;
|
|
67
|
+
/**
|
|
68
|
+
* - The raw target string from package.json.
|
|
69
|
+
*/
|
|
70
|
+
errorPath?: string;
|
|
71
|
+
/**
|
|
72
|
+
* - The invalid target value.
|
|
73
|
+
*/
|
|
74
|
+
target?: string;
|
|
75
|
+
/**
|
|
76
|
+
* - The machine-readable failure reason.
|
|
77
|
+
*/
|
|
78
|
+
reason?: string;
|
|
79
|
+
/**
|
|
80
|
+
* - The wildcard pattern that matched.
|
|
81
|
+
*/
|
|
82
|
+
pattern?: string;
|
|
83
|
+
/**
|
|
84
|
+
* - A generic message payload.
|
|
85
|
+
*/
|
|
86
|
+
message?: string;
|
|
87
|
+
/**
|
|
88
|
+
* - The number of failures found.
|
|
89
|
+
*/
|
|
90
|
+
errorCount?: number;
|
|
91
|
+
};
|
|
92
|
+
export type ExportTargetKind = 'file' | 'pattern' | 'null' | 'invalid';
|
|
93
|
+
export type ExportTargetResult = {
|
|
94
|
+
/**
|
|
95
|
+
* - The dotted context path (e.g. "exports -> . -> import").
|
|
96
|
+
*/
|
|
97
|
+
path: string;
|
|
98
|
+
/**
|
|
99
|
+
* - Whether the target resolves to an existing file.
|
|
100
|
+
*/
|
|
101
|
+
valid: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* - The kind of target that was validated.
|
|
104
|
+
*/
|
|
105
|
+
kind?: ExportTargetKind;
|
|
106
|
+
/**
|
|
107
|
+
* - The raw target string declared in package.json.
|
|
108
|
+
*/
|
|
109
|
+
errorPath?: string;
|
|
110
|
+
/**
|
|
111
|
+
* - A short machine-readable reason code for failures.
|
|
112
|
+
*/
|
|
113
|
+
reason?: string;
|
|
114
|
+
};
|
|
55
115
|
/**
|
|
56
116
|
* Class responsible for validating package exports.
|
|
57
117
|
* Implements state encapsulation, custom logging, and recursive search logic.
|
|
@@ -69,11 +129,7 @@ declare class TinyPkgExportValidator {
|
|
|
69
129
|
get packageData(): Record<string, any>;
|
|
70
130
|
get packageJsonPath(): string;
|
|
71
131
|
get rootDir(): string;
|
|
72
|
-
get results():
|
|
73
|
-
path: string;
|
|
74
|
-
valid: boolean;
|
|
75
|
-
errorPath?: string;
|
|
76
|
-
}[];
|
|
132
|
+
get results(): ExportTargetResult[];
|
|
77
133
|
get started(): boolean;
|
|
78
134
|
get projectName(): string;
|
|
79
135
|
get silent(): boolean;
|
|
@@ -110,7 +166,9 @@ declare class TinyPkgExportValidator {
|
|
|
110
166
|
start(): Promise<void>;
|
|
111
167
|
/**
|
|
112
168
|
* Executes the validation process.
|
|
113
|
-
*
|
|
169
|
+
*
|
|
170
|
+
* @returns {Promise<boolean>} True if all paths are valid, false otherwise.
|
|
171
|
+
* @throws {TypeError} If the "exports" field mixes subpath keys with condition keys.
|
|
114
172
|
*/
|
|
115
173
|
validate(): Promise<boolean>;
|
|
116
174
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TinyPkgExportValidator.d.mts","sourceRoot":"","sources":["../../../../src/v1/libs/tools/TinyPkgExportValidator.mjs"],"names":[],"mappings":"AAIG,YAAkB,aAAa,GAC/B;;;;IAAmB,KAAK,EAAb,MAAM,CACjB;;;;IAAmB,KAAK,EAAb,MAAM,CACjB;;;;IAAmB,GAAG,EAAX,MAAM,CACjB;;;;IAAmB,MAAM,EAAd,MAAM,CACjB;;;;IAAmB,IAAI,EAAZ,MAAM,CACjB;;;;IAAmB,GAAG,EAAX,MAAM,CACnB;CAAA,CAAA;AAGE,YAAkB,gBAAgB,GAClC;;;;IAAoB,WAAW,AAA/B,CACA,EADW,MAAM,CACjB;;;;IAAqB,MAAM,AAA3B,CACA,EADW,OAAO,CAClB;;;;IAA6B,QAAQ,AAArC,CACF,EADa,eAAe,CAC5B;CAAA,CAAA;AAGE,YAAkB,eAAe,GACjC;IAAmB,MAAM,EAAd,MAAM,CACjB;
|
|
1
|
+
{"version":3,"file":"TinyPkgExportValidator.d.mts","sourceRoot":"","sources":["../../../../src/v1/libs/tools/TinyPkgExportValidator.mjs"],"names":[],"mappings":"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"}
|