@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.
Files changed (87) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +294 -0
  3. package/dist/cjs/compact-url.js +272 -0
  4. package/dist/cjs/compact-url.js.map +1 -0
  5. package/dist/cjs/crypto/decrypt.js +125 -0
  6. package/dist/cjs/crypto/decrypt.js.map +1 -0
  7. package/dist/cjs/crypto/encrypt.js +151 -0
  8. package/dist/cjs/crypto/encrypt.js.map +1 -0
  9. package/dist/cjs/crypto/index.js +16 -0
  10. package/dist/cjs/crypto/index.js.map +1 -0
  11. package/dist/cjs/errors.js +188 -0
  12. package/dist/cjs/errors.js.map +1 -0
  13. package/dist/cjs/index.js +81 -0
  14. package/dist/cjs/index.js.map +1 -0
  15. package/dist/cjs/parser.js +148 -0
  16. package/dist/cjs/parser.js.map +1 -0
  17. package/dist/cjs/qr/generate.js +275 -0
  18. package/dist/cjs/qr/generate.js.map +1 -0
  19. package/dist/cjs/qr/index.js +18 -0
  20. package/dist/cjs/qr/index.js.map +1 -0
  21. package/dist/cjs/specimen.js +163 -0
  22. package/dist/cjs/specimen.js.map +1 -0
  23. package/dist/cjs/types.js +78 -0
  24. package/dist/cjs/types.js.map +1 -0
  25. package/dist/cjs/utils/cuid.js +150 -0
  26. package/dist/cjs/utils/cuid.js.map +1 -0
  27. package/dist/cjs/utils/iso8601.js +131 -0
  28. package/dist/cjs/utils/iso8601.js.map +1 -0
  29. package/dist/cjs/validator.js +307 -0
  30. package/dist/cjs/validator.js.map +1 -0
  31. package/dist/esm/compact-url.js +264 -0
  32. package/dist/esm/compact-url.js.map +1 -0
  33. package/dist/esm/crypto/decrypt.js +122 -0
  34. package/dist/esm/crypto/decrypt.js.map +1 -0
  35. package/dist/esm/crypto/encrypt.js +147 -0
  36. package/dist/esm/crypto/encrypt.js.map +1 -0
  37. package/dist/esm/crypto/index.js +10 -0
  38. package/dist/esm/crypto/index.js.map +1 -0
  39. package/dist/esm/errors.js +178 -0
  40. package/dist/esm/errors.js.map +1 -0
  41. package/dist/esm/index.js +47 -0
  42. package/dist/esm/index.js.map +1 -0
  43. package/dist/esm/parser.js +145 -0
  44. package/dist/esm/parser.js.map +1 -0
  45. package/dist/esm/qr/generate.js +235 -0
  46. package/dist/esm/qr/generate.js.map +1 -0
  47. package/dist/esm/qr/index.js +10 -0
  48. package/dist/esm/qr/index.js.map +1 -0
  49. package/dist/esm/specimen.js +159 -0
  50. package/dist/esm/specimen.js.map +1 -0
  51. package/dist/esm/types.js +71 -0
  52. package/dist/esm/types.js.map +1 -0
  53. package/dist/esm/utils/cuid.js +145 -0
  54. package/dist/esm/utils/cuid.js.map +1 -0
  55. package/dist/esm/utils/iso8601.js +122 -0
  56. package/dist/esm/utils/iso8601.js.map +1 -0
  57. package/dist/esm/validator.js +304 -0
  58. package/dist/esm/validator.js.map +1 -0
  59. package/dist/types/compact-url.d.ts +104 -0
  60. package/dist/types/compact-url.d.ts.map +1 -0
  61. package/dist/types/crypto/decrypt.d.ts +33 -0
  62. package/dist/types/crypto/decrypt.d.ts.map +1 -0
  63. package/dist/types/crypto/encrypt.d.ts +32 -0
  64. package/dist/types/crypto/encrypt.d.ts.map +1 -0
  65. package/dist/types/crypto/index.d.ts +10 -0
  66. package/dist/types/crypto/index.d.ts.map +1 -0
  67. package/dist/types/errors.d.ts +103 -0
  68. package/dist/types/errors.d.ts.map +1 -0
  69. package/dist/types/index.d.ts +21 -0
  70. package/dist/types/index.d.ts.map +1 -0
  71. package/dist/types/parser.d.ts +30 -0
  72. package/dist/types/parser.d.ts.map +1 -0
  73. package/dist/types/qr/generate.d.ts +62 -0
  74. package/dist/types/qr/generate.d.ts.map +1 -0
  75. package/dist/types/qr/index.d.ts +10 -0
  76. package/dist/types/qr/index.d.ts.map +1 -0
  77. package/dist/types/specimen.d.ts +71 -0
  78. package/dist/types/specimen.d.ts.map +1 -0
  79. package/dist/types/types.d.ts +269 -0
  80. package/dist/types/types.d.ts.map +1 -0
  81. package/dist/types/utils/cuid.d.ts +44 -0
  82. package/dist/types/utils/cuid.d.ts.map +1 -0
  83. package/dist/types/utils/iso8601.d.ts +79 -0
  84. package/dist/types/utils/iso8601.d.ts.map +1 -0
  85. package/dist/types/validator.d.ts +25 -0
  86. package/dist/types/validator.d.ts.map +1 -0
  87. 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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"}