nats.do 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/README.md +298 -0
- package/dist/env-Ds3wIkQg.d.cts +28 -0
- package/dist/env-Ds3wIkQg.d.ts +28 -0
- package/dist/index.cjs +235 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +34 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +230 -0
- package/dist/index.js.map +1 -0
- package/dist/types.cjs +169 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +444 -0
- package/dist/types.d.ts +444 -0
- package/dist/types.js +155 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.cjs +362 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +214 -0
- package/dist/utils.d.ts +214 -0
- package/dist/utils.js +338 -0
- package/dist/utils.js.map +1 -0
- package/package.json +87 -0
package/dist/utils.cjs
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/utils/subject-matcher.ts
|
|
4
|
+
var VALID_TOKEN_CHARS = /^[a-zA-Z0-9_-]+$/;
|
|
5
|
+
var SINGLE_WILDCARD = "*";
|
|
6
|
+
var MULTI_WILDCARD = ">";
|
|
7
|
+
var TOKEN_SEPARATOR = ".";
|
|
8
|
+
function tokenizeSubject(subject) {
|
|
9
|
+
return subject.split(TOKEN_SEPARATOR);
|
|
10
|
+
}
|
|
11
|
+
function parseSubject(subject) {
|
|
12
|
+
const tokens = tokenizeSubject(subject);
|
|
13
|
+
return {
|
|
14
|
+
tokens,
|
|
15
|
+
tokenCount: tokens.length,
|
|
16
|
+
hasWildcard: tokens.includes(SINGLE_WILDCARD),
|
|
17
|
+
hasGreater: tokens.includes(MULTI_WILDCARD)
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function isValidSubject(subject) {
|
|
21
|
+
if (!subject || subject.length === 0) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
if (subject.includes("\0")) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
if (subject.includes(" ")) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
if (subject.startsWith(TOKEN_SEPARATOR) || subject.endsWith(TOKEN_SEPARATOR)) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
if (subject.includes("..")) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
const tokens = tokenizeSubject(subject);
|
|
37
|
+
for (const token of tokens) {
|
|
38
|
+
if (token.length === 0) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
if (token === SINGLE_WILDCARD || token === MULTI_WILDCARD) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (!VALID_TOKEN_CHARS.test(token)) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
function isValidWildcard(pattern) {
|
|
51
|
+
if (!pattern || pattern.length === 0) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
if (pattern.includes(" ")) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
if (pattern.startsWith(TOKEN_SEPARATOR) || pattern.endsWith(TOKEN_SEPARATOR)) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
if (pattern.includes("..")) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
const tokens = tokenizeSubject(pattern);
|
|
64
|
+
let foundGreater = false;
|
|
65
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
66
|
+
const token = tokens[i];
|
|
67
|
+
if (token.length === 0) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
if (foundGreater) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
if (token === MULTI_WILDCARD) {
|
|
74
|
+
foundGreater = true;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (token === SINGLE_WILDCARD) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (token.includes(SINGLE_WILDCARD) || token.includes(MULTI_WILDCARD)) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
if (!VALID_TOKEN_CHARS.test(token)) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
function matchSubject(pattern, subject) {
|
|
90
|
+
if (!pattern || !subject) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
const patternTokens = tokenizeSubject(pattern);
|
|
94
|
+
const subjectTokens = tokenizeSubject(subject);
|
|
95
|
+
let patternIdx = 0;
|
|
96
|
+
let subjectIdx = 0;
|
|
97
|
+
while (patternIdx < patternTokens.length && subjectIdx < subjectTokens.length) {
|
|
98
|
+
const patternToken = patternTokens[patternIdx];
|
|
99
|
+
const subjectToken = subjectTokens[subjectIdx];
|
|
100
|
+
if (patternToken === MULTI_WILDCARD) {
|
|
101
|
+
return subjectIdx < subjectTokens.length;
|
|
102
|
+
}
|
|
103
|
+
if (patternToken === SINGLE_WILDCARD) {
|
|
104
|
+
patternIdx++;
|
|
105
|
+
subjectIdx++;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (patternToken !== subjectToken) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
patternIdx++;
|
|
112
|
+
subjectIdx++;
|
|
113
|
+
}
|
|
114
|
+
if (patternIdx < patternTokens.length) {
|
|
115
|
+
if (patternTokens[patternIdx] === MULTI_WILDCARD && patternIdx === patternTokens.length - 1) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
if (subjectIdx < subjectTokens.length) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
function subjectToRegex(pattern) {
|
|
126
|
+
const tokens = tokenizeSubject(pattern);
|
|
127
|
+
const regexParts = [];
|
|
128
|
+
for (const token of tokens) {
|
|
129
|
+
if (token === SINGLE_WILDCARD) {
|
|
130
|
+
regexParts.push("[^.]+");
|
|
131
|
+
} else if (token === MULTI_WILDCARD) {
|
|
132
|
+
regexParts.push(".+");
|
|
133
|
+
} else {
|
|
134
|
+
regexParts.push(escapeRegex(token));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return new RegExp(`^${regexParts.join("\\.")}$`);
|
|
138
|
+
}
|
|
139
|
+
function escapeRegex(str) {
|
|
140
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/utils/nuid.ts
|
|
144
|
+
var DIGITS = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
145
|
+
var BASE = 36;
|
|
146
|
+
var PREFIX_LENGTH = 12;
|
|
147
|
+
var SEQ_LENGTH = 10;
|
|
148
|
+
var MAX_SEQ = Math.pow(BASE, SEQ_LENGTH);
|
|
149
|
+
var NUID = class {
|
|
150
|
+
prefix;
|
|
151
|
+
seq;
|
|
152
|
+
inc;
|
|
153
|
+
constructor() {
|
|
154
|
+
this.prefix = this.randomPrefix();
|
|
155
|
+
this.seq = Math.floor(Math.random() * MAX_SEQ);
|
|
156
|
+
this.inc = Math.floor(Math.random() * 33) + 22;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Generate the next NUID
|
|
160
|
+
*/
|
|
161
|
+
next() {
|
|
162
|
+
this.seq += this.inc;
|
|
163
|
+
if (this.seq >= MAX_SEQ) {
|
|
164
|
+
this.prefix = this.randomPrefix();
|
|
165
|
+
this.seq = Math.floor(Math.random() * MAX_SEQ);
|
|
166
|
+
}
|
|
167
|
+
return this.prefix + this.formatSeq(this.seq);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Generate a random prefix
|
|
171
|
+
*/
|
|
172
|
+
randomPrefix() {
|
|
173
|
+
const bytes = new Uint8Array(PREFIX_LENGTH);
|
|
174
|
+
crypto.getRandomValues(bytes);
|
|
175
|
+
let result = "";
|
|
176
|
+
for (let i = 0; i < PREFIX_LENGTH; i++) {
|
|
177
|
+
result += DIGITS[bytes[i] % BASE];
|
|
178
|
+
}
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Format sequence number as fixed-length base36
|
|
183
|
+
*/
|
|
184
|
+
formatSeq(n) {
|
|
185
|
+
let result = "";
|
|
186
|
+
for (let i = 0; i < SEQ_LENGTH; i++) {
|
|
187
|
+
result = DIGITS[n % BASE] + result;
|
|
188
|
+
n = Math.floor(n / BASE);
|
|
189
|
+
}
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Reset with new random state
|
|
194
|
+
*/
|
|
195
|
+
reset() {
|
|
196
|
+
this.prefix = this.randomPrefix();
|
|
197
|
+
this.seq = Math.floor(Math.random() * MAX_SEQ);
|
|
198
|
+
this.inc = Math.floor(Math.random() * 33) + 22;
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
var globalNuid = new NUID();
|
|
202
|
+
function nuid() {
|
|
203
|
+
return globalNuid.next();
|
|
204
|
+
}
|
|
205
|
+
function createInbox(prefix = "_INBOX") {
|
|
206
|
+
return `${prefix}.${nuid()}`;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// src/utils/errors.ts
|
|
210
|
+
var NatsError = class extends Error {
|
|
211
|
+
code;
|
|
212
|
+
name = "NatsError";
|
|
213
|
+
constructor(message, code) {
|
|
214
|
+
super(message);
|
|
215
|
+
this.code = code;
|
|
216
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
var JetStreamError = class extends NatsError {
|
|
220
|
+
name = "JetStreamError";
|
|
221
|
+
stream;
|
|
222
|
+
consumer;
|
|
223
|
+
constructor(message, code, opts) {
|
|
224
|
+
super(message, code);
|
|
225
|
+
this.stream = opts?.stream;
|
|
226
|
+
this.consumer = opts?.consumer;
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
var TimeoutError = class extends NatsError {
|
|
230
|
+
name = "TimeoutError";
|
|
231
|
+
timeout;
|
|
232
|
+
constructor(timeout, message) {
|
|
233
|
+
super(message || `Operation timed out after ${timeout}ms`, "TIMEOUT");
|
|
234
|
+
this.timeout = timeout;
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
var NoRespondersError = class extends NatsError {
|
|
238
|
+
name = "NoRespondersError";
|
|
239
|
+
subject;
|
|
240
|
+
constructor(subject) {
|
|
241
|
+
super(`No responders for subject "${subject}"`, "NO_RESPONDERS");
|
|
242
|
+
this.subject = subject;
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
var ConnectionError = class extends NatsError {
|
|
246
|
+
name = "ConnectionError";
|
|
247
|
+
constructor(message) {
|
|
248
|
+
super(message, "CONNECTION_ERROR");
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
var PermissionError = class extends NatsError {
|
|
252
|
+
name = "PermissionError";
|
|
253
|
+
operation;
|
|
254
|
+
subject;
|
|
255
|
+
constructor(message, opts) {
|
|
256
|
+
super(message, "PERMISSION_DENIED");
|
|
257
|
+
this.operation = opts?.operation;
|
|
258
|
+
this.subject = opts?.subject;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
var StreamNotFoundError = class extends JetStreamError {
|
|
262
|
+
name = "StreamNotFoundError";
|
|
263
|
+
constructor(stream) {
|
|
264
|
+
super(`Stream "${stream}" not found`, "STREAM_NOT_FOUND", { stream });
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
var ConsumerNotFoundError = class extends JetStreamError {
|
|
268
|
+
name = "ConsumerNotFoundError";
|
|
269
|
+
constructor(stream, consumer) {
|
|
270
|
+
super(
|
|
271
|
+
`Consumer "${consumer}" not found on stream "${stream}"`,
|
|
272
|
+
"CONSUMER_NOT_FOUND",
|
|
273
|
+
{ stream, consumer }
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
var MessageNotFoundError = class extends JetStreamError {
|
|
278
|
+
name = "MessageNotFoundError";
|
|
279
|
+
seq;
|
|
280
|
+
constructor(stream, seq) {
|
|
281
|
+
super(`Message ${seq} not found in stream "${stream}"`, "MESSAGE_NOT_FOUND", {
|
|
282
|
+
stream
|
|
283
|
+
});
|
|
284
|
+
this.seq = seq;
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
var StreamExistsError = class extends JetStreamError {
|
|
288
|
+
name = "StreamExistsError";
|
|
289
|
+
constructor(stream) {
|
|
290
|
+
super(`Stream "${stream}" already exists`, "STREAM_EXISTS", { stream });
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
var ConsumerExistsError = class extends JetStreamError {
|
|
294
|
+
name = "ConsumerExistsError";
|
|
295
|
+
constructor(stream, consumer) {
|
|
296
|
+
super(
|
|
297
|
+
`Consumer "${consumer}" already exists on stream "${stream}"`,
|
|
298
|
+
"CONSUMER_EXISTS",
|
|
299
|
+
{ stream, consumer }
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
var InvalidSubjectError = class extends NatsError {
|
|
304
|
+
name = "InvalidSubjectError";
|
|
305
|
+
subject;
|
|
306
|
+
constructor(subject) {
|
|
307
|
+
super(`Invalid subject: "${subject}"`, "INVALID_SUBJECT");
|
|
308
|
+
this.subject = subject;
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
var MaxPayloadError = class extends NatsError {
|
|
312
|
+
name = "MaxPayloadError";
|
|
313
|
+
size;
|
|
314
|
+
maxSize;
|
|
315
|
+
constructor(size, maxSize) {
|
|
316
|
+
super(
|
|
317
|
+
`Message size ${size} exceeds maximum allowed ${maxSize}`,
|
|
318
|
+
"MAX_PAYLOAD_EXCEEDED"
|
|
319
|
+
);
|
|
320
|
+
this.size = size;
|
|
321
|
+
this.maxSize = maxSize;
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
var ErrorCodes = {
|
|
325
|
+
TIMEOUT: "TIMEOUT",
|
|
326
|
+
NO_RESPONDERS: "NO_RESPONDERS",
|
|
327
|
+
CONNECTION_ERROR: "CONNECTION_ERROR",
|
|
328
|
+
PERMISSION_DENIED: "PERMISSION_DENIED",
|
|
329
|
+
STREAM_NOT_FOUND: "STREAM_NOT_FOUND",
|
|
330
|
+
CONSUMER_NOT_FOUND: "CONSUMER_NOT_FOUND",
|
|
331
|
+
MESSAGE_NOT_FOUND: "MESSAGE_NOT_FOUND",
|
|
332
|
+
STREAM_EXISTS: "STREAM_EXISTS",
|
|
333
|
+
CONSUMER_EXISTS: "CONSUMER_EXISTS",
|
|
334
|
+
INVALID_SUBJECT: "INVALID_SUBJECT",
|
|
335
|
+
MAX_PAYLOAD_EXCEEDED: "MAX_PAYLOAD_EXCEEDED"
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
exports.ConnectionError = ConnectionError;
|
|
339
|
+
exports.ConsumerExistsError = ConsumerExistsError;
|
|
340
|
+
exports.ConsumerNotFoundError = ConsumerNotFoundError;
|
|
341
|
+
exports.ErrorCodes = ErrorCodes;
|
|
342
|
+
exports.InvalidSubjectError = InvalidSubjectError;
|
|
343
|
+
exports.JetStreamError = JetStreamError;
|
|
344
|
+
exports.MaxPayloadError = MaxPayloadError;
|
|
345
|
+
exports.MessageNotFoundError = MessageNotFoundError;
|
|
346
|
+
exports.NUID = NUID;
|
|
347
|
+
exports.NatsError = NatsError;
|
|
348
|
+
exports.NoRespondersError = NoRespondersError;
|
|
349
|
+
exports.PermissionError = PermissionError;
|
|
350
|
+
exports.StreamExistsError = StreamExistsError;
|
|
351
|
+
exports.StreamNotFoundError = StreamNotFoundError;
|
|
352
|
+
exports.TimeoutError = TimeoutError;
|
|
353
|
+
exports.createInbox = createInbox;
|
|
354
|
+
exports.isValidSubject = isValidSubject;
|
|
355
|
+
exports.isValidWildcard = isValidWildcard;
|
|
356
|
+
exports.matchSubject = matchSubject;
|
|
357
|
+
exports.nuid = nuid;
|
|
358
|
+
exports.parseSubject = parseSubject;
|
|
359
|
+
exports.subjectToRegex = subjectToRegex;
|
|
360
|
+
exports.tokenizeSubject = tokenizeSubject;
|
|
361
|
+
//# sourceMappingURL=utils.cjs.map
|
|
362
|
+
//# sourceMappingURL=utils.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/subject-matcher.ts","../src/utils/nuid.ts","../src/utils/errors.ts"],"names":[],"mappings":"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","file":"utils.cjs","sourcesContent":["/**\n * Subject Wildcard Matcher\n *\n * Implements NATS subject pattern matching with wildcards:\n * * (asterisk) - matches exactly one token\n * > (greater than) - matches one or more tokens (must be last)\n */\n\n// Valid characters for subject tokens (excluding wildcards)\nconst VALID_TOKEN_CHARS = /^[a-zA-Z0-9_-]+$/\n\n// Wildcard characters\nconst SINGLE_WILDCARD = '*'\nconst MULTI_WILDCARD = '>'\nconst TOKEN_SEPARATOR = '.'\n\n/**\n * Tokenize a subject string into an array of tokens\n */\nexport function tokenizeSubject(subject: string): string[] {\n return subject.split(TOKEN_SEPARATOR)\n}\n\n/**\n * Parse a subject and return metadata about it\n */\nexport interface ParsedSubject {\n tokens: string[]\n tokenCount: number\n hasWildcard: boolean\n hasGreater: boolean\n}\n\nexport function parseSubject(subject: string): ParsedSubject {\n const tokens = tokenizeSubject(subject)\n return {\n tokens,\n tokenCount: tokens.length,\n hasWildcard: tokens.includes(SINGLE_WILDCARD),\n hasGreater: tokens.includes(MULTI_WILDCARD),\n }\n}\n\n/**\n * Check if a subject (not pattern) is valid\n * Subjects cannot contain wildcards\n */\nexport function isValidSubject(subject: string): boolean {\n if (!subject || subject.length === 0) {\n return false\n }\n\n // Check for null bytes\n if (subject.includes('\\x00')) {\n return false\n }\n\n // Check for spaces\n if (subject.includes(' ')) {\n return false\n }\n\n // Check for leading/trailing dots\n if (subject.startsWith(TOKEN_SEPARATOR) || subject.endsWith(TOKEN_SEPARATOR)) {\n return false\n }\n\n // Check for double dots\n if (subject.includes('..')) {\n return false\n }\n\n const tokens = tokenizeSubject(subject)\n\n for (const token of tokens) {\n // Empty tokens (from double dots) are invalid\n if (token.length === 0) {\n return false\n }\n\n // Wildcards are not allowed in plain subjects\n if (token === SINGLE_WILDCARD || token === MULTI_WILDCARD) {\n return false\n }\n\n // Check for valid characters\n if (!VALID_TOKEN_CHARS.test(token)) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Check if a wildcard pattern is valid\n */\nexport function isValidWildcard(pattern: string): boolean {\n if (!pattern || pattern.length === 0) {\n return false\n }\n\n // Check for spaces\n if (pattern.includes(' ')) {\n return false\n }\n\n // Check for leading/trailing dots\n if (pattern.startsWith(TOKEN_SEPARATOR) || pattern.endsWith(TOKEN_SEPARATOR)) {\n return false\n }\n\n // Check for double dots\n if (pattern.includes('..')) {\n return false\n }\n\n const tokens = tokenizeSubject(pattern)\n let foundGreater = false\n\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i]\n\n // Empty tokens are invalid\n if (token.length === 0) {\n return false\n }\n\n // > must be the last token\n if (foundGreater) {\n return false\n }\n\n if (token === MULTI_WILDCARD) {\n foundGreater = true\n continue\n }\n\n if (token === SINGLE_WILDCARD) {\n continue\n }\n\n // Check for partial wildcards (e.g., \"foo*\" or \"*foo\")\n if (token.includes(SINGLE_WILDCARD) || token.includes(MULTI_WILDCARD)) {\n return false\n }\n\n // Check for valid characters\n if (!VALID_TOKEN_CHARS.test(token)) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Match a subject against a pattern\n * Pattern can contain wildcards (* and >)\n * Subject must be a plain subject (no wildcards)\n */\nexport function matchSubject(pattern: string, subject: string): boolean {\n if (!pattern || !subject) {\n return false\n }\n\n const patternTokens = tokenizeSubject(pattern)\n const subjectTokens = tokenizeSubject(subject)\n\n let patternIdx = 0\n let subjectIdx = 0\n\n while (patternIdx < patternTokens.length && subjectIdx < subjectTokens.length) {\n const patternToken = patternTokens[patternIdx]\n const subjectToken = subjectTokens[subjectIdx]\n\n if (patternToken === MULTI_WILDCARD) {\n // > must be last token and matches one or more remaining tokens\n return subjectIdx < subjectTokens.length\n }\n\n if (patternToken === SINGLE_WILDCARD) {\n // * matches exactly one token\n patternIdx++\n subjectIdx++\n continue\n }\n\n // Exact match required\n if (patternToken !== subjectToken) {\n return false\n }\n\n patternIdx++\n subjectIdx++\n }\n\n // Check if we consumed all tokens\n if (patternIdx < patternTokens.length) {\n // Pattern has remaining tokens - only valid if it's just >\n if (patternTokens[patternIdx] === MULTI_WILDCARD && patternIdx === patternTokens.length - 1) {\n // > requires at least one more subject token, which we don't have\n return false\n }\n return false\n }\n\n if (subjectIdx < subjectTokens.length) {\n // Subject has remaining tokens but pattern doesn't\n return false\n }\n\n return true\n}\n\n/**\n * Convert a subject pattern to a RegExp\n * Useful for filtering subjects in bulk\n */\nexport function subjectToRegex(pattern: string): RegExp {\n const tokens = tokenizeSubject(pattern)\n const regexParts: string[] = []\n\n for (const token of tokens) {\n if (token === SINGLE_WILDCARD) {\n // * matches one token (anything except dots)\n regexParts.push('[^.]+')\n } else if (token === MULTI_WILDCARD) {\n // > matches one or more tokens (rest of subject)\n regexParts.push('.+')\n } else {\n // Escape regex special characters\n regexParts.push(escapeRegex(token))\n }\n }\n\n return new RegExp(`^${regexParts.join('\\\\.')}$`)\n}\n\n/**\n * Escape special regex characters\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n","/**\n * NUID Generator\n *\n * Generates unique identifiers compatible with NATS NUIDs.\n * Format: 22 characters using base36 alphabet.\n */\n\nconst DIGITS = '0123456789abcdefghijklmnopqrstuvwxyz'\nconst BASE = 36\nconst PREFIX_LENGTH = 12\nconst SEQ_LENGTH = 10\nconst MAX_SEQ = Math.pow(BASE, SEQ_LENGTH)\n\n/**\n * NUID generator class\n */\nexport class NUID {\n private prefix: string\n private seq: number\n private inc: number\n\n constructor() {\n this.prefix = this.randomPrefix()\n this.seq = Math.floor(Math.random() * MAX_SEQ)\n this.inc = Math.floor(Math.random() * 33) + 22 // Random increment between 22-54\n }\n\n /**\n * Generate the next NUID\n */\n next(): string {\n this.seq += this.inc\n if (this.seq >= MAX_SEQ) {\n this.prefix = this.randomPrefix()\n this.seq = Math.floor(Math.random() * MAX_SEQ)\n }\n return this.prefix + this.formatSeq(this.seq)\n }\n\n /**\n * Generate a random prefix\n */\n private randomPrefix(): string {\n const bytes = new Uint8Array(PREFIX_LENGTH)\n crypto.getRandomValues(bytes)\n let result = ''\n for (let i = 0; i < PREFIX_LENGTH; i++) {\n result += DIGITS[bytes[i] % BASE]\n }\n return result\n }\n\n /**\n * Format sequence number as fixed-length base36\n */\n private formatSeq(n: number): string {\n let result = ''\n for (let i = 0; i < SEQ_LENGTH; i++) {\n result = DIGITS[n % BASE] + result\n n = Math.floor(n / BASE)\n }\n return result\n }\n\n /**\n * Reset with new random state\n */\n reset(): void {\n this.prefix = this.randomPrefix()\n this.seq = Math.floor(Math.random() * MAX_SEQ)\n this.inc = Math.floor(Math.random() * 33) + 22\n }\n}\n\n// Global instance for convenience\nconst globalNuid = new NUID()\n\n/**\n * Generate the next NUID using global instance\n */\nexport function nuid(): string {\n return globalNuid.next()\n}\n\n/**\n * Create a new inbox subject\n */\nexport function createInbox(prefix = '_INBOX'): string {\n return `${prefix}.${nuid()}`\n}\n","/**\n * Error Hierarchy\n *\n * NATS-compatible error types for NatDO.\n */\n\n/**\n * Base NATS error\n */\nexport class NatsError extends Error {\n readonly code: string\n override readonly name: string = 'NatsError'\n\n constructor(message: string, code: string) {\n super(message)\n this.code = code\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\n\n/**\n * JetStream-specific error\n */\nexport class JetStreamError extends NatsError {\n override readonly name: string = 'JetStreamError'\n readonly stream?: string\n readonly consumer?: string\n\n constructor(\n message: string,\n code: string,\n opts?: { stream?: string; consumer?: string }\n ) {\n super(message, code)\n this.stream = opts?.stream\n this.consumer = opts?.consumer\n }\n}\n\n/**\n * Timeout error\n */\nexport class TimeoutError extends NatsError {\n override readonly name = 'TimeoutError'\n readonly timeout: number\n\n constructor(timeout: number, message?: string) {\n super(message || `Operation timed out after ${timeout}ms`, 'TIMEOUT')\n this.timeout = timeout\n }\n}\n\n/**\n * No responders error\n */\nexport class NoRespondersError extends NatsError {\n override readonly name = 'NoRespondersError'\n readonly subject: string\n\n constructor(subject: string) {\n super(`No responders for subject \"${subject}\"`, 'NO_RESPONDERS')\n this.subject = subject\n }\n}\n\n/**\n * Connection error\n */\nexport class ConnectionError extends NatsError {\n override readonly name = 'ConnectionError'\n\n constructor(message: string) {\n super(message, 'CONNECTION_ERROR')\n }\n}\n\n/**\n * Permission error\n */\nexport class PermissionError extends NatsError {\n override readonly name = 'PermissionError'\n readonly operation?: string\n readonly subject?: string\n\n constructor(message: string, opts?: { operation?: string; subject?: string }) {\n super(message, 'PERMISSION_DENIED')\n this.operation = opts?.operation\n this.subject = opts?.subject\n }\n}\n\n/**\n * Stream not found error\n */\nexport class StreamNotFoundError extends JetStreamError {\n override readonly name = 'StreamNotFoundError'\n\n constructor(stream: string) {\n super(`Stream \"${stream}\" not found`, 'STREAM_NOT_FOUND', { stream })\n }\n}\n\n/**\n * Consumer not found error\n */\nexport class ConsumerNotFoundError extends JetStreamError {\n override readonly name = 'ConsumerNotFoundError'\n\n constructor(stream: string, consumer: string) {\n super(\n `Consumer \"${consumer}\" not found on stream \"${stream}\"`,\n 'CONSUMER_NOT_FOUND',\n { stream, consumer }\n )\n }\n}\n\n/**\n * Message not found error\n */\nexport class MessageNotFoundError extends JetStreamError {\n override readonly name = 'MessageNotFoundError'\n readonly seq: number\n\n constructor(stream: string, seq: number) {\n super(`Message ${seq} not found in stream \"${stream}\"`, 'MESSAGE_NOT_FOUND', {\n stream,\n })\n this.seq = seq\n }\n}\n\n/**\n * Stream already exists error\n */\nexport class StreamExistsError extends JetStreamError {\n override readonly name = 'StreamExistsError'\n\n constructor(stream: string) {\n super(`Stream \"${stream}\" already exists`, 'STREAM_EXISTS', { stream })\n }\n}\n\n/**\n * Consumer already exists error\n */\nexport class ConsumerExistsError extends JetStreamError {\n override readonly name = 'ConsumerExistsError'\n\n constructor(stream: string, consumer: string) {\n super(\n `Consumer \"${consumer}\" already exists on stream \"${stream}\"`,\n 'CONSUMER_EXISTS',\n { stream, consumer }\n )\n }\n}\n\n/**\n * Invalid subject error\n */\nexport class InvalidSubjectError extends NatsError {\n override readonly name = 'InvalidSubjectError'\n readonly subject: string\n\n constructor(subject: string) {\n super(`Invalid subject: \"${subject}\"`, 'INVALID_SUBJECT')\n this.subject = subject\n }\n}\n\n/**\n * Max payload exceeded error\n */\nexport class MaxPayloadError extends NatsError {\n override readonly name = 'MaxPayloadError'\n readonly size: number\n readonly maxSize: number\n\n constructor(size: number, maxSize: number) {\n super(\n `Message size ${size} exceeds maximum allowed ${maxSize}`,\n 'MAX_PAYLOAD_EXCEEDED'\n )\n this.size = size\n this.maxSize = maxSize\n }\n}\n\n/**\n * Error codes for RPC responses\n */\nexport const ErrorCodes = {\n TIMEOUT: 'TIMEOUT',\n NO_RESPONDERS: 'NO_RESPONDERS',\n CONNECTION_ERROR: 'CONNECTION_ERROR',\n PERMISSION_DENIED: 'PERMISSION_DENIED',\n STREAM_NOT_FOUND: 'STREAM_NOT_FOUND',\n CONSUMER_NOT_FOUND: 'CONSUMER_NOT_FOUND',\n MESSAGE_NOT_FOUND: 'MESSAGE_NOT_FOUND',\n STREAM_EXISTS: 'STREAM_EXISTS',\n CONSUMER_EXISTS: 'CONSUMER_EXISTS',\n INVALID_SUBJECT: 'INVALID_SUBJECT',\n MAX_PAYLOAD_EXCEEDED: 'MAX_PAYLOAD_EXCEEDED',\n} as const\n\nexport type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes]\n"]}
|
package/dist/utils.d.cts
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subject Wildcard Matcher
|
|
3
|
+
*
|
|
4
|
+
* Implements NATS subject pattern matching with wildcards:
|
|
5
|
+
* * (asterisk) - matches exactly one token
|
|
6
|
+
* > (greater than) - matches one or more tokens (must be last)
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Tokenize a subject string into an array of tokens
|
|
10
|
+
*/
|
|
11
|
+
declare function tokenizeSubject(subject: string): string[];
|
|
12
|
+
/**
|
|
13
|
+
* Parse a subject and return metadata about it
|
|
14
|
+
*/
|
|
15
|
+
interface ParsedSubject {
|
|
16
|
+
tokens: string[];
|
|
17
|
+
tokenCount: number;
|
|
18
|
+
hasWildcard: boolean;
|
|
19
|
+
hasGreater: boolean;
|
|
20
|
+
}
|
|
21
|
+
declare function parseSubject(subject: string): ParsedSubject;
|
|
22
|
+
/**
|
|
23
|
+
* Check if a subject (not pattern) is valid
|
|
24
|
+
* Subjects cannot contain wildcards
|
|
25
|
+
*/
|
|
26
|
+
declare function isValidSubject(subject: string): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Check if a wildcard pattern is valid
|
|
29
|
+
*/
|
|
30
|
+
declare function isValidWildcard(pattern: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Match a subject against a pattern
|
|
33
|
+
* Pattern can contain wildcards (* and >)
|
|
34
|
+
* Subject must be a plain subject (no wildcards)
|
|
35
|
+
*/
|
|
36
|
+
declare function matchSubject(pattern: string, subject: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Convert a subject pattern to a RegExp
|
|
39
|
+
* Useful for filtering subjects in bulk
|
|
40
|
+
*/
|
|
41
|
+
declare function subjectToRegex(pattern: string): RegExp;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* NUID Generator
|
|
45
|
+
*
|
|
46
|
+
* Generates unique identifiers compatible with NATS NUIDs.
|
|
47
|
+
* Format: 22 characters using base36 alphabet.
|
|
48
|
+
*/
|
|
49
|
+
/**
|
|
50
|
+
* NUID generator class
|
|
51
|
+
*/
|
|
52
|
+
declare class NUID {
|
|
53
|
+
private prefix;
|
|
54
|
+
private seq;
|
|
55
|
+
private inc;
|
|
56
|
+
constructor();
|
|
57
|
+
/**
|
|
58
|
+
* Generate the next NUID
|
|
59
|
+
*/
|
|
60
|
+
next(): string;
|
|
61
|
+
/**
|
|
62
|
+
* Generate a random prefix
|
|
63
|
+
*/
|
|
64
|
+
private randomPrefix;
|
|
65
|
+
/**
|
|
66
|
+
* Format sequence number as fixed-length base36
|
|
67
|
+
*/
|
|
68
|
+
private formatSeq;
|
|
69
|
+
/**
|
|
70
|
+
* Reset with new random state
|
|
71
|
+
*/
|
|
72
|
+
reset(): void;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Generate the next NUID using global instance
|
|
76
|
+
*/
|
|
77
|
+
declare function nuid(): string;
|
|
78
|
+
/**
|
|
79
|
+
* Create a new inbox subject
|
|
80
|
+
*/
|
|
81
|
+
declare function createInbox(prefix?: string): string;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Error Hierarchy
|
|
85
|
+
*
|
|
86
|
+
* NATS-compatible error types for NatDO.
|
|
87
|
+
*/
|
|
88
|
+
/**
|
|
89
|
+
* Base NATS error
|
|
90
|
+
*/
|
|
91
|
+
declare class NatsError extends Error {
|
|
92
|
+
readonly code: string;
|
|
93
|
+
readonly name: string;
|
|
94
|
+
constructor(message: string, code: string);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* JetStream-specific error
|
|
98
|
+
*/
|
|
99
|
+
declare class JetStreamError extends NatsError {
|
|
100
|
+
readonly name: string;
|
|
101
|
+
readonly stream?: string;
|
|
102
|
+
readonly consumer?: string;
|
|
103
|
+
constructor(message: string, code: string, opts?: {
|
|
104
|
+
stream?: string;
|
|
105
|
+
consumer?: string;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Timeout error
|
|
110
|
+
*/
|
|
111
|
+
declare class TimeoutError extends NatsError {
|
|
112
|
+
readonly name = "TimeoutError";
|
|
113
|
+
readonly timeout: number;
|
|
114
|
+
constructor(timeout: number, message?: string);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* No responders error
|
|
118
|
+
*/
|
|
119
|
+
declare class NoRespondersError extends NatsError {
|
|
120
|
+
readonly name = "NoRespondersError";
|
|
121
|
+
readonly subject: string;
|
|
122
|
+
constructor(subject: string);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Connection error
|
|
126
|
+
*/
|
|
127
|
+
declare class ConnectionError extends NatsError {
|
|
128
|
+
readonly name = "ConnectionError";
|
|
129
|
+
constructor(message: string);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Permission error
|
|
133
|
+
*/
|
|
134
|
+
declare class PermissionError extends NatsError {
|
|
135
|
+
readonly name = "PermissionError";
|
|
136
|
+
readonly operation?: string;
|
|
137
|
+
readonly subject?: string;
|
|
138
|
+
constructor(message: string, opts?: {
|
|
139
|
+
operation?: string;
|
|
140
|
+
subject?: string;
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Stream not found error
|
|
145
|
+
*/
|
|
146
|
+
declare class StreamNotFoundError extends JetStreamError {
|
|
147
|
+
readonly name = "StreamNotFoundError";
|
|
148
|
+
constructor(stream: string);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Consumer not found error
|
|
152
|
+
*/
|
|
153
|
+
declare class ConsumerNotFoundError extends JetStreamError {
|
|
154
|
+
readonly name = "ConsumerNotFoundError";
|
|
155
|
+
constructor(stream: string, consumer: string);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Message not found error
|
|
159
|
+
*/
|
|
160
|
+
declare class MessageNotFoundError extends JetStreamError {
|
|
161
|
+
readonly name = "MessageNotFoundError";
|
|
162
|
+
readonly seq: number;
|
|
163
|
+
constructor(stream: string, seq: number);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Stream already exists error
|
|
167
|
+
*/
|
|
168
|
+
declare class StreamExistsError extends JetStreamError {
|
|
169
|
+
readonly name = "StreamExistsError";
|
|
170
|
+
constructor(stream: string);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Consumer already exists error
|
|
174
|
+
*/
|
|
175
|
+
declare class ConsumerExistsError extends JetStreamError {
|
|
176
|
+
readonly name = "ConsumerExistsError";
|
|
177
|
+
constructor(stream: string, consumer: string);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Invalid subject error
|
|
181
|
+
*/
|
|
182
|
+
declare class InvalidSubjectError extends NatsError {
|
|
183
|
+
readonly name = "InvalidSubjectError";
|
|
184
|
+
readonly subject: string;
|
|
185
|
+
constructor(subject: string);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Max payload exceeded error
|
|
189
|
+
*/
|
|
190
|
+
declare class MaxPayloadError extends NatsError {
|
|
191
|
+
readonly name = "MaxPayloadError";
|
|
192
|
+
readonly size: number;
|
|
193
|
+
readonly maxSize: number;
|
|
194
|
+
constructor(size: number, maxSize: number);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Error codes for RPC responses
|
|
198
|
+
*/
|
|
199
|
+
declare const ErrorCodes: {
|
|
200
|
+
readonly TIMEOUT: "TIMEOUT";
|
|
201
|
+
readonly NO_RESPONDERS: "NO_RESPONDERS";
|
|
202
|
+
readonly CONNECTION_ERROR: "CONNECTION_ERROR";
|
|
203
|
+
readonly PERMISSION_DENIED: "PERMISSION_DENIED";
|
|
204
|
+
readonly STREAM_NOT_FOUND: "STREAM_NOT_FOUND";
|
|
205
|
+
readonly CONSUMER_NOT_FOUND: "CONSUMER_NOT_FOUND";
|
|
206
|
+
readonly MESSAGE_NOT_FOUND: "MESSAGE_NOT_FOUND";
|
|
207
|
+
readonly STREAM_EXISTS: "STREAM_EXISTS";
|
|
208
|
+
readonly CONSUMER_EXISTS: "CONSUMER_EXISTS";
|
|
209
|
+
readonly INVALID_SUBJECT: "INVALID_SUBJECT";
|
|
210
|
+
readonly MAX_PAYLOAD_EXCEEDED: "MAX_PAYLOAD_EXCEEDED";
|
|
211
|
+
};
|
|
212
|
+
type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
|
|
213
|
+
|
|
214
|
+
export { ConnectionError, ConsumerExistsError, ConsumerNotFoundError, type ErrorCode, ErrorCodes, InvalidSubjectError, JetStreamError, MaxPayloadError, MessageNotFoundError, NUID, NatsError, NoRespondersError, type ParsedSubject, PermissionError, StreamExistsError, StreamNotFoundError, TimeoutError, createInbox, isValidSubject, isValidWildcard, matchSubject, nuid, parseSubject, subjectToRegex, tokenizeSubject };
|