@zmdb/app 1.0.0-beta.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.
Files changed (108) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +27 -0
  3. package/dist/application.d.ts +45 -0
  4. package/dist/application.d.ts.map +1 -0
  5. package/dist/application.js +186 -0
  6. package/dist/application.js.map +1 -0
  7. package/dist/commands/index.d.ts +31 -0
  8. package/dist/commands/index.d.ts.map +1 -0
  9. package/dist/commands/index.js +338 -0
  10. package/dist/commands/index.js.map +1 -0
  11. package/dist/cqrs/index.d.ts +47 -0
  12. package/dist/cqrs/index.d.ts.map +1 -0
  13. package/dist/cqrs/index.js +76 -0
  14. package/dist/cqrs/index.js.map +1 -0
  15. package/dist/data/index.d.ts +12 -0
  16. package/dist/data/index.d.ts.map +1 -0
  17. package/dist/data/index.js +25 -0
  18. package/dist/data/index.js.map +1 -0
  19. package/dist/di/index.d.ts +44 -0
  20. package/dist/di/index.d.ts.map +1 -0
  21. package/dist/di/index.js +136 -0
  22. package/dist/di/index.js.map +1 -0
  23. package/dist/events/index.d.ts +46 -0
  24. package/dist/events/index.d.ts.map +1 -0
  25. package/dist/events/index.js +181 -0
  26. package/dist/events/index.js.map +1 -0
  27. package/dist/health/index.d.ts +35 -0
  28. package/dist/health/index.d.ts.map +1 -0
  29. package/dist/health/index.js +14 -0
  30. package/dist/health/index.js.map +1 -0
  31. package/dist/index.d.ts +11 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +22 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/lifecycle.d.ts +21 -0
  36. package/dist/lifecycle.d.ts.map +1 -0
  37. package/dist/lifecycle.js +52 -0
  38. package/dist/lifecycle.js.map +1 -0
  39. package/dist/messaging/index.d.ts +176 -0
  40. package/dist/messaging/index.d.ts.map +1 -0
  41. package/dist/messaging/index.js +442 -0
  42. package/dist/messaging/index.js.map +1 -0
  43. package/dist/messaging/transport-kit.d.ts +22 -0
  44. package/dist/messaging/transport-kit.d.ts.map +1 -0
  45. package/dist/messaging/transport-kit.js +174 -0
  46. package/dist/messaging/transport-kit.js.map +1 -0
  47. package/dist/modules/index.d.ts +52 -0
  48. package/dist/modules/index.d.ts.map +1 -0
  49. package/dist/modules/index.js +351 -0
  50. package/dist/modules/index.js.map +1 -0
  51. package/dist/modules/lifecycle-instances.d.ts +4 -0
  52. package/dist/modules/lifecycle-instances.d.ts.map +1 -0
  53. package/dist/modules/lifecycle-instances.js +19 -0
  54. package/dist/modules/lifecycle-instances.js.map +1 -0
  55. package/dist/modules/runtime.d.ts +18 -0
  56. package/dist/modules/runtime.d.ts.map +1 -0
  57. package/dist/modules/runtime.js +8 -0
  58. package/dist/modules/runtime.js.map +1 -0
  59. package/dist/observability/index.d.ts +27 -0
  60. package/dist/observability/index.d.ts.map +1 -0
  61. package/dist/observability/index.js +145 -0
  62. package/dist/observability/index.js.map +1 -0
  63. package/dist/observability/propagation.d.ts +10 -0
  64. package/dist/observability/propagation.d.ts.map +1 -0
  65. package/dist/observability/propagation.js +96 -0
  66. package/dist/observability/propagation.js.map +1 -0
  67. package/dist/observability/types.d.ts +66 -0
  68. package/dist/observability/types.d.ts.map +1 -0
  69. package/dist/observability/types.js +10 -0
  70. package/dist/observability/types.js.map +1 -0
  71. package/dist/polyfill.d.ts +2 -0
  72. package/dist/polyfill.d.ts.map +1 -0
  73. package/dist/polyfill.js +21 -0
  74. package/dist/polyfill.js.map +1 -0
  75. package/dist/state/fixtures.d.ts +10 -0
  76. package/dist/state/fixtures.d.ts.map +1 -0
  77. package/dist/state/fixtures.js +14 -0
  78. package/dist/state/fixtures.js.map +1 -0
  79. package/dist/state/index.d.ts +26 -0
  80. package/dist/state/index.d.ts.map +1 -0
  81. package/dist/state/index.js +37 -0
  82. package/dist/state/index.js.map +1 -0
  83. package/dist/state-transitions.d.ts +57 -0
  84. package/dist/state-transitions.d.ts.map +1 -0
  85. package/dist/state-transitions.js +31 -0
  86. package/dist/state-transitions.js.map +1 -0
  87. package/package.json +99 -0
  88. package/src/application.ts +243 -0
  89. package/src/commands/index.ts +447 -0
  90. package/src/cqrs/index.ts +124 -0
  91. package/src/data/index.ts +33 -0
  92. package/src/di/index.ts +179 -0
  93. package/src/events/index.ts +248 -0
  94. package/src/health/index.ts +54 -0
  95. package/src/index.ts +68 -0
  96. package/src/lifecycle.ts +62 -0
  97. package/src/messaging/index.ts +668 -0
  98. package/src/messaging/transport-kit.ts +234 -0
  99. package/src/modules/index.ts +476 -0
  100. package/src/modules/lifecycle-instances.ts +23 -0
  101. package/src/modules/runtime.ts +26 -0
  102. package/src/observability/index.ts +204 -0
  103. package/src/observability/propagation.ts +107 -0
  104. package/src/observability/types.ts +68 -0
  105. package/src/polyfill.ts +24 -0
  106. package/src/state/fixtures.ts +20 -0
  107. package/src/state/index.ts +57 -0
  108. package/src/state-transitions.ts +150 -0
@@ -0,0 +1,145 @@
1
+ import {} from '@zmdb/orm';
2
+ import { appendComment } from '@zmdb/sql';
3
+ import { fromTraceContext, toTraceparent } from './propagation.js';
4
+ import { SpanKind } from './types.js';
5
+ export { fromTraceContext, fromTraceparent, toTraceHeaders, toTraceparent } from './propagation.js';
6
+ export { SpanKind } from './types.js';
7
+ /**
8
+ * Add database spans, metrics and optional sqlcommenter tags at execution.
9
+ *
10
+ * `commentValues` is request-scoped and supplies the low-cardinality values.
11
+ * When selected, `traceparent` comes from the query span (or the supplied
12
+ * parent when no tracer is configured), not from the callback.
13
+ *
14
+ * With no port configured, return the original object: no wrapper, marker,
15
+ * closure or per-query branch is added to the off path.
16
+ */
17
+ export function tracedDriver(driver, observability, parent, commentValues) {
18
+ const { tracer, meter, comments } = observability;
19
+ if (tracer === undefined && meter === undefined && comments === undefined) {
20
+ return driver;
21
+ }
22
+ const duration = meter?.histogram('db.client.operation.duration', 's');
23
+ const execute = async (query, options) => {
24
+ const telemetry = query.telemetry;
25
+ const span = startQuerySpan(tracer, telemetry, parent);
26
+ if (span !== undefined) {
27
+ if (telemetry !== undefined) {
28
+ span.setAttribute('db.system.name', telemetry.system);
29
+ span.setAttribute('db.operation.name', telemetry.operation);
30
+ span.setAttribute('db.collection.name', telemetry.collection);
31
+ }
32
+ // Compiled SQL contains placeholders; parameter values are deliberately
33
+ // absent from every telemetry surface.
34
+ span.setAttribute('db.query.text', query.text);
35
+ span.setAttribute('zmdb.db.parameter_count', query.parameters.length);
36
+ }
37
+ const started = Date.now();
38
+ try {
39
+ const executed = comments === undefined ? query : queryWithComments(query, comments.keys, commentValues?.(), span ?? parent);
40
+ return await driver.execute(executed, options);
41
+ }
42
+ catch (error) {
43
+ if (span !== undefined) {
44
+ const recorded = errorValue(error);
45
+ span.recordException(recorded);
46
+ span.setStatus({ error: true });
47
+ const code = errorCode(error);
48
+ if (code !== undefined) {
49
+ span.setAttribute('db.response.status_code', code);
50
+ }
51
+ }
52
+ throw error;
53
+ }
54
+ finally {
55
+ if (duration !== undefined && telemetry !== undefined) {
56
+ const attributes = {
57
+ 'db.system.name': telemetry.system,
58
+ 'db.operation.name': telemetry.operation,
59
+ 'db.collection.name': telemetry.collection,
60
+ };
61
+ duration.record((Date.now() - started) / 1000, attributes);
62
+ }
63
+ span?.end();
64
+ }
65
+ };
66
+ const wrapped = { ...driver, execute };
67
+ return tracer === undefined && meter === undefined ? wrapped : { ...wrapped, queryTelemetry: true };
68
+ }
69
+ /** Start the consumer side of one propagated message delivery. */
70
+ export function consumerSpan(observability, envelope, delivery) {
71
+ const tracer = observability.tracer;
72
+ if (tracer === undefined) {
73
+ throw new Error('@zmdb/app: consumerSpan requires a configured tracer');
74
+ }
75
+ const remote = fromTraceContext(envelope.traceparent, envelope.tracestate);
76
+ if (remote === undefined) {
77
+ return tracer.startSpan('zmdb.message', { kind: SpanKind.CONSUMER });
78
+ }
79
+ return delivery === 'queued'
80
+ ? tracer.startSpan('zmdb.message', { kind: SpanKind.CONSUMER, link: remote })
81
+ : tracer.startSpan('zmdb.message', { kind: SpanKind.CONSUMER, parent: remote });
82
+ }
83
+ function startQuerySpan(tracer, telemetry, parent) {
84
+ if (tracer === undefined) {
85
+ return undefined;
86
+ }
87
+ const name = telemetry === undefined ? 'db.query' : `${telemetry.operation} ${telemetry.collection}`;
88
+ return parent === undefined
89
+ ? tracer.startSpan(name, { kind: SpanKind.CLIENT })
90
+ : tracer.startSpan(name, { kind: SpanKind.CLIENT, parent: parent.spanContext() });
91
+ }
92
+ function errorValue(error) {
93
+ return error instanceof Error ? error : new Error(String(error));
94
+ }
95
+ function errorCode(error) {
96
+ if (error === null || typeof error !== 'object' || !('code' in error)) {
97
+ return undefined;
98
+ }
99
+ const code = error.code;
100
+ return typeof code === 'string' || typeof code === 'number' ? code : undefined;
101
+ }
102
+ function queryWithComments(query, keys, source, span) {
103
+ const pairs = selectedCommentPairs(keys, source, span);
104
+ const text = appendComment(query.text, pairs);
105
+ return text === query.text ? query : { ...query, text };
106
+ }
107
+ function selectedCommentPairs(keys, source, span) {
108
+ const selected = new Map();
109
+ for (const key of keys) {
110
+ const value = key === 'traceparent' && span !== undefined ? toTraceparent(span) : ownCommentValue(source, key);
111
+ if (value !== undefined) {
112
+ selected.set(key, value);
113
+ }
114
+ }
115
+ const action = selected.get('action');
116
+ const controller = selected.get('controller');
117
+ const framework = selected.get('framework');
118
+ const route = selected.get('route');
119
+ const traceparent = selected.get('traceparent');
120
+ return {
121
+ ...(action === undefined ? {} : { action }),
122
+ ...(controller === undefined ? {} : { controller }),
123
+ ...(framework === undefined ? {} : { framework }),
124
+ ...(route === undefined ? {} : { route }),
125
+ ...(traceparent === undefined ? {} : { traceparent }),
126
+ };
127
+ }
128
+ function ownCommentValue(source, key) {
129
+ if (source === undefined || !Object.hasOwn(source, key)) {
130
+ return undefined;
131
+ }
132
+ switch (key) {
133
+ case 'action':
134
+ return source.action;
135
+ case 'controller':
136
+ return source.controller;
137
+ case 'framework':
138
+ return source.framework;
139
+ case 'route':
140
+ return source.route;
141
+ case 'traceparent':
142
+ return source.traceparent;
143
+ }
144
+ }
145
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Span, SpanContext, TraceCarrier } from './types.js';
2
+ /** Parse one W3C traceparent value, ignoring malformed input. */
3
+ export declare function fromTraceparent(header: string): SpanContext | undefined;
4
+ /** Parse a W3C trace context, keeping a valid parent when tracestate is invalid. */
5
+ export declare function fromTraceContext(traceparent: string | undefined, tracestate?: string): SpanContext | undefined;
6
+ /** Render the current span as a W3C traceparent value for an outbound carrier. */
7
+ export declare function toTraceparent(span: Span): string;
8
+ /** Render the current span as the common outbound W3C trace carrier. */
9
+ export declare function toTraceHeaders(span: Span): TraceCarrier;
10
+ //# sourceMappingURL=propagation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"propagation.d.ts","sourceRoot":"","sources":["../../src/observability/propagation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQlE,iEAAiE;AACjE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAEvE;AAED,oFAAoF;AACpF,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAwC9G;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAEhD;AAOD,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,YAAY,CAOvD"}
@@ -0,0 +1,96 @@
1
+ const LOWER_HEX = /^[0-9a-f]+$/;
2
+ const ZERO_TRACE_ID = '00000000000000000000000000000000';
3
+ const ZERO_SPAN_ID = '0000000000000000';
4
+ const TRACE_STATE_KEY = /^(?:[a-z][_0-9a-z\-*/]{0,255}|[a-z0-9][_0-9a-z\-*/]{0,240}@[a-z][_0-9a-z\-*/]{0,13})$/;
5
+ const TRACE_STATE_VALUE = /^[ -~]{0,255}[!-~]$/;
6
+ /** Parse one W3C traceparent value, ignoring malformed input. */
7
+ export function fromTraceparent(header) {
8
+ return fromTraceContext(header);
9
+ }
10
+ /** Parse a W3C trace context, keeping a valid parent when tracestate is invalid. */
11
+ export function fromTraceContext(traceparent, tracestate) {
12
+ if (traceparent === undefined) {
13
+ return undefined;
14
+ }
15
+ const fields = traceparent.split('-');
16
+ if (fields.length < 4) {
17
+ return undefined;
18
+ }
19
+ const version = fields[0];
20
+ const traceId = fields[1];
21
+ const spanId = fields[2];
22
+ const flags = fields[3];
23
+ if (version === undefined ||
24
+ traceId === undefined ||
25
+ spanId === undefined ||
26
+ flags === undefined ||
27
+ version.length !== 2 ||
28
+ traceId.length !== 32 ||
29
+ spanId.length !== 16 ||
30
+ flags.length !== 2 ||
31
+ !LOWER_HEX.test(version) ||
32
+ !LOWER_HEX.test(traceId) ||
33
+ !LOWER_HEX.test(spanId) ||
34
+ !LOWER_HEX.test(flags) ||
35
+ version === 'ff' ||
36
+ traceId === ZERO_TRACE_ID ||
37
+ spanId === ZERO_SPAN_ID ||
38
+ (version === '00' && fields.length !== 4)) {
39
+ return undefined;
40
+ }
41
+ const traceState = validatedTraceState(tracestate);
42
+ return {
43
+ traceId,
44
+ spanId,
45
+ traceFlags: Number.parseInt(flags, 16),
46
+ isRemote: true,
47
+ ...(traceState === undefined ? {} : { traceState }),
48
+ };
49
+ }
50
+ /** Render the current span as a W3C traceparent value for an outbound carrier. */
51
+ export function toTraceparent(span) {
52
+ return formatTraceparent(span.spanContext());
53
+ }
54
+ function formatTraceparent(context) {
55
+ const flags = (context.traceFlags & 0xff).toString(16).padStart(2, '0');
56
+ return `00-${context.traceId.toLowerCase()}-${context.spanId.toLowerCase()}-${flags}`;
57
+ }
58
+ /** Render the current span as the common outbound W3C trace carrier. */
59
+ export function toTraceHeaders(span) {
60
+ const context = span.spanContext();
61
+ const traceState = validatedTraceState(context.traceState);
62
+ return {
63
+ traceparent: formatTraceparent(context),
64
+ ...(traceState === undefined ? {} : { tracestate: traceState }),
65
+ };
66
+ }
67
+ function validatedTraceState(header) {
68
+ if (header === undefined || header.length === 0 || header.length > 512) {
69
+ return undefined;
70
+ }
71
+ const members = header.split(',');
72
+ if (members.length > 32) {
73
+ return undefined;
74
+ }
75
+ const keys = new Set();
76
+ const normalized = [];
77
+ for (const rawMember of members) {
78
+ const member = trimOptionalWhitespace(rawMember);
79
+ const separator = member.indexOf('=');
80
+ if (separator <= 0 || member.indexOf('=', separator + 1) !== -1) {
81
+ return undefined;
82
+ }
83
+ const key = member.slice(0, separator);
84
+ const value = member.slice(separator + 1);
85
+ if (!TRACE_STATE_KEY.test(key) || !TRACE_STATE_VALUE.test(value) || value.includes(',') || keys.has(key)) {
86
+ return undefined;
87
+ }
88
+ keys.add(key);
89
+ normalized.push(member);
90
+ }
91
+ return normalized.join(',');
92
+ }
93
+ function trimOptionalWhitespace(value) {
94
+ return value.replace(/^[\t ]+|[\t ]+$/g, '');
95
+ }
96
+ //# sourceMappingURL=propagation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"propagation.js","sourceRoot":"","sources":["../../src/observability/propagation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import { type CommentKey, type CommentKeys, type CommentPairs, type QueryTelemetry } from '@zmdb/sql';
2
+ /** Scalar attributes accepted by the framework's telemetry ports. */
3
+ export type Attributes = Readonly<Record<string, string | number | boolean>>;
4
+ /** Span roles understood by the framework's telemetry port. */
5
+ export declare const SpanKind: {
6
+ readonly INTERNAL: 'internal';
7
+ readonly SERVER: 'server';
8
+ readonly CLIENT: 'client';
9
+ readonly PRODUCER: 'producer';
10
+ readonly CONSUMER: 'consumer';
11
+ };
12
+ export type SpanKind = (typeof SpanKind)[keyof typeof SpanKind];
13
+ /** Trace identity carried explicitly between framework layers. */
14
+ export interface SpanContext {
15
+ readonly traceId: string;
16
+ readonly spanId: string;
17
+ readonly traceFlags: number;
18
+ readonly isRemote?: boolean;
19
+ /** W3C tracestate serialized for transport without an SDK type dependency. */
20
+ readonly traceState?: string;
21
+ }
22
+ /** The common W3C trace carrier used by HTTP and message transports. */
23
+ export interface TraceCarrier {
24
+ readonly traceparent?: string;
25
+ readonly tracestate?: string;
26
+ }
27
+ /** The narrow span surface used by @zmdb/app. */
28
+ export interface Span {
29
+ updateName(name: string): void;
30
+ setAttribute(key: string, value: string | number | boolean): void;
31
+ recordException(error: Error): void;
32
+ setStatus(status: {
33
+ readonly error: boolean;
34
+ }): void;
35
+ end(): void;
36
+ spanContext(): SpanContext;
37
+ }
38
+ /** Explicit span creation inputs; ambient context is deliberately absent. */
39
+ export interface SpanOptions {
40
+ readonly parent?: SpanContext;
41
+ readonly link?: SpanContext;
42
+ readonly kind?: SpanKind;
43
+ }
44
+ /** The narrow tracer surface used by @zmdb/app. */
45
+ export interface Tracer {
46
+ startSpan(name: string, options?: SpanOptions): Span;
47
+ }
48
+ /** The narrow meter surface used by @zmdb/app. */
49
+ export interface Meter {
50
+ counter(name: string): {
51
+ add(value: number, attributes: Attributes): void;
52
+ };
53
+ histogram(name: string, unit: 's'): {
54
+ record(value: number, attributes: Attributes): void;
55
+ };
56
+ }
57
+ /** App-owned telemetry configuration. Presence means enabled. */
58
+ export interface Observability {
59
+ readonly tracer?: Tracer;
60
+ readonly meter?: Meter;
61
+ readonly comments?: {
62
+ readonly keys: CommentKeys;
63
+ };
64
+ }
65
+ export type { CommentKey, CommentKeys, CommentPairs, QueryTelemetry };
66
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/observability/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAEtG,qEAAqE;AACrE,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;AAE7E,+DAA+D;AAC/D,eAAO,MAAM,QAAQ;aACnB,QAAQ,EAAE,UAAU;aACpB,MAAM,EAAE,QAAQ;aAChB,MAAM,EAAE,QAAQ;aAChB,QAAQ,EAAE,UAAU;aACpB,QAAQ,EAAE,UAAU;CACZ,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,OAAO,QAAQ,CAAC,CAAC;AAEhE,kEAAkE;AAClE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,iDAAiD;AACjD,MAAM,WAAW,IAAI;IACnB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IAClE,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpC,SAAS,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACrD,GAAG,IAAI,IAAI,CAAC;IACZ,WAAW,IAAI,WAAW,CAAC;CAC5B;AAED,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;CAC1B;AAED,mDAAmD;AACnD,MAAM,WAAW,MAAM;IACrB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CACtD;AAED,kDAAkD;AAClD,MAAM,WAAW,KAAK;IACpB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,CAAC;IAC5E,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG;QAAE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,CAAC;CAC7F;AAED,iEAAiE;AACjE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC;CACpD;AAED,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ import {} from '@zmdb/sql';
2
+ /** Span roles understood by the framework's telemetry port. */
3
+ export const SpanKind = {
4
+ INTERNAL: 'internal',
5
+ SERVER: 'server',
6
+ CLIENT: 'client',
7
+ PRODUCER: 'producer',
8
+ CONSUMER: 'consumer',
9
+ };
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/observability/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6E,MAAM,WAAW,CAAC;AAKtG,+DAA+D;AAC/D,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,UAAU;CACZ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=polyfill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polyfill.d.ts","sourceRoot":"","sources":["../src/polyfill.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ // Zero-dependency Symbol.metadata baseline.
2
+ //
3
+ // Stage-3 decorator metadata relies on the well-known `Symbol.metadata`. Node 26
4
+ // / V8 does not yet expose it (`Symbol.metadata === undefined` as of v26.8), so
5
+ // we install it if — and only if — the runtime lacks it. We assign ONLY the
6
+ // well-known symbol and mutate nothing else on any global. When a future runtime
7
+ // ships it natively this becomes a no-op.
8
+ //
9
+ // This module has a side effect and must be imported before any decorated class
10
+ // is evaluated. `@zmdb/app`'s entry imports it first.
11
+ const carrier = Symbol;
12
+ if (carrier.metadata === undefined) {
13
+ Object.defineProperty(Symbol, 'metadata', {
14
+ value: Symbol.for('Symbol.metadata'),
15
+ writable: false,
16
+ enumerable: false,
17
+ configurable: true,
18
+ });
19
+ }
20
+ export {};
21
+ //# sourceMappingURL=polyfill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polyfill.js","sourceRoot":"","sources":["../src/polyfill.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,EAAE;AACF,iFAAiF;AACjF,gFAAgF;AAChF,4EAA4E;AAC5E,iFAAiF;AACjF,0CAA0C;AAC1C,EAAE;AACF,gFAAgF;AAChF,sDAAsD;AAMtD,MAAM,OAAO,GAAuB,MAAM,CAAC;AAC3C,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;IACnC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE;QACxC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC;QACpC,QAAQ,EAAE,KAAK;QACf,UAAU,EAAE,KAAK;QACjB,YAAY,EAAE,IAAI;KACnB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,10 @@
1
+ export interface Order {
2
+ id: number;
3
+ total: number;
4
+ }
5
+ export declare const Draft: import("./index.js").State<"Draft", Order>;
6
+ export declare const Paid: import("./index.js").State<"Paid", Order>;
7
+ export declare const Shipped: import("./index.js").State<"Shipped", Order>;
8
+ export declare const pay: (value: import("./index.js").Brand<Order, "Draft">) => import("./index.js").Brand<Order, "Paid">;
9
+ export declare const ship: (value: import("./index.js").Brand<Order, "Paid">) => import("./index.js").Brand<Order, "Shipped">;
10
+ //# sourceMappingURL=fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/state/fixtures.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,KAAK,4CAAgC,CAAC;AACnD,eAAO,MAAM,IAAI,2CAA+B,CAAC;AACjD,eAAO,MAAM,OAAO,8CAAkC,CAAC;AAEvD,eAAO,MAAM,GAAG,kGAA2C,CAAC;AAC5D,eAAO,MAAM,IAAI,oGAA6C,CAAC"}
@@ -0,0 +1,14 @@
1
+ // The order workflow both state tests are about.
2
+ //
3
+ // `state.spec.ts` checks what branding does at runtime (nothing) and
4
+ // `state.type-test.ts` checks which transitions compile. Those are two halves of
5
+ // one claim, so they read the states and edges from here rather than each
6
+ // declaring their own — the type-test's extra `Shipped` state exists precisely so
7
+ // there is a `Draft -> Shipped` edge that was never defined.
8
+ import { defineState, transition } from './index.js';
9
+ export const Draft = defineState();
10
+ export const Paid = defineState();
11
+ export const Shipped = defineState();
12
+ export const pay = transition(Draft, Paid, o => ({ ...o }));
13
+ export const ship = transition(Paid, Shipped, o => ({ ...o }));
14
+ //# sourceMappingURL=fixtures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/state/fixtures.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,qEAAqE;AACrE,iFAAiF;AACjF,0EAA0E;AAC1E,kFAAkF;AAClF,6DAA6D;AAC7D,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAOrD,MAAM,CAAC,MAAM,KAAK,GAAG,WAAW,EAAkB,CAAC;AACnD,MAAM,CAAC,MAAM,IAAI,GAAG,WAAW,EAAiB,CAAC;AACjD,MAAM,CAAC,MAAM,OAAO,GAAG,WAAW,EAAoB,CAAC;AAEvD,MAAM,CAAC,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5D,MAAM,CAAC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC"}
@@ -0,0 +1,26 @@
1
+ declare const brand: unique symbol;
2
+ /** `T` nominally tagged with brand `B`. Erases to `T` at runtime. */
3
+ export type Brand<T, B extends string> = T & {
4
+ readonly [brand]: B;
5
+ };
6
+ /** A state maker for a named state over a base type. */
7
+ export interface State<B extends string, T> {
8
+ /** Construct a branded value from base fields — no consumer `as`. */
9
+ create(value: T): Brand<T, B>;
10
+ /** Type guard narrowing an unknown/base value to this branded state. */
11
+ is(value: unknown): value is Brand<T, B>;
12
+ }
13
+ /**
14
+ * Define a domain state. Returns a maker whose `create` brands base values and
15
+ * whose `is` narrows to the branded type. The brand exists only in the type
16
+ * system, so `create` is an identity at runtime.
17
+ */
18
+ export declare function defineState<B extends string, T>(): State<B, T>;
19
+ /**
20
+ * Declare a legal state transition `From -> To`. The returned function only
21
+ * accepts a value already branded `From`, so applying it to any other state is
22
+ * a compile error, and undeclared edges simply have no function.
23
+ */
24
+ export declare function transition<T, From extends string, To extends string>(_from: State<From, T>, to: State<To, T>, fn: (value: Brand<T, From>) => T): (value: Brand<T, From>) => Brand<T, To>;
25
+ export {};
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAOA,OAAO,CAAC,MAAM,KAAK,EAAE,OAAO,MAAM,CAAC;AAEnC,qEAAqE;AACrE,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC;AAErE,wDAAwD;AACxD,MAAM,WAAW,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC;IACxC,qEAAqE;IACrE,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9B,wEAAwE;IACxE,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CAC1C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAgB9D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,SAAS,MAAM,EAAE,EAAE,SAAS,MAAM,EAClE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,EACrB,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAChB,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAC/B,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAIzC"}
@@ -0,0 +1,37 @@
1
+ // @zmdb/app — compile-time domain state machines (epic #267, spec ./SPEC.md).
2
+ // Branded/phantom types make illegal transitions fail to compile; branding
3
+ // erases at runtime (0 cost). No `as` on the consumer surface — construction
4
+ // goes through a checked factory. No reflection.
5
+ /**
6
+ * Define a domain state. Returns a maker whose `create` brands base values and
7
+ * whose `is` narrows to the branded type. The brand exists only in the type
8
+ * system, so `create` is an identity at runtime.
9
+ */
10
+ export function defineState() {
11
+ return {
12
+ create(value) {
13
+ // boundary: branding is a compile-time-only tag (the brand symbol has no
14
+ // runtime representation), so returning the value unchanged as the branded
15
+ // type is sound. This is the single enumerated brand-attach boundary
16
+ // (ARCHITECTURE.md §2.1); it never appears on the consumer surface.
17
+ return value;
18
+ },
19
+ is(value) {
20
+ // The brand is erased at runtime; a value "is" this state by construction.
21
+ // We can only assert non-nullish here — the compile-time brand carries the
22
+ // real guarantee. Callers use `is` to narrow values they already trust.
23
+ return value !== undefined && value !== null;
24
+ },
25
+ };
26
+ }
27
+ /**
28
+ * Declare a legal state transition `From -> To`. The returned function only
29
+ * accepts a value already branded `From`, so applying it to any other state is
30
+ * a compile error, and undeclared edges simply have no function.
31
+ */
32
+ export function transition(_from, to, fn) {
33
+ return function (value) {
34
+ return to.create(fn(value));
35
+ };
36
+ }
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,2EAA2E;AAC3E,6EAA6E;AAC7E,iDAAiD;AAiBjD;;;;GAIG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO;QACL,MAAM,CAAC,KAAQ;YACb,yEAAyE;YACzE,2EAA2E;YAC3E,qEAAqE;YACrE,oEAAoE;YACpE,OAAO,KAAoB,CAAC;QAC9B,CAAC;QACD,EAAE,CAAC,KAAc;YACf,2EAA2E;YAC3E,2EAA2E;YAC3E,wEAAwE;YACxE,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC;QAC/C,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CACxB,KAAqB,EACrB,EAAgB,EAChB,EAAgC;IAEhC,OAAO,UAAU,KAAqB;QACpC,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,57 @@
1
+ import type { DeclaredTable, TaggedSchema, UpdateDTO } from '@zmdb/schema';
2
+ export type StateTransitions<StateValues extends string | number | symbol = string> = {
3
+ readonly [From in StateValues]?: readonly StateValues[];
4
+ };
5
+ export declare function defineStateTransitions<StateValues extends string, const T extends {
6
+ readonly [From in StateValues]?: readonly StateValues[];
7
+ }>(transitions: T): T;
8
+ export type AllowedTargetStates<Transitions, From extends string> = Transitions extends {
9
+ readonly [k in From]?: readonly (infer To extends string)[];
10
+ } ? To : never;
11
+ export type StateUpdateDTO<T extends DeclaredTable, StateField extends string, FromState extends string, Transitions, AllowedFields extends keyof UpdateDTO<T> = keyof UpdateDTO<T>> = Pick<UpdateDTO<T>, Exclude<AllowedFields, StateField>> & {
12
+ [P in StateField]?: AllowedTargetStates<Transitions, FromState>;
13
+ };
14
+ /** What a transition out of `From` is allowed to patch: the declared restriction if there is one, otherwise every updatable field. */
15
+ type PatchableFields<T extends DeclaredTable, Transitions extends Record<string, readonly string[]>, FieldRestrictions extends {
16
+ readonly [From in keyof Transitions]?: readonly (keyof UpdateDTO<T>)[];
17
+ }, From extends keyof Transitions & string> = FieldRestrictions[From] extends readonly (keyof UpdateDTO<T>)[] ? FieldRestrictions[From][number] : keyof UpdateDTO<T>;
18
+ /**
19
+ * The `patch` argument of a transition out of `From`. When the only patchable
20
+ * field is the state field itself there is nothing left to pass, so the argument
21
+ * narrows to `Record<string, never>` and any property is a type error.
22
+ */
23
+ type TransitionPatch<T extends DeclaredTable, StateField extends string, Transitions extends Record<string, readonly string[]>, FieldRestrictions extends {
24
+ readonly [From in keyof Transitions]?: readonly (keyof UpdateDTO<T>)[];
25
+ }, From extends keyof Transitions & string> = [Exclude<PatchableFields<T, Transitions, FieldRestrictions, From>, StateField>] extends [never] ? Record<string, never> : Omit<Pick<UpdateDTO<T>, PatchableFields<T, Transitions, FieldRestrictions, From>>, StateField>;
26
+ export interface EntityStateMachineOptions<T extends DeclaredTable, StateField extends string, Transitions extends Record<string, readonly string[]>, FieldRestrictions extends {
27
+ readonly [From in keyof Transitions]?: readonly (keyof UpdateDTO<T>)[];
28
+ } = {}> {
29
+ /**
30
+ * The generated schema value, for inference only — nothing reads it.
31
+ *
32
+ * It is the whole reason this machine knows what a patch may contain: `T` is the
33
+ * declared type, recovered from the value's phantom, and `UpdateDTO<T>` is what the
34
+ * transitions are checked against. Passing a schema for a different table is the one
35
+ * mistake this cannot catch, and it is the same mistake as pointing a repository at
36
+ * the wrong table.
37
+ */
38
+ schema?: TaggedSchema<T>;
39
+ stateField: StateField;
40
+ transitions: Transitions;
41
+ allowedFields?: FieldRestrictions | undefined;
42
+ }
43
+ export interface EntityStateMachine<T extends DeclaredTable, StateField extends string, Transitions extends Record<string, readonly string[]>, FieldRestrictions extends {
44
+ readonly [From in keyof Transitions]?: readonly (keyof UpdateDTO<T>)[];
45
+ } = {}> {
46
+ readonly stateField: StateField;
47
+ readonly transitions: Transitions;
48
+ readonly allowedFields?: FieldRestrictions | undefined;
49
+ canTransition<From extends keyof Transitions & string>(from: From, to: string): boolean;
50
+ createUpdatePayload<From extends keyof Transitions & string, To extends Transitions[From][number]>(from: From, to: To, patch?: TransitionPatch<T, StateField, Transitions, FieldRestrictions, From>): StateUpdateDTO<T, StateField, From, Transitions, PatchableFields<T, Transitions, FieldRestrictions, From>>;
51
+ }
52
+ export declare function createStateUpdatePayload<T extends DeclaredTable, StateField extends string, From extends keyof Transitions & string, const Transitions extends Record<string, readonly string[]>, AllowedFields extends keyof UpdateDTO<T> = keyof UpdateDTO<T>>(stateField: StateField, transitions: Transitions, from: From, to: Transitions[From][number], patch?: Omit<Pick<UpdateDTO<T>, AllowedFields>, StateField> | Record<string, never>): StateUpdateDTO<T, StateField, From, Transitions, AllowedFields>;
53
+ export declare function defineEntityStateMachine<T extends DeclaredTable, StateField extends string, const Transitions extends Record<string, readonly string[]>, const FieldRestrictions extends {
54
+ readonly [From in keyof Transitions]?: readonly (keyof UpdateDTO<T>)[];
55
+ } = {}>(options: EntityStateMachineOptions<T, StateField, Transitions, FieldRestrictions>): EntityStateMachine<T, StateField, Transitions, FieldRestrictions>;
56
+ export {};
57
+ //# sourceMappingURL=state-transitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-transitions.d.ts","sourceRoot":"","sources":["../src/state-transitions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ export function defineStateTransitions(transitions) {
2
+ return transitions;
3
+ }
4
+ export function createStateUpdatePayload(stateField, transitions, from, to, patch) {
5
+ const allowed = transitions[from];
6
+ if (!Array.isArray(allowed) || !allowed.includes(to)) {
7
+ throw new Error(`Invalid state transition from "${from}" to "${to}" for field "${stateField}"`);
8
+ }
9
+ const payload = {
10
+ ...patch,
11
+ [stateField]: to,
12
+ };
13
+ // boundary: return value is certified as StateUpdateDTO after runtime transition validation.
14
+ return payload;
15
+ }
16
+ export function defineEntityStateMachine(options) {
17
+ const { stateField, transitions, allowedFields } = options;
18
+ return {
19
+ stateField,
20
+ transitions,
21
+ allowedFields,
22
+ canTransition(from, to) {
23
+ const allowed = transitions[from];
24
+ return Array.isArray(allowed) && allowed.includes(to);
25
+ },
26
+ createUpdatePayload(from, to, patch) {
27
+ return createStateUpdatePayload(stateField, transitions, from, to, patch);
28
+ },
29
+ };
30
+ }
31
+ //# sourceMappingURL=state-transitions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-transitions.js","sourceRoot":"","sources":["../src/state-transitions.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,sBAAsB,CAGpC,WAAc;IACd,OAAO,WAAW,CAAC;AACrB,CAAC;AAiFD,MAAM,UAAU,wBAAwB,CAOtC,UAAsB,EACtB,WAAwB,EACxB,IAAU,EACV,EAA6B,EAC7B,KAAmF;IAEnF,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,kCAAkC,IAAI,SAAS,EAAE,gBAAgB,UAAU,GAAG,CAAC,CAAC;IAClG,CAAC;IACD,MAAM,OAAO,GAAG;QACd,GAAG,KAAK;QACR,CAAC,UAAU,CAAC,EAAE,EAAE;KACjB,CAAC;IACF,6FAA6F;IAC7F,OAAO,OAA0E,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,wBAAwB,CAMtC,OAAiF;IAEjF,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;IAE3D,OAAO;QACL,UAAU;QACV,WAAW;QACX,aAAa;QACb,aAAa,CAAC,IAAgC,EAAE,EAAU;YACxD,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;YAClC,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACxD,CAAC;QACD,mBAAmB,CACjB,IAAU,EACV,EAAM,EACN,KAA4E;YAE5E,OAAO,wBAAwB,CAM7B,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QAC9C,CAAC;KACF,CAAC;AACJ,CAAC"}