@selvajs/server 0.2.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 (123) hide show
  1. package/LICENSE +21 -0
  2. package/dist/compute/__tests__/client-cache.test.d.ts +11 -0
  3. package/dist/compute/__tests__/client-cache.test.d.ts.map +1 -0
  4. package/dist/compute/__tests__/client-cache.test.js +149 -0
  5. package/dist/compute/__tests__/client-cache.test.js.map +1 -0
  6. package/dist/compute/__tests__/rate-limit.test.d.ts +2 -0
  7. package/dist/compute/__tests__/rate-limit.test.d.ts.map +1 -0
  8. package/dist/compute/__tests__/rate-limit.test.js +62 -0
  9. package/dist/compute/__tests__/rate-limit.test.js.map +1 -0
  10. package/dist/compute/__tests__/remote-definition.test.d.ts +11 -0
  11. package/dist/compute/__tests__/remote-definition.test.d.ts.map +1 -0
  12. package/dist/compute/__tests__/remote-definition.test.js +114 -0
  13. package/dist/compute/__tests__/remote-definition.test.js.map +1 -0
  14. package/dist/compute/__tests__/safe-url.test.d.ts +2 -0
  15. package/dist/compute/__tests__/safe-url.test.d.ts.map +1 -0
  16. package/dist/compute/__tests__/safe-url.test.js +71 -0
  17. package/dist/compute/__tests__/safe-url.test.js.map +1 -0
  18. package/dist/compute/__tests__/solve-pipeline.test.d.ts +11 -0
  19. package/dist/compute/__tests__/solve-pipeline.test.d.ts.map +1 -0
  20. package/dist/compute/__tests__/solve-pipeline.test.js +245 -0
  21. package/dist/compute/__tests__/solve-pipeline.test.js.map +1 -0
  22. package/dist/compute/__tests__/transform-input.test.d.ts +14 -0
  23. package/dist/compute/__tests__/transform-input.test.d.ts.map +1 -0
  24. package/dist/compute/__tests__/transform-input.test.js +114 -0
  25. package/dist/compute/__tests__/transform-input.test.js.map +1 -0
  26. package/dist/compute/client-cache.d.ts +104 -0
  27. package/dist/compute/client-cache.d.ts.map +1 -0
  28. package/dist/compute/client-cache.js +147 -0
  29. package/dist/compute/client-cache.js.map +1 -0
  30. package/dist/compute/index.d.ts +8 -0
  31. package/dist/compute/index.d.ts.map +1 -0
  32. package/dist/compute/index.js +9 -0
  33. package/dist/compute/index.js.map +1 -0
  34. package/dist/compute/limits.d.ts +102 -0
  35. package/dist/compute/limits.d.ts.map +1 -0
  36. package/dist/compute/limits.js +76 -0
  37. package/dist/compute/limits.js.map +1 -0
  38. package/dist/compute/rate-limit.d.ts +49 -0
  39. package/dist/compute/rate-limit.d.ts.map +1 -0
  40. package/dist/compute/rate-limit.js +49 -0
  41. package/dist/compute/rate-limit.js.map +1 -0
  42. package/dist/compute/remote-definition.d.ts +53 -0
  43. package/dist/compute/remote-definition.d.ts.map +1 -0
  44. package/dist/compute/remote-definition.js +110 -0
  45. package/dist/compute/remote-definition.js.map +1 -0
  46. package/dist/compute/safe-url.d.ts +15 -0
  47. package/dist/compute/safe-url.d.ts.map +1 -0
  48. package/dist/compute/safe-url.js +195 -0
  49. package/dist/compute/safe-url.js.map +1 -0
  50. package/dist/compute/solve-pipeline.d.ts +127 -0
  51. package/dist/compute/solve-pipeline.d.ts.map +1 -0
  52. package/dist/compute/solve-pipeline.js +195 -0
  53. package/dist/compute/solve-pipeline.js.map +1 -0
  54. package/dist/compute/transform-input.d.ts +20 -0
  55. package/dist/compute/transform-input.d.ts.map +1 -0
  56. package/dist/compute/transform-input.js +47 -0
  57. package/dist/compute/transform-input.js.map +1 -0
  58. package/dist/definitions/__tests__/load-for-render.test.d.ts +8 -0
  59. package/dist/definitions/__tests__/load-for-render.test.d.ts.map +1 -0
  60. package/dist/definitions/__tests__/load-for-render.test.js +196 -0
  61. package/dist/definitions/__tests__/load-for-render.test.js.map +1 -0
  62. package/dist/definitions/__tests__/schema-extraction.test.d.ts +11 -0
  63. package/dist/definitions/__tests__/schema-extraction.test.d.ts.map +1 -0
  64. package/dist/definitions/__tests__/schema-extraction.test.js +115 -0
  65. package/dist/definitions/__tests__/schema-extraction.test.js.map +1 -0
  66. package/dist/definitions/definition-service.d.ts +77 -0
  67. package/dist/definitions/definition-service.d.ts.map +1 -0
  68. package/dist/definitions/definition-service.js +184 -0
  69. package/dist/definitions/definition-service.js.map +1 -0
  70. package/dist/definitions/index.d.ts +4 -0
  71. package/dist/definitions/index.d.ts.map +1 -0
  72. package/dist/definitions/index.js +8 -0
  73. package/dist/definitions/index.js.map +1 -0
  74. package/dist/definitions/load-for-render.d.ts +61 -0
  75. package/dist/definitions/load-for-render.d.ts.map +1 -0
  76. package/dist/definitions/load-for-render.js +165 -0
  77. package/dist/definitions/load-for-render.js.map +1 -0
  78. package/dist/definitions/schema-extraction.d.ts +22 -0
  79. package/dist/definitions/schema-extraction.d.ts.map +1 -0
  80. package/dist/definitions/schema-extraction.js +89 -0
  81. package/dist/definitions/schema-extraction.js.map +1 -0
  82. package/dist/index.d.ts +18 -0
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/index.js +18 -0
  85. package/dist/index.js.map +1 -0
  86. package/dist/providers/__tests__/create-selva-providers.test.d.ts +7 -0
  87. package/dist/providers/__tests__/create-selva-providers.test.d.ts.map +1 -0
  88. package/dist/providers/__tests__/create-selva-providers.test.js +135 -0
  89. package/dist/providers/__tests__/create-selva-providers.test.js.map +1 -0
  90. package/dist/providers/create-selva-providers.d.ts +53 -0
  91. package/dist/providers/create-selva-providers.d.ts.map +1 -0
  92. package/dist/providers/create-selva-providers.js +152 -0
  93. package/dist/providers/create-selva-providers.js.map +1 -0
  94. package/dist/providers/index.d.ts +2 -0
  95. package/dist/providers/index.d.ts.map +1 -0
  96. package/dist/providers/index.js +6 -0
  97. package/dist/providers/index.js.map +1 -0
  98. package/package.json +60 -0
  99. package/src/compute/__tests__/client-cache.test.ts +164 -0
  100. package/src/compute/__tests__/rate-limit.test.ts +69 -0
  101. package/src/compute/__tests__/remote-definition.test.ts +140 -0
  102. package/src/compute/__tests__/safe-url.test.ts +72 -0
  103. package/src/compute/__tests__/solve-pipeline.test.ts +294 -0
  104. package/src/compute/__tests__/transform-input.test.ts +155 -0
  105. package/src/compute/client-cache.ts +278 -0
  106. package/src/compute/index.ts +48 -0
  107. package/src/compute/limits.ts +147 -0
  108. package/src/compute/rate-limit.ts +83 -0
  109. package/src/compute/remote-definition.ts +149 -0
  110. package/src/compute/safe-url.ts +186 -0
  111. package/src/compute/solve-pipeline.ts +324 -0
  112. package/src/compute/transform-input.ts +52 -0
  113. package/src/definitions/__tests__/load-for-render.test.ts +244 -0
  114. package/src/definitions/__tests__/schema-extraction.test.ts +137 -0
  115. package/src/definitions/definition-service.ts +243 -0
  116. package/src/definitions/index.ts +22 -0
  117. package/src/definitions/load-for-render.ts +272 -0
  118. package/src/definitions/schema-extraction.ts +117 -0
  119. package/src/index.ts +18 -0
  120. package/src/providers/__tests__/create-selva-providers.test.ts +172 -0
  121. package/src/providers/__tests__/fixtures/override-config.mjs +8 -0
  122. package/src/providers/create-selva-providers.ts +241 -0
  123. package/src/providers/index.ts +12 -0
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Tests for `runSolvePipeline` — the transport-agnostic solve core (K3).
3
+ *
4
+ * `@selvajs/compute` is mocked so the pipeline runs without a live compute
5
+ * server: `TreeBuilder.fromInputParams` returns a marker tree and the scheduler
6
+ * is a stub whose `solve` we script per test (resolve a response, throw an
7
+ * AbortError, etc.). That isolates the pipeline's own behavior — outcome
8
+ * classification, size cap, gzip, and the Server-Timing / version envelope.
9
+ */
10
+ import { describe, it, expect, vi } from 'vitest';
11
+ import { gunzipSync } from 'node:zlib';
12
+ // --- Mock @selvajs/compute -------------------------------------------------
13
+ vi.mock('@selvajs/compute', () => {
14
+ return {
15
+ TreeBuilder: {
16
+ fromInputParams: (params) => ({ __tree: true, count: params.length })
17
+ },
18
+ // transform-input.ts (imported by the pipeline) calls processInput; return
19
+ // the raw shape as an InputParam so filtering/mapping runs end-to-end.
20
+ processInput: (raw) => raw
21
+ };
22
+ });
23
+ import { runSolvePipeline, COMPUTE_CONTRACT_VERSION, COMPUTE_VERSION_HEADER } from '../index.js';
24
+ /** A CachedClient stub whose scheduler.solve is scripted per test. */
25
+ function fakeClient(solve) {
26
+ return {
27
+ client: {},
28
+ scheduler: { solve },
29
+ rhinoTiming: { last: null },
30
+ solveMeta: { last: null }
31
+ };
32
+ }
33
+ function baseArgs(over = {}) {
34
+ return {
35
+ definitionSource: new Uint8Array([1, 2, 3]),
36
+ inputs: [{ id: 'a', paramType: 'number', nickname: 'A' }],
37
+ values: { a: 5 },
38
+ client: fakeClient(async () => ({ values: [], errors: [], warnings: [] })),
39
+ responseMaxBytes: 10 * 1024 * 1024,
40
+ maxSolveDurationMs: 100_000,
41
+ acceptEncoding: '',
42
+ signal: new AbortController().signal,
43
+ loadStartMs: performance.now(),
44
+ defLoadMs: 1.5,
45
+ prepMarks: [['body', 0.2]],
46
+ ...over
47
+ };
48
+ }
49
+ describe('runSolvePipeline — success', () => {
50
+ it('returns an ok envelope with a JSON body and the version header', async () => {
51
+ const result = { values: [{ id: 'out' }], errors: [], warnings: ['w'] };
52
+ const outcome = await runSolvePipeline(baseArgs({ client: fakeClient(async () => result) }));
53
+ expect(outcome.kind).toBe('ok');
54
+ if (outcome.kind !== 'ok')
55
+ return;
56
+ expect(outcome.errorCount).toBe(0);
57
+ expect(outcome.warningCount).toBe(1);
58
+ expect(outcome.envelope.encoding).toBeUndefined();
59
+ expect(JSON.parse(outcome.envelope.body)).toEqual(result);
60
+ expect(outcome.envelope.headers[COMPUTE_VERSION_HEADER]).toBe(String(COMPUTE_CONTRACT_VERSION));
61
+ expect(outcome.envelope.headers['Content-Type']).toBe('application/json');
62
+ expect(outcome.envelope.headers['Content-Length']).toBe(String(Buffer.byteLength(outcome.envelope.body)));
63
+ });
64
+ it('only sends inputs with a paramType to the tree builder', async () => {
65
+ let seenTree;
66
+ const outcome = await runSolvePipeline(baseArgs({
67
+ inputs: [
68
+ { id: 'a', paramType: 'number', nickname: 'A' },
69
+ { id: 'b', nickname: 'B' } // no paramType → filtered out
70
+ ],
71
+ client: fakeClient(async (_def, tree) => {
72
+ seenTree = tree;
73
+ return { errors: [], warnings: [] };
74
+ })
75
+ }));
76
+ expect(outcome.kind).toBe('ok');
77
+ expect(seenTree).toEqual({ __tree: true, count: 1 });
78
+ });
79
+ it('forwards the abort signal to the scheduler', async () => {
80
+ const controller = new AbortController();
81
+ let seenSignal;
82
+ await runSolvePipeline(baseArgs({
83
+ signal: controller.signal,
84
+ client: fakeClient(async (_d, _t, opts) => {
85
+ seenSignal = opts.signal;
86
+ return { errors: [], warnings: [] };
87
+ })
88
+ }));
89
+ expect(seenSignal).toBe(controller.signal);
90
+ });
91
+ });
92
+ describe('runSolvePipeline — gzip', () => {
93
+ it('compresses when Accept-Encoding allows and the body is over 1 KB', async () => {
94
+ // A payload comfortably over the 1 KB gzip threshold.
95
+ const big = { values: Array.from({ length: 500 }, (_, i) => ({ i, s: 'xxxxxxxxxx' })) };
96
+ const outcome = await runSolvePipeline(baseArgs({ acceptEncoding: 'gzip, br', client: fakeClient(async () => big) }));
97
+ expect(outcome.kind).toBe('ok');
98
+ if (outcome.kind !== 'ok')
99
+ return;
100
+ expect(outcome.envelope.encoding).toBe('gzip');
101
+ expect(outcome.envelope.headers['Content-Encoding']).toBe('gzip');
102
+ expect(outcome.envelope.headers['Vary']).toBe('Accept-Encoding');
103
+ // The gzip body round-trips back to the original JSON.
104
+ const inflated = gunzipSync(Buffer.from(outcome.envelope.body)).toString();
105
+ expect(JSON.parse(inflated)).toEqual(big);
106
+ expect(outcome.envelope.metrics.compressedBytes).toBeGreaterThan(0);
107
+ });
108
+ it('does NOT compress when Accept-Encoding lacks gzip', async () => {
109
+ const big = { values: Array.from({ length: 500 }, (_, i) => ({ i, s: 'xxxxxxxxxx' })) };
110
+ const outcome = await runSolvePipeline(baseArgs({ acceptEncoding: 'br', client: fakeClient(async () => big) }));
111
+ expect(outcome.kind).toBe('ok');
112
+ if (outcome.kind !== 'ok')
113
+ return;
114
+ expect(outcome.envelope.encoding).toBeUndefined();
115
+ expect(outcome.envelope.headers['Content-Encoding']).toBeUndefined();
116
+ expect(outcome.envelope.metrics.compressedBytes).toBeNull();
117
+ });
118
+ it('does NOT compress a tiny body even with gzip advertised', async () => {
119
+ const outcome = await runSolvePipeline(baseArgs({ acceptEncoding: 'gzip', client: fakeClient(async () => ({ ok: 1 })) }));
120
+ expect(outcome.kind).toBe('ok');
121
+ if (outcome.kind !== 'ok')
122
+ return;
123
+ expect(outcome.envelope.encoding).toBeUndefined();
124
+ });
125
+ });
126
+ describe('runSolvePipeline — failure outcomes', () => {
127
+ it('classifies the scheduler deadline (AbortError, signal NOT aborted) as timeout', async () => {
128
+ const outcome = await runSolvePipeline(baseArgs({
129
+ maxSolveDurationMs: 42_000,
130
+ client: fakeClient(async () => {
131
+ const e = new Error('aborted');
132
+ e.name = 'AbortError';
133
+ throw e;
134
+ })
135
+ }));
136
+ expect(outcome.kind).toBe('timeout');
137
+ if (outcome.kind !== 'timeout')
138
+ return;
139
+ expect(outcome.message).toContain('42s');
140
+ expect(outcome.durationMs).toBeGreaterThanOrEqual(0);
141
+ });
142
+ it('classifies AbortError with the request signal aborted as client_abort', async () => {
143
+ const controller = new AbortController();
144
+ controller.abort();
145
+ const outcome = await runSolvePipeline(baseArgs({
146
+ signal: controller.signal,
147
+ client: fakeClient(async () => {
148
+ const e = new Error('aborted');
149
+ e.name = 'AbortError';
150
+ throw e;
151
+ })
152
+ }));
153
+ expect(outcome.kind).toBe('client_abort');
154
+ });
155
+ it('classifies any other throw as compute_error carrying the original error', async () => {
156
+ const boom = new TypeError('fetch failed');
157
+ const outcome = await runSolvePipeline(baseArgs({
158
+ client: fakeClient(async () => {
159
+ throw boom;
160
+ })
161
+ }));
162
+ expect(outcome.kind).toBe('compute_error');
163
+ if (outcome.kind !== 'compute_error')
164
+ return;
165
+ expect(outcome.error).toBe(boom);
166
+ });
167
+ it('returns too_large when the serialized result exceeds responseMaxBytes', async () => {
168
+ const outcome = await runSolvePipeline(baseArgs({
169
+ responseMaxBytes: 10, // tiny cap
170
+ client: fakeClient(async () => ({ values: 'a bigger than ten bytes payload' }))
171
+ }));
172
+ expect(outcome.kind).toBe('too_large');
173
+ });
174
+ });
175
+ describe('runSolvePipeline — Server-Timing', () => {
176
+ it('emits the core phases and echoes prep marks as p_*', async () => {
177
+ const outcome = await runSolvePipeline(baseArgs({
178
+ defLoadMs: 12.3,
179
+ prepMarks: [
180
+ ['body', 0.5],
181
+ ['client', 3.1]
182
+ ],
183
+ client: fakeClient(async () => ({ errors: [], warnings: [] }))
184
+ }));
185
+ expect(outcome.kind).toBe('ok');
186
+ if (outcome.kind !== 'ok')
187
+ return;
188
+ const st = outcome.envelope.headers['Server-Timing'];
189
+ expect(st).toContain('load;dur=12.3');
190
+ expect(st).toContain('tree;dur=');
191
+ expect(st).toContain('solve;dur=');
192
+ expect(st).toContain('serialize;dur=');
193
+ expect(st).toContain('total;dur=');
194
+ expect(st).toContain('p_body;dur=0.5');
195
+ expect(st).toContain('p_client;dur=3.1');
196
+ });
197
+ it('splits solve into rhino_* + compute_link when the client reported server timing', async () => {
198
+ // The real onServerTiming callback fires DURING the solve, after the
199
+ // pipeline has reset the holder — so populate it inside the solve stub, not
200
+ // before the call (which the pipeline's pre-solve reset would wipe).
201
+ const client = fakeClient(async () => {
202
+ client.rhinoTiming.last = { decode: 5, solve: 20, encode: 3 };
203
+ return { errors: [], warnings: [] };
204
+ });
205
+ const outcome = await runSolvePipeline(baseArgs({ client }));
206
+ expect(outcome.kind).toBe('ok');
207
+ if (outcome.kind !== 'ok')
208
+ return;
209
+ const st = outcome.envelope.headers['Server-Timing'];
210
+ expect(st).toContain('rhino_decode;dur=5.0');
211
+ expect(st).toContain('rhino_solve;dur=20.0');
212
+ expect(st).toContain('rhino_encode;dur=3.0');
213
+ expect(st).toContain('compute_link;dur=');
214
+ });
215
+ it('surfaces selva_cache + def_reupload verdicts as 0/1 flags', async () => {
216
+ // Populate during the solve (the onSettle callback's real timing), not
217
+ // before — the pipeline resets solveMeta before it runs.
218
+ const client = fakeClient(async () => {
219
+ client.solveMeta.last = { fromCache: true, definitionReuploaded: false };
220
+ return { errors: [], warnings: [] };
221
+ });
222
+ const outcome = await runSolvePipeline(baseArgs({ client }));
223
+ expect(outcome.kind).toBe('ok');
224
+ if (outcome.kind !== 'ok')
225
+ return;
226
+ const st = outcome.envelope.headers['Server-Timing'];
227
+ expect(st).toContain('selva_cache;dur=1');
228
+ expect(st).toContain('def_reupload;dur=0');
229
+ });
230
+ it('resets stale telemetry holders before solving', async () => {
231
+ // A warm client carrying a previous request's timing must not leak it into
232
+ // this solve's Server-Timing when the current solve reports nothing.
233
+ const client = fakeClient(async () => ({ errors: [], warnings: [] }));
234
+ client.rhinoTiming.last = { decode: 99, solve: 99, encode: 99 };
235
+ client.solveMeta.last = { fromCache: true };
236
+ const outcome = await runSolvePipeline(baseArgs({ client }));
237
+ expect(outcome.kind).toBe('ok');
238
+ if (outcome.kind !== 'ok')
239
+ return;
240
+ // Holders were reset to null before solve; the stub never repopulated them.
241
+ expect(outcome.envelope.headers['Server-Timing']).not.toContain('rhino_decode');
242
+ expect(outcome.envelope.headers['Server-Timing']).not.toContain('selva_cache');
243
+ });
244
+ });
245
+ //# sourceMappingURL=solve-pipeline.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solve-pipeline.test.js","sourceRoot":"","sources":["../../../src/compute/__tests__/solve-pipeline.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Tests for `transformInputParameter` — the adapter that turns a persisted `SchemaInput`
3
+ * (plus the user's chosen value) into the `@selvajs/compute` `InputParam` that
4
+ * `TreeBuilder.fromInputParams` serializes for the solve.
5
+ *
6
+ * The adapter delegates to the package's `processInput`, so these assert the
7
+ * package-aligned behavior: correct `paramType` for every type (not the old
8
+ * coerce-everything-to-Text), and `default` carrying the user's value. Where a value/
9
+ * default is absent, `processInput` leaves `default` undefined and `fromInputParams`
10
+ * omits the input entirely — letting Grasshopper use its own internal default rather
11
+ * than forcing `''`/`false`.
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=transform-input.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform-input.test.d.ts","sourceRoot":"","sources":["../../../src/compute/__tests__/transform-input.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Tests for `transformInputParameter` — the adapter that turns a persisted `SchemaInput`
3
+ * (plus the user's chosen value) into the `@selvajs/compute` `InputParam` that
4
+ * `TreeBuilder.fromInputParams` serializes for the solve.
5
+ *
6
+ * The adapter delegates to the package's `processInput`, so these assert the
7
+ * package-aligned behavior: correct `paramType` for every type (not the old
8
+ * coerce-everything-to-Text), and `default` carrying the user's value. Where a value/
9
+ * default is absent, `processInput` leaves `default` undefined and `fromInputParams`
10
+ * omits the input entirely — letting Grasshopper use its own internal default rather
11
+ * than forcing `''`/`false`.
12
+ */
13
+ import { describe, it, expect } from 'vitest';
14
+ import { transformInputParameter } from '../transform-input.js';
15
+ function input(partial) {
16
+ return {
17
+ id: 'id-1',
18
+ nickname: 'Param',
19
+ paramType: 'text',
20
+ ...partial
21
+ };
22
+ }
23
+ describe('transformInputParameter — identity fields', () => {
24
+ it('carries id, name, nickname, description through', () => {
25
+ const out = transformInputParameter(input({ id: 'guid-x', nickname: 'Width', description: 'the width' }), 5);
26
+ expect(out.id).toBe('guid-x');
27
+ expect(out.name).toBe('Width');
28
+ expect(out.nickname).toBe('Width');
29
+ expect(out.description).toBe('the width');
30
+ });
31
+ it('defaults a blank nickname to null and an absent description to empty string', () => {
32
+ const out = transformInputParameter(input({ nickname: '', description: undefined }), 'v');
33
+ expect(out.nickname).toBeNull();
34
+ expect(out.description).toBe('');
35
+ });
36
+ });
37
+ describe('transformInputParameter — number / integer', () => {
38
+ it('maps number with the user value winning over the schema default', () => {
39
+ const out = transformInputParameter(input({ paramType: 'number', default: 1, minimum: 0, maximum: 10, stepSize: 0.5 }), 7);
40
+ expect(out).toMatchObject({ paramType: 'Number', default: 7, minimum: 0, maximum: 10 });
41
+ });
42
+ it('falls back to the schema default when no value is supplied', () => {
43
+ const out = transformInputParameter(input({ paramType: 'number', default: 3 }), undefined);
44
+ expect(out.default).toBe(3);
45
+ });
46
+ it('forces stepSize to 1 for integers', () => {
47
+ const out = transformInputParameter(input({ paramType: 'integer', stepSize: 0.5, default: 2 }), 4);
48
+ expect(out).toMatchObject({ paramType: 'Integer', stepSize: 1, default: 4 });
49
+ });
50
+ });
51
+ describe('transformInputParameter — text', () => {
52
+ it('maps text and keeps the user value', () => {
53
+ const out = transformInputParameter(input({ paramType: 'text', default: 'd' }), 'hello');
54
+ expect(out).toMatchObject({ paramType: 'Text', default: 'hello' });
55
+ });
56
+ it('falls back to the schema default when no value is supplied', () => {
57
+ expect(transformInputParameter(input({ paramType: 'text', default: 'd' }), undefined).default).toBe('d');
58
+ });
59
+ it('leaves default undefined when neither value nor schema default exist (input is then omitted)', () => {
60
+ // processInput does not force ''. fromInputParams filters undefined defaults, so the
61
+ // param is simply not sent and Grasshopper uses its own internal default.
62
+ expect(transformInputParameter(input({ paramType: 'text', default: undefined }), undefined).default).toBeUndefined();
63
+ });
64
+ });
65
+ describe('transformInputParameter — boolean', () => {
66
+ it('maps boolean and preserves an explicit false (the bug-prone case)', () => {
67
+ const out = transformInputParameter(input({ paramType: 'boolean', default: true }), false);
68
+ expect(out).toMatchObject({ paramType: 'Boolean', default: false });
69
+ });
70
+ it('falls back to the schema default when no value is supplied', () => {
71
+ expect(transformInputParameter(input({ paramType: 'boolean', default: true }), undefined).default).toBe(true);
72
+ });
73
+ it('leaves default undefined when neither value nor schema default exist (input is then omitted)', () => {
74
+ expect(transformInputParameter(input({ paramType: 'boolean', default: undefined }), undefined)
75
+ .default).toBeUndefined();
76
+ });
77
+ });
78
+ describe('transformInputParameter — value-list / file / color / generic', () => {
79
+ // The regression that motivated the swap: these used to be silently coerced to Text.
80
+ // processInput now types them correctly. (The options map for ValueList isn't carried
81
+ // on SchemaInput, so `values` is empty and the selected value rides on `default` —
82
+ // which is exactly the string a contextual ValueList param consumes.)
83
+ it('maps valueList to ValueList, carrying the selected value', () => {
84
+ const out = transformInputParameter(input({ paramType: 'valueList', default: '0' }), '1');
85
+ expect(out).toMatchObject({ paramType: 'ValueList', default: '1' });
86
+ });
87
+ // Regression: processInput has no dynamicValueList handler, so without the explicit
88
+ // mapping it fell to the Geometry fallback with a null default — and fromInputParams
89
+ // then DROPPED the input, so the user's selection never reached the definition.
90
+ // The plugin's GetDynamicValueListParameter reuses the ValueList wire contract
91
+ // (TypeName "ValueList"), so ValueList is the correct target type.
92
+ it('maps dynamicValueList to ValueList, carrying the selected value', () => {
93
+ const out = transformInputParameter(input({ paramType: 'dynamicValueList', default: '0' }), '3.5');
94
+ expect(out).toMatchObject({ paramType: 'ValueList', default: '3.5' });
95
+ });
96
+ it('maps dynamicValueList checklist (array value) to ValueList, carrying all selections', () => {
97
+ const out = transformInputParameter(input({ paramType: 'dynamicValueList' }), ['a', 'b']);
98
+ expect(out.paramType).toBe('ValueList');
99
+ expect(out.default).toEqual(['a', 'b']);
100
+ });
101
+ it('maps file to File', () => {
102
+ const out = transformInputParameter(input({ paramType: 'file' }), { fileName: 'a.3dm' });
103
+ expect(out.paramType).toBe('File');
104
+ });
105
+ it('maps color to Color, carrying the value', () => {
106
+ const out = transformInputParameter(input({ paramType: 'color' }), '255,0,0');
107
+ expect(out).toMatchObject({ paramType: 'Color', default: '255,0,0' });
108
+ });
109
+ it('maps generic to the package fallback type (Geometry), not Text', () => {
110
+ const out = transformInputParameter(input({ paramType: 'generic', default: 'd' }), undefined);
111
+ expect(out.paramType).toBe('Geometry');
112
+ });
113
+ });
114
+ //# sourceMappingURL=transform-input.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform-input.test.js","sourceRoot":"","sources":["../../../src/compute/__tests__/transform-input.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAKhE,SAAS,KAAK,CAAC,OAAuB;IACrC,OAAO;QACN,EAAE,EAAE,MAAM;QACV,QAAQ,EAAE,OAAO;QACjB,SAAS,EAAE,MAAM;QACjB,GAAG,OAAO;KACD,CAAC;AACZ,CAAC;AAED,QAAQ,CAAC,2CAA2C,EAAE,GAAG,EAAE;IAC1D,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QAC1D,MAAM,GAAG,GAAG,uBAAuB,CAClC,KAAK,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,EACpE,CAAC,CACD,CAAC;QACF,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/B,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACtF,MAAM,GAAG,GAAG,uBAAuB,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;QAC1F,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,4CAA4C,EAAE,GAAG,EAAE;IAC3D,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QAC1E,MAAM,GAAG,GAAG,uBAAuB,CAClC,KAAK,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAClF,CAAC,CACD,CAAC;QACF,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACrE,MAAM,GAAG,GAAG,uBAAuB,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QAC3F,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC5C,MAAM,GAAG,GAAG,uBAAuB,CAClC,KAAK,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAC1D,CAAC,CACD,CAAC;QACF,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC/C,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC7C,MAAM,GAAG,GAAG,uBAAuB,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;QACzF,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACrE,MAAM,CACL,uBAAuB,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,OAAO,CACtF,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8FAA8F,EAAE,GAAG,EAAE;QACvG,qFAAqF;QACrF,0EAA0E;QAC1E,MAAM,CACL,uBAAuB,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,OAAO,CAC5F,CAAC,aAAa,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IAClD,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC5E,MAAM,GAAG,GAAG,uBAAuB,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAC3F,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACrE,MAAM,CACL,uBAAuB,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,OAAO,CAC1F,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8FAA8F,EAAE,GAAG,EAAE;QACvG,MAAM,CACL,uBAAuB,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,CAAC;aACrF,OAAO,CACT,CAAC,aAAa,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,+DAA+D,EAAE,GAAG,EAAE;IAC9E,qFAAqF;IACrF,sFAAsF;IACtF,mFAAmF;IACnF,sEAAsE;IACtE,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QACnE,MAAM,GAAG,GAAG,uBAAuB,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;QAC1F,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,oFAAoF;IACpF,qFAAqF;IACrF,gFAAgF;IAChF,+EAA+E;IAC/E,mEAAmE;IACnE,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QAC1E,MAAM,GAAG,GAAG,uBAAuB,CAClC,KAAK,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EACtD,KAAK,CACL,CAAC;QACF,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qFAAqF,EAAE,GAAG,EAAE;QAC9F,MAAM,GAAG,GAAG,uBAAuB,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QAC1F,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC5B,MAAM,GAAG,GAAG,uBAAuB,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QACzF,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QAClD,MAAM,GAAG,GAAG,uBAAuB,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QAC9E,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACzE,MAAM,GAAG,GAAG,uBAAuB,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QAC9F,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1,104 @@
1
+ import { GrasshopperClient, type SolveScheduler } from '@selvajs/compute';
2
+ /**
3
+ * Opaque identity of a compute server. Callers never construct the branded
4
+ * string directly — they pass a resolved server config to `serverIdentity()`.
5
+ * Keeping this opaque from day one (ADR 0004 D1) means "a server is now a pool
6
+ * of URLs behind one id" stays an additive, non-breaking change.
7
+ */
8
+ export type ServerIdentity = string & {
9
+ readonly __brand: 'ServerIdentity';
10
+ };
11
+ /** Minimal resolved-server shape the cache needs (a subset of the app's `ComputeServerConfig`). */
12
+ export interface ResolvedServer {
13
+ /** Stable identity — the cache key. */
14
+ id: string;
15
+ /** Base URL of the Rhino.Compute instance (a resolution detail of `id`). */
16
+ serverUrl: string;
17
+ /** Sent as `RhinoComputeKey`. */
18
+ apiKey?: string;
19
+ }
20
+ /** Derive the opaque cache identity from a resolved server. Identity is the `id`. */
21
+ export declare function serverIdentity(server: Pick<ResolvedServer, 'id'>): ServerIdentity;
22
+ /**
23
+ * Per-request telemetry holders read by the caller right after a solve resolves
24
+ * to build a Server-Timing header. Populated by the client/scheduler callbacks.
25
+ */
26
+ export interface CachedClient {
27
+ client: GrasshopperClient;
28
+ scheduler: SolveScheduler;
29
+ /**
30
+ * Last decode/solve/encode reported by the compute server (Server-Timing).
31
+ * Written by onServerTiming, read right after scheduler.solve resolves to split
32
+ * the solve wall time into on-compute-server work vs. the compute↔web-server
33
+ * link. Queue-mode schedulers serialize solves, so this correlates with the
34
+ * request that just resolved; a Selva-cache hit leaves it null (no compute
35
+ * call). Debug aid — a concurrent burst may misattribute one request's timing.
36
+ */
37
+ rhinoTiming: {
38
+ last: {
39
+ decode: number;
40
+ solve: number;
41
+ encode: number;
42
+ } | null;
43
+ };
44
+ /**
45
+ * Last solve's cache verdicts from the scheduler's onSettle: whether the
46
+ * in-process response cache served it (no compute call) and whether the
47
+ * definition had to be re-uploaded. Same read-after-solve pattern and
48
+ * concurrency caveat as rhinoTiming.
49
+ */
50
+ solveMeta: {
51
+ last: {
52
+ fromCache: boolean;
53
+ definitionReuploaded?: boolean;
54
+ } | null;
55
+ };
56
+ }
57
+ /**
58
+ * Config injected by the consuming app. Everything that used to be read from
59
+ * `$env` / `computeLimits` in the app module is passed in, so this module stays
60
+ * env-agnostic and testable.
61
+ */
62
+ export interface ClientCacheConfig {
63
+ /** Per-solve timeout forwarded to the scheduler (`ComputeLimits.maxSolveDurationMs`). */
64
+ maxSolveDurationMs: number;
65
+ /** Ask Rhino.Compute to cache solve results and return them on identical repeats. */
66
+ cachesolve: boolean;
67
+ /** Also cache solves that reported GH errors (only meaningful with `cachesolve`). */
68
+ cacheerroredsolves: boolean;
69
+ /** Reference large definitions by server cache key (pointer) instead of re-uploading. */
70
+ reuseServerDefinitionCache: boolean;
71
+ /** Concise cache/timing logs. When false, `onDebugLog` is never invoked. */
72
+ debug: boolean;
73
+ /** VERBOSE lib-level logging (full solve request/response incl. geometry). */
74
+ debugVerbose: boolean;
75
+ /** Max distinct warm clients before the LRU evicts the oldest. Default 16. */
76
+ maxCachedClients?: number;
77
+ /** Sink for the concise debug lines (the app wires `console.log`). */
78
+ onDebugLog?: (message: string) => void;
79
+ }
80
+ export interface ClientCache {
81
+ /**
82
+ * Get (or create) the warm client + scheduler for a resolved compute server,
83
+ * keyed by its `id`. `definitionGuid`, when present, is stamped as the
84
+ * `X-Selva-Definition` header on this client's outbound solve/IO requests —
85
+ * inert routing/telemetry metadata until a pool router exists (ADR 0004 D2).
86
+ */
87
+ getClient(server: ResolvedServer, opts?: {
88
+ definitionGuid?: string;
89
+ }): Promise<CachedClient>;
90
+ /**
91
+ * Dispose and drop the warm client for `id` (or a `ServerIdentity`). Called by
92
+ * the config-write path when a server's URL/key rotates so the next request
93
+ * rebuilds against fresh connection details (ADR 0004 Consequences).
94
+ */
95
+ evict(id: string | ServerIdentity): void;
96
+ /** Dispose every warm client. Test seam / shutdown hook. */
97
+ disposeAll(): void;
98
+ }
99
+ /**
100
+ * Build a per-server warm-client cache. Each cache owns its own LRU `Map` keyed
101
+ * on server `id`.
102
+ */
103
+ export declare function createClientCache(config: ClientCacheConfig): ClientCache;
104
+ //# sourceMappingURL=client-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-cache.d.ts","sourceRoot":"","sources":["../../src/compute/client-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,iBAAiB,EAGjB,KAAK,cAAc,EACnB,MAAM,kBAAkB,CAAC;AAyB1B;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAE7E,mGAAmG;AACnG,MAAM,WAAW,cAAc;IAC9B,uCAAuC;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,GAAG,cAAc,CAEjF;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,SAAS,EAAE,cAAc,CAAC;IAC1B;;;;;;;OAOG;IACH,WAAW,EAAE;QAAE,IAAI,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAA;KAAE,CAAC;IAChF;;;;;OAKG;IACH,SAAS,EAAE;QAAE,IAAI,EAAE;YAAE,SAAS,EAAE,OAAO,CAAC;YAAC,oBAAoB,CAAC,EAAE,OAAO,CAAA;SAAE,GAAG,IAAI,CAAA;KAAE,CAAC;CACnF;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IACjC,yFAAyF;IACzF,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qFAAqF;IACrF,UAAU,EAAE,OAAO,CAAC;IACpB,qFAAqF;IACrF,kBAAkB,EAAE,OAAO,CAAC;IAC5B,yFAAyF;IACzF,0BAA0B,EAAE,OAAO,CAAC;IACpC,4EAA4E;IAC5E,KAAK,EAAE,OAAO,CAAC;IACf,8EAA8E;IAC9E,YAAY,EAAE,OAAO,CAAC;IACtB,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sEAAsE;IACtE,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,WAAW;IAC3B;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7F;;;;OAIG;IACH,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAAC;IACzC,4DAA4D;IAC5D,UAAU,IAAI,IAAI,CAAC;CACnB;AAID;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,WAAW,CAuJxE"}