@camera.ui/rpc 1.0.1

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.
@@ -0,0 +1,286 @@
1
+ import { Svcm } from '@nats-io/services';
2
+ import { decode } from './codec.js';
3
+ import { extractNestedMethodsWithDecorators } from './decorators.js';
4
+ import { formatErrorObject, handleNormalRPC, handlePullIteratorRequest, handleStreamRequest } from './handler.js';
5
+ /**
6
+ * RPC Service wrapper with automatic encoding/decoding and streaming support
7
+ */
8
+ export class RPCService {
9
+ client;
10
+ svc;
11
+ services = [];
12
+ initialized = false;
13
+ constructor(client) {
14
+ this.client = client;
15
+ }
16
+ /**
17
+ * Initialize the service manager
18
+ */
19
+ init(nc) {
20
+ if (this.initialized) {
21
+ return;
22
+ }
23
+ this.initialized = true;
24
+ this.svc = new Svcm(nc);
25
+ this.services = [];
26
+ }
27
+ /**
28
+ * Add a service with automatic RPC endpoint wrapping
29
+ * Supports objects, classes, nested structures, streaming, and chunking
30
+ */
31
+ async registerHandler(config, handlers, options) {
32
+ if (!this.svc) {
33
+ throw new Error('RPCService is not initialized. Call init() first.');
34
+ }
35
+ // Track pull iterator cleanups for this service
36
+ const pullIteratorCleanups = new Map();
37
+ // Use isolated connection if requested
38
+ let serviceClient = this.client;
39
+ let svc = this.svc;
40
+ if (options?.isolatedConnection) {
41
+ // Create isolated connection for this service
42
+ serviceClient = this.client.createIsolatedClient({
43
+ ...this.client.options,
44
+ name: `${this.client.options.name}-service-${config.name}`,
45
+ });
46
+ // Initialize isolated client
47
+ const nc = await serviceClient.connect();
48
+ // Create service manager for isolated connection
49
+ svc = new Svcm(nc);
50
+ }
51
+ const service = await svc.add(config);
52
+ this.services.push(service);
53
+ // Store reference to isolated connection if used
54
+ if (options?.isolatedConnection) {
55
+ service._isolatedClient = serviceClient;
56
+ }
57
+ // Extract all methods including nested ones
58
+ const methods = extractNestedMethodsWithDecorators(handlers);
59
+ // Create groups for nested paths
60
+ const groups = new Map();
61
+ for (const [path, handler] of Object.entries(methods)) {
62
+ const parts = path.split('.');
63
+ const methodName = parts.pop();
64
+ let target = service;
65
+ // Create nested groups if needed
66
+ if (parts.length > 0) {
67
+ const groupPath = parts.join('.');
68
+ if (!groups.has(groupPath)) {
69
+ let current = service;
70
+ for (const part of parts) {
71
+ current = current.addGroup(part);
72
+ }
73
+ groups.set(groupPath, current);
74
+ }
75
+ target = groups.get(groupPath);
76
+ }
77
+ // Add endpoint with auto-encoding/decoding
78
+ target.addEndpoint(methodName, async (err, msg) => {
79
+ if (err) {
80
+ msg.respondError(500, err.message);
81
+ return;
82
+ }
83
+ try {
84
+ const chunkType = msg.headers?.get('x-chunked-transfer');
85
+ if (chunkType === 'header') {
86
+ // Chunked transfer header
87
+ const data = decode(msg.data);
88
+ const chunkId = msg.headers?.get('x-chunk-id');
89
+ if (!chunkId || data.transferId !== chunkId) {
90
+ console.error('Invalid chunk header');
91
+ return;
92
+ }
93
+ // Setup chunk assembly with pre-allocated buffer (optimized)
94
+ serviceClient.chunkingManager.startReceiving(data.transferId, data.totalChunks, async (assembledData) => {
95
+ // Process the assembled RPC message
96
+ await processRPCMessage(assembledData, msg);
97
+ }, (error) => {
98
+ console.error(`Error assembling chunks for ${methodName}:`, error);
99
+ }, data.totalSize, // Pass totalSize for pre-allocated buffer optimization
100
+ data.chunkSize);
101
+ }
102
+ else if (chunkType === 'chunk') {
103
+ // Chunk data
104
+ const chunkId = msg.headers?.get('x-chunk-id');
105
+ const chunkIndex = parseInt(msg.headers?.get('x-chunk-index') ?? '0');
106
+ if (!chunkId) {
107
+ console.error('Chunk missing chunk ID');
108
+ return;
109
+ }
110
+ // Process raw chunk data
111
+ serviceClient.chunkingManager.processChunk({
112
+ id: chunkId,
113
+ chunkIndex,
114
+ data: msg.data,
115
+ isLast: false, // Determined by total chunks from header
116
+ });
117
+ }
118
+ else {
119
+ // Regular message - decode MessagePack data
120
+ const rpcMsg = decode(msg.data);
121
+ await processRPCMessage(rpcMsg, msg);
122
+ }
123
+ }
124
+ catch (error) {
125
+ console.error(`Error processing message for ${methodName}:`, error);
126
+ }
127
+ // Define the RPC message processor function
128
+ async function processRPCMessage(rpcMsg, originalMsg) {
129
+ const response = { id: rpcMsg.id };
130
+ try {
131
+ // Handle stream request
132
+ if (rpcMsg.params?.__stream && rpcMsg.params?.__streamSubject) {
133
+ const streamSubject = rpcMsg.params.__streamSubject;
134
+ const args = rpcMsg.params.args ?? [];
135
+ await handleStreamRequest(handler, args, streamSubject, rpcMsg.id, serviceClient);
136
+ }
137
+ else if (
138
+ // Check if it's a pull iterator request
139
+ // Could be direct object or wrapped in array from call()
140
+ rpcMsg.params?.__pullIterator ||
141
+ (Array.isArray(rpcMsg.params) && rpcMsg.params[0]?.__pullIterator)) {
142
+ // Extract pull iterator params
143
+ const pullParams = rpcMsg.params?.__pullIterator ? rpcMsg.params : rpcMsg.params[0];
144
+ const args = pullParams.args ?? [];
145
+ const iteratorId = pullParams.__iteratorId ?? rpcMsg.id;
146
+ const cleanup = await handlePullIteratorRequest(handler, args, iteratorId, serviceClient);
147
+ // Store cleanup function for later
148
+ pullIteratorCleanups.set(iteratorId, cleanup);
149
+ response.result = { iteratorId };
150
+ // Send response with iterator ID
151
+ const replySubject = `${originalMsg.subject}.reply.${rpcMsg.id}`;
152
+ await serviceClient.publish(replySubject, response);
153
+ }
154
+ else {
155
+ // Normal RPC call
156
+ const result = await handleNormalRPC(handler, rpcMsg.params);
157
+ response.result = result;
158
+ // Send response
159
+ const replySubject = `${originalMsg.subject}.reply.${rpcMsg.id}`;
160
+ await serviceClient.publish(replySubject, response);
161
+ }
162
+ }
163
+ catch (error) {
164
+ response.error = formatErrorObject(error);
165
+ try {
166
+ const replySubject = `${originalMsg.subject}.reply.${rpcMsg.id}`;
167
+ await serviceClient.publish(replySubject, response);
168
+ }
169
+ catch (publishError) {
170
+ if (serviceClient.isClosed) {
171
+ return; // Ignore if client is closed
172
+ }
173
+ console.error('Failed to send error response:', publishError);
174
+ }
175
+ }
176
+ }
177
+ });
178
+ }
179
+ // Extend service with cleanup management
180
+ const extendedService = service;
181
+ extendedService._pullIteratorCleanups = pullIteratorCleanups;
182
+ // Override stop method to clean up pull iterators
183
+ const originalStop = service.stop.bind(service);
184
+ service.stop = async (err) => {
185
+ // Clean up all pull iterators
186
+ await Promise.allSettled(Array.from(pullIteratorCleanups.values()).map((cleanup) => cleanup()));
187
+ pullIteratorCleanups.clear();
188
+ // Call original stop
189
+ return originalStop(err);
190
+ };
191
+ return new Service(service);
192
+ }
193
+ /**
194
+ * Get service monitoring client
195
+ */
196
+ monitor() {
197
+ if (!this.svc) {
198
+ throw new Error('RPCService is not initialized. Call init() first.');
199
+ }
200
+ return this.svc.client({ strategy: 'stall', stall: 10, maxWait: 2000 });
201
+ }
202
+ /**
203
+ * Stop all services and cleanup isolated connections
204
+ */
205
+ async stopAll() {
206
+ await Promise.allSettled(this.services.map(async (s) => {
207
+ await s.stop();
208
+ // Disconnect isolated connection if present
209
+ const isolatedClient = s._isolatedClient;
210
+ if (isolatedClient) {
211
+ await isolatedClient.disconnect();
212
+ }
213
+ }));
214
+ this.services = [];
215
+ }
216
+ /**
217
+ * Stop a specific service by name
218
+ */
219
+ async stop(serviceName) {
220
+ const service = this.services.find((s) => s.info().name === serviceName);
221
+ if (service) {
222
+ try {
223
+ await service.stop();
224
+ // Disconnect isolated connection if present
225
+ const isolatedClient = service._isolatedClient;
226
+ if (isolatedClient) {
227
+ await isolatedClient.disconnect();
228
+ }
229
+ this.services = this.services.filter((s) => s !== service);
230
+ }
231
+ catch {
232
+ // Ignore errors during stop
233
+ }
234
+ }
235
+ }
236
+ /**
237
+ * Get all services info
238
+ */
239
+ getAllInfo() {
240
+ return this.services.map((s) => s.info());
241
+ }
242
+ /**
243
+ * Get info for a specific service
244
+ */
245
+ getInfo(serviceName) {
246
+ const service = this.services.find((s) => s.info().name === serviceName);
247
+ return service?.info();
248
+ }
249
+ /**
250
+ * Get all services stats
251
+ */
252
+ async getAllStats() {
253
+ return Promise.all(this.services.map((s) => s.stats()));
254
+ }
255
+ /**
256
+ * Get stats for a specific service
257
+ */
258
+ async getStats(serviceName) {
259
+ const service = this.services.find((s) => s.info().name === serviceName);
260
+ return service?.stats();
261
+ }
262
+ }
263
+ export class Service {
264
+ natsService;
265
+ get isStopped() {
266
+ return this.natsService.isStopped;
267
+ }
268
+ constructor(natsService) {
269
+ this.natsService = natsService;
270
+ }
271
+ info() {
272
+ return this.natsService.info();
273
+ }
274
+ stats() {
275
+ return this.natsService.stats();
276
+ }
277
+ async stop(err) {
278
+ try {
279
+ await this.natsService.stop(err);
280
+ }
281
+ catch {
282
+ // Ignore errors during stop
283
+ }
284
+ }
285
+ }
286
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,300 @@
1
+ import type { NatsConnection, Status } from '@nats-io/nats-core';
2
+ import type { Channel, PrivateChannel } from './channel.js';
3
+ import type { RPCService } from './service.js';
4
+ export interface RPCClient {
5
+ readonly service: RPCService;
6
+ readonly isConnected: boolean;
7
+ readonly isClosed: boolean;
8
+ readonly maxPayloadSize: number;
9
+ connect(options?: {
10
+ signal?: AbortSignal;
11
+ }): Promise<NatsConnection>;
12
+ disconnect(): Promise<void>;
13
+ suspend(): Promise<void>;
14
+ reconfigure(overrides: {
15
+ servers?: string[];
16
+ auth?: RPCAuthOptions;
17
+ }): void;
18
+ setServers(servers: string[]): void;
19
+ forceReconnect(): Promise<void>;
20
+ abortClose(err?: Error): void;
21
+ status(): AsyncIterable<Status> | undefined;
22
+ flush(timeoutMs?: number): Promise<void>;
23
+ publish<TMessage = any>(subject: string, data: TMessage): Promise<void>;
24
+ subscribe<TResponse = any>(pattern: string, handler: (data: TResponse) => void | Promise<void>, options?: {
25
+ queue?: string;
26
+ }): Promise<() => void>;
27
+ request<TRequest = any, TResponse = any>(subject: string, data: TRequest, options?: {
28
+ timeout?: number;
29
+ noResponderRetry?: {
30
+ maxRetries?: number;
31
+ delays?: number[];
32
+ };
33
+ }): Promise<TResponse>;
34
+ onRequest<TRequest = any, TResponse = any>(pattern: string, handler: (data: TRequest) => Promise<TResponse> | TResponse): Promise<() => void>;
35
+ registerHandler(namespace: string, handlers: object, options?: {
36
+ isolatedConnection?: boolean;
37
+ withoutDecorators?: boolean;
38
+ queue?: string;
39
+ }): Promise<() => Promise<void>>;
40
+ callWithCallback<TResponse = any>(subject: string, args: any[], callback: (value: TResponse) => void | Promise<void>): Promise<() => void>;
41
+ callPullIteratorWithCallback(subject: string, callbacks: Record<string, (...a: any[]) => any>, onewayMethods: string[], ...args: any[]): AsyncGenerator<void>;
42
+ channel(channelId: string, options?: {
43
+ isolatedConnection?: boolean;
44
+ }): Promise<Channel>;
45
+ privateChannel(channelId: string, targetClientId: string, options?: {
46
+ isolatedConnection?: boolean;
47
+ }): Promise<PrivateChannel>;
48
+ createProxy<T extends object>(namespace: string): Promisify<T>;
49
+ createProxy<T extends object>(namespace: string, options: {
50
+ isolatedConnection: false;
51
+ }): Promisify<T>;
52
+ createProxy<T extends object>(namespace: string, options: {
53
+ isolatedConnection: true;
54
+ }): {
55
+ proxy: Promisify<T>;
56
+ close: () => Promise<void>;
57
+ };
58
+ createServiceProxy<T extends object>(serviceName: string): Promise<Promisify<T>>;
59
+ createServiceProxy<T extends object>(serviceName: string, options: {
60
+ preferredId?: string;
61
+ timeout?: number;
62
+ isolatedConnection?: false;
63
+ }): Promise<Promisify<T>>;
64
+ createServiceProxy<T extends object>(serviceName: string, options: {
65
+ preferredId?: string;
66
+ timeout?: number;
67
+ isolatedConnection?: true;
68
+ }): Promise<{
69
+ proxy: Promisify<T>;
70
+ close: () => Promise<void>;
71
+ }>;
72
+ }
73
+ export interface RPCAuthOptions {
74
+ /** Username for authentication */
75
+ user: string;
76
+ /** Password for authentication */
77
+ password: string;
78
+ }
79
+ /**
80
+ * Configuration options for RPC client
81
+ */
82
+ export interface RPCClientOptions {
83
+ /** NATS server URLs */
84
+ servers: string[];
85
+ /** Client name for identification */
86
+ name: string;
87
+ /** Authentication credentials */
88
+ auth?: RPCAuthOptions;
89
+ /** Default RPC call timeout in milliseconds */
90
+ timeout?: number;
91
+ /** Enable automatic reconnection */
92
+ reconnect?: boolean;
93
+ /** Max number of pings the client will allow unanswered before raising a stale connection error */
94
+ maxPingOut?: number;
95
+ /** Number of milliseconds between client-sent pings */
96
+ pingInterval?: number;
97
+ /** Number of milliseconds to wait for a ping response before considering the connection stale and initiating a reconnect */
98
+ pingTimeout?: number;
99
+ /** Maximum reconnection attempts (-1 for infinite) */
100
+ maxReconnectAttempts?: number;
101
+ /** Delay between reconnection attempts in milliseconds */
102
+ reconnectTimeWait?: number;
103
+ /** Maximum delay between reconnection attempts in milliseconds (default: 0 - disabled — legacy linear delay) */
104
+ reconnectionDelayMax?: number;
105
+ /** Randomization factor for reconnection delay (default: 0 - no multiplicative jitter) */
106
+ reconnectionRandomizationFactor?: number;
107
+ /** Random jitter in ms added to `reconnectTimeWait` */
108
+ reconnectJitter?: number;
109
+ /** Random jitter in ms added to `reconnectTimeWait` for TLS connections */
110
+ reconnectJitterTLS?: number;
111
+ /** Don't abort the connection after two consecutive auth errors. Important
112
+ * for clients with token rotation: a brief window where the proxy still
113
+ * sees the previous token would otherwise kill reconnection permanently
114
+ * and require a full page reload */
115
+ ignoreAuthErrorAbort?: boolean;
116
+ /** Print NATS protocol traffic to the console. Development only. */
117
+ debug?: boolean;
118
+ /** TLS configuration */
119
+ tls?: {
120
+ cert: string;
121
+ key: string;
122
+ ca: string;
123
+ };
124
+ /** Maximum payload size in bytes (default: auto-detect from NATS server) */
125
+ maxPayloadSize?: number;
126
+ /** Block connect() until the first connection succeeds (default: true).
127
+ * Set to false for browser clients where disconnect() must be able to
128
+ * abort an in-flight connection attempt immediately. */
129
+ waitOnFirstConnect?: boolean;
130
+ /** Maximum time in ms to wait for the NATS connection to fully close
131
+ * during disconnect(). Relevant when waitOnFirstConnect is false, as the
132
+ * underlying transport may still be mid-handshake when close() is called.
133
+ * Default: 2000 */
134
+ disconnectTimeout?: number;
135
+ /** Retry configuration for 503 / no-responder errors. */
136
+ noResponderRetry?: {
137
+ /** Maximum number of retries (default: 3) */
138
+ maxRetries?: number;
139
+ /** Delay in ms before each retry attempt (default: [500, 1000, 2000]) */
140
+ delays?: number[];
141
+ };
142
+ }
143
+ /**
144
+ * RPC request message format
145
+ */
146
+ export interface RPCMessage<T = any> {
147
+ /** Unique request ID */
148
+ id: string;
149
+ /** Method name to call */
150
+ method: string;
151
+ /** Method parameters */
152
+ params: T;
153
+ /** Optional error (unused in requests) */
154
+ error?: RPCError;
155
+ }
156
+ /**
157
+ * RPC response message format
158
+ */
159
+ export interface RPCResponse<T = any> {
160
+ /** Request ID this response belongs to */
161
+ id: string;
162
+ /** Result data (if successful) */
163
+ result?: T;
164
+ /** Error information (if failed) */
165
+ error?: RPCError;
166
+ /** Available methods on namespace (internal metadata for proxy) */
167
+ __methods?: string[];
168
+ }
169
+ /**
170
+ * RPC error format
171
+ */
172
+ export interface RPCError {
173
+ /** Error code (see ERROR_CODES) */
174
+ code: string;
175
+ /** Human-readable error message */
176
+ message: string;
177
+ /** Additional error data */
178
+ data?: any;
179
+ }
180
+ /**
181
+ * Convert service interface to async client interface
182
+ * - Regular methods become Promise-returning
183
+ * - AsyncGenerator methods stay as AsyncGenerators
184
+ * - Generator methods become AsyncGenerators
185
+ * - Promise<Generator> becomes AsyncGenerator
186
+ * - Promise<AsyncGenerator> becomes AsyncGenerator
187
+ * - Generic methods preserve their generic parameters
188
+ */
189
+ type PromisifyMethod<T> = T extends (...args: infer Args) => infer R ? R extends AsyncGenerator<infer Y, any, any> ? (...args: Args) => AsyncGenerator<Y, any, any> : R extends Generator<infer Y, any, any> ? (...args: Args) => AsyncGenerator<Y, any, any> : R extends Promise<infer U> ? U extends AsyncGenerator<infer Y, any, any> ? (...args: Args) => AsyncGenerator<Y, any, any> : U extends Generator<infer Y, any, any> ? (...args: Args) => AsyncGenerator<Y, any, any> : T : (...args: Args) => Promise<R> : T;
190
+ export type Promisify<T> = {
191
+ [K in keyof T]: T[K] extends ((...args: any[]) => any) | undefined ? T[K] extends undefined ? undefined : PromisifyMethod<Exclude<T[K], undefined>> | (T[K] extends undefined ? undefined : never) : T[K] extends (...args: any[]) => any ? PromisifyMethod<T[K]> : T[K];
192
+ };
193
+ /**
194
+ * Message format for streaming data
195
+ */
196
+ export interface StreamMessage<T = any> {
197
+ /** Stream ID (same as request ID) */
198
+ id: string;
199
+ /** Message type */
200
+ type: 'data' | 'end' | 'error';
201
+ /** Data payload (for 'data' type) */
202
+ data?: T;
203
+ /** Error information (for 'error' type) */
204
+ error?: RPCError;
205
+ }
206
+ /**
207
+ * Pull iterator request message
208
+ */
209
+ export interface PullIteratorRequest {
210
+ /** Iterator ID */
211
+ id: string;
212
+ /** Request type */
213
+ type: 'next' | 'cancel';
214
+ }
215
+ /**
216
+ * Pull iterator response message
217
+ */
218
+ export interface PullIteratorResponse<T = any> {
219
+ /** Iterator ID */
220
+ id: string;
221
+ /** Response type */
222
+ type: 'value' | 'done' | 'error';
223
+ /** Value (for 'value' type) */
224
+ value?: T;
225
+ /** Error (for 'error' type) */
226
+ error?: RPCError;
227
+ }
228
+ /**
229
+ * Parameters for callback subscription request
230
+ */
231
+ export interface CallbackParams {
232
+ __callback: true;
233
+ __callbackSubject: string;
234
+ args: any[];
235
+ }
236
+ /**
237
+ * Message format for callback data pushed to subscribers
238
+ */
239
+ export interface CallbackMessage<T = any> {
240
+ id: string;
241
+ type: 'data' | 'error';
242
+ data?: T;
243
+ error?: RPCError;
244
+ }
245
+ /**
246
+ * Parameters for pull-iterator-with-callbacks request.
247
+ * Combines pull-iterator flow control with oneway callbacks for frame-level delivery.
248
+ */
249
+ export interface PullCallbackParams {
250
+ __pullCallback: true;
251
+ __iteratorId: string;
252
+ __callbackSubject: string;
253
+ __callbackMethods: string[];
254
+ __onewayMethods: string[];
255
+ args: any[];
256
+ }
257
+ /**
258
+ * A single callback invocation pushed from server to client on the callback subject.
259
+ * Oneway: no reply expected.
260
+ */
261
+ export interface CallbackInvocation {
262
+ method: string;
263
+ args: any[];
264
+ }
265
+ /**
266
+ * Standard error codes
267
+ */
268
+ export declare const ERROR_CODES: {
269
+ readonly METHOD_NOT_FOUND: "METHOD_NOT_FOUND";
270
+ readonly INVALID_PARAMS: "INVALID_PARAMS";
271
+ readonly INTERNAL_ERROR: "INTERNAL_ERROR";
272
+ readonly TIMEOUT: "TIMEOUT";
273
+ readonly CONNECTION_CLOSED: "CONNECTION_CLOSED";
274
+ readonly STREAM_ERROR: "STREAM_ERROR";
275
+ readonly PAYLOAD_TOO_LARGE: "PAYLOAD_TOO_LARGE";
276
+ readonly NOT_FOUND: "NOT_FOUND";
277
+ };
278
+ /**
279
+ * Error code type
280
+ */
281
+ export type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES];
282
+ /**
283
+ * Chunked transfer header
284
+ */
285
+ export interface ChunkedTransferHeader {
286
+ type: 'chunked';
287
+ transferId: string;
288
+ totalChunks: number;
289
+ totalSize: number;
290
+ chunkSize: number;
291
+ }
292
+ /**
293
+ * Individual chunk message
294
+ */
295
+ export interface ChunkData {
296
+ transferId: string;
297
+ index: number;
298
+ data: Uint8Array;
299
+ }
300
+ export {};
package/dist/types.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Standard error codes
3
+ */
4
+ export const ERROR_CODES = {
5
+ METHOD_NOT_FOUND: 'METHOD_NOT_FOUND',
6
+ INVALID_PARAMS: 'INVALID_PARAMS',
7
+ INTERNAL_ERROR: 'INTERNAL_ERROR',
8
+ TIMEOUT: 'TIMEOUT',
9
+ CONNECTION_CLOSED: 'CONNECTION_CLOSED',
10
+ STREAM_ERROR: 'STREAM_ERROR',
11
+ PAYLOAD_TOO_LARGE: 'PAYLOAD_TOO_LARGE',
12
+ NOT_FOUND: 'NOT_FOUND',
13
+ };
14
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAwTA;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,gBAAgB,EAAE,kBAAkB;IACpC,cAAc,EAAE,gBAAgB;IAChC,cAAc,EAAE,gBAAgB;IAChC,OAAO,EAAE,SAAS;IAClB,iBAAiB,EAAE,mBAAmB;IACtC,YAAY,EAAE,cAAc;IAC5B,iBAAiB,EAAE,mBAAmB;IACtC,SAAS,EAAE,WAAW;CACd,CAAC"}