@ressjs/platform 0.6.0-experimental.0 → 0.6.0-rc.1
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/LICENSE +69 -0
- package/README.md +10 -82
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/registry/parse.d.ts +28 -0
- package/dist/registry/parse.js +37 -5
- package/dist/rules/request-headers.d.ts +5 -4
- package/dist/rules/request-headers.js +5 -5
- package/package.json +2 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
ress.js Proprietary License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 gabrielspisso. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This license applies to the ress.js packages (the "Software"), published on npm
|
|
6
|
+
under the @ressjs and @gzzy scopes, in every version released from 0.6.0-rc.0
|
|
7
|
+
onwards. Earlier versions were released under the MIT License and remain
|
|
8
|
+
available under those terms.
|
|
9
|
+
|
|
10
|
+
1. GRANT
|
|
11
|
+
Subject to this license, the Licensor grants you a worldwide, non-exclusive,
|
|
12
|
+
non-transferable, non-sublicensable, royalty-free license to install and use
|
|
13
|
+
the Software, as distributed by the Licensor, to build, run and deploy your
|
|
14
|
+
own applications and services, including commercial ones, and to charge your
|
|
15
|
+
own customers for them.
|
|
16
|
+
|
|
17
|
+
2. RESTRICTIONS
|
|
18
|
+
You may not:
|
|
19
|
+
a) fork, copy, or redistribute the Software, in whole or in part, except for
|
|
20
|
+
the portions that are necessarily included in the build output of your own
|
|
21
|
+
application in order to run it;
|
|
22
|
+
b) publish, distribute or make available a modified version of the Software
|
|
23
|
+
or any work derived from it. Modifications for your own internal use are
|
|
24
|
+
allowed, but they remain subject to this license;
|
|
25
|
+
c) use the Software, or any part of it, to build, offer or support a
|
|
26
|
+
framework, library, tool or service that competes with the Software;
|
|
27
|
+
d) sell, sublicense, rent or host the Software itself as a product or service
|
|
28
|
+
for third parties, as opposed to hosting your own application built with
|
|
29
|
+
it;
|
|
30
|
+
e) remove or alter copyright, license or attribution notices;
|
|
31
|
+
f) use the name "ress.js" or the Licensor's names or marks to endorse or
|
|
32
|
+
promote your products without written permission.
|
|
33
|
+
|
|
34
|
+
3. SCAFFOLDING OUTPUT
|
|
35
|
+
Files that @ressjs/create-ress-app copies into your project (templates and
|
|
36
|
+
generated configuration) are yours: you may use, modify and distribute them
|
|
37
|
+
without restriction. This does not extend to the Software packages that the
|
|
38
|
+
generated project installs as dependencies.
|
|
39
|
+
|
|
40
|
+
4. SUPPORT
|
|
41
|
+
The Software is provided without any obligation of support, maintenance or
|
|
42
|
+
updates. The Licensor may offer support, maintenance, training or consulting
|
|
43
|
+
under a separate paid agreement; that agreement does not change this license
|
|
44
|
+
unless it says so explicitly and is signed by the Licensor.
|
|
45
|
+
|
|
46
|
+
5. OWNERSHIP
|
|
47
|
+
The Software is licensed, not sold. The Licensor retains all rights not
|
|
48
|
+
expressly granted here. Feedback and suggestions you send may be used by the
|
|
49
|
+
Licensor without obligation to you.
|
|
50
|
+
|
|
51
|
+
6. TERMINATION
|
|
52
|
+
This license ends automatically if you breach it. On termination you must
|
|
53
|
+
stop using the Software and delete your copies. Sections 4 to 8 survive
|
|
54
|
+
termination.
|
|
55
|
+
|
|
56
|
+
7. NO WARRANTY
|
|
57
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
58
|
+
IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
59
|
+
PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
|
60
|
+
|
|
61
|
+
8. LIMITATION OF LIABILITY
|
|
62
|
+
TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE LICENSOR WILL NOT BE LIABLE FOR
|
|
63
|
+
ANY INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES, OR FOR LOSS OF
|
|
64
|
+
PROFITS, DATA OR BUSINESS, ARISING FROM THE USE OF OR INABILITY TO USE THE
|
|
65
|
+
SOFTWARE. THE LICENSOR'S TOTAL LIABILITY IS LIMITED TO THE AMOUNT YOU PAID
|
|
66
|
+
FOR THE SOFTWARE, WHICH MAY BE ZERO.
|
|
67
|
+
|
|
68
|
+
For other uses, including exceptions to section 2, contact the Licensor to
|
|
69
|
+
agree a separate license.
|
package/README.md
CHANGED
|
@@ -1,95 +1,23 @@
|
|
|
1
1
|
# @ressjs/platform
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Detección de la plataforma del cliente (sistema operativo, tipo de dispositivo y si corre dentro de un WebView) para ress.js.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
consumidor externo. Por eso vive en su propio paquete y no depende de nada.
|
|
5
|
+
> Pre-release (`0.6.0-rc`). La API puede cambiar antes de `0.6.0`.
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
import { detect } from '@ressjs/platform'
|
|
7
|
+
## Instalación
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
```bash
|
|
10
|
+
npm install @ressjs/platform
|
|
13
11
|
```
|
|
14
12
|
|
|
15
|
-
##
|
|
16
|
-
|
|
17
|
-
Tres ejes ortogonales. Cualquier combinación es expresable.
|
|
18
|
-
|
|
19
|
-
| Eje | Valores | Qué describe |
|
|
20
|
-
|---|---|---|
|
|
21
|
-
| `context` | `webview` | la página está incrustada dentro de una app; su ausencia es un navegador |
|
|
22
|
-
| `os` | `ios` `android` `tizen` `webos` `windows` `macos` `linux` | sistema operativo |
|
|
23
|
-
| `device` | `phone` `tablet` `tv` `desktop` | forma del aparato y modo de operación |
|
|
24
|
-
|
|
25
|
-
Los datos de la app que embebe la página —cuál es, en qué versión, sobre qué
|
|
26
|
-
versión del sistema— llegan en `nativeApp` y **nunca** eligen qué archivo servir.
|
|
27
|
-
|
|
28
|
-
## Cómo se decide
|
|
29
|
-
|
|
30
|
-
Seis capas, de lo que el cliente afirma a lo que se adivina. Cada una aporta
|
|
31
|
-
sólo los campos que puede determinar, y un campo ya resuelto no se sobrescribe.
|
|
32
|
-
Ninguna capa devuelve un resultado completo ni corta la evaluación: por eso
|
|
33
|
-
ninguna puede volver inalcanzable a la siguiente.
|
|
34
|
-
|
|
35
|
-
1. `override` — forzado para depurar, apagado salvo que se habilite
|
|
36
|
-
2. `explicit-headers` — el contrato v2
|
|
37
|
-
3. `legacy-headers` — el contrato v1 de los clientes ya publicados
|
|
38
|
-
4. `client-hints` — lo que el navegador manda por su cuenta
|
|
39
|
-
5. `user-agent` — la tabla de reglas
|
|
40
|
-
6. `default` — lo que quede sin resolver
|
|
41
|
-
|
|
42
|
-
Cada campo del resultado declara de qué capa salió y con cuánta confianza:
|
|
13
|
+
## Uso
|
|
43
14
|
|
|
44
15
|
```ts
|
|
45
|
-
platform
|
|
46
|
-
// { layer: 'user-agent', confidence: 'high', rule: 'ua:android-tv' }
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Un `webview: false` que nadie afirmó se distingue así de uno detectado.
|
|
50
|
-
|
|
51
|
-
## Cabeceras
|
|
52
|
-
|
|
53
|
-
| Cabecera | Aporta |
|
|
54
|
-
|---|---|
|
|
55
|
-
| `x-ressjs-webview` | `webview` |
|
|
56
|
-
| `x-ressjs-os` | `os` |
|
|
57
|
-
| `x-ressjs-device` | `device` |
|
|
58
|
-
| `x-ressjs-app-id` | `nativeApp.id`, e implica `webview: true` |
|
|
59
|
-
| `x-ressjs-app-version` | `nativeApp.version` |
|
|
60
|
-
| `x-ressjs-os-version` | `nativeApp.osVersion` |
|
|
61
|
-
| `x-ressjs-capabilities` | `capabilities`, separadas por comas |
|
|
62
|
-
|
|
63
|
-
Las del contrato anterior —`x-ressjs-platform`, `x-webview`, `x-rn-platform`,
|
|
64
|
-
`x-ressjs-version`— se siguen aceptando y se traducen.
|
|
65
|
-
|
|
66
|
-
## Agregar una plataforma
|
|
67
|
-
|
|
68
|
-
Es un dato, no un cambio de código:
|
|
16
|
+
import { detect } from '@ressjs/platform'
|
|
69
17
|
|
|
70
|
-
|
|
71
|
-
const registry = createPlatformRegistry({
|
|
72
|
-
values: [{ token: 'kaios', axis: 'os' }],
|
|
73
|
-
detect: [
|
|
74
|
-
{
|
|
75
|
-
name: 'ua:kaios',
|
|
76
|
-
test: /KAIOS/i,
|
|
77
|
-
set: { os: 'kaios', device: 'phone' },
|
|
78
|
-
confidence: 'high',
|
|
79
|
-
priority: 150,
|
|
80
|
-
},
|
|
81
|
-
],
|
|
82
|
-
})
|
|
18
|
+
const platform = detect({ userAgent, headers })
|
|
83
19
|
```
|
|
84
20
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
## Desde el navegador
|
|
88
|
-
|
|
89
|
-
```ts
|
|
90
|
-
import { getPlatform } from '@ressjs/platform/client'
|
|
91
|
-
```
|
|
21
|
+
## Licencia
|
|
92
22
|
|
|
93
|
-
|
|
94
|
-
cliente y servidor coinciden exactamente. Sólo detecta por su cuenta si no hay
|
|
95
|
-
nada serializado.
|
|
23
|
+
Proprietary. See [LICENSE](./LICENSE).
|
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export { detectPlatform } from './compat';
|
|
|
11
11
|
export { DETECTION_LAYERS } from './detect/layers';
|
|
12
12
|
export type { DetectionInput, DetectionLayer } from './detect/layers';
|
|
13
13
|
export { createPlatformRegistry, defaultPlatformRegistry } from './registry/create';
|
|
14
|
-
export { parseVariantSuffix } from './registry/parse';
|
|
14
|
+
export { parseVariantSuffix, PlatformTokenError } from './registry/parse';
|
|
15
15
|
export { ALL_AXES, DEFAULT_AXIS_PRECEDENCE, DEFAULT_VALUES, RETIRED_TOKENS, } from './registry/defaults';
|
|
16
16
|
export { DEFAULT_RULES } from './rules/user-agent';
|
|
17
17
|
export { EDGE_PRESETS, readEdgeHeaders } from './rules/edge';
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* de nada.
|
|
9
9
|
*/
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.serializePlatform = exports.platformScriptTag = exports.isWebView = exports.isTV = exports.isHandheld = exports.hasCapability = exports.DEFAULT_PLATFORM = exports.varyHeadersForAxes = exports.HEADERS_BY_AXIS = exports.PLATFORM_VARY_HEADERS = exports.PLATFORM_REQUEST_HEADERS = exports.HEADERS_V2 = exports.HEADERS_LEGACY = exports.HEADERS_CLIENT_HINTS = exports.HEADER_OVERRIDE = exports.readEdgeHeaders = exports.EDGE_PRESETS = exports.DEFAULT_RULES = exports.RETIRED_TOKENS = exports.DEFAULT_VALUES = exports.DEFAULT_AXIS_PRECEDENCE = exports.ALL_AXES = exports.parseVariantSuffix = exports.defaultPlatformRegistry = exports.createPlatformRegistry = exports.DETECTION_LAYERS = exports.detectPlatform = exports.detect = void 0;
|
|
11
|
+
exports.serializePlatform = exports.platformScriptTag = exports.isWebView = exports.isTV = exports.isHandheld = exports.hasCapability = exports.DEFAULT_PLATFORM = exports.varyHeadersForAxes = exports.HEADERS_BY_AXIS = exports.PLATFORM_VARY_HEADERS = exports.PLATFORM_REQUEST_HEADERS = exports.HEADERS_V2 = exports.HEADERS_LEGACY = exports.HEADERS_CLIENT_HINTS = exports.HEADER_OVERRIDE = exports.readEdgeHeaders = exports.EDGE_PRESETS = exports.DEFAULT_RULES = exports.RETIRED_TOKENS = exports.DEFAULT_VALUES = exports.DEFAULT_AXIS_PRECEDENCE = exports.ALL_AXES = exports.PlatformTokenError = exports.parseVariantSuffix = exports.defaultPlatformRegistry = exports.createPlatformRegistry = exports.DETECTION_LAYERS = exports.detectPlatform = exports.detect = void 0;
|
|
12
12
|
var pipeline_1 = require("./detect/pipeline");
|
|
13
13
|
Object.defineProperty(exports, "detect", { enumerable: true, get: function () { return pipeline_1.detect; } });
|
|
14
14
|
var compat_1 = require("./compat");
|
|
@@ -20,6 +20,7 @@ Object.defineProperty(exports, "createPlatformRegistry", { enumerable: true, get
|
|
|
20
20
|
Object.defineProperty(exports, "defaultPlatformRegistry", { enumerable: true, get: function () { return create_1.defaultPlatformRegistry; } });
|
|
21
21
|
var parse_1 = require("./registry/parse");
|
|
22
22
|
Object.defineProperty(exports, "parseVariantSuffix", { enumerable: true, get: function () { return parse_1.parseVariantSuffix; } });
|
|
23
|
+
Object.defineProperty(exports, "PlatformTokenError", { enumerable: true, get: function () { return parse_1.PlatformTokenError; } });
|
|
23
24
|
var defaults_1 = require("./registry/defaults");
|
|
24
25
|
Object.defineProperty(exports, "ALL_AXES", { enumerable: true, get: function () { return defaults_1.ALL_AXES; } });
|
|
25
26
|
Object.defineProperty(exports, "DEFAULT_AXIS_PRECEDENCE", { enumerable: true, get: function () { return defaults_1.DEFAULT_AXIS_PRECEDENCE; } });
|
package/dist/registry/parse.d.ts
CHANGED
|
@@ -1,4 +1,32 @@
|
|
|
1
1
|
import type { PlatformRegistry, VariantTag } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Un token de plataforma del nombre de un archivo no se pudo clasificar.
|
|
4
|
+
*
|
|
5
|
+
* Lleva los datos además del texto, para que quien lo muestre (la CLI) pueda
|
|
6
|
+
* darle el formato de sus demás errores sin interpretar el mensaje.
|
|
7
|
+
*/
|
|
8
|
+
export declare class PlatformTokenError extends Error {
|
|
9
|
+
/** Estable: lo reconocen quienes no pueden importar esta clase. */
|
|
10
|
+
readonly code: "RESS_PLATFORM_TOKEN";
|
|
11
|
+
readonly kind: 'retired' | 'unknown';
|
|
12
|
+
readonly token: string;
|
|
13
|
+
readonly origin?: string;
|
|
14
|
+
/** Sólo `retired`: con qué se reemplaza y por qué se retiró. */
|
|
15
|
+
readonly replacement?: string;
|
|
16
|
+
readonly reason?: string;
|
|
17
|
+
/** Sólo `unknown`: el token válido más parecido. */
|
|
18
|
+
readonly suggestion?: string;
|
|
19
|
+
readonly valid: readonly string[];
|
|
20
|
+
constructor(message: string, details: {
|
|
21
|
+
kind: 'retired' | 'unknown';
|
|
22
|
+
token: string;
|
|
23
|
+
origin?: string;
|
|
24
|
+
replacement?: string;
|
|
25
|
+
reason?: string;
|
|
26
|
+
suggestion?: string;
|
|
27
|
+
valid: readonly string[];
|
|
28
|
+
});
|
|
29
|
+
}
|
|
2
30
|
/**
|
|
3
31
|
* Convierte el sufijo de un archivo de variante en tags clasificados.
|
|
4
32
|
*
|
package/dist/registry/parse.js
CHANGED
|
@@ -1,6 +1,38 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PlatformTokenError = void 0;
|
|
3
4
|
exports.parseVariantSuffix = parseVariantSuffix;
|
|
5
|
+
/**
|
|
6
|
+
* Un token de plataforma del nombre de un archivo no se pudo clasificar.
|
|
7
|
+
*
|
|
8
|
+
* Lleva los datos además del texto, para que quien lo muestre (la CLI) pueda
|
|
9
|
+
* darle el formato de sus demás errores sin interpretar el mensaje.
|
|
10
|
+
*/
|
|
11
|
+
class PlatformTokenError extends Error {
|
|
12
|
+
/** Estable: lo reconocen quienes no pueden importar esta clase. */
|
|
13
|
+
code = 'RESS_PLATFORM_TOKEN';
|
|
14
|
+
kind;
|
|
15
|
+
token;
|
|
16
|
+
origin;
|
|
17
|
+
/** Sólo `retired`: con qué se reemplaza y por qué se retiró. */
|
|
18
|
+
replacement;
|
|
19
|
+
reason;
|
|
20
|
+
/** Sólo `unknown`: el token válido más parecido. */
|
|
21
|
+
suggestion;
|
|
22
|
+
valid;
|
|
23
|
+
constructor(message, details) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = 'PlatformTokenError';
|
|
26
|
+
this.kind = details.kind;
|
|
27
|
+
this.token = details.token;
|
|
28
|
+
this.origin = details.origin;
|
|
29
|
+
this.replacement = details.replacement;
|
|
30
|
+
this.reason = details.reason;
|
|
31
|
+
this.suggestion = details.suggestion;
|
|
32
|
+
this.valid = details.valid;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.PlatformTokenError = PlatformTokenError;
|
|
4
36
|
/**
|
|
5
37
|
* Convierte el sufijo de un archivo de variante en tags clasificados.
|
|
6
38
|
*
|
|
@@ -40,17 +72,17 @@ function parseVariantSuffix(suffix, registry, origin) {
|
|
|
40
72
|
* desconocido con la lista de válidos y la sugerencia más cercana.
|
|
41
73
|
*/
|
|
42
74
|
function unknownToken(token, registry, origin) {
|
|
75
|
+
const valid = allTokens(registry);
|
|
43
76
|
const retired = registry.retired(token);
|
|
44
77
|
if (retired) {
|
|
45
|
-
return new
|
|
78
|
+
return new PlatformTokenError(`[ress] El token de plataforma "${token}"${where(origin)} ya no existe. ` +
|
|
46
79
|
`Usá ${retired.replacement}.\n` +
|
|
47
|
-
`Se retiró porque ${retired.reason}
|
|
80
|
+
`Se retiró porque ${retired.reason}.`, { kind: 'retired', token, origin, replacement: retired.replacement, reason: retired.reason, valid });
|
|
48
81
|
}
|
|
49
|
-
const valid = allTokens(registry);
|
|
50
82
|
const suggestion = closest(token, valid);
|
|
51
|
-
return new
|
|
83
|
+
return new PlatformTokenError(`[ress] Token de plataforma desconocido: "${token}"${where(origin)}.` +
|
|
52
84
|
(suggestion ? ` ¿Quisiste decir "${suggestion}"?` : '') +
|
|
53
|
-
`\nTokens válidos: ${valid.join(', ')}
|
|
85
|
+
`\nTokens válidos: ${valid.join(', ')}.`, { kind: 'unknown', token, origin, suggestion, valid });
|
|
54
86
|
}
|
|
55
87
|
const where = (origin) => (origin ? ` en "${origin}"` : '');
|
|
56
88
|
function allTokens(registry) {
|
|
@@ -43,12 +43,13 @@ export declare const HEADERS_BY_AXIS: {
|
|
|
43
43
|
/**
|
|
44
44
|
* Las cabeceras a declarar para una respuesta que varía por estos ejes.
|
|
45
45
|
*
|
|
46
|
-
* `User-Agent
|
|
47
|
-
*
|
|
48
|
-
*
|
|
46
|
+
* Nunca incluye `User-Agent`: la detección lo usa para resolver (R-10), pero
|
|
47
|
+
* tiene tantos valores que una caché que separe por él casi nunca acierta. No
|
|
48
|
+
* declararlo es una política: lo que depende de la plataforma no se declara
|
|
49
|
+
* compartible (`security/headers.ts` en vite-router). Sin ejes, la lista es
|
|
50
|
+
* vacía — y una respuesta que no varía por nada no debe declarar `Vary`.
|
|
49
51
|
*/
|
|
50
52
|
export declare function varyHeadersForAxes(axes: readonly ('context' | 'os' | 'device')[], options?: {
|
|
51
|
-
includeUserAgent?: boolean;
|
|
52
53
|
/**
|
|
53
54
|
* Cabeceras que el proyecto declaró para su red de distribución. Se suman
|
|
54
55
|
* porque también cambian la respuesta; si no declaró ninguna, no aparece
|
|
@@ -91,16 +91,16 @@ exports.HEADERS_BY_AXIS = {
|
|
|
91
91
|
/**
|
|
92
92
|
* Las cabeceras a declarar para una respuesta que varía por estos ejes.
|
|
93
93
|
*
|
|
94
|
-
* `User-Agent
|
|
95
|
-
*
|
|
96
|
-
*
|
|
94
|
+
* Nunca incluye `User-Agent`: la detección lo usa para resolver (R-10), pero
|
|
95
|
+
* tiene tantos valores que una caché que separe por él casi nunca acierta. No
|
|
96
|
+
* declararlo es una política: lo que depende de la plataforma no se declara
|
|
97
|
+
* compartible (`security/headers.ts` en vite-router). Sin ejes, la lista es
|
|
98
|
+
* vacía — y una respuesta que no varía por nada no debe declarar `Vary`.
|
|
97
99
|
*/
|
|
98
100
|
function varyHeadersForAxes(axes, options = {}) {
|
|
99
101
|
if (axes.length === 0)
|
|
100
102
|
return [];
|
|
101
103
|
const fields = new Set();
|
|
102
|
-
if (options.includeUserAgent ?? true)
|
|
103
|
-
fields.add('User-Agent');
|
|
104
104
|
for (const axis of axes) {
|
|
105
105
|
for (const header of exports.HEADERS_BY_AXIS[axis])
|
|
106
106
|
fields.add(header);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ressjs/platform",
|
|
3
|
-
"version": "0.6.0-
|
|
3
|
+
"version": "0.6.0-rc.1",
|
|
4
4
|
"description": "Modelo de plataforma de ress.js: registro de tokens y detección del cliente. Sin dependencias.",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"tv",
|
|
41
41
|
"ressjs"
|
|
42
42
|
],
|
|
43
|
-
"license": "
|
|
43
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"typescript": "^5.9.3",
|
|
46
46
|
"vitest": "^3.2.4"
|