@skrr-ai/signals 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/dist/index.cjs ADDED
@@ -0,0 +1,563 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ SIGNAL_API_VERSION: () => SIGNAL_API_VERSION,
24
+ SIGNAL_CLOUDEVENTS_CONTENT_TYPE: () => SIGNAL_CLOUDEVENTS_CONTENT_TYPE,
25
+ SignalAPIError: () => SignalAPIError,
26
+ SignalContractError: () => SignalContractError,
27
+ SignalPublisher: () => SignalPublisher,
28
+ createSignalEnvelope: () => createSignalEnvelope,
29
+ parseSignalEnvelope: () => parseSignalEnvelope,
30
+ parseSignalTypeDefinition: () => parseSignalTypeDefinition,
31
+ validateSignalEnvelope: () => validateSignalEnvelope,
32
+ validateSignalTypeDefinition: () => validateSignalTypeDefinition
33
+ });
34
+ module.exports = __toCommonJS(index_exports);
35
+
36
+ // src/contracts.ts
37
+ var import_cloudevents = require("cloudevents");
38
+ var SIGNAL_CLOUDEVENTS_CONTENT_TYPE = "application/cloudevents+json";
39
+ var SIGNAL_API_VERSION = "v1";
40
+ var CLOUD_EVENTS_V1 = "1.0";
41
+ var REQUIRED_CLOUDEVENT_ATTRIBUTES = /* @__PURE__ */ new Set(["specversion", "id", "source", "type"]);
42
+ var STANDARD_CLOUDEVENT_ATTRIBUTES = /* @__PURE__ */ new Set([
43
+ ...REQUIRED_CLOUDEVENT_ATTRIBUTES,
44
+ "subject",
45
+ "time",
46
+ "datacontenttype",
47
+ "dataschema",
48
+ "data",
49
+ "data_base64"
50
+ ]);
51
+ var LEGACY_CLOUDEVENT_ATTRIBUTES = /* @__PURE__ */ new Set(["datacontentencoding", "schemaurl"]);
52
+ var TYPE_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9][a-z0-9-]*)+\.v[1-9][0-9]*$/;
53
+ var FIELD_NAME_PATTERN = /^[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)*$/;
54
+ var EXTENSION_NAME_PATTERN = /^[a-z][a-z0-9]{0,19}$/;
55
+ var RFC3339_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/;
56
+ var SignalContractError = class extends TypeError {
57
+ issues;
58
+ constructor(message, issues) {
59
+ super(message);
60
+ this.name = "SignalContractError";
61
+ this.issues = issues;
62
+ }
63
+ };
64
+ function validateSignalEnvelope(input) {
65
+ const issues = [];
66
+ if (!isRecord(input)) {
67
+ return invalid([{ path: "$", code: "type", message: "Signal must be a JSON object." }]);
68
+ }
69
+ if (input.specversion !== CLOUD_EVENTS_V1) {
70
+ issues.push({
71
+ path: "$.specversion",
72
+ code: "value",
73
+ message: 'Signal must use CloudEvents specversion "1.0".'
74
+ });
75
+ }
76
+ validateNonEmptyString(input.id, "$.id", issues);
77
+ validateUriReference(input.source, "$.source", issues);
78
+ validateTypeName(input.type, "$.type", issues);
79
+ if (input.datacontenttype !== "application/json") {
80
+ issues.push({
81
+ path: "$.datacontenttype",
82
+ code: "value",
83
+ message: 'Signal datacontenttype must be "application/json".'
84
+ });
85
+ }
86
+ if (typeof input.subject !== "undefined") {
87
+ validateNonEmptyString(input.subject, "$.subject", issues);
88
+ }
89
+ if (!isRfc3339Timestamp(input.time)) {
90
+ issues.push({
91
+ path: "$.time",
92
+ code: "format",
93
+ message: "Signal time must be an RFC 3339 timestamp with a timezone."
94
+ });
95
+ }
96
+ validateAbsoluteUri(input.dataschema, "$.dataschema", issues);
97
+ if (!Object.prototype.hasOwnProperty.call(input, "data")) {
98
+ issues.push({ path: "$.data", code: "required", message: "Signal data is required." });
99
+ } else if (!isJsonValue(input.data)) {
100
+ issues.push({ path: "$.data", code: "type", message: "Signal data must be JSON-compatible." });
101
+ }
102
+ if (typeof input.data_base64 !== "undefined") {
103
+ issues.push({
104
+ path: "$.data_base64",
105
+ code: "unsupported",
106
+ message: "Binary CloudEvents data is not supported by the Signal API."
107
+ });
108
+ }
109
+ for (const key of LEGACY_CLOUDEVENT_ATTRIBUTES) {
110
+ if (typeof input[key] !== "undefined") {
111
+ issues.push({
112
+ path: `$.${key}`,
113
+ code: "unsupported",
114
+ message: `${key} is a legacy CloudEvents attribute and is not supported by the Signal API.`
115
+ });
116
+ }
117
+ }
118
+ for (const [key, value] of Object.entries(input)) {
119
+ if (STANDARD_CLOUDEVENT_ATTRIBUTES.has(key)) continue;
120
+ if (typeof value === "undefined") continue;
121
+ validateExtension(key, value, issues);
122
+ }
123
+ if (issues.length > 0) return invalid(issues);
124
+ try {
125
+ new import_cloudevents.CloudEvent(input).validate();
126
+ } catch (error) {
127
+ const message = error instanceof import_cloudevents.ValidationError ? error.message : "Invalid CloudEvents envelope.";
128
+ return invalid([{ path: "$", code: "format", message }]);
129
+ }
130
+ return {
131
+ ok: true,
132
+ value: input
133
+ };
134
+ }
135
+ function parseSignalEnvelope(input) {
136
+ const result = validateSignalEnvelope(input);
137
+ if (result.ok) return result.value;
138
+ throw new SignalContractError("Invalid Signal envelope.", result.issues);
139
+ }
140
+ function createSignalEnvelope(source, input, traceContext) {
141
+ const extensions = input.extensions ?? {};
142
+ for (const key of Object.keys(extensions)) {
143
+ if (STANDARD_CLOUDEVENT_ATTRIBUTES.has(key) || LEGACY_CLOUDEVENT_ATTRIBUTES.has(key) || key === "traceparent" || key === "tracestate") {
144
+ throw new SignalContractError("Invalid Signal extension.", [
145
+ {
146
+ path: `$.extensions.${key}`,
147
+ code: "reserved_attribute",
148
+ message: `${key} is a reserved CloudEvents or trace-context attribute.`
149
+ }
150
+ ]);
151
+ }
152
+ }
153
+ const event = new import_cloudevents.CloudEvent({
154
+ specversion: CLOUD_EVENTS_V1,
155
+ id: input.id ?? globalThis.crypto.randomUUID(),
156
+ source,
157
+ type: input.type,
158
+ subject: input.subject,
159
+ time: normalizeTime(input.time),
160
+ datacontenttype: "application/json",
161
+ dataschema: input.dataschema,
162
+ data: input.data,
163
+ ...extensions,
164
+ ...traceContext ? { traceparent: traceContext.traceparent } : {},
165
+ ...traceContext?.tracestate ? { tracestate: traceContext.tracestate } : {}
166
+ });
167
+ return parseSignalEnvelope(omitUndefined(event.toJSON()));
168
+ }
169
+ function validateSignalTypeDefinition(input) {
170
+ const issues = [];
171
+ if (!isRecord(input)) {
172
+ return invalid([
173
+ { path: "$", code: "type", message: "Signal type definition must be an object." }
174
+ ]);
175
+ }
176
+ validateTypeName(input.type, "$.type", issues);
177
+ validateAbsoluteUri(input.dataschema, "$.dataschema", issues);
178
+ validateNonEmptyString(input.displayName, "$.displayName", issues);
179
+ validateNonEmptyString(input.description, "$.description", issues);
180
+ if (!Array.isArray(input.subjectKinds) || input.subjectKinds.length === 0) {
181
+ issues.push({
182
+ path: "$.subjectKinds",
183
+ code: "required",
184
+ message: "At least one subject kind is required."
185
+ });
186
+ } else {
187
+ for (const [index, value] of input.subjectKinds.entries()) {
188
+ validateNonEmptyString(value, `$.subjectKinds[${index}]`, issues);
189
+ }
190
+ }
191
+ if (input.compatibility !== "backward_compatible_additions") {
192
+ issues.push({
193
+ path: "$.compatibility",
194
+ code: "value",
195
+ message: 'Signal type compatibility must be "backward_compatible_additions".'
196
+ });
197
+ }
198
+ validateTypeFields(input.fields, issues);
199
+ if (issues.length > 0) return invalid(issues);
200
+ return { ok: true, value: input };
201
+ }
202
+ function parseSignalTypeDefinition(input) {
203
+ const result = validateSignalTypeDefinition(input);
204
+ if (result.ok) return result.value;
205
+ throw new SignalContractError("Invalid Signal type definition.", result.issues);
206
+ }
207
+ function validateTypeFields(input, issues) {
208
+ if (!Array.isArray(input) || input.length === 0) {
209
+ issues.push({ path: "$.fields", code: "required", message: "At least one field is required." });
210
+ return;
211
+ }
212
+ const names = /* @__PURE__ */ new Set();
213
+ for (const [index, field] of input.entries()) {
214
+ const path = `$.fields[${index}]`;
215
+ if (!isRecord(field)) {
216
+ issues.push({ path, code: "type", message: "Field definition must be an object." });
217
+ continue;
218
+ }
219
+ if (typeof field.name !== "string" || !FIELD_NAME_PATTERN.test(field.name)) {
220
+ issues.push({
221
+ path: `${path}.name`,
222
+ code: "format",
223
+ message: "Field name must be a dot-separated, declared field name, not JSONPath."
224
+ });
225
+ } else if (names.has(field.name)) {
226
+ issues.push({ path: `${path}.name`, code: "value", message: "Field names must be unique." });
227
+ } else {
228
+ names.add(field.name);
229
+ }
230
+ validateNonEmptyString(field.displayName, `${path}.displayName`, issues);
231
+ if (!isSignalFieldDataType(field.dataType)) {
232
+ issues.push({
233
+ path: `${path}.dataType`,
234
+ code: "value",
235
+ message: "Unsupported field data type."
236
+ });
237
+ }
238
+ if (!isSignalCardinality(field.cardinality)) {
239
+ issues.push({
240
+ path: `${path}.cardinality`,
241
+ code: "value",
242
+ message: "Unsupported cardinality."
243
+ });
244
+ }
245
+ if (!Array.isArray(field.classifications) || field.classifications.length === 0) {
246
+ issues.push({
247
+ path: `${path}.classifications`,
248
+ code: "required",
249
+ message: "At least one field classification is required."
250
+ });
251
+ } else {
252
+ for (const [classificationIndex, classification] of field.classifications.entries()) {
253
+ if (!isSignalFieldClassification(classification)) {
254
+ issues.push({
255
+ path: `${path}.classifications[${classificationIndex}]`,
256
+ code: "value",
257
+ message: "Unsupported field classification."
258
+ });
259
+ }
260
+ }
261
+ if (field.cardinality === "high" && field.classifications.includes("groupable")) {
262
+ issues.push({
263
+ path: `${path}.classifications`,
264
+ code: "unsafe_extension",
265
+ message: "High-cardinality fields cannot be groupable."
266
+ });
267
+ }
268
+ if (field.classifications.includes("sensitive") && field.classifications.includes("groupable")) {
269
+ issues.push({
270
+ path: `${path}.classifications`,
271
+ code: "unsafe_extension",
272
+ message: "Sensitive fields cannot be groupable."
273
+ });
274
+ }
275
+ }
276
+ }
277
+ }
278
+ function isSignalFieldDataType(value) {
279
+ return ["string", "number", "integer", "boolean", "timestamp", "uri"].includes(value);
280
+ }
281
+ function isSignalCardinality(value) {
282
+ return ["low", "bounded", "high"].includes(value);
283
+ }
284
+ function isSignalFieldClassification(value) {
285
+ return ["filterable", "groupable", "displayable", "sensitive", "evidence_only"].includes(
286
+ value
287
+ );
288
+ }
289
+ function validateExtension(key, value, issues) {
290
+ if (!EXTENSION_NAME_PATTERN.test(key)) {
291
+ issues.push({
292
+ path: `$.${key}`,
293
+ code: "format",
294
+ message: "CloudEvents extension names must be lowercase alphanumeric identifiers up to 20 characters."
295
+ });
296
+ }
297
+ if (!isJsonPrimitive(value)) {
298
+ issues.push({
299
+ path: `$.${key}`,
300
+ code: "type",
301
+ message: "Signal extension values must be JSON primitives."
302
+ });
303
+ }
304
+ }
305
+ function validateTypeName(value, path, issues) {
306
+ if (typeof value !== "string" || !TYPE_PATTERN.test(value)) {
307
+ issues.push({
308
+ path,
309
+ code: "format",
310
+ message: 'Signal type must be reverse-DNS style and end with a major version such as ".v1".'
311
+ });
312
+ }
313
+ }
314
+ function validateNonEmptyString(value, path, issues) {
315
+ if (typeof value !== "string" || value.trim().length === 0) {
316
+ issues.push({ path, code: "required", message: "A non-empty string is required." });
317
+ }
318
+ }
319
+ function validateUriReference(value, path, issues) {
320
+ if (typeof value !== "string" || value.trim().length === 0 || /\s/.test(value)) {
321
+ issues.push({ path, code: "format", message: "A non-empty URI-reference is required." });
322
+ }
323
+ }
324
+ function validateAbsoluteUri(value, path, issues) {
325
+ if (typeof value !== "string" || value.trim().length === 0) {
326
+ issues.push({ path, code: "format", message: "An absolute URI is required." });
327
+ return;
328
+ }
329
+ try {
330
+ const uri = new URL(value);
331
+ if (!uri.protocol) throw new Error("missing protocol");
332
+ } catch {
333
+ issues.push({ path, code: "format", message: "An absolute URI is required." });
334
+ }
335
+ }
336
+ function isRfc3339Timestamp(value) {
337
+ return typeof value === "string" && RFC3339_TIMESTAMP_PATTERN.test(value) && !Number.isNaN(Date.parse(value));
338
+ }
339
+ function normalizeTime(value) {
340
+ if (typeof value === "undefined") return (/* @__PURE__ */ new Date()).toISOString();
341
+ if (value instanceof Date) {
342
+ if (Number.isNaN(value.getTime())) {
343
+ throw new SignalContractError("Invalid Signal time.", [
344
+ { path: "$.time", code: "format", message: "Date must be valid." }
345
+ ]);
346
+ }
347
+ return value.toISOString();
348
+ }
349
+ return value;
350
+ }
351
+ function isRecord(value) {
352
+ return typeof value === "object" && value !== null && !Array.isArray(value);
353
+ }
354
+ function isJsonPrimitive(value) {
355
+ return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
356
+ }
357
+ function isJsonValue(value) {
358
+ if (isJsonPrimitive(value)) return Number.isFinite(value) || typeof value !== "number";
359
+ if (Array.isArray(value)) return value.every(isJsonValue);
360
+ if (!isRecord(value)) return false;
361
+ return Object.values(value).every(isJsonValue);
362
+ }
363
+ function invalid(issues) {
364
+ return { ok: false, issues };
365
+ }
366
+ function omitUndefined(input) {
367
+ return Object.fromEntries(
368
+ Object.entries(input).filter(([, value]) => typeof value !== "undefined")
369
+ );
370
+ }
371
+
372
+ // src/publisher.ts
373
+ var import_cloudevents2 = require("cloudevents");
374
+ var SignalAPIError = class extends Error {
375
+ status;
376
+ code;
377
+ requestId;
378
+ details;
379
+ constructor(message, status, code, requestId, details) {
380
+ super(`[${status} ${code}] ${message}`);
381
+ this.name = "SignalAPIError";
382
+ this.status = status;
383
+ this.code = code;
384
+ this.requestId = requestId;
385
+ this.details = details;
386
+ }
387
+ get isRetriable() {
388
+ return this.status === 0 || this.status === 408 || this.status === 429 || this.status >= 500 && this.status <= 599;
389
+ }
390
+ };
391
+ var SignalPublisher = class {
392
+ endpoint;
393
+ source;
394
+ timeoutMs;
395
+ maxRetries;
396
+ defaultHeaders;
397
+ token;
398
+ fetchImplementation;
399
+ traceContextProvider;
400
+ constructor(options) {
401
+ if (!options.endpoint) throw new Error("[OverSky Signals] endpoint is required.");
402
+ if (!options.source) throw new Error("[OverSky Signals] source is required.");
403
+ if (!options.token) throw new Error("[OverSky Signals] source-scoped token is required.");
404
+ this.endpoint = options.endpoint.replace(/\/$/, "");
405
+ this.source = options.source;
406
+ this.token = options.token;
407
+ this.timeoutMs = options.timeoutMs ?? 15e3;
408
+ this.maxRetries = options.maxRetries ?? 2;
409
+ this.defaultHeaders = options.defaultHeaders ?? {};
410
+ this.fetchImplementation = options.fetch ?? globalThis.fetch.bind(globalThis);
411
+ this.traceContextProvider = options.traceContextProvider;
412
+ }
413
+ create(input) {
414
+ return createSignalEnvelope(this.source, input, this.traceContextProvider?.());
415
+ }
416
+ async emit(input) {
417
+ return this.publish(this.create(input));
418
+ }
419
+ async publish(event) {
420
+ if (event.source !== this.source) {
421
+ throw new SignalAPIError(
422
+ "The event source must match this publisher source.",
423
+ 0,
424
+ "source_mismatch",
425
+ null
426
+ );
427
+ }
428
+ const message = import_cloudevents2.HTTP.structured(new import_cloudevents2.CloudEvent(event));
429
+ const headers = {
430
+ Authorization: `Bearer ${this.token}`,
431
+ Accept: "application/json",
432
+ "User-Agent": "@skrr-ai/signals/0.1.0",
433
+ ...toStringHeaders(message.headers),
434
+ ...this.defaultHeaders
435
+ };
436
+ if (event.traceparent) headers.traceparent = event.traceparent;
437
+ if (event.tracestate) headers.tracestate = event.tracestate;
438
+ let attempt = 0;
439
+ for (; ; ) {
440
+ const controller = new AbortController();
441
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
442
+ let response;
443
+ try {
444
+ response = await this.fetchImplementation(this.endpoint, {
445
+ method: "POST",
446
+ headers,
447
+ body: typeof message.body === "string" ? message.body : JSON.stringify(message.body),
448
+ signal: controller.signal
449
+ });
450
+ } catch (error) {
451
+ clearTimeout(timer);
452
+ const caught = error;
453
+ const apiError2 = new SignalAPIError(
454
+ caught?.message ?? "Network error while publishing Signal.",
455
+ 0,
456
+ caught?.name === "AbortError" ? "timeout" : "network_error",
457
+ null
458
+ );
459
+ if (apiError2.isRetriable && attempt < this.maxRetries) {
460
+ await sleep(backoffMs(attempt));
461
+ attempt += 1;
462
+ continue;
463
+ }
464
+ throw apiError2;
465
+ } finally {
466
+ clearTimeout(timer);
467
+ }
468
+ if (response.ok) {
469
+ const body = await response.json();
470
+ return parseSignalReceipt(body, response.headers.get("x-request-id"));
471
+ }
472
+ const apiError = await parseSignalAPIError(response);
473
+ if (apiError.isRetriable && attempt < this.maxRetries) {
474
+ const retryAfterMs = retryAfterMilliseconds(response.headers.get("retry-after"));
475
+ await sleep(retryAfterMs ?? backoffMs(attempt));
476
+ attempt += 1;
477
+ continue;
478
+ }
479
+ throw apiError;
480
+ }
481
+ }
482
+ };
483
+ function parseSignalReceipt(input, requestId) {
484
+ if (!isRecord2(input)) {
485
+ throw new SignalAPIError(
486
+ "Signal API returned an invalid receipt.",
487
+ 502,
488
+ "invalid_receipt",
489
+ requestId
490
+ );
491
+ }
492
+ const outcome = input.outcome;
493
+ const processingStatus = input.processingStatus;
494
+ if (typeof input.receiptId !== "string" || typeof input.sourceId !== "string" || typeof input.canonicalSource !== "string" || typeof input.eventId !== "string" || outcome !== "accepted" && outcome !== "duplicate" || processingStatus !== "pending" && processingStatus !== "processing" && processingStatus !== "completed" || typeof input.receivedAt !== "string") {
495
+ throw new SignalAPIError(
496
+ "Signal API returned an invalid receipt.",
497
+ 502,
498
+ "invalid_receipt",
499
+ requestId
500
+ );
501
+ }
502
+ return {
503
+ receiptId: input.receiptId,
504
+ sourceId: input.sourceId,
505
+ canonicalSource: input.canonicalSource,
506
+ eventId: input.eventId,
507
+ outcome,
508
+ processingStatus,
509
+ receivedAt: input.receivedAt,
510
+ ...requestId ? { requestId } : {}
511
+ };
512
+ }
513
+ async function parseSignalAPIError(response) {
514
+ let body = {};
515
+ try {
516
+ body = await response.json();
517
+ } catch {
518
+ }
519
+ return new SignalAPIError(
520
+ body.error?.message ?? response.statusText ?? "Signal API request failed.",
521
+ response.status,
522
+ body.error?.code ?? `http_${response.status}`,
523
+ response.headers.get("x-request-id"),
524
+ body.error?.details
525
+ );
526
+ }
527
+ function toStringHeaders(headers) {
528
+ return Object.fromEntries(
529
+ Object.entries(headers).filter((entry) => typeof entry[1] !== "undefined").map(([key, value]) => [key, Array.isArray(value) ? value.join(", ") : value])
530
+ );
531
+ }
532
+ function retryAfterMilliseconds(value) {
533
+ if (!value) return void 0;
534
+ const seconds = Number(value);
535
+ if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1e3;
536
+ const dateMilliseconds = Date.parse(value);
537
+ if (Number.isNaN(dateMilliseconds)) return void 0;
538
+ return Math.max(0, dateMilliseconds - Date.now());
539
+ }
540
+ function backoffMs(attempt) {
541
+ const base = Math.min(250 * 2 ** attempt, 5e3);
542
+ return base + Math.floor(Math.random() * 125);
543
+ }
544
+ function sleep(milliseconds) {
545
+ return new Promise((resolve) => setTimeout(resolve, milliseconds));
546
+ }
547
+ function isRecord2(value) {
548
+ return typeof value === "object" && value !== null && !Array.isArray(value);
549
+ }
550
+ // Annotate the CommonJS export names for ESM import in node:
551
+ 0 && (module.exports = {
552
+ SIGNAL_API_VERSION,
553
+ SIGNAL_CLOUDEVENTS_CONTENT_TYPE,
554
+ SignalAPIError,
555
+ SignalContractError,
556
+ SignalPublisher,
557
+ createSignalEnvelope,
558
+ parseSignalEnvelope,
559
+ parseSignalTypeDefinition,
560
+ validateSignalEnvelope,
561
+ validateSignalTypeDefinition
562
+ });
563
+ //# sourceMappingURL=index.cjs.map