@openclaw/lobster 2026.9.6 → 2026.9.8
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/assets/icon.png +0 -0
- package/dist/index.js +8 -294
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/README.md +1 -0
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/SECURITY.md +62 -13
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/index.js +40 -9
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/lib/schemes.js +76 -16
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/lib/utils.js +54 -10
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/package.json +1 -1
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/test/fixtures/uri-js-parse.json +1 -0
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/test/ipv6-validation.test.js +130 -0
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/test/mailto-authority-security.test.js +125 -0
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/test/mailto-field-name-security.test.js +151 -0
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/test/security-normalization.test.js +38 -0
- package/node_modules/@clawdbot/lobster/node_modules/fast-uri/types/index.d.ts +16 -0
- package/node_modules/@clawdbot/lobster/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +19 -18
- package/node_modules/@clawdbot/lobster/node_modules/yaml/browser/dist/nodes/Alias.js +25 -23
- package/node_modules/@clawdbot/lobster/node_modules/yaml/dist/compose/resolve-flow-scalar.js +19 -18
- package/node_modules/@clawdbot/lobster/node_modules/yaml/dist/nodes/Alias.js +25 -23
- package/node_modules/@clawdbot/lobster/node_modules/yaml/package.json +1 -1
- package/node_modules/typebox/build/compile/code.mjs +1 -2
- package/node_modules/typebox/build/compile/validator.mjs +5 -1
- package/node_modules/typebox/build/format/iri.mjs +16 -9
- package/node_modules/typebox/build/guard/emit.mjs +2 -2
- package/node_modules/typebox/build/guard/guard.d.mts +7 -5
- package/node_modules/typebox/build/guard/guard.mjs +14 -9
- package/node_modules/typebox/build/guard/index.mjs +6 -0
- package/node_modules/typebox/build/guard/unicode/unicode.d.mts +6 -0
- package/node_modules/typebox/build/guard/unicode/unicode.mjs +35 -0
- package/node_modules/typebox/build/guard/{string.mjs → unicode/unicode_segment.mjs} +16 -19
- package/node_modules/typebox/build/schema/build.mjs +2 -3
- package/node_modules/typebox/build/schema/engine/_pathing.d.mts +1 -0
- package/node_modules/typebox/build/schema/engine/_pathing.mjs +11 -0
- package/node_modules/typebox/build/schema/engine/_refine.mjs +13 -5
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dependencies.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dependentSchemas.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/format.mjs +9 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/properties.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/ref.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/ref.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/schema.mjs +24 -24
- package/node_modules/typebox/build/schema/parse.mjs +3 -0
- package/node_modules/typebox/build/schema/pointer/pointer.d.mts +1 -6
- package/node_modules/typebox/build/schema/pointer/pointer.mjs +47 -64
- package/node_modules/typebox/build/system/settings/internal.d.mts +2 -0
- package/node_modules/typebox/build/system/settings/internal.mjs +20 -0
- package/node_modules/typebox/build/system/settings/settings.d.mts +11 -0
- package/node_modules/typebox/build/system/settings/settings.mjs +14 -0
- package/node_modules/typebox/build/type/extends/inference.d.mts +1 -1
- package/node_modules/typebox/build/type/extends/inference.mjs +15 -2
- package/node_modules/typebox/build/type/extends/tuple.d.mts +2 -1
- package/node_modules/typebox/build/type/extends/tuple.mjs +21 -1
- package/node_modules/typebox/build/value/parse/parse.mjs +10 -4
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +3 -1
- package/package.json +5 -5
- package/dist/runtime-api.js +0 -3
- /package/node_modules/typebox/build/guard/{string.d.mts → unicode/unicode_segment.d.mts} +0 -0
package/node_modules/@clawdbot/lobster/node_modules/fast-uri/test/security-normalization.test.js
CHANGED
|
@@ -126,6 +126,44 @@ test('hostname normalization decodes only current unreserved escapes', (t) => {
|
|
|
126
126
|
t.end()
|
|
127
127
|
})
|
|
128
128
|
|
|
129
|
+
test('scheme-relative hostname normalization folds decoded ASCII case', (t) => {
|
|
130
|
+
const encodedHost = '//%41.com'
|
|
131
|
+
const normalizedHost = fastURI.normalize(encodedHost)
|
|
132
|
+
const encodedMetadata = '//%4Detadata.internal/private'
|
|
133
|
+
const literalMetadata = '//metadata.internal/private'
|
|
134
|
+
|
|
135
|
+
t.equal(fastURI.parse(encodedHost).host, 'a.com', 'parse folds an encoded uppercase host letter')
|
|
136
|
+
t.equal(normalizedHost, '//a.com', 'normalize emits a lowercase host')
|
|
137
|
+
t.equal(fastURI.normalize(normalizedHost), normalizedHost, 'host normalization is idempotent')
|
|
138
|
+
t.equal(fastURI.equal(encodedHost, '//a.com'), true, 'encoded and literal host spellings compare equal')
|
|
139
|
+
t.equal(fastURI.equal(encodedMetadata, literalMetadata), true, 'encoded metadata host compares equal')
|
|
140
|
+
t.equal(
|
|
141
|
+
fastURI.resolve('x://trusted.example/', encodedMetadata),
|
|
142
|
+
fastURI.resolve('x://trusted.example/', literalMetadata),
|
|
143
|
+
'encoded and literal metadata hosts resolve identically'
|
|
144
|
+
)
|
|
145
|
+
t.equal(
|
|
146
|
+
fastURI.normalize('//example.com%2fpath'),
|
|
147
|
+
'//example.com%2Fpath',
|
|
148
|
+
'reserved host escapes remain encoded with uppercase hex'
|
|
149
|
+
)
|
|
150
|
+
t.equal(fastURI.normalize('//%2541.com'), '//%2541.com', 'nested host escapes are not decoded twice')
|
|
151
|
+
t.equal(fastURI.equal('//User@%41.com/path', '//user@a.com/path'), false, 'userinfo remains case-sensitive')
|
|
152
|
+
t.equal(fastURI.equal('//%41.com/Path', '//a.com/path'), false, 'path remains case-sensitive')
|
|
153
|
+
t.equal(fastURI.equal('//%41.com/?Token=Value', '//a.com/?token=value'), false, 'query remains case-sensitive')
|
|
154
|
+
t.end()
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
test('host normalization applies to schemes that skip path normalization', (t) => {
|
|
158
|
+
const encodedHost = 'mailto://%41.com'
|
|
159
|
+
const literalHost = 'mailto://a.com'
|
|
160
|
+
|
|
161
|
+
t.equal(fastURI.parse(encodedHost).host, fastURI.parse(literalHost).host, 'parse results have consistent hosts')
|
|
162
|
+
t.equal(fastURI.normalize(encodedHost), fastURI.normalize(literalHost), 'normalize results are consistent')
|
|
163
|
+
t.equal(fastURI.equal(encodedHost, literalHost), true, 'encoded and literal hosts compare equal')
|
|
164
|
+
t.end()
|
|
165
|
+
})
|
|
166
|
+
|
|
129
167
|
test('host conversion failures are not treated as comparable URLs', (t) => {
|
|
130
168
|
const malformedHost = 'http://trusted.test%2540evil.test/'
|
|
131
169
|
|
|
@@ -5,6 +5,22 @@ declare namespace fastUri {
|
|
|
5
5
|
scheme?: string;
|
|
6
6
|
userinfo?: string;
|
|
7
7
|
host?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Zone identifier of a zoned IPv6 host, e.g. `"eth0"` or `"25eth0"`. Set by
|
|
10
|
+
* `parse` for a bracketed IPv6 literal so `serialize`/`normalize` can
|
|
11
|
+
* reproduce the exact zone without re-deriving it from the ambiguous
|
|
12
|
+
* single-`%` form. It is validated on use, so a value that does not match
|
|
13
|
+
* `host` (for example after `host` is reassigned) is ignored.
|
|
14
|
+
*
|
|
15
|
+
* When building a component object by hand, set `ipv6Zone` to disambiguate
|
|
16
|
+
* a single-`%` host whose zone is ambiguous (a zone beginning with `25`
|
|
17
|
+
* is re-read as a `%25` separator). Without it, `serialize` falls back to
|
|
18
|
+
* a best-effort heuristic and may reinterpret such a zone, e.g. `{ host:
|
|
19
|
+
* "fe80::1%25eth0" }` serializes to `[fe80::1%25eth0]` (zone `eth0`), while
|
|
20
|
+
* `{ host: "fe80::1%25eth0", ipv6Zone: "25eth0" }` serializes to
|
|
21
|
+
* `[fe80::1%2525eth0]` (zone `25eth0`).
|
|
22
|
+
*/
|
|
23
|
+
ipv6Zone?: string;
|
|
8
24
|
port?: number | string;
|
|
9
25
|
path?: string;
|
|
10
26
|
query?: string;
|
package/node_modules/@clawdbot/lobster/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js
CHANGED
|
@@ -64,46 +64,47 @@ function plainValue(source, onError) {
|
|
|
64
64
|
}
|
|
65
65
|
if (badChar)
|
|
66
66
|
onError(0, 'BAD_SCALAR_START', `Plain value cannot start with ${badChar}`);
|
|
67
|
-
return
|
|
67
|
+
return unfoldLines(source);
|
|
68
68
|
}
|
|
69
69
|
function singleQuotedValue(source, onError) {
|
|
70
70
|
if (source[source.length - 1] !== "'" || source.length === 1)
|
|
71
71
|
onError(source.length, 'MISSING_CHAR', "Missing closing 'quote");
|
|
72
|
-
return
|
|
72
|
+
return unfoldLines(source.slice(1, -1)).replace(/''/g, "'");
|
|
73
73
|
}
|
|
74
|
-
function
|
|
74
|
+
function unfoldLines(source) {
|
|
75
|
+
const line = /(.*?)\r?\n/sy;
|
|
76
|
+
let match = line.exec(source);
|
|
77
|
+
if (!match)
|
|
78
|
+
return source;
|
|
75
79
|
/**
|
|
76
|
-
* The negative
|
|
80
|
+
* The negative lookbehinds in these RegExps are to
|
|
77
81
|
* prevent causing a polynomial search time in certain cases.
|
|
78
82
|
*
|
|
79
|
-
* The try-catch is for Safari
|
|
83
|
+
* The try-catch is for Safari < 16.4 and other old browsers:
|
|
80
84
|
* https://caniuse.com/js-regexp-lookbehind
|
|
81
85
|
*/
|
|
82
|
-
let
|
|
86
|
+
let trimEnd, trimBoth;
|
|
83
87
|
try {
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
trimEnd = new RegExp('(?<![ \t])[ \t]+$');
|
|
89
|
+
trimBoth = new RegExp('^[ \t]+|(?<![ \t])[ \t]+$', 'g');
|
|
86
90
|
}
|
|
87
91
|
catch {
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
trimEnd = /[ \t]+$/;
|
|
93
|
+
trimBoth = /^[ \t]+|[ \t]+$/g;
|
|
90
94
|
}
|
|
91
|
-
let
|
|
92
|
-
if (!match)
|
|
93
|
-
return source;
|
|
94
|
-
let res = match[1];
|
|
95
|
+
let res = match[1].replace(trimEnd, '');
|
|
95
96
|
let sep = ' ';
|
|
96
|
-
let pos =
|
|
97
|
-
line.lastIndex = pos;
|
|
97
|
+
let pos = line.lastIndex;
|
|
98
98
|
while ((match = line.exec(source))) {
|
|
99
|
-
|
|
99
|
+
const lm = match[1].replace(trimBoth, '');
|
|
100
|
+
if (lm === '') {
|
|
100
101
|
if (sep === '\n')
|
|
101
102
|
res += sep;
|
|
102
103
|
else
|
|
103
104
|
sep = '\n';
|
|
104
105
|
}
|
|
105
106
|
else {
|
|
106
|
-
res += sep +
|
|
107
|
+
res += sep + lm;
|
|
107
108
|
sep = ' ';
|
|
108
109
|
}
|
|
109
110
|
pos = line.lastIndex;
|
|
@@ -43,38 +43,40 @@ class Alias extends NodeBase {
|
|
|
43
43
|
if (node.anchor === this.source)
|
|
44
44
|
found = node;
|
|
45
45
|
}
|
|
46
|
+
if (found && ctx) {
|
|
47
|
+
const { anchors, doc, maxAliasCount } = ctx;
|
|
48
|
+
let data = anchors.get(found);
|
|
49
|
+
if (!data) {
|
|
50
|
+
// Resolve anchors for Node.prototype.toJS()
|
|
51
|
+
toJS(found, null, ctx);
|
|
52
|
+
data = anchors.get(found);
|
|
53
|
+
}
|
|
54
|
+
/* istanbul ignore if */
|
|
55
|
+
if (data?.res === undefined) {
|
|
56
|
+
const msg = 'This should not happen: Alias anchor was not resolved?';
|
|
57
|
+
throw new ReferenceError(msg);
|
|
58
|
+
}
|
|
59
|
+
if (maxAliasCount >= 0) {
|
|
60
|
+
data.count += 1;
|
|
61
|
+
if (data.aliasCount === 0)
|
|
62
|
+
data.aliasCount = getAliasCount(doc, found, anchors);
|
|
63
|
+
if (data.count * data.aliasCount > maxAliasCount) {
|
|
64
|
+
const msg = 'Excessive alias count indicates a resource exhaustion attack';
|
|
65
|
+
throw new ReferenceError(msg);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
46
69
|
return found;
|
|
47
70
|
}
|
|
48
71
|
toJSON(_arg, ctx) {
|
|
49
72
|
if (!ctx)
|
|
50
73
|
return { source: this.source };
|
|
51
|
-
const
|
|
52
|
-
const source = this.resolve(doc, ctx);
|
|
74
|
+
const source = this.resolve(ctx.doc, ctx);
|
|
53
75
|
if (!source) {
|
|
54
76
|
const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
|
|
55
77
|
throw new ReferenceError(msg);
|
|
56
78
|
}
|
|
57
|
-
|
|
58
|
-
if (!data) {
|
|
59
|
-
// Resolve anchors for Node.prototype.toJS()
|
|
60
|
-
toJS(source, null, ctx);
|
|
61
|
-
data = anchors.get(source);
|
|
62
|
-
}
|
|
63
|
-
/* istanbul ignore if */
|
|
64
|
-
if (data?.res === undefined) {
|
|
65
|
-
const msg = 'This should not happen: Alias anchor was not resolved?';
|
|
66
|
-
throw new ReferenceError(msg);
|
|
67
|
-
}
|
|
68
|
-
if (maxAliasCount >= 0) {
|
|
69
|
-
data.count += 1;
|
|
70
|
-
if (data.aliasCount === 0)
|
|
71
|
-
data.aliasCount = getAliasCount(doc, source, anchors);
|
|
72
|
-
if (data.count * data.aliasCount > maxAliasCount) {
|
|
73
|
-
const msg = 'Excessive alias count indicates a resource exhaustion attack';
|
|
74
|
-
throw new ReferenceError(msg);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return data.res;
|
|
79
|
+
return ctx.anchors.get(source).res;
|
|
78
80
|
}
|
|
79
81
|
toString(ctx, _onComment, _onChompKeep) {
|
|
80
82
|
const src = `*${this.source}`;
|
package/node_modules/@clawdbot/lobster/node_modules/yaml/dist/compose/resolve-flow-scalar.js
CHANGED
|
@@ -66,46 +66,47 @@ function plainValue(source, onError) {
|
|
|
66
66
|
}
|
|
67
67
|
if (badChar)
|
|
68
68
|
onError(0, 'BAD_SCALAR_START', `Plain value cannot start with ${badChar}`);
|
|
69
|
-
return
|
|
69
|
+
return unfoldLines(source);
|
|
70
70
|
}
|
|
71
71
|
function singleQuotedValue(source, onError) {
|
|
72
72
|
if (source[source.length - 1] !== "'" || source.length === 1)
|
|
73
73
|
onError(source.length, 'MISSING_CHAR', "Missing closing 'quote");
|
|
74
|
-
return
|
|
74
|
+
return unfoldLines(source.slice(1, -1)).replace(/''/g, "'");
|
|
75
75
|
}
|
|
76
|
-
function
|
|
76
|
+
function unfoldLines(source) {
|
|
77
|
+
const line = /(.*?)\r?\n/sy;
|
|
78
|
+
let match = line.exec(source);
|
|
79
|
+
if (!match)
|
|
80
|
+
return source;
|
|
77
81
|
/**
|
|
78
|
-
* The negative
|
|
82
|
+
* The negative lookbehinds in these RegExps are to
|
|
79
83
|
* prevent causing a polynomial search time in certain cases.
|
|
80
84
|
*
|
|
81
|
-
* The try-catch is for Safari
|
|
85
|
+
* The try-catch is for Safari < 16.4 and other old browsers:
|
|
82
86
|
* https://caniuse.com/js-regexp-lookbehind
|
|
83
87
|
*/
|
|
84
|
-
let
|
|
88
|
+
let trimEnd, trimBoth;
|
|
85
89
|
try {
|
|
86
|
-
|
|
87
|
-
|
|
90
|
+
trimEnd = new RegExp('(?<![ \t])[ \t]+$');
|
|
91
|
+
trimBoth = new RegExp('^[ \t]+|(?<![ \t])[ \t]+$', 'g');
|
|
88
92
|
}
|
|
89
93
|
catch {
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
trimEnd = /[ \t]+$/;
|
|
95
|
+
trimBoth = /^[ \t]+|[ \t]+$/g;
|
|
92
96
|
}
|
|
93
|
-
let
|
|
94
|
-
if (!match)
|
|
95
|
-
return source;
|
|
96
|
-
let res = match[1];
|
|
97
|
+
let res = match[1].replace(trimEnd, '');
|
|
97
98
|
let sep = ' ';
|
|
98
|
-
let pos =
|
|
99
|
-
line.lastIndex = pos;
|
|
99
|
+
let pos = line.lastIndex;
|
|
100
100
|
while ((match = line.exec(source))) {
|
|
101
|
-
|
|
101
|
+
const lm = match[1].replace(trimBoth, '');
|
|
102
|
+
if (lm === '') {
|
|
102
103
|
if (sep === '\n')
|
|
103
104
|
res += sep;
|
|
104
105
|
else
|
|
105
106
|
sep = '\n';
|
|
106
107
|
}
|
|
107
108
|
else {
|
|
108
|
-
res += sep +
|
|
109
|
+
res += sep + lm;
|
|
109
110
|
sep = ' ';
|
|
110
111
|
}
|
|
111
112
|
pos = line.lastIndex;
|
|
@@ -45,38 +45,40 @@ class Alias extends Node.NodeBase {
|
|
|
45
45
|
if (node.anchor === this.source)
|
|
46
46
|
found = node;
|
|
47
47
|
}
|
|
48
|
+
if (found && ctx) {
|
|
49
|
+
const { anchors, doc, maxAliasCount } = ctx;
|
|
50
|
+
let data = anchors.get(found);
|
|
51
|
+
if (!data) {
|
|
52
|
+
// Resolve anchors for Node.prototype.toJS()
|
|
53
|
+
toJS.toJS(found, null, ctx);
|
|
54
|
+
data = anchors.get(found);
|
|
55
|
+
}
|
|
56
|
+
/* istanbul ignore if */
|
|
57
|
+
if (data?.res === undefined) {
|
|
58
|
+
const msg = 'This should not happen: Alias anchor was not resolved?';
|
|
59
|
+
throw new ReferenceError(msg);
|
|
60
|
+
}
|
|
61
|
+
if (maxAliasCount >= 0) {
|
|
62
|
+
data.count += 1;
|
|
63
|
+
if (data.aliasCount === 0)
|
|
64
|
+
data.aliasCount = getAliasCount(doc, found, anchors);
|
|
65
|
+
if (data.count * data.aliasCount > maxAliasCount) {
|
|
66
|
+
const msg = 'Excessive alias count indicates a resource exhaustion attack';
|
|
67
|
+
throw new ReferenceError(msg);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
48
71
|
return found;
|
|
49
72
|
}
|
|
50
73
|
toJSON(_arg, ctx) {
|
|
51
74
|
if (!ctx)
|
|
52
75
|
return { source: this.source };
|
|
53
|
-
const
|
|
54
|
-
const source = this.resolve(doc, ctx);
|
|
76
|
+
const source = this.resolve(ctx.doc, ctx);
|
|
55
77
|
if (!source) {
|
|
56
78
|
const msg = `Unresolved alias (the anchor must be set before the alias): ${this.source}`;
|
|
57
79
|
throw new ReferenceError(msg);
|
|
58
80
|
}
|
|
59
|
-
|
|
60
|
-
if (!data) {
|
|
61
|
-
// Resolve anchors for Node.prototype.toJS()
|
|
62
|
-
toJS.toJS(source, null, ctx);
|
|
63
|
-
data = anchors.get(source);
|
|
64
|
-
}
|
|
65
|
-
/* istanbul ignore if */
|
|
66
|
-
if (data?.res === undefined) {
|
|
67
|
-
const msg = 'This should not happen: Alias anchor was not resolved?';
|
|
68
|
-
throw new ReferenceError(msg);
|
|
69
|
-
}
|
|
70
|
-
if (maxAliasCount >= 0) {
|
|
71
|
-
data.count += 1;
|
|
72
|
-
if (data.aliasCount === 0)
|
|
73
|
-
data.aliasCount = getAliasCount(doc, source, anchors);
|
|
74
|
-
if (data.count * data.aliasCount > maxAliasCount) {
|
|
75
|
-
const msg = 'Excessive alias count indicates a resource exhaustion attack';
|
|
76
|
-
throw new ReferenceError(msg);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return data.res;
|
|
81
|
+
return ctx.anchors.get(source).res;
|
|
80
82
|
}
|
|
81
83
|
toString(ctx, _onComment, _onChompKeep) {
|
|
82
84
|
const src = `*${this.source}`;
|
|
@@ -16,9 +16,8 @@ function Separator() {
|
|
|
16
16
|
function ImportSection(build) {
|
|
17
17
|
const context = build.UseUnevaluated() ? [`import { CheckContext } from "typebox/schema"`] : [];
|
|
18
18
|
const hashing = `import { Hashing } from "typebox/system"`;
|
|
19
|
-
const format = `import { Format } from "typebox/format"`;
|
|
20
19
|
const guard = `import { Guard } from "typebox/guard"`;
|
|
21
|
-
return [...context, hashing,
|
|
20
|
+
return [...context, hashing, guard];
|
|
22
21
|
}
|
|
23
22
|
// ------------------------------------------------------------------
|
|
24
23
|
// ExternalSection
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// deno-fmt-ignore-file
|
|
2
|
+
import { EnableParseErrors, DisableParseErrors } from '../system/settings/internal.mjs';
|
|
2
3
|
import { Settings } from '../system/settings/index.mjs';
|
|
3
4
|
import { Errors, Clean, Convert, Create, Default, Decode, Encode, HasCodec, Parser, ParseError } from '../value/index.mjs';
|
|
4
5
|
import { Build } from '../schema/index.mjs';
|
|
@@ -51,7 +52,10 @@ export class Validator {
|
|
|
51
52
|
return value;
|
|
52
53
|
if (Settings.Get().correctiveParse)
|
|
53
54
|
return Parser(this.Context(), this.Type(), value);
|
|
54
|
-
|
|
55
|
+
EnableParseErrors();
|
|
56
|
+
const errors = this.Errors(value);
|
|
57
|
+
DisableParseErrors();
|
|
58
|
+
throw new ParseError(value, errors);
|
|
55
59
|
}
|
|
56
60
|
/** Returns an array of validation errors for the given value. */
|
|
57
61
|
Errors(value) {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// deno-lint-ignore-file no-control-regex
|
|
2
|
-
const IpvFutureMatchMaxLength = 2048;
|
|
3
|
-
const IpvFutureMatch = /\[[vV][0-9a-fA-F]+\.[^\]]+\]/; // Guarded By IpvFutureMatchMaxLength
|
|
4
|
-
const InvalidIriChars = /[\x00-\x20<>\^`{|}\\]/;
|
|
5
|
-
const InvalidPercentEncoding = /%(?![0-9a-fA-F]{2})/;
|
|
6
2
|
// ------------------------------------------------------------------
|
|
3
|
+
//
|
|
4
|
+
// Removed by the following PR
|
|
5
|
+
//
|
|
6
|
+
// https://github.com/json-schema-org/JSON-Schema-Test-Suite/pull/1176
|
|
7
|
+
//
|
|
7
8
|
// NarrowIpvFuture
|
|
8
9
|
//
|
|
9
10
|
// Substitutes an IPvFuture address with a standard IPv6 loopback
|
|
@@ -13,12 +14,18 @@ const InvalidPercentEncoding = /%(?![0-9a-fA-F]{2})/;
|
|
|
13
14
|
// be expensive on large strings, this operation is strictly
|
|
14
15
|
// limited to inputs under a defined length threshold.
|
|
15
16
|
//
|
|
16
|
-
//
|
|
17
|
+
// ------------------------------------------------------------------
|
|
18
|
+
//
|
|
19
|
+
// const IpvFutureMatchMaxLength = 2048
|
|
20
|
+
// const IpvFutureMatch = /\[[vV][0-9a-fA-F]+\.[^\]]+\]/ // Guarded By IpvFutureMatchMaxLength
|
|
21
|
+
//
|
|
22
|
+
// function NarrowIpvFuture(value: string): string {
|
|
23
|
+
// return value.length < IpvFutureMatchMaxLength ? value.replace(IpvFutureMatch, '[::1]') : value
|
|
24
|
+
// }
|
|
17
25
|
//
|
|
18
26
|
// ------------------------------------------------------------------
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
27
|
+
const InvalidIriChars = /[\x00-\x20<>\^`{|}\\]/;
|
|
28
|
+
const InvalidPercentEncoding = /%(?![0-9a-fA-F]{2})/;
|
|
22
29
|
/**
|
|
23
30
|
* Returns true if the value is a valid Internationalized Resource Identifier.
|
|
24
31
|
* @specification https://datatracker.ietf.org/doc/html/rfc3987
|
|
@@ -31,5 +38,5 @@ export function IsIri(value) {
|
|
|
31
38
|
if (InvalidPercentEncoding.test(value))
|
|
32
39
|
return false;
|
|
33
40
|
// 3. Delegate to the native URL parser, patching the IPvFuture edge case beforehand.
|
|
34
|
-
return URL.canParse(
|
|
41
|
+
return URL.canParse(value);
|
|
35
42
|
}
|
|
@@ -97,10 +97,10 @@ export function IsGreaterEqualThan(left, right) {
|
|
|
97
97
|
// String
|
|
98
98
|
// --------------------------------------------------------------------------
|
|
99
99
|
export function IsMinLength(value, length) {
|
|
100
|
-
return `Guard.
|
|
100
|
+
return `(${value}.length >= ${(+length) << 1} || (${value}.length >= ${length} && Guard.CodePointCount(${value}) >= ${length}))`;
|
|
101
101
|
}
|
|
102
102
|
export function IsMaxLength(value, length) {
|
|
103
|
-
return `Guard.
|
|
103
|
+
return `(${value}.length <= ${length} || (${value}.length <= ${(+length) << 1} && Guard.CodePointCount(${value}) <= ${length}))`;
|
|
104
104
|
}
|
|
105
105
|
// --------------------------------------------------------------------------
|
|
106
106
|
// Array
|
|
@@ -33,12 +33,14 @@ export declare function IsMultipleOf(dividend: bigint | number, divisor: bigint
|
|
|
33
33
|
/** Returns true if the value appears to be an instance of a class. */
|
|
34
34
|
export declare function IsClassInstance(value: unknown): boolean;
|
|
35
35
|
export declare function IsValueLike(value: unknown): value is bigint | boolean | null | number | string | undefined;
|
|
36
|
-
/** Returns the number of grapheme clusters in the string */
|
|
36
|
+
/** Returns the total number of visual grapheme clusters in the string. */
|
|
37
37
|
export declare function GraphemeCount(value: string): number;
|
|
38
|
-
/** Returns
|
|
39
|
-
export declare function
|
|
40
|
-
/** Returns true if the string
|
|
41
|
-
export declare function
|
|
38
|
+
/** Returns the total number of Unicode code points in the string. */
|
|
39
|
+
export declare function CodePointCount(value: string): number;
|
|
40
|
+
/** Returns true if the string length in Unicode code points does not exceed maxLength */
|
|
41
|
+
export declare function IsMaxLength(value: string, maxLength: number): boolean;
|
|
42
|
+
/** Returns true if the string length in Unicode code points is at least minLength */
|
|
43
|
+
export declare function IsMinLength(value: string, minLength: number): boolean;
|
|
42
44
|
/** Returns true if every element from offset satisfies the callback, short-circuiting on the first failure */
|
|
43
45
|
export declare function Every<T>(value: T[], offset: number, callback: (value: T, index: number) => boolean): boolean;
|
|
44
46
|
/** Returns true if every element from offset satisfies the callback, using exhaustive enumeration */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// deno-fmt-ignore-file
|
|
2
|
-
import * as
|
|
2
|
+
import * as UnicodeSegmentGuard from './unicode/unicode_segment.mjs';
|
|
3
|
+
import * as UnicodeGuard from './unicode/unicode.mjs';
|
|
3
4
|
// --------------------------------------------------------------------------
|
|
4
5
|
// Guards
|
|
5
6
|
// --------------------------------------------------------------------------
|
|
@@ -123,17 +124,21 @@ export function IsValueLike(value) {
|
|
|
123
124
|
// --------------------------------------------------------------------------
|
|
124
125
|
// String
|
|
125
126
|
// --------------------------------------------------------------------------
|
|
126
|
-
/** Returns the number of grapheme clusters in the string */
|
|
127
|
+
/** Returns the total number of visual grapheme clusters in the string. */
|
|
127
128
|
export function GraphemeCount(value) {
|
|
128
|
-
return
|
|
129
|
+
return UnicodeSegmentGuard.GraphemeCount(value);
|
|
129
130
|
}
|
|
130
|
-
/** Returns
|
|
131
|
-
export function
|
|
132
|
-
return
|
|
131
|
+
/** Returns the total number of Unicode code points in the string. */
|
|
132
|
+
export function CodePointCount(value) {
|
|
133
|
+
return UnicodeGuard.CodePointCount(value);
|
|
133
134
|
}
|
|
134
|
-
/** Returns true if the string
|
|
135
|
-
export function
|
|
136
|
-
return
|
|
135
|
+
/** Returns true if the string length in Unicode code points does not exceed maxLength */
|
|
136
|
+
export function IsMaxLength(value, maxLength) {
|
|
137
|
+
return UnicodeGuard.IsMaxLength(value, maxLength);
|
|
138
|
+
}
|
|
139
|
+
/** Returns true if the string length in Unicode code points is at least minLength */
|
|
140
|
+
export function IsMinLength(value, minLength) {
|
|
141
|
+
return UnicodeGuard.IsMinLength(value, minLength);
|
|
137
142
|
}
|
|
138
143
|
// --------------------------------------------------------------------------
|
|
139
144
|
// Array
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
// ------------------------------------------------------------------
|
|
2
|
+
// Guards
|
|
3
|
+
// ------------------------------------------------------------------
|
|
1
4
|
export * as EmitGuard from './emit.mjs';
|
|
2
5
|
export * as GlobalsGuard from './globals.mjs';
|
|
3
6
|
export * as NativeGuard from './native.mjs';
|
|
7
|
+
// ------------------------------------------------------------------
|
|
8
|
+
// Default
|
|
9
|
+
// ------------------------------------------------------------------
|
|
4
10
|
import * as Guard from './guard.mjs';
|
|
5
11
|
export * as Guard from './guard.mjs';
|
|
6
12
|
export default Guard;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Returns the total number of Unicode code points in the string */
|
|
2
|
+
export declare function CodePointCount(value: string): number;
|
|
3
|
+
/** Returns true if the string length in Unicode code points is less than or equal to maxLength */
|
|
4
|
+
export declare function IsMaxLength(value: string, maxLength: number): boolean;
|
|
5
|
+
/** Returns true if the string length in Unicode code points is greater than or equal to minLength */
|
|
6
|
+
export declare function IsMinLength(value: string, minLength: number): boolean;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// ------------------------------------------------------------------
|
|
2
|
+
// CodePointCount (10-bit Shift Branchless)
|
|
3
|
+
//
|
|
4
|
+
// Counts code points by enumerating UTF-16 sequences and incrementing
|
|
5
|
+
// when not within a high/low pairing. Because surrogate blocks are
|
|
6
|
+
// 1024 (2^10) wide and aligned, by shifting right by (0xA), we can
|
|
7
|
+
// collapse each unit to a constant per block (high: 0x36, low: 0x37)
|
|
8
|
+
// and shift again into a packed (0x3637) for comparison. Fetch calls
|
|
9
|
+
// to charCodeAt(...) are kept to one call per iteration.
|
|
10
|
+
//
|
|
11
|
+
// ------------------------------------------------------------------
|
|
12
|
+
/** Returns the total number of Unicode code points in the string */
|
|
13
|
+
export function CodePointCount(value) {
|
|
14
|
+
let result = 0, index = 0, prev = 0;
|
|
15
|
+
while (index < value.length) {
|
|
16
|
+
const next = value.charCodeAt(index++) >> 0xA; // shift (10-bits into high/low)
|
|
17
|
+
result += +(((prev << 8) | next) !== 0x3637); // packed (or +!(prev === 0x36 && next === 0x37))
|
|
18
|
+
prev = next;
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
// ------------------------------------------------------------------
|
|
23
|
+
// IsMaxLength
|
|
24
|
+
// ------------------------------------------------------------------
|
|
25
|
+
/** Returns true if the string length in Unicode code points is less than or equal to maxLength */
|
|
26
|
+
export function IsMaxLength(value, maxLength) {
|
|
27
|
+
return value.length <= maxLength || (value.length <= (maxLength << 1) && CodePointCount(value) <= maxLength);
|
|
28
|
+
}
|
|
29
|
+
// ------------------------------------------------------------------
|
|
30
|
+
// IsMinLength
|
|
31
|
+
// ------------------------------------------------------------------
|
|
32
|
+
/** Returns true if the string length in Unicode code points is greater than or equal to minLength */
|
|
33
|
+
export function IsMinLength(value, minLength) {
|
|
34
|
+
return value.length >= (minLength << 1) || (value.length >= minLength && CodePointCount(value) >= minLength);
|
|
35
|
+
}
|
|
@@ -91,26 +91,12 @@ function IsGraphemeCodePoint(value) {
|
|
|
91
91
|
IsZeroWidthJoiner(value)));
|
|
92
92
|
}
|
|
93
93
|
// --------------------------------------------------------------------------
|
|
94
|
-
// GraphemeCount
|
|
95
|
-
// --------------------------------------------------------------------------
|
|
96
|
-
/** Returns the number of grapheme clusters in a string */
|
|
97
|
-
export function GraphemeCount(value) {
|
|
98
|
-
let count = 0;
|
|
99
|
-
let index = 0;
|
|
100
|
-
while (index < value.length) {
|
|
101
|
-
index = NextGraphemeClusterIndex(value, index);
|
|
102
|
-
count++;
|
|
103
|
-
}
|
|
104
|
-
return count;
|
|
105
|
-
}
|
|
106
|
-
// --------------------------------------------------------------------------
|
|
107
94
|
// IsMinLengthSegmented
|
|
108
95
|
// --------------------------------------------------------------------------
|
|
109
96
|
/** Checks if a string has at least a minimum number of grapheme clusters */
|
|
110
97
|
function IsMinLengthSegmented(value, minLength) {
|
|
111
98
|
// if (minLength === 0) return true // 0-length (unreachable)
|
|
112
|
-
let count = 0;
|
|
113
|
-
let index = 0;
|
|
99
|
+
let count = 0, index = 0;
|
|
114
100
|
while (index < value.length) {
|
|
115
101
|
index = NextGraphemeClusterIndex(value, index);
|
|
116
102
|
if ((++count) >= minLength)
|
|
@@ -123,8 +109,7 @@ function IsMinLengthSegmented(value, minLength) {
|
|
|
123
109
|
// --------------------------------------------------------------------------
|
|
124
110
|
/** Checks if a string has at most a maximum number of grapheme clusters */
|
|
125
111
|
function IsMaxLengthSegmented(value, maxLength) {
|
|
126
|
-
let count = 0;
|
|
127
|
-
let index = 0;
|
|
112
|
+
let count = 0, index = 0;
|
|
128
113
|
while (index < value.length) {
|
|
129
114
|
index = NextGraphemeClusterIndex(value, index);
|
|
130
115
|
if ((++count) > maxLength)
|
|
@@ -133,7 +118,19 @@ function IsMaxLengthSegmented(value, maxLength) {
|
|
|
133
118
|
return true;
|
|
134
119
|
}
|
|
135
120
|
// --------------------------------------------------------------------------
|
|
136
|
-
//
|
|
121
|
+
// GraphemeCount
|
|
122
|
+
// --------------------------------------------------------------------------
|
|
123
|
+
/** Returns the number of grapheme clusters in a string */
|
|
124
|
+
export function GraphemeCount(value) {
|
|
125
|
+
let count = 0, index = 0;
|
|
126
|
+
while (index < value.length) {
|
|
127
|
+
index = NextGraphemeClusterIndex(value, index);
|
|
128
|
+
count++;
|
|
129
|
+
}
|
|
130
|
+
return count;
|
|
131
|
+
}
|
|
132
|
+
// --------------------------------------------------------------------------
|
|
133
|
+
// IsMinLength
|
|
137
134
|
// --------------------------------------------------------------------------
|
|
138
135
|
/** Fast check for minimum grapheme length, falls back to full check if needed */
|
|
139
136
|
export function IsMinLength(value, minLength) {
|
|
@@ -151,7 +148,7 @@ export function IsMinLength(value, minLength) {
|
|
|
151
148
|
}
|
|
152
149
|
}
|
|
153
150
|
// --------------------------------------------------------------------------
|
|
154
|
-
//
|
|
151
|
+
// IsMaxLength
|
|
155
152
|
// --------------------------------------------------------------------------
|
|
156
153
|
/** Fast check for maximum grapheme length, falls back to full check if needed */
|
|
157
154
|
export function IsMaxLength(value, maxLength) {
|
|
@@ -4,7 +4,6 @@ import { Arguments } from '../system/arguments/index.mjs';
|
|
|
4
4
|
import { Environment } from '../system/environment/index.mjs';
|
|
5
5
|
import { Hashing } from '../system/hashing/index.mjs';
|
|
6
6
|
import { Guard } from '../guard/index.mjs';
|
|
7
|
-
import { Format } from '../format/index.mjs';
|
|
8
7
|
import * as Engine from './engine/index.mjs';
|
|
9
8
|
// ------------------------------------------------------------------
|
|
10
9
|
// CreateCode
|
|
@@ -20,8 +19,8 @@ function CreateCode(build) {
|
|
|
20
19
|
// CreateEvaluatedCheck
|
|
21
20
|
// ------------------------------------------------------------------
|
|
22
21
|
function CreateEvaluatedCheck(build, code) {
|
|
23
|
-
const factory = Environment.Evaluate('CheckContext', 'Guard', '
|
|
24
|
-
return factory(Engine.CheckContext, Guard,
|
|
22
|
+
const factory = Environment.Evaluate('CheckContext', 'Guard', 'Hashing', build.External().identifier, code);
|
|
23
|
+
return factory(Engine.CheckContext, Guard, Hashing, build.External().variables);
|
|
25
24
|
}
|
|
26
25
|
// ------------------------------------------------------------------
|
|
27
26
|
// CreateDynamicCheck
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function EncodeFragment(fragment: string): string;
|