+1
-2
deno.json
+1
-2
deno.json
···
12
12
"dev:cli": "deno run --allow-all packages/cli/src/mod.ts",
13
13
"build:cli": "cd packages/cli && deno compile --allow-all --output bin/slices src/mod.ts",
14
14
"build:lexicon": "cd packages/lexicon && deno task build",
15
+
"build:lexicon-intellisense": "cd ./packages/lexicon-rs && wasm-pack build --target web --features wasm && cp pkg/* ../lexicon-intellisense/wasm/",
15
16
"codegen:cli": "deno task dev:cli codegen --lexicons ./lexicons --slice at://did:plc:bcgltzqazw5tb6k2g3ttenbj/network.slices.slice/3lymhd4jhrd2z --output ./packages/cli/src/generated_client.ts --include-slices",
16
17
"codegen:frontend": "deno task dev:cli codegen --lexicons ./lexicons --slice at://did:plc:bcgltzqazw5tb6k2g3ttenbj/network.slices.slice/3lymhd4jhrd2z --output ./frontend/src/client.ts --include-slices",
17
18
"dev:frontend": "cd frontend && deno task dev",
18
-
"build:lexicon-intellisense-wasm": "cd ./packages/lexicon-rs && wasm-pack build --target web --features wasm && cp pkg/* ../lexicon-intellisense/wasm/",
19
-
"build:lexicon-intellisense-lexicon": "deno bundle ./packages/lexicon/mod.ts -o ./packages/lexicon-intellisense/src/slices_lexicon.js",
20
19
"test": "deno test --allow-all packages/*/tests/ packages/*/src/ frontend/src/",
21
20
"check": "deno check packages/*/src/ packages/*/mod.ts packages/*/src/mod.ts frontend/src/**/*.ts frontend/src/**/*.tsx",
22
21
"fmt": "deno fmt packages/ frontend/",
+2
-2
packages/lexicon-intellisense/package.json
+2
-2
packages/lexicon-intellisense/package.json
···
1
1
{
2
2
"name": "lexicon-intellisense",
3
-
"version": "0.2.0",
3
+
"version": "0.2.1",
4
4
"description": "VS Code IntelliSense support for AT Protocol lexicon JSON files",
5
5
"main": "./out/extension.js",
6
6
"license": "MIT",
···
59
59
}
60
60
},
61
61
"scripts": {
62
-
"compile": "tsc -p ./",
62
+
"compile": "rm -rf ./out && tsc -p ./",
63
63
"watch": "tsc -watch -p ./"
64
64
},
65
65
"devDependencies": {
+29
-34
packages/lexicon-intellisense/src/language-server.ts
+29
-34
packages/lexicon-intellisense/src/language-server.ts
···
7
7
ServerOptions,
8
8
TransportKind,
9
9
} from "vscode-languageclient/node";
10
-
// @ts-ignore - No declaration file for bundled module
11
10
import {
12
11
LexiconValidator,
13
12
ValidationError,
14
13
validate,
15
14
validateWithDetails,
16
-
// @ts-ignore
17
-
} from "./slices_lexicon.js";
18
-
19
-
// Type definitions for lexicon documents
20
-
interface LexiconDoc {
21
-
id: string;
22
-
defs: Record<string, unknown>;
23
-
lexicon?: number;
24
-
}
15
+
type LexiconDoc,
16
+
} from "./lexicon";
25
17
26
18
export class LexiconLanguageServer {
27
19
private client: LanguageClient | undefined;
···
186
178
const lexicon = JSON.parse(content);
187
179
console.log(lexicon.id, "loaded from", filePath);
188
180
if (lexicon.id && lexicon.defs) {
189
-
lexicons.push(lexicon as LexiconDoc);
181
+
lexicons.push(lexicon);
190
182
idToFileMap.set(lexicon.id, filePath);
191
183
}
192
184
} catch (error) {
···
204
196
// Attribute errors to specific files
205
197
if (errorsByLexiconId) {
206
198
for (const [lexiconId, errors] of Object.entries(errorsByLexiconId)) {
207
-
const filePath = idToFileMap.get(lexiconId);
208
-
if (filePath) {
209
-
const uri = vscode.Uri.file(filePath);
210
-
const existingDiagnostics =
211
-
this.diagnosticCollection.get(uri) || [];
212
-
const diagnostics = [...existingDiagnostics];
199
+
const filePath = idToFileMap.get(lexiconId);
200
+
if (filePath) {
201
+
const uri = vscode.Uri.file(filePath);
202
+
const existingDiagnostics =
203
+
this.diagnosticCollection.get(uri) || [];
204
+
const diagnostics = [...existingDiagnostics];
213
205
214
-
// Add each error as a diagnostic
215
-
for (const error of errors as string[]) {
216
-
diagnostics.push(
217
-
this.createDiagnostic(
218
-
new vscode.Range(0, 0, 0, 0),
219
-
error,
220
-
vscode.DiagnosticSeverity.Error
221
-
)
222
-
);
206
+
// Add each error as a diagnostic
207
+
for (const error of errors as string[]) {
208
+
diagnostics.push(
209
+
this.createDiagnostic(
210
+
new vscode.Range(0, 0, 0, 0),
211
+
error,
212
+
vscode.DiagnosticSeverity.Error
213
+
)
214
+
);
215
+
}
216
+
217
+
this.diagnosticCollection.set(uri, diagnostics);
223
218
}
224
-
225
-
this.diagnosticCollection.set(uri, diagnostics);
226
-
}
227
219
}
228
220
}
229
221
230
-
const totalErrors = errorsByLexiconId ? Object.values(errorsByLexiconId).reduce(
231
-
(sum: number, errors) => sum + (errors as string[]).length,
232
-
0
233
-
) : 0;
222
+
const totalErrors = errorsByLexiconId
223
+
? Object.values(errorsByLexiconId).reduce(
224
+
(sum: number, errors) => sum + (errors as string[]).length,
225
+
0
226
+
)
227
+
: 0;
234
228
if (totalErrors === 0) {
235
229
console.log(
236
230
`Successfully validated ${lexicons.length} lexicon files`
237
231
);
238
232
} else {
233
+
const errorCount = errorsByLexiconId ? Object.keys(errorsByLexiconId).length : 0;
239
234
console.log(
240
-
`Validation found ${totalErrors} errors across ${errorsByLexiconId.size} lexicons`
235
+
`Validation found ${totalErrors} errors across ${errorCount} lexicons`
241
236
);
242
237
}
243
238
} catch (error) {
+570
packages/lexicon-intellisense/src/lexicon.ts
+570
packages/lexicon-intellisense/src/lexicon.ts
···
1
+
/**
2
+
* AT Protocol Lexicon Validation Library
3
+
*
4
+
* Core implementation for comprehensive validation of AT Protocol lexicon documents and data records.
5
+
* Built on WebAssembly for high performance validation with full AT Protocol compliance.
6
+
*/
7
+
8
+
import init, {
9
+
WasmLexiconValidator,
10
+
validate_string_format,
11
+
is_valid_nsid,
12
+
validate_lexicons_and_get_errors,
13
+
} from "../wasm/slices_lexicon.js";
14
+
15
+
// ============================================================================
16
+
// Module Initialization
17
+
// ============================================================================
18
+
19
+
/** Global WASM initialization state */
20
+
let wasmInitialized = false;
21
+
let wasmInitPromise: Promise<void> | null = null;
22
+
23
+
/**
24
+
* Ensures the WebAssembly module is properly initialized before use.
25
+
* This is called automatically by all public methods.
26
+
*
27
+
* @internal
28
+
*/
29
+
export async function ensureWasmInit(): Promise<void> {
30
+
if (!wasmInitialized) {
31
+
if (!wasmInitPromise) {
32
+
wasmInitPromise = (async () => {
33
+
// Try to load WASM file - works in both Node.js and browser contexts
34
+
try {
35
+
// In Node.js (VS Code extension), use fs to load the file
36
+
if (typeof process !== 'undefined' && process.versions && process.versions.node) {
37
+
const fs = require('fs');
38
+
const path = require('path');
39
+
40
+
// Use __dirname which is available in CommonJS
41
+
const wasmPath = path.join(__dirname, '../wasm/slices_lexicon_bg.wasm');
42
+
const wasmBuffer = fs.readFileSync(wasmPath);
43
+
await init({ module_or_path: wasmBuffer });
44
+
} else {
45
+
// In browser, fetch the WASM file
46
+
const wasmPath = '../wasm/slices_lexicon_bg.wasm';
47
+
const response = await fetch(wasmPath);
48
+
const wasmBuffer = await response.arrayBuffer();
49
+
await init({ module_or_path: wasmBuffer });
50
+
}
51
+
wasmInitialized = true;
52
+
} catch (error) {
53
+
wasmInitPromise = null; // Reset so we can retry
54
+
throw error;
55
+
}
56
+
})();
57
+
}
58
+
await wasmInitPromise;
59
+
}
60
+
}
61
+
62
+
// ============================================================================
63
+
// Types and Interfaces
64
+
// ============================================================================
65
+
66
+
/**
67
+
* Custom error class for lexicon validation failures.
68
+
* Extends the native Error class with validation-specific context.
69
+
*/
70
+
export class ValidationError extends Error {
71
+
/**
72
+
* Creates a new ValidationError instance.
73
+
*
74
+
* @param message - Human-readable error description
75
+
*/
76
+
constructor(message: string) {
77
+
super(message);
78
+
this.name = "ValidationError";
79
+
}
80
+
}
81
+
82
+
/**
83
+
* Represents a complete AT Protocol lexicon document.
84
+
* Contains schema definitions and metadata for a specific collection or service.
85
+
*/
86
+
export interface LexiconDoc {
87
+
/** Unique namespace identifier (NSID) for this lexicon */
88
+
id: string;
89
+
90
+
/** Schema definitions mapping definition names to their schemas */
91
+
defs: Record<string, LexiconDefinition>;
92
+
93
+
/** Lexicon format version (currently 1) */
94
+
lexicon?: number;
95
+
}
96
+
97
+
/**
98
+
* Base lexicon definition interface
99
+
*/
100
+
export interface LexiconDefinition {
101
+
type: string;
102
+
description?: string;
103
+
[key: string]: unknown; // Allow additional properties
104
+
}
105
+
106
+
/**
107
+
* String format types supported by AT Protocol
108
+
*/
109
+
export type StringFormat =
110
+
| "datetime"
111
+
| "uri"
112
+
| "at-uri"
113
+
| "did"
114
+
| "handle"
115
+
| "at-identifier"
116
+
| "nsid"
117
+
| "cid"
118
+
| "language"
119
+
| "tid"
120
+
| "record-key";
121
+
122
+
/**
123
+
* Type alias for validation error results
124
+
*/
125
+
export type ValidationErrors = Record<string, string[]> | null;
126
+
127
+
/**
128
+
* Comprehensive validation result with error details and statistics.
129
+
*/
130
+
export interface ValidationResult {
131
+
/** Whether all lexicons passed validation */
132
+
valid: boolean;
133
+
134
+
/** Map of lexicon IDs to their error messages */
135
+
errors: Record<string, string[]>;
136
+
137
+
/** Total count of all validation errors across all lexicons */
138
+
totalErrors: number;
139
+
140
+
/** Number of lexicons that have validation errors */
141
+
lexiconsWithErrors: number;
142
+
}
143
+
144
+
/**
145
+
* Detailed error context information for debugging validation failures.
146
+
*/
147
+
export interface ErrorContext {
148
+
/** Current path in the schema being validated */
149
+
path: string;
150
+
151
+
/** ID of the lexicon currently being validated */
152
+
current_lexicon: string | null;
153
+
154
+
/** Whether a circular reference was detected */
155
+
has_circular_reference: boolean;
156
+
157
+
/** Stack of references being resolved (for circular detection) */
158
+
reference_stack: string[];
159
+
}
160
+
161
+
// ============================================================================
162
+
// Core Validator Class
163
+
// ============================================================================
164
+
165
+
/**
166
+
* High-performance AT Protocol lexicon validator with resource management.
167
+
*
168
+
* Provides comprehensive validation capabilities including:
169
+
* - Schema structure validation
170
+
* - Cross-reference resolution
171
+
* - Data format validation
172
+
* - Circular dependency detection
173
+
*
174
+
* Implements Disposable for automatic resource cleanup.
175
+
*/
176
+
export class LexiconValidator implements Disposable {
177
+
private wasmValidator: WasmLexiconValidator;
178
+
179
+
/**
180
+
* Creates a new validator instance with the provided lexicon documents.
181
+
*
182
+
* Note: Prefer using the static `create()` method for async initialization.
183
+
*
184
+
* @param lexicons - Array of lexicon documents to validate
185
+
*/
186
+
constructor(lexicons: LexiconDoc[]) {
187
+
const lexiconsJson = JSON.stringify(lexicons);
188
+
this.wasmValidator = new WasmLexiconValidator(lexiconsJson);
189
+
}
190
+
191
+
/**
192
+
* Creates a new validator instance with proper async initialization.
193
+
* Ensures WASM module is loaded before creating the validator.
194
+
*
195
+
* @param lexicons - Array of lexicon documents to validate
196
+
* @returns Promise resolving to a new validator instance
197
+
*
198
+
* @example
199
+
* ```typescript
200
+
* const lexicons = [{ id: "com.example.post", defs: {...} }];
201
+
* const validator = await LexiconValidator.create(lexicons);
202
+
* ```
203
+
*/
204
+
static async create(lexicons: LexiconDoc[]): Promise<LexiconValidator> {
205
+
await ensureWasmInit();
206
+
return new LexiconValidator(lexicons);
207
+
}
208
+
209
+
/**
210
+
* Validates a data record against its collection's lexicon schema.
211
+
*
212
+
* Performs comprehensive validation including:
213
+
* - Type checking
214
+
* - Constraint validation
215
+
* - Format validation
216
+
* - Required field checking
217
+
*
218
+
* @param collection - NSID of the collection (lexicon) to validate against
219
+
* @param record - Data record to validate
220
+
* @throws {ValidationError} If validation fails
221
+
*
222
+
* @example
223
+
* ```typescript
224
+
* validator.validateRecord("com.example.post", {
225
+
* text: "Hello world!",
226
+
* createdAt: "2024-01-01T12:00:00Z"
227
+
* });
228
+
* ```
229
+
*/
230
+
validateRecord(collection: string, record: Record<string, unknown>): void {
231
+
try {
232
+
const recordJson = JSON.stringify(record);
233
+
this.wasmValidator.validate_record(collection, recordJson);
234
+
} catch (error) {
235
+
throw new ValidationError(
236
+
error instanceof Error ? error.message : String(error)
237
+
);
238
+
}
239
+
}
240
+
241
+
/**
242
+
* Validates all lexicon documents and returns comprehensive error information.
243
+
*
244
+
* Uses the enhanced validation system that collects ALL errors for each lexicon,
245
+
* not just the first error encountered.
246
+
*
247
+
* @returns Null if validation passes, or error map if validation fails
248
+
*
249
+
* @example
250
+
* ```typescript
251
+
* const errors = validator.validateLexicons();
252
+
* if (errors) {
253
+
* console.log(`Found errors in ${Object.keys(errors).length} lexicons`);
254
+
* }
255
+
* ```
256
+
*/
257
+
validateLexicons(): Record<string, string[]> | null {
258
+
try {
259
+
const result = this.wasmValidator.validate_lexicons();
260
+
const errorMap = JSON.parse(result);
261
+
262
+
// Return null for success case (no errors)
263
+
if (Object.keys(errorMap).length === 0) {
264
+
return null;
265
+
}
266
+
267
+
return errorMap;
268
+
} catch (error) {
269
+
throw new ValidationError(
270
+
error instanceof Error ? error.message : String(error)
271
+
);
272
+
}
273
+
}
274
+
275
+
/**
276
+
* Checks for unresolved references across the lexicon set.
277
+
*
278
+
* Identifies references (like "$ref": "com.example.collection#definition")
279
+
* that point to non-existent lexicons or definitions.
280
+
*
281
+
* @returns Array of unresolved reference strings
282
+
*
283
+
* @example
284
+
* ```typescript
285
+
* const unresolved = validator.checkReferences();
286
+
* if (unresolved.length > 0) {
287
+
* console.log("Unresolved references:", unresolved);
288
+
* }
289
+
* ```
290
+
*/
291
+
checkReferences(): string[] {
292
+
try {
293
+
const result = this.wasmValidator.check_references();
294
+
return JSON.parse(result);
295
+
} catch (error) {
296
+
throw new ValidationError(
297
+
error instanceof Error ? error.message : String(error)
298
+
);
299
+
}
300
+
}
301
+
302
+
/**
303
+
* Retrieves detailed error context for debugging validation failures.
304
+
*
305
+
* Provides path information, current lexicon context, and circular
306
+
* reference detection state for enhanced debugging.
307
+
*
308
+
* @param path - Schema path to get context for
309
+
* @returns Detailed error context information
310
+
*
311
+
* @example
312
+
* ```typescript
313
+
* const context = validator.getErrorContext("com.example.post#main");
314
+
* console.log(`Validating at path: ${context.path}`);
315
+
* ```
316
+
*/
317
+
getErrorContext(path: string): ErrorContext {
318
+
try {
319
+
const result = this.wasmValidator.get_error_context(path);
320
+
return JSON.parse(result);
321
+
} catch (error) {
322
+
throw new ValidationError(
323
+
error instanceof Error ? error.message : String(error)
324
+
);
325
+
}
326
+
}
327
+
328
+
/**
329
+
* Manually releases WASM resources.
330
+
*
331
+
* Call this when done with the validator to free memory.
332
+
* Automatically called by dispose methods when using `using` syntax.
333
+
*/
334
+
free(): void {
335
+
this.wasmValidator.free();
336
+
}
337
+
338
+
/**
339
+
* Synchronous dispose method for automatic resource cleanup.
340
+
* Called automatically when using `using` keyword.
341
+
*
342
+
* @example
343
+
* ```typescript
344
+
* using validator = await LexiconValidator.create(lexicons);
345
+
* // Automatically cleaned up at end of scope
346
+
* ```
347
+
*/
348
+
[Symbol.dispose](): void {
349
+
this.free();
350
+
}
351
+
352
+
/**
353
+
* Asynchronous dispose method for automatic resource cleanup.
354
+
* Called automatically when using `await using` keyword.
355
+
*/
356
+
async [Symbol.asyncDispose](): Promise<void> {
357
+
await Promise.resolve(this.free());
358
+
}
359
+
}
360
+
361
+
// ============================================================================
362
+
// Standalone Validation Functions
363
+
// ============================================================================
364
+
365
+
/**
366
+
* Validates lexicon documents using the enhanced validation system.
367
+
*
368
+
* This is the primary validation function that collects ALL validation errors
369
+
* for each lexicon, enabling comprehensive error reporting.
370
+
*
371
+
* @param lexicons - Array of lexicon documents to validate
372
+
* @returns Null if validation succeeds, or error map if validation fails
373
+
*
374
+
* @example
375
+
* ```typescript
376
+
* const errors = await validate([
377
+
* { id: "com.example.post", defs: {...} },
378
+
* { id: "com.example.user", defs: {...} }
379
+
* ]);
380
+
*
381
+
* if (errors) {
382
+
* for (const [lexiconId, errorList] of Object.entries(errors)) {
383
+
* console.log(`${lexiconId}: ${errorList.length} errors`);
384
+
* }
385
+
* }
386
+
* ```
387
+
*/
388
+
export async function validate(
389
+
lexicons: LexiconDoc[]
390
+
): Promise<Record<string, string[]> | null> {
391
+
await ensureWasmInit();
392
+
393
+
const lexiconsJson = JSON.stringify(lexicons);
394
+
const result = validate_lexicons_and_get_errors(lexiconsJson);
395
+
const errorMap = JSON.parse(result);
396
+
397
+
// Success case: no errors found
398
+
if (Object.keys(errorMap).length === 0) {
399
+
return null;
400
+
}
401
+
402
+
// Return complete error map with all errors for each lexicon
403
+
return errorMap;
404
+
}
405
+
406
+
/**
407
+
* Enhanced validation function with comprehensive result statistics.
408
+
*
409
+
* Provides detailed validation results including error counts and statistics
410
+
* for better reporting and debugging.
411
+
*
412
+
* @param lexicons - Array of lexicon documents to validate
413
+
* @returns Detailed validation result with statistics
414
+
*
415
+
* @example
416
+
* ```typescript
417
+
* const result = await validateWithDetails(lexicons);
418
+
* console.log(`Validation ${result.valid ? 'passed' : 'failed'}`);
419
+
* console.log(`Total errors: ${result.totalErrors}`);
420
+
* console.log(`Lexicons with errors: ${result.lexiconsWithErrors}`);
421
+
* ```
422
+
*/
423
+
export async function validateWithDetails(
424
+
lexicons: LexiconDoc[]
425
+
): Promise<ValidationResult> {
426
+
const errors = await validate(lexicons);
427
+
428
+
if (errors === null) {
429
+
return {
430
+
valid: true,
431
+
errors: {},
432
+
totalErrors: 0,
433
+
lexiconsWithErrors: 0,
434
+
};
435
+
}
436
+
437
+
const totalErrors = Object.values(errors).reduce(
438
+
(sum, errorArray) => sum + errorArray.length,
439
+
0
440
+
);
441
+
442
+
return {
443
+
valid: false,
444
+
errors,
445
+
totalErrors,
446
+
lexiconsWithErrors: Object.keys(errors).length,
447
+
};
448
+
}
449
+
450
+
/**
451
+
* Validates a single data record against lexicon schemas.
452
+
*
453
+
* Convenience function that creates a temporary validator instance
454
+
* and automatically manages resources.
455
+
*
456
+
* @param lexicons - Array of lexicon documents containing the target schema
457
+
* @param collection - NSID of the collection to validate against
458
+
* @param record - Data record to validate
459
+
* @throws {ValidationError} If validation fails
460
+
*
461
+
* @example
462
+
* ```typescript
463
+
* await validateRecord(lexicons, "com.example.post", {
464
+
* text: "Hello world!",
465
+
* createdAt: "2024-01-01T12:00:00Z"
466
+
* });
467
+
* ```
468
+
*/
469
+
export async function validateRecord(
470
+
lexicons: LexiconDoc[],
471
+
collection: string,
472
+
record: Record<string, unknown>
473
+
): Promise<void> {
474
+
return await withValidator(lexicons, (validator) => {
475
+
validator.validateRecord(collection, record);
476
+
});
477
+
}
478
+
479
+
// ============================================================================
480
+
// Format and Utility Functions
481
+
// ============================================================================
482
+
483
+
/**
484
+
* Validates a string value against a specific AT Protocol format.
485
+
*
486
+
* Supports all AT Protocol string formats including:
487
+
* - datetime (RFC 3339)
488
+
* - uri, at-uri
489
+
* - did, handle
490
+
* - cid, tid
491
+
* - language (BCP 47)
492
+
*
493
+
* @param value - String value to validate
494
+
* @param format - AT Protocol format name
495
+
* @throws {ValidationError} If format validation fails
496
+
*
497
+
* @example
498
+
* ```typescript
499
+
* await validateStringFormat("2024-01-01T12:00:00Z", "datetime");
500
+
* await validateStringFormat("did:plc:example123", "did");
501
+
* ```
502
+
*/
503
+
export async function validateStringFormat(
504
+
value: string,
505
+
format: string
506
+
): Promise<void> {
507
+
await ensureWasmInit();
508
+
try {
509
+
validate_string_format(value, format);
510
+
} catch (error) {
511
+
throw new ValidationError(
512
+
error instanceof Error ? error.message : String(error)
513
+
);
514
+
}
515
+
}
516
+
517
+
/**
518
+
* Checks if a string is a valid NSID (Namespaced Identifier).
519
+
*
520
+
* NSIDs are used throughout AT Protocol to identify lexicons, collections,
521
+
* and procedures. They follow reverse-domain-name format with at least
522
+
* 3 segments (e.g., "com.example.collection").
523
+
*
524
+
* @param nsid - String to validate as NSID
525
+
* @returns True if valid NSID, false otherwise
526
+
*
527
+
* @example
528
+
* ```typescript
529
+
* console.log(await isValidNsid("com.example.post")); // true
530
+
* console.log(await isValidNsid("invalid-nsid")); // false
531
+
* ```
532
+
*/
533
+
export async function isValidNsid(nsid: string): Promise<boolean> {
534
+
await ensureWasmInit();
535
+
return is_valid_nsid(nsid);
536
+
}
537
+
538
+
// ============================================================================
539
+
// Resource Management Utilities
540
+
// ============================================================================
541
+
542
+
/**
543
+
* Utility function for automatic validator lifecycle management.
544
+
*
545
+
* Uses the callback pattern to ensure WASM resources are properly
546
+
* cleaned up, even if an exception occurs during validation.
547
+
*
548
+
* @param lexicons - Array of lexicon documents
549
+
* @param callback - Function to execute with the validator
550
+
* @returns Promise resolving to the callback's return value
551
+
*
552
+
* @example
553
+
* ```typescript
554
+
* const result = await withValidator(lexicons, (validator) => {
555
+
* validator.validateRecord("com.example.post", record);
556
+
* return "validation passed";
557
+
* });
558
+
* ```
559
+
*/
560
+
export async function withValidator<T>(
561
+
lexicons: LexiconDoc[],
562
+
callback: (validator: LexiconValidator) => T | Promise<T>
563
+
): Promise<T> {
564
+
const validator = await LexiconValidator.create(lexicons);
565
+
try {
566
+
return await callback(validator);
567
+
} finally {
568
+
validator.free();
569
+
}
570
+
}
-595
packages/lexicon-intellisense/src/slices_lexicon.js
-595
packages/lexicon-intellisense/src/slices_lexicon.js
···
1
-
// packages/lexicon/wasm/slices_lexicon.js
2
-
var wasm;
3
-
var cachedUint8ArrayMemory0 = null;
4
-
function getUint8ArrayMemory0() {
5
-
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
6
-
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
7
-
}
8
-
return cachedUint8ArrayMemory0;
9
-
}
10
-
var cachedTextDecoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf-8", {
11
-
ignoreBOM: true,
12
-
fatal: true
13
-
}) : {
14
-
decode: () => {
15
-
throw Error("TextDecoder not available");
16
-
}
17
-
};
18
-
if (typeof TextDecoder !== "undefined") {
19
-
cachedTextDecoder.decode();
20
-
}
21
-
var MAX_SAFARI_DECODE_BYTES = 2146435072;
22
-
var numBytesDecoded = 0;
23
-
function decodeText(ptr, len) {
24
-
numBytesDecoded += len;
25
-
if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
26
-
cachedTextDecoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf-8", {
27
-
ignoreBOM: true,
28
-
fatal: true
29
-
}) : {
30
-
decode: () => {
31
-
throw Error("TextDecoder not available");
32
-
}
33
-
};
34
-
cachedTextDecoder.decode();
35
-
numBytesDecoded = len;
36
-
}
37
-
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
38
-
}
39
-
function getStringFromWasm0(ptr, len) {
40
-
ptr = ptr >>> 0;
41
-
return decodeText(ptr, len);
42
-
}
43
-
var WASM_VECTOR_LEN = 0;
44
-
var cachedTextEncoder = typeof TextEncoder !== "undefined" ? new TextEncoder("utf-8") : {
45
-
encode: () => {
46
-
throw Error("TextEncoder not available");
47
-
}
48
-
};
49
-
var encodeString = typeof cachedTextEncoder.encodeInto === "function" ? function(arg, view) {
50
-
return cachedTextEncoder.encodeInto(arg, view);
51
-
} : function(arg, view) {
52
-
const buf = cachedTextEncoder.encode(arg);
53
-
view.set(buf);
54
-
return {
55
-
read: arg.length,
56
-
written: buf.length
57
-
};
58
-
};
59
-
function passStringToWasm0(arg, malloc, realloc) {
60
-
if (realloc === void 0) {
61
-
const buf = cachedTextEncoder.encode(arg);
62
-
const ptr2 = malloc(buf.length, 1) >>> 0;
63
-
getUint8ArrayMemory0().subarray(ptr2, ptr2 + buf.length).set(buf);
64
-
WASM_VECTOR_LEN = buf.length;
65
-
return ptr2;
66
-
}
67
-
let len = arg.length;
68
-
let ptr = malloc(len, 1) >>> 0;
69
-
const mem = getUint8ArrayMemory0();
70
-
let offset = 0;
71
-
for (; offset < len; offset++) {
72
-
const code = arg.charCodeAt(offset);
73
-
if (code > 127) break;
74
-
mem[ptr + offset] = code;
75
-
}
76
-
if (offset !== len) {
77
-
if (offset !== 0) {
78
-
arg = arg.slice(offset);
79
-
}
80
-
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
81
-
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
82
-
const ret = encodeString(arg, view);
83
-
offset += ret.written;
84
-
ptr = realloc(ptr, len, offset, 1) >>> 0;
85
-
}
86
-
WASM_VECTOR_LEN = offset;
87
-
return ptr;
88
-
}
89
-
var cachedDataViewMemory0 = null;
90
-
function getDataViewMemory0() {
91
-
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || cachedDataViewMemory0.buffer.detached === void 0 && cachedDataViewMemory0.buffer !== wasm.memory.buffer) {
92
-
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
93
-
}
94
-
return cachedDataViewMemory0;
95
-
}
96
-
function takeFromExternrefTable0(idx) {
97
-
const value = wasm.__wbindgen_export_3.get(idx);
98
-
wasm.__externref_table_dealloc(idx);
99
-
return value;
100
-
}
101
-
function validate_lexicons_and_get_errors(lexicons_json) {
102
-
let deferred2_0;
103
-
let deferred2_1;
104
-
try {
105
-
const ptr0 = passStringToWasm0(lexicons_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
106
-
const len0 = WASM_VECTOR_LEN;
107
-
const ret = wasm.validate_lexicons_and_get_errors(ptr0, len0);
108
-
deferred2_0 = ret[0];
109
-
deferred2_1 = ret[1];
110
-
return getStringFromWasm0(ret[0], ret[1]);
111
-
} finally {
112
-
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
113
-
}
114
-
}
115
-
function validate_string_format(value, format) {
116
-
const ptr0 = passStringToWasm0(value, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
117
-
const len0 = WASM_VECTOR_LEN;
118
-
const ptr1 = passStringToWasm0(format, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
119
-
const len1 = WASM_VECTOR_LEN;
120
-
const ret = wasm.validate_string_format(ptr0, len0, ptr1, len1);
121
-
if (ret[1]) {
122
-
throw takeFromExternrefTable0(ret[0]);
123
-
}
124
-
}
125
-
function is_valid_nsid(nsid) {
126
-
const ptr0 = passStringToWasm0(nsid, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
127
-
const len0 = WASM_VECTOR_LEN;
128
-
const ret = wasm.is_valid_nsid(ptr0, len0);
129
-
return ret !== 0;
130
-
}
131
-
var WasmLexiconValidatorFinalization = typeof FinalizationRegistry === "undefined" ? {
132
-
register: () => {
133
-
},
134
-
unregister: () => {
135
-
}
136
-
} : new FinalizationRegistry((ptr) => wasm.__wbg_wasmlexiconvalidator_free(ptr >>> 0, 1));
137
-
var WasmLexiconValidator = class {
138
-
__destroy_into_raw() {
139
-
const ptr = this.__wbg_ptr;
140
-
this.__wbg_ptr = 0;
141
-
WasmLexiconValidatorFinalization.unregister(this);
142
-
return ptr;
143
-
}
144
-
free() {
145
-
const ptr = this.__destroy_into_raw();
146
-
wasm.__wbg_wasmlexiconvalidator_free(ptr, 0);
147
-
}
148
-
/**
149
-
* Create a new validator with the given lexicon documents
150
-
* Takes a JSON string containing an array of lexicon documents
151
-
* @param {string} lexicons_json
152
-
*/
153
-
constructor(lexicons_json) {
154
-
const ptr0 = passStringToWasm0(lexicons_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
155
-
const len0 = WASM_VECTOR_LEN;
156
-
const ret = wasm.wasmlexiconvalidator_new(ptr0, len0);
157
-
if (ret[2]) {
158
-
throw takeFromExternrefTable0(ret[1]);
159
-
}
160
-
this.__wbg_ptr = ret[0] >>> 0;
161
-
WasmLexiconValidatorFinalization.register(this, this.__wbg_ptr, this);
162
-
return this;
163
-
}
164
-
/**
165
-
* Validate a record against its collection's lexicon
166
-
* Takes collection name and record as JSON strings
167
-
* @param {string} collection
168
-
* @param {string} record_json
169
-
*/
170
-
validate_record(collection, record_json) {
171
-
const ptr0 = passStringToWasm0(collection, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
172
-
const len0 = WASM_VECTOR_LEN;
173
-
const ptr1 = passStringToWasm0(record_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
174
-
const len1 = WASM_VECTOR_LEN;
175
-
const ret = wasm.wasmlexiconvalidator_validate_record(this.__wbg_ptr, ptr0, len0, ptr1, len1);
176
-
if (ret[1]) {
177
-
throw takeFromExternrefTable0(ret[0]);
178
-
}
179
-
}
180
-
/**
181
-
* Validate lexicon documents and return detailed validation results
182
-
* Returns a JSON string containing validation results with enhanced error context
183
-
* @returns {string}
184
-
*/
185
-
validate_lexicons() {
186
-
let deferred1_0;
187
-
let deferred1_1;
188
-
try {
189
-
const ret = wasm.wasmlexiconvalidator_validate_lexicons(this.__wbg_ptr);
190
-
deferred1_0 = ret[0];
191
-
deferred1_1 = ret[1];
192
-
return getStringFromWasm0(ret[0], ret[1]);
193
-
} finally {
194
-
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
195
-
}
196
-
}
197
-
/**
198
-
* Check if all references in the lexicon set can be resolved
199
-
* Returns a JSON string with any unresolved references
200
-
* @returns {string}
201
-
*/
202
-
check_references() {
203
-
let deferred1_0;
204
-
let deferred1_1;
205
-
try {
206
-
const ret = wasm.wasmlexiconvalidator_check_references(this.__wbg_ptr);
207
-
deferred1_0 = ret[0];
208
-
deferred1_1 = ret[1];
209
-
return getStringFromWasm0(ret[0], ret[1]);
210
-
} finally {
211
-
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
212
-
}
213
-
}
214
-
/**
215
-
* Get detailed error context for validation failures
216
-
* Returns enhanced error information with path context
217
-
* @param {string} path
218
-
* @returns {string}
219
-
*/
220
-
get_error_context(path) {
221
-
let deferred2_0;
222
-
let deferred2_1;
223
-
try {
224
-
const ptr0 = passStringToWasm0(path, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
225
-
const len0 = WASM_VECTOR_LEN;
226
-
const ret = wasm.wasmlexiconvalidator_get_error_context(this.__wbg_ptr, ptr0, len0);
227
-
deferred2_0 = ret[0];
228
-
deferred2_1 = ret[1];
229
-
return getStringFromWasm0(ret[0], ret[1]);
230
-
} finally {
231
-
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
232
-
}
233
-
}
234
-
};
235
-
var EXPECTED_RESPONSE_TYPES = /* @__PURE__ */ new Set([
236
-
"basic",
237
-
"cors",
238
-
"default"
239
-
]);
240
-
async function __wbg_load(module, imports) {
241
-
if (typeof Response === "function" && module instanceof Response) {
242
-
if (typeof WebAssembly.instantiateStreaming === "function") {
243
-
try {
244
-
return await WebAssembly.instantiateStreaming(module, imports);
245
-
} catch (e) {
246
-
const validResponse = module.ok && EXPECTED_RESPONSE_TYPES.has(module.type);
247
-
if (validResponse && module.headers.get("Content-Type") !== "application/wasm") {
248
-
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
249
-
} else {
250
-
throw e;
251
-
}
252
-
}
253
-
}
254
-
const bytes = await module.arrayBuffer();
255
-
return await WebAssembly.instantiate(bytes, imports);
256
-
} else {
257
-
const instance = await WebAssembly.instantiate(module, imports);
258
-
if (instance instanceof WebAssembly.Instance) {
259
-
return {
260
-
instance,
261
-
module
262
-
};
263
-
} else {
264
-
return instance;
265
-
}
266
-
}
267
-
}
268
-
function __wbg_get_imports() {
269
-
const imports = {};
270
-
imports.wbg = {};
271
-
imports.wbg.__wbg_error_7534b8e9a36f1ab4 = function(arg0, arg1) {
272
-
let deferred0_0;
273
-
let deferred0_1;
274
-
try {
275
-
deferred0_0 = arg0;
276
-
deferred0_1 = arg1;
277
-
console.error(getStringFromWasm0(arg0, arg1));
278
-
} finally {
279
-
wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
280
-
}
281
-
};
282
-
imports.wbg.__wbg_new_8a6f238a6ece86ea = function() {
283
-
const ret = new Error();
284
-
return ret;
285
-
};
286
-
imports.wbg.__wbg_stack_0ed75d68575b0f3c = function(arg0, arg1) {
287
-
const ret = arg1.stack;
288
-
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
289
-
const len1 = WASM_VECTOR_LEN;
290
-
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
291
-
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
292
-
};
293
-
imports.wbg.__wbg_wbindgenthrow_4c11a24fca429ccf = function(arg0, arg1) {
294
-
throw new Error(getStringFromWasm0(arg0, arg1));
295
-
};
296
-
imports.wbg.__wbindgen_cast_2241b6af4c4b2941 = function(arg0, arg1) {
297
-
const ret = getStringFromWasm0(arg0, arg1);
298
-
return ret;
299
-
};
300
-
imports.wbg.__wbindgen_init_externref_table = function() {
301
-
const table = wasm.__wbindgen_export_3;
302
-
const offset = table.grow(4);
303
-
table.set(0, void 0);
304
-
table.set(offset + 0, void 0);
305
-
table.set(offset + 1, null);
306
-
table.set(offset + 2, true);
307
-
table.set(offset + 3, false);
308
-
;
309
-
};
310
-
return imports;
311
-
}
312
-
function __wbg_init_memory(imports, memory) {
313
-
}
314
-
function __wbg_finalize_init(instance, module) {
315
-
wasm = instance.exports;
316
-
__wbg_init.__wbindgen_wasm_module = module;
317
-
cachedDataViewMemory0 = null;
318
-
cachedUint8ArrayMemory0 = null;
319
-
wasm.__wbindgen_start();
320
-
return wasm;
321
-
}
322
-
async function __wbg_init(module_or_path) {
323
-
if (wasm !== void 0) return wasm;
324
-
if (typeof module_or_path !== "undefined") {
325
-
if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
326
-
({ module_or_path } = module_or_path);
327
-
} else {
328
-
console.warn("using deprecated parameters for the initialization function; pass a single object instead");
329
-
}
330
-
}
331
-
if (typeof module_or_path === "undefined") {
332
-
module_or_path = new URL("slices_lexicon_bg.wasm", import.meta.url);
333
-
}
334
-
const imports = __wbg_get_imports();
335
-
if (typeof module_or_path === "string" || typeof Request === "function" && module_or_path instanceof Request || typeof URL === "function" && module_or_path instanceof URL) {
336
-
module_or_path = fetch(module_or_path);
337
-
}
338
-
__wbg_init_memory(imports);
339
-
const { instance, module } = await __wbg_load(await module_or_path, imports);
340
-
return __wbg_finalize_init(instance, module);
341
-
}
342
-
var slices_lexicon_default = __wbg_init;
343
-
344
-
// packages/lexicon/lexicon.ts
345
-
var _computedKey;
346
-
var _computedKey1;
347
-
var wasmInitialized = false;
348
-
async function ensureWasmInit() {
349
-
if (!wasmInitialized) {
350
-
const wasmUrl = new URL("./wasm/slices_lexicon_bg.wasm", import.meta.url);
351
-
await slices_lexicon_default({
352
-
module_or_path: wasmUrl
353
-
});
354
-
wasmInitialized = true;
355
-
}
356
-
}
357
-
var ValidationError = class extends Error {
358
-
/**
359
-
* Creates a new ValidationError instance.
360
-
*
361
-
* @param message - Human-readable error description
362
-
*/
363
-
constructor(message) {
364
-
super(message);
365
-
this.name = "ValidationError";
366
-
}
367
-
};
368
-
_computedKey = Symbol.dispose, _computedKey1 = Symbol.asyncDispose;
369
-
var LexiconValidator = class _LexiconValidator {
370
-
wasmValidator;
371
-
/**
372
-
* Creates a new validator instance with the provided lexicon documents.
373
-
*
374
-
* Note: Prefer using the static `create()` method for async initialization.
375
-
*
376
-
* @param lexicons - Array of lexicon documents to validate
377
-
*/
378
-
constructor(lexicons) {
379
-
const lexiconsJson = JSON.stringify(lexicons);
380
-
this.wasmValidator = new WasmLexiconValidator(lexiconsJson);
381
-
}
382
-
/**
383
-
* Creates a new validator instance with proper async initialization.
384
-
* Ensures WASM module is loaded before creating the validator.
385
-
*
386
-
* @param lexicons - Array of lexicon documents to validate
387
-
* @returns Promise resolving to a new validator instance
388
-
*
389
-
* @example
390
-
* ```typescript
391
-
* const lexicons = [{ id: "com.example.post", defs: {...} }];
392
-
* const validator = await LexiconValidator.create(lexicons);
393
-
* ```
394
-
*/
395
-
static async create(lexicons) {
396
-
await ensureWasmInit();
397
-
return new _LexiconValidator(lexicons);
398
-
}
399
-
/**
400
-
* Validates a data record against its collection's lexicon schema.
401
-
*
402
-
* Performs comprehensive validation including:
403
-
* - Type checking
404
-
* - Constraint validation
405
-
* - Format validation
406
-
* - Required field checking
407
-
*
408
-
* @param collection - NSID of the collection (lexicon) to validate against
409
-
* @param record - Data record to validate
410
-
* @throws {ValidationError} If validation fails
411
-
*
412
-
* @example
413
-
* ```typescript
414
-
* validator.validateRecord("com.example.post", {
415
-
* text: "Hello world!",
416
-
* createdAt: "2024-01-01T12:00:00Z"
417
-
* });
418
-
* ```
419
-
*/
420
-
validateRecord(collection, record) {
421
-
try {
422
-
const recordJson = JSON.stringify(record);
423
-
this.wasmValidator.validate_record(collection, recordJson);
424
-
} catch (error) {
425
-
throw new ValidationError(error instanceof Error ? error.message : String(error));
426
-
}
427
-
}
428
-
/**
429
-
* Validates all lexicon documents and returns comprehensive error information.
430
-
*
431
-
* Uses the enhanced validation system that collects ALL errors for each lexicon,
432
-
* not just the first error encountered.
433
-
*
434
-
* @returns Null if validation passes, or error map if validation fails
435
-
*
436
-
* @example
437
-
* ```typescript
438
-
* const errors = validator.validateLexicons();
439
-
* if (errors) {
440
-
* console.log(`Found errors in ${Object.keys(errors).length} lexicons`);
441
-
* }
442
-
* ```
443
-
*/
444
-
validateLexicons() {
445
-
try {
446
-
const result = this.wasmValidator.validate_lexicons();
447
-
const errorMap = JSON.parse(result);
448
-
if (Object.keys(errorMap).length === 0) {
449
-
return null;
450
-
}
451
-
return errorMap;
452
-
} catch (error) {
453
-
throw new ValidationError(error instanceof Error ? error.message : String(error));
454
-
}
455
-
}
456
-
/**
457
-
* Checks for unresolved references across the lexicon set.
458
-
*
459
-
* Identifies references (like "$ref": "com.example.collection#definition")
460
-
* that point to non-existent lexicons or definitions.
461
-
*
462
-
* @returns Array of unresolved reference strings
463
-
*
464
-
* @example
465
-
* ```typescript
466
-
* const unresolved = validator.checkReferences();
467
-
* if (unresolved.length > 0) {
468
-
* console.log("Unresolved references:", unresolved);
469
-
* }
470
-
* ```
471
-
*/
472
-
checkReferences() {
473
-
try {
474
-
const result = this.wasmValidator.check_references();
475
-
return JSON.parse(result);
476
-
} catch (error) {
477
-
throw new ValidationError(error instanceof Error ? error.message : String(error));
478
-
}
479
-
}
480
-
/**
481
-
* Retrieves detailed error context for debugging validation failures.
482
-
*
483
-
* Provides path information, current lexicon context, and circular
484
-
* reference detection state for enhanced debugging.
485
-
*
486
-
* @param path - Schema path to get context for
487
-
* @returns Detailed error context information
488
-
*
489
-
* @example
490
-
* ```typescript
491
-
* const context = validator.getErrorContext("com.example.post#main");
492
-
* console.log(`Validating at path: ${context.path}`);
493
-
* ```
494
-
*/
495
-
getErrorContext(path) {
496
-
try {
497
-
const result = this.wasmValidator.get_error_context(path);
498
-
return JSON.parse(result);
499
-
} catch (error) {
500
-
throw new ValidationError(error instanceof Error ? error.message : String(error));
501
-
}
502
-
}
503
-
/**
504
-
* Manually releases WASM resources.
505
-
*
506
-
* Call this when done with the validator to free memory.
507
-
* Automatically called by dispose methods when using `using` syntax.
508
-
*/
509
-
free() {
510
-
this.wasmValidator.free();
511
-
}
512
-
/**
513
-
* Synchronous dispose method for automatic resource cleanup.
514
-
* Called automatically when using `using` keyword.
515
-
*
516
-
* @example
517
-
* ```typescript
518
-
* using validator = await LexiconValidator.create(lexicons);
519
-
* // Automatically cleaned up at end of scope
520
-
* ```
521
-
*/
522
-
[_computedKey]() {
523
-
this.free();
524
-
}
525
-
/**
526
-
* Asynchronous dispose method for automatic resource cleanup.
527
-
* Called automatically when using `await using` keyword.
528
-
*/
529
-
async [_computedKey1]() {
530
-
await Promise.resolve(this.free());
531
-
}
532
-
};
533
-
async function validate(lexicons) {
534
-
await ensureWasmInit();
535
-
const lexiconsJson = JSON.stringify(lexicons);
536
-
const result = validate_lexicons_and_get_errors(lexiconsJson);
537
-
const errorMap = JSON.parse(result);
538
-
if (Object.keys(errorMap).length === 0) {
539
-
return null;
540
-
}
541
-
return errorMap;
542
-
}
543
-
async function validateWithDetails(lexicons) {
544
-
const errors = await validate(lexicons);
545
-
if (errors === null) {
546
-
return {
547
-
valid: true,
548
-
errors: {},
549
-
totalErrors: 0,
550
-
lexiconsWithErrors: 0
551
-
};
552
-
}
553
-
const totalErrors = Object.values(errors).reduce((sum, errorArray) => sum + errorArray.length, 0);
554
-
return {
555
-
valid: false,
556
-
errors,
557
-
totalErrors,
558
-
lexiconsWithErrors: Object.keys(errors).length
559
-
};
560
-
}
561
-
async function validateRecord(lexicons, collection, record) {
562
-
return await withValidator(lexicons, (validator) => {
563
-
validator.validateRecord(collection, record);
564
-
});
565
-
}
566
-
async function validateStringFormat(value, format) {
567
-
await ensureWasmInit();
568
-
try {
569
-
validate_string_format(value, format);
570
-
} catch (error) {
571
-
throw new ValidationError(error instanceof Error ? error.message : String(error));
572
-
}
573
-
}
574
-
async function isValidNsid(nsid) {
575
-
await ensureWasmInit();
576
-
return is_valid_nsid(nsid);
577
-
}
578
-
async function withValidator(lexicons, callback) {
579
-
const validator = await LexiconValidator.create(lexicons);
580
-
try {
581
-
return await callback(validator);
582
-
} finally {
583
-
validator.free();
584
-
}
585
-
}
586
-
export {
587
-
LexiconValidator,
588
-
ValidationError,
589
-
isValidNsid,
590
-
validate,
591
-
validateRecord,
592
-
validateStringFormat,
593
-
validateWithDetails,
594
-
withValidator
595
-
};
packages/lexicon-intellisense/wasm/slices_lexicon_bg.wasm
packages/lexicon-intellisense/wasm/slices_lexicon_bg.wasm
This is a binary file and will not be displayed.