@wemush/wols 0.1.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/LICENSE +201 -0
- package/README.md +294 -0
- package/dist/cjs/compact-url.js +272 -0
- package/dist/cjs/compact-url.js.map +1 -0
- package/dist/cjs/crypto/decrypt.js +125 -0
- package/dist/cjs/crypto/decrypt.js.map +1 -0
- package/dist/cjs/crypto/encrypt.js +151 -0
- package/dist/cjs/crypto/encrypt.js.map +1 -0
- package/dist/cjs/crypto/index.js +16 -0
- package/dist/cjs/crypto/index.js.map +1 -0
- package/dist/cjs/errors.js +188 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/index.js +81 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/parser.js +148 -0
- package/dist/cjs/parser.js.map +1 -0
- package/dist/cjs/qr/generate.js +275 -0
- package/dist/cjs/qr/generate.js.map +1 -0
- package/dist/cjs/qr/index.js +18 -0
- package/dist/cjs/qr/index.js.map +1 -0
- package/dist/cjs/specimen.js +163 -0
- package/dist/cjs/specimen.js.map +1 -0
- package/dist/cjs/types.js +78 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/utils/cuid.js +150 -0
- package/dist/cjs/utils/cuid.js.map +1 -0
- package/dist/cjs/utils/iso8601.js +131 -0
- package/dist/cjs/utils/iso8601.js.map +1 -0
- package/dist/cjs/validator.js +307 -0
- package/dist/cjs/validator.js.map +1 -0
- package/dist/esm/compact-url.js +264 -0
- package/dist/esm/compact-url.js.map +1 -0
- package/dist/esm/crypto/decrypt.js +122 -0
- package/dist/esm/crypto/decrypt.js.map +1 -0
- package/dist/esm/crypto/encrypt.js +147 -0
- package/dist/esm/crypto/encrypt.js.map +1 -0
- package/dist/esm/crypto/index.js +10 -0
- package/dist/esm/crypto/index.js.map +1 -0
- package/dist/esm/errors.js +178 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/index.js +47 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/parser.js +145 -0
- package/dist/esm/parser.js.map +1 -0
- package/dist/esm/qr/generate.js +235 -0
- package/dist/esm/qr/generate.js.map +1 -0
- package/dist/esm/qr/index.js +10 -0
- package/dist/esm/qr/index.js.map +1 -0
- package/dist/esm/specimen.js +159 -0
- package/dist/esm/specimen.js.map +1 -0
- package/dist/esm/types.js +71 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/utils/cuid.js +145 -0
- package/dist/esm/utils/cuid.js.map +1 -0
- package/dist/esm/utils/iso8601.js +122 -0
- package/dist/esm/utils/iso8601.js.map +1 -0
- package/dist/esm/validator.js +304 -0
- package/dist/esm/validator.js.map +1 -0
- package/dist/types/compact-url.d.ts +104 -0
- package/dist/types/compact-url.d.ts.map +1 -0
- package/dist/types/crypto/decrypt.d.ts +33 -0
- package/dist/types/crypto/decrypt.d.ts.map +1 -0
- package/dist/types/crypto/encrypt.d.ts +32 -0
- package/dist/types/crypto/encrypt.d.ts.map +1 -0
- package/dist/types/crypto/index.d.ts +10 -0
- package/dist/types/crypto/index.d.ts.map +1 -0
- package/dist/types/errors.d.ts +103 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/parser.d.ts +30 -0
- package/dist/types/parser.d.ts.map +1 -0
- package/dist/types/qr/generate.d.ts +62 -0
- package/dist/types/qr/generate.d.ts.map +1 -0
- package/dist/types/qr/index.d.ts +10 -0
- package/dist/types/qr/index.d.ts.map +1 -0
- package/dist/types/specimen.d.ts +71 -0
- package/dist/types/specimen.d.ts.map +1 -0
- package/dist/types/types.d.ts +269 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/utils/cuid.d.ts +44 -0
- package/dist/types/utils/cuid.d.ts.map +1 -0
- package/dist/types/utils/iso8601.d.ts +79 -0
- package/dist/types/utils/iso8601.d.ts.map +1 -0
- package/dist/types/validator.d.ts +25 -0
- package/dist/types/validator.d.ts.map +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CUID2 Generator - Zero-dependency implementation
|
|
4
|
+
*
|
|
5
|
+
* Generates collision-resistant unique identifiers following the CUID2 algorithm.
|
|
6
|
+
* This is a minimal implementation focused on the needs of WOLS specimen IDs.
|
|
7
|
+
*
|
|
8
|
+
* @module utils/cuid
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.createId = createId;
|
|
12
|
+
exports.createSpecimenId = createSpecimenId;
|
|
13
|
+
exports.isValidSpecimenId = isValidSpecimenId;
|
|
14
|
+
// Character set for base36 encoding (0-9, a-z)
|
|
15
|
+
const ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz';
|
|
16
|
+
// Default length for generated IDs
|
|
17
|
+
const DEFAULT_LENGTH = 24;
|
|
18
|
+
// Counter for additional entropy
|
|
19
|
+
let counter = 0;
|
|
20
|
+
/**
|
|
21
|
+
* Get cryptographically secure random bytes.
|
|
22
|
+
* Uses Web Crypto API (works in Node.js 18+ and modern browsers).
|
|
23
|
+
*/
|
|
24
|
+
function getRandomBytes(length) {
|
|
25
|
+
const bytes = new Uint8Array(length);
|
|
26
|
+
// Use globalThis.crypto for cross-platform compatibility
|
|
27
|
+
const cryptoObj = typeof globalThis !== 'undefined'
|
|
28
|
+
? globalThis.crypto
|
|
29
|
+
: undefined;
|
|
30
|
+
if (cryptoObj?.getRandomValues) {
|
|
31
|
+
cryptoObj.getRandomValues(bytes);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
// Fallback for older environments (should not happen with Node 18+)
|
|
35
|
+
for (let i = 0; i < length; i++) {
|
|
36
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return bytes;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Convert a byte array to a base36 string.
|
|
43
|
+
*/
|
|
44
|
+
function toBase36(bytes) {
|
|
45
|
+
let result = '';
|
|
46
|
+
for (const byte of bytes) {
|
|
47
|
+
result += ALPHABET[byte % 36];
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get a timestamp component for the ID.
|
|
53
|
+
* Uses high-resolution time when available.
|
|
54
|
+
*/
|
|
55
|
+
function getTimestamp() {
|
|
56
|
+
const now = Date.now();
|
|
57
|
+
return now.toString(36);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get counter component to ensure uniqueness within same millisecond.
|
|
61
|
+
*/
|
|
62
|
+
function getCounter() {
|
|
63
|
+
counter = (counter + 1) % 1679616; // Max 4 base36 chars
|
|
64
|
+
return counter.toString(36).padStart(4, '0');
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Generate a fingerprint based on environment.
|
|
68
|
+
* In browsers, uses navigator info. In Node.js, uses process info.
|
|
69
|
+
*/
|
|
70
|
+
function getFingerprint() {
|
|
71
|
+
const parts = [];
|
|
72
|
+
// Node.js environment - use globalThis for cross-platform compatibility
|
|
73
|
+
const processObj = typeof globalThis !== 'undefined'
|
|
74
|
+
? globalThis.process
|
|
75
|
+
: undefined;
|
|
76
|
+
const navigatorObj = typeof globalThis !== 'undefined'
|
|
77
|
+
? globalThis.navigator
|
|
78
|
+
: undefined;
|
|
79
|
+
if (processObj?.pid) {
|
|
80
|
+
parts.push(processObj.pid.toString(36));
|
|
81
|
+
const hrtime = processObj.hrtime?.();
|
|
82
|
+
if (hrtime) {
|
|
83
|
+
parts.push((hrtime[1] ?? 0).toString(36));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Browser environment
|
|
87
|
+
if (navigatorObj) {
|
|
88
|
+
parts.push((navigatorObj.userAgent?.length ?? 0).toString(36));
|
|
89
|
+
parts.push((navigatorObj.language?.length ?? 0).toString(36));
|
|
90
|
+
}
|
|
91
|
+
// Fallback random
|
|
92
|
+
if (parts.length === 0) {
|
|
93
|
+
const random = getRandomBytes(4);
|
|
94
|
+
parts.push(toBase36(random));
|
|
95
|
+
}
|
|
96
|
+
return parts.join('').slice(0, 4);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Generate a CUID2-style identifier.
|
|
100
|
+
*
|
|
101
|
+
* The ID format is: [random][timestamp][counter][fingerprint][random]
|
|
102
|
+
* All components are base36 encoded for URL safety.
|
|
103
|
+
*
|
|
104
|
+
* @param length - Length of the generated ID (default: 24)
|
|
105
|
+
* @returns A unique, URL-safe identifier
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```typescript
|
|
109
|
+
* const id = createId();
|
|
110
|
+
* // Returns something like: "clx1a2b3c4d5e6f7g8h9i0j1"
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
function createId(length = DEFAULT_LENGTH) {
|
|
114
|
+
const timestamp = getTimestamp();
|
|
115
|
+
const count = getCounter();
|
|
116
|
+
const fingerprint = getFingerprint();
|
|
117
|
+
// Calculate random bytes needed
|
|
118
|
+
const fixedLength = timestamp.length + count.length + fingerprint.length;
|
|
119
|
+
const randomLength = Math.max(0, length - fixedLength);
|
|
120
|
+
// Generate random component
|
|
121
|
+
const randomBytes = getRandomBytes(randomLength);
|
|
122
|
+
const random = toBase36(randomBytes);
|
|
123
|
+
// Combine components
|
|
124
|
+
const id = (random + timestamp + count + fingerprint).slice(0, length);
|
|
125
|
+
return id;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Generate a specimen ID with the WOLS prefix.
|
|
129
|
+
*
|
|
130
|
+
* @returns A specimen ID in format "wemush:{cuid}"
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* const specimenId = createSpecimenId();
|
|
135
|
+
* // Returns: "wemush:clx1a2b3c4d5e6f7g8h9i0j1"
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
function createSpecimenId() {
|
|
139
|
+
return `wemush:${createId()}`;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Validate a specimen ID format.
|
|
143
|
+
*
|
|
144
|
+
* @param id - The ID to validate
|
|
145
|
+
* @returns true if the ID matches the expected format
|
|
146
|
+
*/
|
|
147
|
+
function isValidSpecimenId(id) {
|
|
148
|
+
return /^wemush:[a-z0-9]+$/.test(id);
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=cuid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cuid.js","sourceRoot":"","sources":["../../../src/utils/cuid.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ISO 8601 Date Utilities
|
|
4
|
+
*
|
|
5
|
+
* Provides parsing and formatting for ISO 8601 date strings
|
|
6
|
+
* as used in WOLS specimens.
|
|
7
|
+
*
|
|
8
|
+
* @module utils/iso8601
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.isValidISO8601 = isValidISO8601;
|
|
12
|
+
exports.isValidDateOnly = isValidDateOnly;
|
|
13
|
+
exports.getCurrentISO8601 = getCurrentISO8601;
|
|
14
|
+
exports.parseISO8601 = parseISO8601;
|
|
15
|
+
exports.formatISO8601 = formatISO8601;
|
|
16
|
+
exports.toUnixTimestamp = toUnixTimestamp;
|
|
17
|
+
exports.fromUnixTimestamp = fromUnixTimestamp;
|
|
18
|
+
/**
|
|
19
|
+
* Regular expression for validating ISO 8601 date strings.
|
|
20
|
+
* Matches formats like:
|
|
21
|
+
* - 2025-12-16T10:30:00Z
|
|
22
|
+
* - 2025-12-16T10:30:00.000Z
|
|
23
|
+
* - 2025-12-16T10:30:00+00:00
|
|
24
|
+
* - 2025-12-16T10:30:00-05:00
|
|
25
|
+
*/
|
|
26
|
+
const ISO8601_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
27
|
+
/**
|
|
28
|
+
* Simple date-only regex for partial dates
|
|
29
|
+
*/
|
|
30
|
+
const DATE_ONLY_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
31
|
+
/**
|
|
32
|
+
* Check if a string is a valid ISO 8601 date.
|
|
33
|
+
*
|
|
34
|
+
* @param value - The string to validate
|
|
35
|
+
* @returns true if valid ISO 8601 format
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* isValidISO8601('2025-12-16T10:30:00Z'); // true
|
|
40
|
+
* isValidISO8601('2025-12-16'); // false (date-only)
|
|
41
|
+
* isValidISO8601('invalid'); // false
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
function isValidISO8601(value) {
|
|
45
|
+
if (!ISO8601_REGEX.test(value)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
// Also verify it's a parseable date
|
|
49
|
+
const date = new Date(value);
|
|
50
|
+
return !isNaN(date.getTime());
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Check if a string is a valid date-only format (YYYY-MM-DD).
|
|
54
|
+
*
|
|
55
|
+
* @param value - The string to validate
|
|
56
|
+
* @returns true if valid date-only format
|
|
57
|
+
*/
|
|
58
|
+
function isValidDateOnly(value) {
|
|
59
|
+
if (!DATE_ONLY_REGEX.test(value)) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
const date = new Date(value + 'T00:00:00Z');
|
|
63
|
+
return !isNaN(date.getTime());
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get the current timestamp in ISO 8601 format.
|
|
67
|
+
*
|
|
68
|
+
* @returns Current time as ISO 8601 string
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* const now = getCurrentISO8601();
|
|
73
|
+
* // Returns: "2025-12-16T10:30:00.000Z"
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
function getCurrentISO8601() {
|
|
77
|
+
return new Date().toISOString();
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Parse an ISO 8601 date string to a Date object.
|
|
81
|
+
*
|
|
82
|
+
* @param value - The ISO 8601 string to parse
|
|
83
|
+
* @returns The parsed Date, or null if invalid
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const date = parseISO8601('2025-12-16T10:30:00Z');
|
|
88
|
+
* // Returns: Date object
|
|
89
|
+
*
|
|
90
|
+
* const invalid = parseISO8601('invalid');
|
|
91
|
+
* // Returns: null
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
function parseISO8601(value) {
|
|
95
|
+
if (!isValidISO8601(value)) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
return new Date(value);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Format a Date object to ISO 8601 string.
|
|
102
|
+
*
|
|
103
|
+
* @param date - The Date to format
|
|
104
|
+
* @returns ISO 8601 string
|
|
105
|
+
*/
|
|
106
|
+
function formatISO8601(date) {
|
|
107
|
+
return date.toISOString();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get Unix timestamp (seconds since epoch) from ISO 8601 string.
|
|
111
|
+
*
|
|
112
|
+
* @param value - The ISO 8601 string
|
|
113
|
+
* @returns Unix timestamp in seconds, or null if invalid
|
|
114
|
+
*/
|
|
115
|
+
function toUnixTimestamp(value) {
|
|
116
|
+
const date = parseISO8601(value);
|
|
117
|
+
if (!date) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
return Math.floor(date.getTime() / 1000);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Convert Unix timestamp to ISO 8601 string.
|
|
124
|
+
*
|
|
125
|
+
* @param timestamp - Unix timestamp in seconds
|
|
126
|
+
* @returns ISO 8601 string
|
|
127
|
+
*/
|
|
128
|
+
function fromUnixTimestamp(timestamp) {
|
|
129
|
+
return new Date(timestamp * 1000).toISOString();
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=iso8601.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iso8601.js","sourceRoot":"","sources":["../../../src/utils/iso8601.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AA8BH,wCAQC;AAQD,0CAOC;AAaD,8CAEC;AAiBD,oCAKC;AAQD,sCAEC;AAQD,0CAMC;AAQD,8CAEC;AA1HD;;;;;;;GAOG;AACH,MAAM,aAAa,GAAG,0EAA0E,CAAC;AAEjG;;GAEG;AACH,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAE9C;;;;;;;;;;;;GAYG;AACH,SAAgB,cAAc,CAAC,KAAa;IAC1C,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,oCAAoC;IACpC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;AAChC,CAAC;AAED;;;;;GAKG;AACH,SAAgB,eAAe,CAAC,KAAa;IAC3C,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC,CAAC;IAC5C,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,iBAAiB;IAC/B,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAgB,YAAY,CAAC,KAAa;IACxC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED;;;;;GAKG;AACH,SAAgB,aAAa,CAAC,IAAU;IACtC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;AAC5B,CAAC;AAED;;;;;GAKG;AACH,SAAgB,eAAe,CAAC,KAAa;IAC3C,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,SAAgB,iBAAiB,CAAC,SAAiB;IACjD,OAAO,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* WOLS Specimen Validator
|
|
4
|
+
*
|
|
5
|
+
* This module provides validation functionality for WOLS specimen objects.
|
|
6
|
+
*
|
|
7
|
+
* @module validator
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.validateSpecimen = validateSpecimen;
|
|
11
|
+
const errors_js_1 = require("./errors.js");
|
|
12
|
+
const types_js_1 = require("./types.js");
|
|
13
|
+
const iso8601_js_1 = require("./utils/iso8601.js");
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// VALIDATION PATTERNS
|
|
16
|
+
// =============================================================================
|
|
17
|
+
/**
|
|
18
|
+
* Pattern for valid specimen ID: wemush:[a-z0-9]+
|
|
19
|
+
*/
|
|
20
|
+
const SPECIMEN_ID_PATTERN = /^wemush:[a-z0-9]+$/;
|
|
21
|
+
/**
|
|
22
|
+
* Pattern for valid semver version: major.minor.patch
|
|
23
|
+
*/
|
|
24
|
+
const SEMVER_PATTERN = /^\d+\.\d+\.\d+$/;
|
|
25
|
+
/**
|
|
26
|
+
* Pattern for valid strain generation: P, F1, F2, F3, etc.
|
|
27
|
+
*/
|
|
28
|
+
const GENERATION_PATTERN = /^(P|F\d+)$/;
|
|
29
|
+
/**
|
|
30
|
+
* Known WOLS specimen fields (for unknown field detection).
|
|
31
|
+
*/
|
|
32
|
+
const KNOWN_FIELDS = new Set([
|
|
33
|
+
'@context',
|
|
34
|
+
'@type',
|
|
35
|
+
'id',
|
|
36
|
+
'version',
|
|
37
|
+
'type',
|
|
38
|
+
'species',
|
|
39
|
+
'strain',
|
|
40
|
+
'stage',
|
|
41
|
+
'created',
|
|
42
|
+
'batch',
|
|
43
|
+
'organization',
|
|
44
|
+
'creator',
|
|
45
|
+
'custom',
|
|
46
|
+
'signature',
|
|
47
|
+
]);
|
|
48
|
+
// =============================================================================
|
|
49
|
+
// HELPER FUNCTIONS
|
|
50
|
+
// =============================================================================
|
|
51
|
+
/**
|
|
52
|
+
* Create a validation error.
|
|
53
|
+
*/
|
|
54
|
+
function error(path, code, message) {
|
|
55
|
+
return { path, code, message };
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Create a validation warning.
|
|
59
|
+
*/
|
|
60
|
+
function warning(path, code, message, suggestion) {
|
|
61
|
+
const result = { path, code, message };
|
|
62
|
+
if (suggestion !== undefined) {
|
|
63
|
+
result.suggestion = suggestion;
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Check if a value is a non-empty string.
|
|
69
|
+
*/
|
|
70
|
+
function isNonEmptyString(value) {
|
|
71
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Check if a value is a plain object.
|
|
75
|
+
*/
|
|
76
|
+
function isPlainObject(value) {
|
|
77
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
78
|
+
}
|
|
79
|
+
// =============================================================================
|
|
80
|
+
// FIELD VALIDATORS
|
|
81
|
+
// =============================================================================
|
|
82
|
+
/**
|
|
83
|
+
* Validate @context field.
|
|
84
|
+
*/
|
|
85
|
+
function validateContext(value, errors, _options) {
|
|
86
|
+
if (value === undefined || value === null) {
|
|
87
|
+
errors.push(error('@context', errors_js_1.WolsErrorCode.INVALID_CONTEXT, '@context is required'));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (value !== types_js_1.WOLS_CONTEXT) {
|
|
91
|
+
errors.push(error('@context', errors_js_1.WolsErrorCode.INVALID_CONTEXT, `@context must be '${types_js_1.WOLS_CONTEXT}', got '${value}'`));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Validate @type field.
|
|
96
|
+
*/
|
|
97
|
+
function validateType(value, errors, _options) {
|
|
98
|
+
if (value === undefined || value === null) {
|
|
99
|
+
errors.push(error('@type', errors_js_1.WolsErrorCode.INVALID_TYPE, '@type is required'));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (value !== 'Specimen') {
|
|
103
|
+
errors.push(error('@type', errors_js_1.WolsErrorCode.INVALID_TYPE, `@type must be 'Specimen', got '${value}'`));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Validate id field.
|
|
108
|
+
*/
|
|
109
|
+
function validateId(value, errors, _options) {
|
|
110
|
+
if (value === undefined || value === null) {
|
|
111
|
+
errors.push(error('id', errors_js_1.WolsErrorCode.REQUIRED_FIELD, 'id is required'));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (typeof value !== 'string') {
|
|
115
|
+
errors.push(error('id', errors_js_1.WolsErrorCode.INVALID_ID_FORMAT, 'id must be a string'));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (!SPECIMEN_ID_PATTERN.test(value)) {
|
|
119
|
+
errors.push(error('id', errors_js_1.WolsErrorCode.INVALID_ID_FORMAT, `id must match pattern 'wemush:[a-z0-9]+', got '${value}'`));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Validate version field.
|
|
124
|
+
*/
|
|
125
|
+
function validateVersion(value, errors, _options) {
|
|
126
|
+
if (value === undefined || value === null) {
|
|
127
|
+
errors.push(error('version', errors_js_1.WolsErrorCode.REQUIRED_FIELD, 'version is required'));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (typeof value !== 'string') {
|
|
131
|
+
errors.push(error('version', errors_js_1.WolsErrorCode.INVALID_VERSION, 'version must be a string'));
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (!SEMVER_PATTERN.test(value)) {
|
|
135
|
+
errors.push(error('version', errors_js_1.WolsErrorCode.INVALID_VERSION, `version must be valid semver (major.minor.patch), got '${value}'`));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Validate specimen type field.
|
|
140
|
+
*/
|
|
141
|
+
function validateSpecimenType(value, errors, _options) {
|
|
142
|
+
if (value === undefined || value === null) {
|
|
143
|
+
errors.push(error('type', errors_js_1.WolsErrorCode.REQUIRED_FIELD, 'type is required'));
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (!(0, types_js_1.isSpecimenType)(value)) {
|
|
147
|
+
errors.push(error('type', errors_js_1.WolsErrorCode.INVALID_SPECIMEN_TYPE, `type must be one of CULTURE, SPAWN, SUBSTRATE, FRUITING, HARVEST, got '${value}'`));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Validate species field.
|
|
152
|
+
*/
|
|
153
|
+
function validateSpecies(value, errors, _options) {
|
|
154
|
+
if (value === undefined || value === null) {
|
|
155
|
+
errors.push(error('species', errors_js_1.WolsErrorCode.REQUIRED_FIELD, 'species is required'));
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (!isNonEmptyString(value)) {
|
|
159
|
+
errors.push(error('species', errors_js_1.WolsErrorCode.REQUIRED_FIELD, 'species must be a non-empty string'));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Validate optional stage field.
|
|
164
|
+
*/
|
|
165
|
+
function validateStage(value, errors, warnings, options) {
|
|
166
|
+
if (value === undefined || value === null) {
|
|
167
|
+
return; // Optional field
|
|
168
|
+
}
|
|
169
|
+
if (!(0, types_js_1.isGrowthStage)(value)) {
|
|
170
|
+
if (options.level === 'lenient') {
|
|
171
|
+
warnings.push(warning('stage', 'UNKNOWN_GROWTH_STAGE', `Unknown growth stage '${value}'`, 'Use one of: INOCULATION, COLONIZATION, FRUITING, HARVEST'));
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
errors.push(error('stage', 'INVALID_GROWTH_STAGE', `stage must be one of INOCULATION, COLONIZATION, FRUITING, HARVEST, got '${value}'`));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Validate optional created field.
|
|
180
|
+
*/
|
|
181
|
+
function validateCreated(value, errors, warnings, options) {
|
|
182
|
+
if (value === undefined || value === null) {
|
|
183
|
+
return; // Optional field
|
|
184
|
+
}
|
|
185
|
+
if (typeof value !== 'string') {
|
|
186
|
+
errors.push(error('created', errors_js_1.WolsErrorCode.INVALID_DATE_FORMAT, 'created must be a string'));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (!(0, iso8601_js_1.isValidISO8601)(value)) {
|
|
190
|
+
if (options.level === 'lenient') {
|
|
191
|
+
warnings.push(warning('created', errors_js_1.WolsErrorCode.INVALID_DATE_FORMAT, `Invalid ISO 8601 date format: '${value}'`, 'Use format: YYYY-MM-DDTHH:mm:ssZ'));
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
errors.push(error('created', errors_js_1.WolsErrorCode.INVALID_DATE_FORMAT, `created must be valid ISO 8601 datetime, got '${value}'`));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Validate strain object.
|
|
200
|
+
*/
|
|
201
|
+
function validateStrain(value, errors, _options) {
|
|
202
|
+
if (value === undefined || value === null) {
|
|
203
|
+
return; // Optional field
|
|
204
|
+
}
|
|
205
|
+
if (!isPlainObject(value)) {
|
|
206
|
+
errors.push(error('strain', errors_js_1.WolsErrorCode.INVALID_FORMAT, 'strain must be an object'));
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const strain = value;
|
|
210
|
+
// name is required in Strain
|
|
211
|
+
if (!isNonEmptyString(strain.name)) {
|
|
212
|
+
errors.push(error('strain.name', errors_js_1.WolsErrorCode.REQUIRED_FIELD, 'strain.name is required'));
|
|
213
|
+
}
|
|
214
|
+
// Validate generation format if present
|
|
215
|
+
if (strain.generation !== undefined) {
|
|
216
|
+
if (typeof strain.generation !== 'string' || !GENERATION_PATTERN.test(strain.generation)) {
|
|
217
|
+
errors.push(error('strain.generation', errors_js_1.WolsErrorCode.INVALID_GENERATION, `strain.generation must match pattern 'P' or 'F<number>', got '${strain.generation}'`));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// Validate clonalGeneration if present
|
|
221
|
+
if (strain.clonalGeneration !== undefined) {
|
|
222
|
+
if (typeof strain.clonalGeneration !== 'number' ||
|
|
223
|
+
!Number.isInteger(strain.clonalGeneration) ||
|
|
224
|
+
strain.clonalGeneration < 1) {
|
|
225
|
+
errors.push(error('strain.clonalGeneration', errors_js_1.WolsErrorCode.INVALID_FORMAT, 'strain.clonalGeneration must be a positive integer'));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// Validate source if present (informational, no strict enum)
|
|
229
|
+
if (strain.source !== undefined && typeof strain.source !== 'string') {
|
|
230
|
+
errors.push(error('strain.source', errors_js_1.WolsErrorCode.INVALID_FORMAT, 'strain.source must be a string'));
|
|
231
|
+
}
|
|
232
|
+
// Validate lineage if present
|
|
233
|
+
if (strain.lineage !== undefined && typeof strain.lineage !== 'string') {
|
|
234
|
+
errors.push(error('strain.lineage', errors_js_1.WolsErrorCode.INVALID_FORMAT, 'strain.lineage must be a string'));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Check for unknown fields and add warnings.
|
|
239
|
+
*/
|
|
240
|
+
function checkUnknownFields(specimen, warnings, options) {
|
|
241
|
+
if (options.allowUnknownFields) {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
for (const key of Object.keys(specimen)) {
|
|
245
|
+
if (!KNOWN_FIELDS.has(key)) {
|
|
246
|
+
warnings.push(warning(key, 'UNKNOWN_FIELD', `Unknown field '${key}'`, 'Unknown fields should be placed in the custom object'));
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// =============================================================================
|
|
251
|
+
// MAIN VALIDATION FUNCTION
|
|
252
|
+
// =============================================================================
|
|
253
|
+
/**
|
|
254
|
+
* Validate a specimen object against the WOLS v1.1.0 schema.
|
|
255
|
+
*
|
|
256
|
+
* @param specimen - The specimen object to validate
|
|
257
|
+
* @param options - Validation options
|
|
258
|
+
* @returns ValidationResult with errors and warnings
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```typescript
|
|
262
|
+
* const result = validateSpecimen(specimen);
|
|
263
|
+
* if (!result.valid) {
|
|
264
|
+
* console.error('Validation errors:', result.errors);
|
|
265
|
+
* }
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
268
|
+
function validateSpecimen(specimen, options = {}) {
|
|
269
|
+
const errors = [];
|
|
270
|
+
const warnings = [];
|
|
271
|
+
// Default options
|
|
272
|
+
const opts = {
|
|
273
|
+
allowUnknownFields: options.allowUnknownFields ?? false,
|
|
274
|
+
level: options.level ?? 'strict',
|
|
275
|
+
};
|
|
276
|
+
// Handle null/undefined input
|
|
277
|
+
if (specimen === null || specimen === undefined) {
|
|
278
|
+
errors.push(error('', errors_js_1.WolsErrorCode.REQUIRED_FIELD, 'Specimen is required'));
|
|
279
|
+
return { valid: false, errors, warnings };
|
|
280
|
+
}
|
|
281
|
+
// Handle non-object input
|
|
282
|
+
if (!isPlainObject(specimen)) {
|
|
283
|
+
errors.push(error('', errors_js_1.WolsErrorCode.INVALID_FORMAT, 'Specimen must be an object'));
|
|
284
|
+
return { valid: false, errors, warnings };
|
|
285
|
+
}
|
|
286
|
+
const data = specimen;
|
|
287
|
+
// Validate required JSON-LD fields
|
|
288
|
+
validateContext(data['@context'], errors, opts);
|
|
289
|
+
validateType(data['@type'], errors, opts);
|
|
290
|
+
// Validate required specimen fields
|
|
291
|
+
validateId(data['id'], errors, opts);
|
|
292
|
+
validateVersion(data['version'], errors, opts);
|
|
293
|
+
validateSpecimenType(data['type'], errors, opts);
|
|
294
|
+
validateSpecies(data['species'], errors, opts);
|
|
295
|
+
// Validate optional fields
|
|
296
|
+
validateStage(data['stage'], errors, warnings, opts);
|
|
297
|
+
validateCreated(data['created'], errors, warnings, opts);
|
|
298
|
+
validateStrain(data['strain'], errors, opts);
|
|
299
|
+
// Check for unknown fields
|
|
300
|
+
checkUnknownFields(data, warnings, opts);
|
|
301
|
+
return {
|
|
302
|
+
valid: errors.length === 0,
|
|
303
|
+
errors,
|
|
304
|
+
warnings,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/validator.ts"],"names":[],"mappings":"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"}
|