functionalscript 0.46.0 → 0.47.0
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/fjs/basen/cbase32/module.f.mjs +18 -10
- package/fjs/basen/cbase32/proof.f.d.mts +3 -0
- package/fjs/basen/cbase32/proof.f.mjs +24 -2
- package/fjs/basen/proof.f.mjs +8 -16
- package/fjs/bnf/ll1/proof.f.d.mts +2 -0
- package/fjs/bnf/ll1/proof.f.mjs +33 -18
- package/fjs/bnf/module.f.d.mts +2 -2
- package/fjs/bnf/module.f.mjs +2 -2
- package/fjs/cas/proof.f.mjs +4 -26
- package/fjs/ci/common/module.f.mjs +6 -0
- package/fjs/ci/config/module.f.d.mts +7 -7
- package/fjs/ci/config/module.f.mjs +7 -7
- package/fjs/cli/module.f.mjs +14 -10
- package/fjs/crypto/vdf/module.f.d.mts +0 -1
- package/fjs/crypto/vdf/module.f.mjs +3 -14
- package/fjs/dev/module.f.mjs +10 -20
- package/fjs/djs/parser/module.f.d.mts +101 -53
- package/fjs/djs/parser/module.f.mjs +732 -525
- package/fjs/djs/parser/proof.f.d.mts +6 -0
- package/fjs/djs/parser/proof.f.mjs +315 -11
- package/fjs/djs/parser/types.d.ts +29 -2
- package/fjs/djs/tokenizer/module.f.mjs +122 -105
- package/fjs/djs/tokenizer/proof.f.mjs +17 -0
- package/fjs/djs/transpiler/module.f.mjs +4 -5
- package/fjs/djs/transpiler/proof.f.d.mts +2 -0
- package/fjs/djs/transpiler/proof.f.mjs +25 -0
- package/fjs/edag/amnesia/module.f.d.mts +20 -0
- package/fjs/edag/amnesia/module.f.mjs +303 -0
- package/fjs/edag/amnesia/proof.f.d.mts +79 -0
- package/fjs/edag/amnesia/proof.f.mjs +573 -0
- package/fjs/edag/amnesia/types.d.ts +15 -0
- package/fjs/edag/module.f.d.mts +410 -0
- package/fjs/edag/module.f.mjs +559 -0
- package/fjs/edag/proof.f.d.mts +116 -0
- package/fjs/edag/proof.f.mjs +686 -0
- package/fjs/edag/types.d.ts +55 -0
- package/fjs/effects/node/memory/module.d.mts +37 -3
- package/fjs/effects/node/memory/module.mjs +38 -4
- package/fjs/effects/node/memory/proof.d.mts +5 -2
- package/fjs/effects/node/memory/proof.mjs +36 -6
- package/fjs/effects/node/module.d.mts +9 -1
- package/fjs/effects/node/module.f.d.mts +39 -0
- package/fjs/effects/node/module.f.mjs +46 -0
- package/fjs/effects/node/module.mjs +234 -32
- package/fjs/effects/node/types.d.ts +28 -2
- package/fjs/effects/node/virtual/module.f.d.mts +19 -10
- package/fjs/effects/node/virtual/module.f.mjs +246 -32
- package/fjs/effects/node/virtual/proof.f.d.mts +17 -2
- package/fjs/effects/node/virtual/proof.f.mjs +232 -8
- package/fjs/effects/node/virtual/types.d.ts +57 -1
- package/fjs/emergent_testing/browser/proof.d.mts +55 -0
- package/fjs/emergent_testing/browser/proof.mjs +352 -0
- package/fjs/emergent_testing/browser/species.proof.d.mts +4 -0
- package/fjs/emergent_testing/browser/species.proof.mjs +45 -0
- package/fjs/emergent_testing/browser.d.mts +79 -0
- package/fjs/emergent_testing/browser.mjs +432 -0
- package/fjs/emergent_testing/proof.f.d.mts +1 -1
- package/fjs/emergent_testing/proof.f.mjs +2 -2
- package/fjs/js/string_escape/module.f.d.mts +47 -0
- package/fjs/js/string_escape/module.f.mjs +95 -0
- package/fjs/js/string_escape/proof.f.d.mts +8 -0
- package/fjs/js/string_escape/proof.f.mjs +68 -0
- package/fjs/js/tokenizer/module.f.mjs +14 -12
- package/fjs/mcp/cas/module.f.d.mts +1 -7
- package/fjs/mcp/cas/module.f.mjs +24 -15
- package/fjs/mcp/evo/module.f.mjs +9 -24
- package/fjs/mcp/module.f.d.mts +3 -1
- package/fjs/mcp/module.f.mjs +4 -2
- package/fjs/media/json/rtti/module.f.d.mts +2 -2
- package/fjs/media/json/rtti/module.f.mjs +1 -1
- package/fjs/media/json/schema/module.f.d.mts +15 -5
- package/fjs/media/json/schema/module.f.mjs +42 -15
- package/fjs/media/json/schema/proof.f.d.mts +10 -1
- package/fjs/media/json/schema/proof.f.mjs +88 -16
- package/fjs/media/json/serializer/module.f.mjs +14 -26
- package/fjs/media/json/types.d.ts +1 -1
- package/fjs/media/lock/module.f.d.mts +8 -3
- package/fjs/media/lock/module.f.mjs +9 -3
- package/fjs/media/lock/proof.f.d.mts +1 -1
- package/fjs/media/lock/proof.f.mjs +2 -2
- package/fjs/media/lock/types.d.ts +1 -3
- package/fjs/media/module.f.d.mts +20 -13
- package/fjs/media/module.f.mjs +29 -16
- package/fjs/media/note/module.f.d.mts +14 -7
- package/fjs/media/note/module.f.mjs +14 -7
- package/fjs/media/note/proof.f.mjs +1 -1
- package/fjs/media/proof.f.mjs +5 -5
- package/fjs/media/revision/module.f.d.mts +8 -2
- package/fjs/media/revision/module.f.mjs +9 -3
- package/fjs/media/revision/proof.f.mjs +1 -1
- package/fjs/media/revision/types.d.ts +1 -1
- package/fjs/media/type/module.f.d.mts +20 -0
- package/fjs/media/type/module.f.mjs +74 -0
- package/fjs/media/type/proof.f.d.mts +5 -0
- package/fjs/media/type/proof.f.mjs +24 -1
- package/fjs/module.f.mjs +6 -0
- package/fjs/path/module.f.d.mts +60 -3
- package/fjs/path/module.f.mjs +138 -14
- package/fjs/path/proof.f.d.mts +3 -0
- package/fjs/path/proof.f.mjs +298 -2
- package/fjs/protocol/json_rpc/module.f.d.mts +65 -28
- package/fjs/protocol/json_rpc/module.f.mjs +49 -13
- package/fjs/protocol/json_rpc/proof.f.d.mts +4 -0
- package/fjs/protocol/json_rpc/proof.f.mjs +29 -0
- package/fjs/protocol/json_rpc/types.d.ts +12 -2
- package/fjs/protocol/mcp/module.f.d.mts +89 -54
- package/fjs/protocol/mcp/module.f.mjs +110 -56
- package/fjs/protocol/mcp/proof.f.d.mts +13 -0
- package/fjs/protocol/mcp/proof.f.mjs +107 -7
- package/fjs/protocol/mcp/stdio/module.f.mjs +3 -4
- package/fjs/protocol/mcp/stdio/proof.f.mjs +2 -2
- package/fjs/protocol/mcp/types.d.ts +14 -2
- package/fjs/text/utf8/module.f.mjs +27 -1
- package/fjs/text/utf8/proof.f.mjs +37 -0
- package/fjs/types/array/module.f.mjs +18 -11
- package/fjs/types/array/proof.f.mjs +27 -1
- package/fjs/types/bigfloat/module.f.d.mts +48 -9
- package/fjs/types/bigfloat/module.f.mjs +147 -59
- package/fjs/types/bigfloat/proof.f.d.mts +2 -0
- package/fjs/types/bigfloat/proof.f.mjs +136 -4
- package/fjs/types/bigfloat/types.d.ts +17 -0
- package/fjs/types/function/module.f.d.mts +11 -2
- package/fjs/types/function/module.f.mjs +20 -2
- package/fjs/types/function/proof.f.mjs +5 -1
- package/fjs/types/phantom/types.d.ts +21 -0
- package/fjs/types/result/module.f.d.mts +4 -4
- package/fjs/types/result/module.f.mjs +2 -2
- package/fjs/types/result/proof.f.d.mts +6 -2
- package/fjs/types/result/proof.f.mjs +17 -1
- package/fjs/types/rtti/common/module.f.d.mts +78 -5
- package/fjs/types/rtti/common/module.f.mjs +168 -3
- package/fjs/types/rtti/common/proof.f.d.mts +14 -0
- package/fjs/types/rtti/common/proof.f.mjs +61 -2
- package/fjs/types/rtti/common/types.d.ts +23 -1
- package/fjs/types/rtti/data/module.f.d.mts +57 -1
- package/fjs/types/rtti/data/module.f.mjs +241 -47
- package/fjs/types/rtti/data/proof.f.d.mts +10 -0
- package/fjs/types/rtti/data/proof.f.mjs +272 -39
- package/fjs/types/rtti/data/types.d.ts +14 -7
- package/fjs/types/rtti/host.proof.d.mts +33 -0
- package/fjs/types/rtti/host.proof.mjs +170 -0
- package/fjs/types/rtti/module.f.d.mts +51 -6
- package/fjs/types/rtti/module.f.mjs +50 -3
- package/fjs/types/rtti/parse/module.f.d.mts +31 -24
- package/fjs/types/rtti/parse/module.f.mjs +197 -59
- package/fjs/types/rtti/parse/proof.f.d.mts +37 -2
- package/fjs/types/rtti/parse/proof.f.mjs +171 -47
- package/fjs/types/rtti/proof.f.d.mts +6 -0
- package/fjs/types/rtti/proof.f.mjs +42 -1
- package/fjs/types/rtti/ts/module.f.d.mts +9 -3
- package/fjs/types/rtti/ts/module.f.mjs +68 -15
- package/fjs/types/rtti/ts/proof.f.d.mts +42 -2
- package/fjs/types/rtti/ts/proof.f.mjs +139 -6
- package/fjs/types/rtti/ts/types.d.ts +164 -16
- package/fjs/types/rtti/types.d.ts +31 -3
- package/fjs/types/rtti/validate/module.f.d.mts +120 -0
- package/fjs/types/rtti/validate/module.f.mjs +351 -0
- package/fjs/types/rtti/validate/proof.f.d.mts +154 -0
- package/fjs/types/rtti/validate/proof.f.mjs +781 -0
- package/fjs/types/ts/types.d.ts +4 -0
- package/fjs/web/module.f.d.mts +115 -0
- package/fjs/web/module.f.mjs +581 -0
- package/fjs/web/proof.f.d.mts +39 -0
- package/fjs/web/proof.f.mjs +413 -0
- package/fjs/web/types.d.ts +39 -0
- package/fjs/website/browser-prepare.d.mts +5 -0
- package/fjs/website/browser-prepare.mjs +115 -0
- package/fjs/website/browser-source.d.mts +37 -0
- package/fjs/website/browser-source.mjs +202 -0
- package/fjs/website/browser-source.proof.d.mts +31 -0
- package/fjs/website/browser-source.proof.mjs +162 -0
- package/fjs/website/browser.d.mts +5 -0
- package/fjs/website/browser.mjs +8 -0
- package/fjs/website/module.f.d.mts +3 -3
- package/fjs/website/module.f.mjs +62 -9
- package/fjs/website/proof.f.d.mts +4 -0
- package/fjs/website/proof.f.mjs +18 -3
- package/package.json +2 -3
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @import { Data } from '../../../types/rtti/data/types.ts'
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { boolean, number, string, bigint, never, unknown, array, record, or, option } from '../../../types/rtti/module.f.mjs'
|
|
6
|
+
import { boolean, number, string, bigint, never, unknown, array, open, record, or, option } from '../../../types/rtti/module.f.mjs'
|
|
7
7
|
import { stringify } from '../module.f.mjs'
|
|
8
8
|
import { dataToJsonSchema, toJsonSchema, unknown as schemaUnknown } from './module.f.mjs'
|
|
9
9
|
import { unitBit } from '../../../types/rtti/data/module.f.mjs'
|
|
@@ -80,37 +80,77 @@ export const proof = {
|
|
|
80
80
|
record: eq(record(string), { type: 'object', additionalProperties: { type: 'string' } }),
|
|
81
81
|
// `anyOf` members follow the canonical kind order, not the operand order
|
|
82
82
|
or: eq(or(string, number), { anyOf: [{ type: 'number' }, { type: 'string' }] }),
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
83
|
+
// A bare tuple is closed, which JSON Schema spells `items: false`; a
|
|
84
|
+
// position admitting `undefined` may be absent instead, which is
|
|
85
|
+
// `minItems`. `open` is what admits what follows the prefix, and prints
|
|
86
|
+
// the unconstrained `items: {}`.
|
|
87
|
+
tuple: {
|
|
88
|
+
allRequired: eq(/** @type {const} */ ([number, string]), {
|
|
89
|
+
type: 'array',
|
|
90
|
+
prefixItems: [{ type: 'number' }, { type: 'string' }],
|
|
91
|
+
minItems: 2,
|
|
92
|
+
items: false,
|
|
93
|
+
}),
|
|
94
|
+
withOptional: eq(/** @type {const} */ ([number, option(string)]), {
|
|
95
|
+
type: 'array',
|
|
96
|
+
prefixItems: [{ type: 'number' }, { type: 'string' }],
|
|
97
|
+
minItems: 1,
|
|
98
|
+
items: false,
|
|
99
|
+
}),
|
|
100
|
+
allOptional: eq(/** @type {const} */ ([option(number)]), {
|
|
101
|
+
type: 'array',
|
|
102
|
+
prefixItems: [{ type: 'number' }],
|
|
103
|
+
items: false,
|
|
104
|
+
}),
|
|
105
|
+
open: eq(open(/** @type {const} */ ([number, string])), {
|
|
106
|
+
type: 'array',
|
|
107
|
+
prefixItems: [{ type: 'number' }, { type: 'string' }],
|
|
108
|
+
minItems: 2,
|
|
109
|
+
items: {},
|
|
110
|
+
}),
|
|
111
|
+
},
|
|
112
|
+
// The same on the other kind: a bare struct names every key it admits,
|
|
113
|
+
// which is `additionalProperties: { not: {} }`.
|
|
89
114
|
struct: {
|
|
90
115
|
allRequired: eq(/** @type {const} */ ({ x: number, y: string }), {
|
|
91
116
|
type: 'object',
|
|
92
117
|
properties: { x: { type: 'number' }, y: { type: 'string' } },
|
|
93
118
|
required: ['x', 'y'],
|
|
119
|
+
additionalProperties: { not: {} },
|
|
94
120
|
}),
|
|
95
121
|
withOptional: eq(/** @type {const} */ ({ x: number, y: option(string) }), {
|
|
96
122
|
type: 'object',
|
|
97
123
|
properties: { x: { type: 'number' }, y: { type: 'string' } },
|
|
98
124
|
required: ['x'],
|
|
125
|
+
additionalProperties: { not: {} },
|
|
99
126
|
}),
|
|
100
127
|
allOptional: eq(/** @type {const} */ ({ x: option(number) }), {
|
|
101
128
|
type: 'object',
|
|
102
129
|
properties: { x: { type: 'number' } },
|
|
130
|
+
additionalProperties: { not: {} },
|
|
131
|
+
}),
|
|
132
|
+
// a closed struct declaring nothing is the empty object
|
|
133
|
+
empty: eq(/** @type {const} */ ({}), {
|
|
134
|
+
type: 'object',
|
|
135
|
+
additionalProperties: { not: {} },
|
|
103
136
|
}),
|
|
104
137
|
// an unconstrained struct is the whole object kind
|
|
105
|
-
|
|
138
|
+
openEmpty: eq(open(/** @type {const} */ ({})), { type: 'object' }),
|
|
139
|
+
open: eq(open(/** @type {const} */ ({ x: number, y: string })), {
|
|
140
|
+
type: 'object',
|
|
141
|
+
properties: { x: { type: 'number' }, y: { type: 'string' } },
|
|
142
|
+
required: ['x', 'y'],
|
|
143
|
+
}),
|
|
106
144
|
orOptional: eq(/** @type {const} */ ({ x: or(string, number, undefined) }), {
|
|
107
145
|
type: 'object',
|
|
108
146
|
properties: { x: { anyOf: [{ type: 'number' }, { type: 'string' }] } },
|
|
147
|
+
additionalProperties: { not: {} },
|
|
109
148
|
}),
|
|
110
149
|
withConst: eq(/** @type {const} */ ({ x: null, y: string }), {
|
|
111
150
|
type: 'object',
|
|
112
151
|
properties: { x: { const: null }, y: { type: 'string' } },
|
|
113
152
|
required: ['x', 'y'],
|
|
153
|
+
additionalProperties: { not: {} },
|
|
114
154
|
}),
|
|
115
155
|
optionalOfEveryKind: eq(/** @type {const} */ ({
|
|
116
156
|
a: option(number),
|
|
@@ -129,6 +169,7 @@ export const proof = {
|
|
|
129
169
|
e: { type: 'object', additionalProperties: { type: 'string' } },
|
|
130
170
|
f: { const: null },
|
|
131
171
|
},
|
|
172
|
+
additionalProperties: { not: {} },
|
|
132
173
|
}),
|
|
133
174
|
},
|
|
134
175
|
schemaUnknownTag: () => {
|
|
@@ -140,7 +181,7 @@ export const proof = {
|
|
|
140
181
|
type: 'array',
|
|
141
182
|
items: { type: 'object', additionalProperties: { type: 'boolean' } },
|
|
142
183
|
}),
|
|
143
|
-
orWithConst: eq(or(null, string,
|
|
184
|
+
orWithConst: eq(or(null, string, 42), {
|
|
144
185
|
anyOf: [{ const: null }, { const: 42 }, { type: 'string' }],
|
|
145
186
|
}),
|
|
146
187
|
structWithOr: eq(/** @type {const} */ ({ id: or(string, number), name: option(string) }), {
|
|
@@ -150,7 +191,10 @@ export const proof = {
|
|
|
150
191
|
name: { type: 'string' },
|
|
151
192
|
},
|
|
152
193
|
required: ['id'],
|
|
194
|
+
additionalProperties: { not: {} },
|
|
153
195
|
}),
|
|
196
|
+
// the top position is required — the array cannot end before the
|
|
197
|
+
// `number` after it — so its `undefined` is not stripped away
|
|
154
198
|
topInsideTuple: eq(/** @type {const} */ ([unknown, number]), {
|
|
155
199
|
type: 'array',
|
|
156
200
|
prefixItems: [{}, { type: 'number' }],
|
|
@@ -163,15 +207,41 @@ export const proof = {
|
|
|
163
207
|
unitMembers: eq(or(null, undefined, true), {
|
|
164
208
|
anyOf: [{ const: null }, { not: {} }, { const: true }],
|
|
165
209
|
}),
|
|
166
|
-
literalAbsorbed: eq(or(
|
|
167
|
-
duplicateLiteral: eq(or(
|
|
210
|
+
literalAbsorbed: eq(or(42, number), { type: 'number' }),
|
|
211
|
+
duplicateLiteral: eq(or(1, 1), { const: 1 }),
|
|
168
212
|
never: eq(never, { not: {} }),
|
|
213
|
+
// a closed tuple declaring nothing is the empty array
|
|
169
214
|
emptyTuple: eq(/** @type {const} */ ([]), { type: 'array', items: false }),
|
|
170
|
-
//
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
215
|
+
// an open one declaring nothing is the whole array kind
|
|
216
|
+
openEmptyTuple: eq(open(/** @type {const} */ ([])), { type: 'array' }),
|
|
217
|
+
// a longer tuple pattern is included in a shorter one when both are
|
|
218
|
+
// open; closed, the two lengths are disjoint and both patterns stay
|
|
219
|
+
coverageCollapse: eq(
|
|
220
|
+
or(open([number, number]), open([number])),
|
|
221
|
+
{
|
|
222
|
+
type: 'array',
|
|
223
|
+
prefixItems: [{ type: 'number' }],
|
|
224
|
+
minItems: 1,
|
|
225
|
+
items: {},
|
|
226
|
+
}),
|
|
227
|
+
noCollapseWhenClosed: eq(
|
|
228
|
+
or(/** @type {const} */ ([number, number]), /** @type {const} */ ([number])),
|
|
229
|
+
{
|
|
230
|
+
anyOf: [
|
|
231
|
+
{
|
|
232
|
+
type: 'array',
|
|
233
|
+
prefixItems: [{ type: 'number' }],
|
|
234
|
+
minItems: 1,
|
|
235
|
+
items: false,
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
type: 'array',
|
|
239
|
+
prefixItems: [{ type: 'number' }, { type: 'number' }],
|
|
240
|
+
minItems: 2,
|
|
241
|
+
items: false,
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
}),
|
|
175
245
|
commutative: () => {
|
|
176
246
|
const a = serialize(toJsonSchema(or(string, number)))
|
|
177
247
|
const b = serialize(toJsonSchema(or(number, string)))
|
|
@@ -193,6 +263,7 @@ export const proof = {
|
|
|
193
263
|
optionalRecursiveProperty: eq(/** @type {const} */ ({ p: option(list) }), {
|
|
194
264
|
type: 'object',
|
|
195
265
|
properties: { p: { type: 'array', items: listRef } },
|
|
266
|
+
additionalProperties: { not: {} },
|
|
196
267
|
$defs: { list: listDef },
|
|
197
268
|
}),
|
|
198
269
|
revisionLock: eq(lock, {
|
|
@@ -215,6 +286,7 @@ export const proof = {
|
|
|
215
286
|
type: 'object',
|
|
216
287
|
properties: { name: { type: 'string' } },
|
|
217
288
|
required: ['name'],
|
|
289
|
+
additionalProperties: { not: {} },
|
|
218
290
|
}
|
|
219
291
|
eq(/** @type {const} */ ([person, person]), {
|
|
220
292
|
type: 'array',
|
|
@@ -24,36 +24,14 @@ import { codePointToString, stringToCodePointList } from '../../../text/utf16/mo
|
|
|
24
24
|
import { errorMask } from '../../../text/code_point/module.f.mjs'
|
|
25
25
|
import { definedEntries, isObject } from '../../../types/object/module.f.mjs'
|
|
26
26
|
import { compose, fn } from '../../../types/function/module.f.mjs'
|
|
27
|
-
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
ff,
|
|
31
|
-
hexDigitCodePoint,
|
|
32
|
-
ht,
|
|
33
|
-
lf,
|
|
34
|
-
quotationMark,
|
|
35
|
-
reverseSolidus,
|
|
36
|
-
space,
|
|
37
|
-
} from '../../../text/ascii/module.f.mjs'
|
|
27
|
+
import { hexDigitCodePoint, space } from '../../../text/ascii/module.f.mjs'
|
|
28
|
+
import { codePointToEscape } from '../../../js/string_escape/module.f.mjs'
|
|
29
|
+
import { map as nullableMap } from '../../../types/nullable/module.f.mjs'
|
|
38
30
|
|
|
39
31
|
const jsonStringify = JSON.stringify
|
|
40
32
|
|
|
41
33
|
const { fromCharCode } = String
|
|
42
34
|
|
|
43
|
-
/**
|
|
44
|
-
* The code points JSON gives a two-character escape. Every other code point
|
|
45
|
-
* below `space` has no short form and goes through `unicodeEscape` instead.
|
|
46
|
-
*/
|
|
47
|
-
const escapeTable = /** @type {const} */ ({
|
|
48
|
-
[backspace]: '\\b',
|
|
49
|
-
[ht]: '\\t',
|
|
50
|
-
[lf]: '\\n',
|
|
51
|
-
[ff]: '\\f',
|
|
52
|
-
[cr]: '\\r',
|
|
53
|
-
[quotationMark]: '\\"',
|
|
54
|
-
[reverseSolidus]: '\\\\',
|
|
55
|
-
})
|
|
56
|
-
|
|
57
35
|
/** @type {(value: number) => string} */
|
|
58
36
|
const hexDigit = value => fromCharCode(hexDigitCodePoint(value))
|
|
59
37
|
|
|
@@ -65,6 +43,16 @@ const hexDigit = value => fromCharCode(hexDigitCodePoint(value))
|
|
|
65
43
|
const unicodeEscape = unit =>
|
|
66
44
|
`\\u${hexDigit(unit >> 12 & 0xf)}${hexDigit(unit >> 8 & 0xf)}${hexDigit(unit >> 4 & 0xf)}${hexDigit(unit & 0xf)}`
|
|
67
45
|
|
|
46
|
+
/**
|
|
47
|
+
* The two-character escape a letter spells, projected over the lookup's
|
|
48
|
+
* `null`. Bound here rather than inside `escapeCodePoint`: it depends on
|
|
49
|
+
* nothing that varies per code point, and `escapeCodePoint` runs once per
|
|
50
|
+
* character of every string serialized.
|
|
51
|
+
*
|
|
52
|
+
* @type {(letter: number | null) => string | null}
|
|
53
|
+
*/
|
|
54
|
+
const simpleEscape = nullableMap(letter => `\\${codePointToString(letter)}`)
|
|
55
|
+
|
|
68
56
|
/**
|
|
69
57
|
* Escapes one decoded code point. A code point tagged with `errorMask` is an
|
|
70
58
|
* unpaired surrogate, which well-formed JSON stringification (ES2019) emits as
|
|
@@ -76,7 +64,7 @@ const unicodeEscape = unit =>
|
|
|
76
64
|
const escapeCodePoint = codePoint =>
|
|
77
65
|
(codePoint & errorMask) !== 0
|
|
78
66
|
? unicodeEscape(codePoint & 0xffff)
|
|
79
|
-
:
|
|
67
|
+
: simpleEscape(codePointToEscape(codePoint))
|
|
80
68
|
?? (codePoint < space ? unicodeEscape(codePoint) : codePointToString(codePoint))
|
|
81
69
|
|
|
82
70
|
/**
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* `Unknown` is written by hand rather than derived, so that the recursion
|
|
6
6
|
* reads directly, and is then pinned against the rtti schemas in the sibling
|
|
7
7
|
* [`./rtti/module.f.mjs`](./rtti/module.f.mjs) with
|
|
8
|
-
* `Assert<
|
|
8
|
+
* `Assert<Check<Unknown, typeof unknown>>`. The pin is what keeps the two
|
|
9
9
|
* descriptions of the same data model from drifting apart — and it holds the
|
|
10
10
|
* `Tree<Primitive>` spelling to the same data model the schemas describe.
|
|
11
11
|
*
|
|
@@ -41,7 +41,12 @@ export declare const dialect: 'vnd.fjs.lock';
|
|
|
41
41
|
/** The media type derived from {@link dialect}: `application/vnd.fjs.lock+json`. */
|
|
42
42
|
export declare const mediaType: "application/vnd.fjs.lock+json";
|
|
43
43
|
/**
|
|
44
|
-
* rtti schema for a `lock` BLOB: the dialect tag and the map
|
|
44
|
+
* rtti schema for a `lock` BLOB: the dialect tag and the map.
|
|
45
|
+
*
|
|
46
|
+
* `open`, and deliberately so: a bare struct is closed, so an older reader
|
|
47
|
+
* would reject a blob a newer writer had added a field to, and the versioning
|
|
48
|
+
* rule in `../revision/README.md` — additive extension keeps the tag — needs
|
|
49
|
+
* that older reader to accept it. Do not drop the wrapper.
|
|
45
50
|
*
|
|
46
51
|
* `lock` is `fjs/media/revision`'s own schema, so the shared form admits
|
|
47
52
|
* exactly the maps the inline form does, to the same depth, with the same
|
|
@@ -54,10 +59,10 @@ export declare const mediaType: "application/vnd.fjs.lock+json";
|
|
|
54
59
|
* [Composition](./README.md#composition)), so following a reference always
|
|
55
60
|
* terminates in one step.
|
|
56
61
|
*/
|
|
57
|
-
export declare const lockSchema: {
|
|
62
|
+
export declare const lockSchema: import("../../types/rtti/types.ts").Rest<{
|
|
58
63
|
readonly dialect: "vnd.fjs.lock";
|
|
59
64
|
readonly lock: import("../revision/types.ts").LockSchema;
|
|
60
|
-
}
|
|
65
|
+
}, import("../../types/rtti/types.ts").Unknown>;
|
|
61
66
|
/** Serializes a lock blob canonically, recursively sorting every object's property names.
|
|
62
67
|
* @type {(lock: Lock) => string}
|
|
63
68
|
*/
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
* @import { Lock, LockError } from './types.ts'
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
|
+
import { open } from '../../types/rtti/module.f.mjs'
|
|
33
34
|
import { parse as rttiParse } from '../../types/rtti/parse/module.f.mjs'
|
|
34
35
|
import { parse as parseJson, stringify } from '../json/module.f.mjs'
|
|
35
36
|
import { error, ok, okThen } from '../../types/result/module.f.mjs'
|
|
@@ -47,7 +48,12 @@ export const dialect = /** @type {const} */ ('vnd.fjs.lock')
|
|
|
47
48
|
export const mediaType = /** @type {const} */ (`application/${dialect}+json`)
|
|
48
49
|
|
|
49
50
|
/**
|
|
50
|
-
* rtti schema for a `lock` BLOB: the dialect tag and the map
|
|
51
|
+
* rtti schema for a `lock` BLOB: the dialect tag and the map.
|
|
52
|
+
*
|
|
53
|
+
* `open`, and deliberately so: a bare struct is closed, so an older reader
|
|
54
|
+
* would reject a blob a newer writer had added a field to, and the versioning
|
|
55
|
+
* rule in `../revision/README.md` — additive extension keeps the tag — needs
|
|
56
|
+
* that older reader to accept it. Do not drop the wrapper.
|
|
51
57
|
*
|
|
52
58
|
* `lock` is `fjs/media/revision`'s own schema, so the shared form admits
|
|
53
59
|
* exactly the maps the inline form does, to the same depth, with the same
|
|
@@ -60,10 +66,10 @@ export const mediaType = /** @type {const} */ (`application/${dialect}+json`)
|
|
|
60
66
|
* [Composition](./README.md#composition)), so following a reference always
|
|
61
67
|
* terminates in one step.
|
|
62
68
|
*/
|
|
63
|
-
export const lockSchema = /** @type {const} */ ({
|
|
69
|
+
export const lockSchema = open(/** @type {const} */ ({
|
|
64
70
|
dialect,
|
|
65
71
|
lock,
|
|
66
|
-
})
|
|
72
|
+
}))
|
|
67
73
|
|
|
68
74
|
/** Serializes a lock blob canonically, recursively sorting every object's property names.
|
|
69
75
|
* @type {(lock: Lock) => string}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @import { Object as JsonObject } from '../json/types.ts'
|
|
3
|
-
* @import { LockMap } from '
|
|
3
|
+
* @import { LockMap } from '../revision/types.ts'
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { assert, assertEq } from '../../asserts/module.f.mjs'
|
|
@@ -89,7 +89,7 @@ export const proof = {
|
|
|
89
89
|
},
|
|
90
90
|
|
|
91
91
|
// No `subject`, `parents`, `generation` or `archived`: this dialect is
|
|
92
|
-
// a value, not a step.
|
|
92
|
+
// a value, not a step. `lockSchema` says `open`, so such fields are
|
|
93
93
|
// ignored rather than rejected — the additive forward-compatibility
|
|
94
94
|
// path, the same one the revision dialect relies on.
|
|
95
95
|
revisionFieldsIgnored: () => {
|
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
* Type-level API for `fjs/media/lock/module.f.mjs`: `Lock` and `LockError`.
|
|
3
3
|
*
|
|
4
4
|
* The map type itself is not restated here — it is `fjs/media/revision`'s
|
|
5
|
-
* `LockMap
|
|
6
|
-
* import, and so nothing can define a second, drifting spelling of it.
|
|
5
|
+
* `LockMap`; import it from there directly rather than through this module.
|
|
7
6
|
*/
|
|
8
7
|
import type { ValidationError } from '../../types/rtti/common/types.ts';
|
|
9
8
|
import type { Ts } from '../../types/rtti/ts/types.ts';
|
|
10
9
|
import type { lockSchema } from './module.f.mjs';
|
|
11
|
-
export type { LockMap } from '../revision/types.ts';
|
|
12
10
|
/** The TypeScript type derived from `lockSchema` — the single source of truth. */
|
|
13
11
|
export type Lock = Ts<typeof lockSchema>;
|
|
14
12
|
/** Either a structural validation error or a semantic (hash) error message. */
|
package/fjs/media/module.f.d.mts
CHANGED
|
@@ -44,14 +44,14 @@
|
|
|
44
44
|
*
|
|
45
45
|
* @import { Vec } from '../types/bit_vec/types.ts'
|
|
46
46
|
* @import { DetectMeta } from './type/types.ts'
|
|
47
|
-
* @import { Struct } from '../types/rtti/types.ts'
|
|
47
|
+
* @import { Rest, Struct, Type } from '../types/rtti/types.ts'
|
|
48
48
|
* @import { Ts, Unknown } from '../types/rtti/ts/types.ts'
|
|
49
|
-
* @import {
|
|
49
|
+
* @import { ValidateE } from '../types/rtti/common/types.ts'
|
|
50
50
|
* @import { DialectEntry } from './types.ts'
|
|
51
51
|
*/
|
|
52
52
|
import type { Vec } from '../types/bit_vec/types.ts';
|
|
53
53
|
import type { DetectMeta } from './type/types.ts';
|
|
54
|
-
import type { Struct } from '../types/rtti/types.ts';
|
|
54
|
+
import type { Rest, Struct, Type } from '../types/rtti/types.ts';
|
|
55
55
|
import type { Ts } from '../types/rtti/ts/types.ts';
|
|
56
56
|
import type { DialectEntry } from './types.ts';
|
|
57
57
|
/**
|
|
@@ -87,21 +87,28 @@ import type { DialectEntry } from './types.ts';
|
|
|
87
87
|
* not.) Registering a name that is not a valid RFC 6838 restricted-name yields
|
|
88
88
|
* a malformed media type in the registrant's own results, and nowhere else.
|
|
89
89
|
*
|
|
90
|
-
* The constraint is `Struct` — every member must be a real rtti
|
|
91
|
-
* is what rejects a member like `() => 42` at compile time (rtti
|
|
92
|
-
* as a thunk and `match` would *throw* on the first blob rather
|
|
93
|
-
* `false`). TypeScript cannot also require a direct string
|
|
94
|
-
* under that constraint, so that half is asserted here
|
|
95
|
-
* when the entry is constructed. A thunk-form `dialect`
|
|
90
|
+
* The container's constraint is `Struct` — every member must be a real rtti
|
|
91
|
+
* `Type`, which is what rejects a member like `() => 42` at compile time (rtti
|
|
92
|
+
* would read it as a thunk and `match` would *throw* on the first blob rather
|
|
93
|
+
* than return `false`). TypeScript cannot also require a direct string
|
|
94
|
+
* `dialect` member under that constraint, so that half is asserted here
|
|
95
|
+
* instead: loudly, once, when the entry is constructed. A thunk-form `dialect`
|
|
96
96
|
* (`() => ['const', 'x']`) is a perfectly valid rtti schema, it just is not
|
|
97
97
|
* registerable — write the string directly, as `revisionSchema` does.
|
|
98
98
|
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
99
|
+
* The schema is a **container with a stated rest** rather than a bare struct,
|
|
100
|
+
* and every dialect in this repo states `open`. A bare struct is closed, so an
|
|
101
|
+
* older reader would reject a blob a newer writer had added a field to, which
|
|
102
|
+
* is precisely the fail-closed misread the additive-extension rule in
|
|
103
|
+
* `./revision/README.md` exists to avoid. Requiring the wrapper here is what
|
|
104
|
+
* makes that a decision a registrant states rather than one they inherit.
|
|
105
|
+
*
|
|
106
|
+
* @template {Struct} S
|
|
107
|
+
* @param {Rest<S, Type>} type
|
|
108
|
+
* @param {(_: Ts<S>) => boolean} [extraValidate]
|
|
102
109
|
* @returns {DialectEntry}
|
|
103
110
|
*/
|
|
104
|
-
export declare const dialectEntry: <
|
|
111
|
+
export declare const dialectEntry: <S extends Struct>(type: Rest<S, Type>, extraValidate?: (_: Ts<S>) => boolean) => DialectEntry;
|
|
105
112
|
/**
|
|
106
113
|
* Classifies a whole buffered `Vec` against `dialects`, returning the same
|
|
107
114
|
* three-way `{ length, mime_type, type }` shape as `fjs/media/type`
|
package/fjs/media/module.f.mjs
CHANGED
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
*
|
|
45
45
|
* @import { Vec } from '../types/bit_vec/types.ts'
|
|
46
46
|
* @import { DetectMeta } from './type/types.ts'
|
|
47
|
-
* @import { Struct } from '../types/rtti/types.ts'
|
|
47
|
+
* @import { Rest, Struct, Type } from '../types/rtti/types.ts'
|
|
48
48
|
* @import { Ts, Unknown } from '../types/rtti/ts/types.ts'
|
|
49
|
-
* @import {
|
|
49
|
+
* @import { ValidateE } from '../types/rtti/common/types.ts'
|
|
50
50
|
* @import { DialectEntry } from './types.ts'
|
|
51
51
|
*/
|
|
52
52
|
|
|
@@ -61,9 +61,13 @@ const always = () => true
|
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* Structural validation followed by the dialect's own refinement.
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
64
|
+
*
|
|
65
|
+
* Typed over the **erased** `ValidateE`: a `T extends Type` template would
|
|
66
|
+
* instantiate `Ts<Type>` here and raise TS2589. {@link dialectEntry} states
|
|
67
|
+
* the precise `extraValidate` type its callers are held to.
|
|
68
|
+
*
|
|
69
|
+
* @param {ValidateE} v
|
|
70
|
+
* @returns {(extraValidate: (_: any) => boolean) => (u: Unknown) => boolean}
|
|
67
71
|
*/
|
|
68
72
|
const matchWith = v => extraValidate => u => {
|
|
69
73
|
const [tag, value] = v(u)
|
|
@@ -103,24 +107,33 @@ const matchWith = v => extraValidate => u => {
|
|
|
103
107
|
* not.) Registering a name that is not a valid RFC 6838 restricted-name yields
|
|
104
108
|
* a malformed media type in the registrant's own results, and nowhere else.
|
|
105
109
|
*
|
|
106
|
-
* The constraint is `Struct` — every member must be a real rtti
|
|
107
|
-
* is what rejects a member like `() => 42` at compile time (rtti
|
|
108
|
-
* as a thunk and `match` would *throw* on the first blob rather
|
|
109
|
-
* `false`). TypeScript cannot also require a direct string
|
|
110
|
-
* under that constraint, so that half is asserted here
|
|
111
|
-
* when the entry is constructed. A thunk-form `dialect`
|
|
110
|
+
* The container's constraint is `Struct` — every member must be a real rtti
|
|
111
|
+
* `Type`, which is what rejects a member like `() => 42` at compile time (rtti
|
|
112
|
+
* would read it as a thunk and `match` would *throw* on the first blob rather
|
|
113
|
+
* than return `false`). TypeScript cannot also require a direct string
|
|
114
|
+
* `dialect` member under that constraint, so that half is asserted here
|
|
115
|
+
* instead: loudly, once, when the entry is constructed. A thunk-form `dialect`
|
|
112
116
|
* (`() => ['const', 'x']`) is a perfectly valid rtti schema, it just is not
|
|
113
117
|
* registerable — write the string directly, as `revisionSchema` does.
|
|
114
118
|
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
119
|
+
* The schema is a **container with a stated rest** rather than a bare struct,
|
|
120
|
+
* and every dialect in this repo states `open`. A bare struct is closed, so an
|
|
121
|
+
* older reader would reject a blob a newer writer had added a field to, which
|
|
122
|
+
* is precisely the fail-closed misread the additive-extension rule in
|
|
123
|
+
* `./revision/README.md` exists to avoid. Requiring the wrapper here is what
|
|
124
|
+
* makes that a decision a registrant states rather than one they inherit.
|
|
125
|
+
*
|
|
126
|
+
* @template {Struct} S
|
|
127
|
+
* @param {Rest<S, Type>} type
|
|
128
|
+
* @param {(_: Ts<S>) => boolean} [extraValidate]
|
|
118
129
|
* @returns {DialectEntry}
|
|
119
130
|
*/
|
|
120
131
|
export const dialectEntry = (type, extraValidate = always) => {
|
|
121
|
-
const
|
|
132
|
+
const [, container] = type()
|
|
133
|
+
const { dialect } = /** @type {Struct} */ (container)
|
|
122
134
|
assert(typeof dialect === 'string', 'dialectEntry: schema has no direct string `dialect` member')
|
|
123
|
-
|
|
135
|
+
const v = /** @type {ValidateE} */ (rttiParse(type))
|
|
136
|
+
return { dialect, match: matchWith(v)(extraValidate) }
|
|
124
137
|
}
|
|
125
138
|
|
|
126
139
|
/**
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* The format is deliberately minimal: the dialect tag, the text, and
|
|
6
6
|
* optionally the subjects the item depends on and a priority. Everything
|
|
7
7
|
* else a richer item needs — a title, tags, dates, a status — is a future
|
|
8
|
-
* **optional** field:
|
|
9
|
-
*
|
|
10
|
-
* versioning rule in `fjs/media/revision/README.md`),
|
|
11
|
-
* what keeps every extension additive.
|
|
8
|
+
* **optional** field: {@link noteSchema} says `open`, so an older reader
|
|
9
|
+
* accepts a blob a newer writer has added fields to and additive extension
|
|
10
|
+
* keeps the tag (see the versioning rule in `fjs/media/revision/README.md`),
|
|
11
|
+
* and starting minimal is what keeps every extension additive.
|
|
12
12
|
*
|
|
13
13
|
* Like `vnd.fjs.lock`, a note is a **value**, not a step: no timestamps, no
|
|
14
14
|
* author, no history of its own. Edits over time are ordinary
|
|
@@ -85,12 +85,19 @@ export declare const mediaType: "application/vnd.fjs.note+json";
|
|
|
85
85
|
* rather than misreading it.
|
|
86
86
|
*/
|
|
87
87
|
export declare const priorities: readonly ['P1', 'P2', 'P3', 'P4', 'P5'];
|
|
88
|
-
|
|
88
|
+
/**
|
|
89
|
+
* `open`, and that is the extension strategy rather than a default: a bare
|
|
90
|
+
* struct is closed, so an older reader would reject a blob a newer writer had
|
|
91
|
+
* added a field to, and the versioning rule in
|
|
92
|
+
* `../revision/README.md` — additive extension keeps the tag — depends on the
|
|
93
|
+
* older reader accepting it. Do not drop the wrapper.
|
|
94
|
+
*/
|
|
95
|
+
export declare const noteSchema: import("../../types/rtti/types.ts").Rest<{
|
|
89
96
|
readonly dialect: "vnd.fjs.note";
|
|
90
97
|
readonly text: import("../../types/rtti/types.ts")._Type0<"string">;
|
|
91
98
|
readonly dependencies: import("../../types/rtti/types.ts").Or<readonly [import("../../types/rtti/types.ts").Type1<"array", import("../../types/rtti/types.ts")._Type0<"string">>, undefined]>;
|
|
92
|
-
readonly priority: import("../../types/rtti/types.ts").Or<readonly [import("../../types/rtti/types.ts").Or<["P1", "P2", "P3", "P4", "P5"]>, undefined]>;
|
|
93
|
-
}
|
|
99
|
+
readonly priority: import("../../types/rtti/types.ts").Or<readonly [import("../../types/rtti/types.ts").Or<readonly ["P1", "P2", "P3", "P4", "P5"]>, undefined]>;
|
|
100
|
+
}, import("../../types/rtti/types.ts").Unknown>;
|
|
94
101
|
/** Serializes a note canonically, sorting every object's property names.
|
|
95
102
|
* @type {(note: Note) => string}
|
|
96
103
|
*/
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* The format is deliberately minimal: the dialect tag, the text, and
|
|
6
6
|
* optionally the subjects the item depends on and a priority. Everything
|
|
7
7
|
* else a richer item needs — a title, tags, dates, a status — is a future
|
|
8
|
-
* **optional** field:
|
|
9
|
-
*
|
|
10
|
-
* versioning rule in `fjs/media/revision/README.md`),
|
|
11
|
-
* what keeps every extension additive.
|
|
8
|
+
* **optional** field: {@link noteSchema} says `open`, so an older reader
|
|
9
|
+
* accepts a blob a newer writer has added fields to and additive extension
|
|
10
|
+
* keeps the tag (see the versioning rule in `fjs/media/revision/README.md`),
|
|
11
|
+
* and starting minimal is what keeps every extension additive.
|
|
12
12
|
*
|
|
13
13
|
* Like `vnd.fjs.lock`, a note is a **value**, not a step: no timestamps, no
|
|
14
14
|
* author, no history of its own. Edits over time are ordinary
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
* @import { Note, NoteError } from './types.ts'
|
|
33
33
|
*/
|
|
34
34
|
|
|
35
|
-
import { array, option, or, string } from '../../types/rtti/module.f.mjs'
|
|
35
|
+
import { array, open, option, or, string } from '../../types/rtti/module.f.mjs'
|
|
36
36
|
import { parse as rttiParse } from '../../types/rtti/parse/module.f.mjs'
|
|
37
37
|
import { parse as parseJson, stringify } from '../json/module.f.mjs'
|
|
38
38
|
import { okThen } from '../../types/result/module.f.mjs'
|
|
@@ -91,12 +91,19 @@ export const mediaType = /** @type {const} */ (`application/${dialect}+json`)
|
|
|
91
91
|
*/
|
|
92
92
|
export const priorities = /** @type {const} */ (['P1', 'P2', 'P3', 'P4', 'P5'])
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
/**
|
|
95
|
+
* `open`, and that is the extension strategy rather than a default: a bare
|
|
96
|
+
* struct is closed, so an older reader would reject a blob a newer writer had
|
|
97
|
+
* added a field to, and the versioning rule in
|
|
98
|
+
* `../revision/README.md` — additive extension keeps the tag — depends on the
|
|
99
|
+
* older reader accepting it. Do not drop the wrapper.
|
|
100
|
+
*/
|
|
101
|
+
export const noteSchema = open(/** @type {const} */ ({
|
|
95
102
|
dialect,
|
|
96
103
|
text: string,
|
|
97
104
|
dependencies: option(array(string)),
|
|
98
105
|
priority: option(or(...priorities)),
|
|
99
|
-
})
|
|
106
|
+
}))
|
|
100
107
|
|
|
101
108
|
/** Serializes a note canonically, sorting every object's property names.
|
|
102
109
|
* @type {(note: Note) => string}
|
|
@@ -89,7 +89,7 @@ export const proof = {
|
|
|
89
89
|
assertEq(t, 'error')
|
|
90
90
|
},
|
|
91
91
|
|
|
92
|
-
//
|
|
92
|
+
// `noteSchema` says `open`, so unknown fields are ignored rather than
|
|
93
93
|
// rejected — the additive forward-compatibility path every future
|
|
94
94
|
// extension (title, tags, dates, …) relies on.
|
|
95
95
|
unknownFieldsIgnored: () => {
|
package/fjs/media/proof.f.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { detect, dialectEntry } from './module.f.mjs'
|
|
|
8
8
|
import { dialect, revisionDialect } from './revision/module.f.mjs'
|
|
9
9
|
import { dialect as lockDialectName, lockDialect } from './lock/module.f.mjs'
|
|
10
10
|
import { dialect as noteDialectName, noteDialect } from './note/module.f.mjs'
|
|
11
|
-
import { number, string } from '../types/rtti/module.f.mjs'
|
|
11
|
+
import { number, open, string } from '../types/rtti/module.f.mjs'
|
|
12
12
|
|
|
13
13
|
// All test strings here are ASCII, so char code === UTF-8 byte value.
|
|
14
14
|
/** @type {(s: string) => Vec} */
|
|
@@ -24,10 +24,10 @@ const dialects = [revisionDialect, lockDialect, noteDialect]
|
|
|
24
24
|
const detectRevision = detect(dialects)
|
|
25
25
|
|
|
26
26
|
/** A dialect name outside `vnd.fjs.*` — registerable, and detected as itself. */
|
|
27
|
-
const gadgetSchema = /** @type {const} */ ({
|
|
27
|
+
const gadgetSchema = open(/** @type {const} */ ({
|
|
28
28
|
dialect: 'application.gadget',
|
|
29
29
|
size: number,
|
|
30
|
-
})
|
|
30
|
+
}))
|
|
31
31
|
|
|
32
32
|
/** @type {DialectEntry} */
|
|
33
33
|
const gadgetDialect = dialectEntry(gadgetSchema)
|
|
@@ -170,9 +170,9 @@ export const proof = {
|
|
|
170
170
|
// The `dialect` member must be a direct string const. A thunk-form one
|
|
171
171
|
// is a valid rtti schema but is not registerable, and `dialectEntry`
|
|
172
172
|
// says so at registration rather than per blob.
|
|
173
|
-
thunkDialectMember: () => dialectEntry({ dialect: string }),
|
|
173
|
+
thunkDialectMember: () => dialectEntry(open({ dialect: string })),
|
|
174
174
|
|
|
175
175
|
// A schema with no `dialect` member at all is likewise refused.
|
|
176
|
-
noDialectMember: () => dialectEntry({ text: string }),
|
|
176
|
+
noDialectMember: () => dialectEntry(open({ text: string })),
|
|
177
177
|
},
|
|
178
178
|
}
|