@selvajs/server 0.2.0-beta.2 → 0.2.0-beta.4

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 (155) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +32 -0
  3. package/dist/compute/client-cache.d.ts +12 -0
  4. package/dist/compute/client-cache.d.ts.map +1 -1
  5. package/dist/compute/client-cache.js +18 -3
  6. package/dist/compute/client-cache.js.map +1 -1
  7. package/dist/compute/definition-byte-cache.d.ts +85 -0
  8. package/dist/compute/definition-byte-cache.d.ts.map +1 -0
  9. package/dist/compute/definition-byte-cache.js +110 -0
  10. package/dist/compute/definition-byte-cache.js.map +1 -0
  11. package/dist/compute/index.d.ts +7 -2
  12. package/dist/compute/index.d.ts.map +1 -1
  13. package/dist/compute/index.js +6 -1
  14. package/dist/compute/index.js.map +1 -1
  15. package/dist/compute/limits.d.ts +52 -0
  16. package/dist/compute/limits.d.ts.map +1 -1
  17. package/dist/compute/limits.js +33 -1
  18. package/dist/compute/limits.js.map +1 -1
  19. package/dist/compute/memory-solve-cache.d.ts +58 -0
  20. package/dist/compute/memory-solve-cache.d.ts.map +1 -0
  21. package/dist/compute/memory-solve-cache.js +0 -0
  22. package/dist/compute/memory-solve-cache.js.map +1 -0
  23. package/dist/compute/safe-url.d.ts.map +1 -1
  24. package/dist/compute/safe-url.js +16 -0
  25. package/dist/compute/safe-url.js.map +1 -1
  26. package/dist/compute/solve-cache-envelope.d.ts +53 -0
  27. package/dist/compute/solve-cache-envelope.d.ts.map +1 -0
  28. package/dist/compute/solve-cache-envelope.js +66 -0
  29. package/dist/compute/solve-cache-envelope.js.map +1 -0
  30. package/dist/compute/solve-cache-key.d.ts +65 -0
  31. package/dist/compute/solve-cache-key.d.ts.map +1 -0
  32. package/dist/compute/solve-cache-key.js +50 -0
  33. package/dist/compute/solve-cache-key.js.map +1 -0
  34. package/dist/compute/solve-cache-single-flight.d.ts +42 -0
  35. package/dist/compute/solve-cache-single-flight.d.ts.map +1 -0
  36. package/dist/compute/solve-cache-single-flight.js +50 -0
  37. package/dist/compute/solve-cache-single-flight.js.map +1 -0
  38. package/dist/compute/solve-pipeline.d.ts +71 -8
  39. package/dist/compute/solve-pipeline.d.ts.map +1 -1
  40. package/dist/compute/solve-pipeline.js +180 -8
  41. package/dist/compute/solve-pipeline.js.map +1 -1
  42. package/dist/definitions/definition-service.d.ts +1 -1
  43. package/dist/definitions/definition-service.d.ts.map +1 -1
  44. package/dist/definitions/definition-service.js +8 -4
  45. package/dist/definitions/definition-service.js.map +1 -1
  46. package/package.json +14 -18
  47. package/dist/access/__tests__/project-access-input.test.d.ts +0 -2
  48. package/dist/access/__tests__/project-access-input.test.d.ts.map +0 -1
  49. package/dist/access/__tests__/project-access-input.test.js +0 -146
  50. package/dist/access/__tests__/project-access-input.test.js.map +0 -1
  51. package/dist/compute/__tests__/client-cache.test.d.ts +0 -11
  52. package/dist/compute/__tests__/client-cache.test.d.ts.map +0 -1
  53. package/dist/compute/__tests__/client-cache.test.js +0 -200
  54. package/dist/compute/__tests__/client-cache.test.js.map +0 -1
  55. package/dist/compute/__tests__/rate-limit.test.d.ts +0 -2
  56. package/dist/compute/__tests__/rate-limit.test.d.ts.map +0 -1
  57. package/dist/compute/__tests__/rate-limit.test.js +0 -98
  58. package/dist/compute/__tests__/rate-limit.test.js.map +0 -1
  59. package/dist/compute/__tests__/remote-definition.test.d.ts +0 -11
  60. package/dist/compute/__tests__/remote-definition.test.d.ts.map +0 -1
  61. package/dist/compute/__tests__/remote-definition.test.js +0 -114
  62. package/dist/compute/__tests__/remote-definition.test.js.map +0 -1
  63. package/dist/compute/__tests__/safe-url.test.d.ts +0 -2
  64. package/dist/compute/__tests__/safe-url.test.d.ts.map +0 -1
  65. package/dist/compute/__tests__/safe-url.test.js +0 -71
  66. package/dist/compute/__tests__/safe-url.test.js.map +0 -1
  67. package/dist/compute/__tests__/solve-pipeline.test.d.ts +0 -11
  68. package/dist/compute/__tests__/solve-pipeline.test.d.ts.map +0 -1
  69. package/dist/compute/__tests__/solve-pipeline.test.js +0 -292
  70. package/dist/compute/__tests__/solve-pipeline.test.js.map +0 -1
  71. package/dist/compute/__tests__/transform-input.test.d.ts +0 -14
  72. package/dist/compute/__tests__/transform-input.test.d.ts.map +0 -1
  73. package/dist/compute/__tests__/transform-input.test.js +0 -120
  74. package/dist/compute/__tests__/transform-input.test.js.map +0 -1
  75. package/dist/definitions/__tests__/load-for-render.test.d.ts +0 -8
  76. package/dist/definitions/__tests__/load-for-render.test.d.ts.map +0 -1
  77. package/dist/definitions/__tests__/load-for-render.test.js +0 -196
  78. package/dist/definitions/__tests__/load-for-render.test.js.map +0 -1
  79. package/dist/definitions/__tests__/schema-extraction.test.d.ts +0 -11
  80. package/dist/definitions/__tests__/schema-extraction.test.d.ts.map +0 -1
  81. package/dist/definitions/__tests__/schema-extraction.test.js +0 -115
  82. package/dist/definitions/__tests__/schema-extraction.test.js.map +0 -1
  83. package/dist/http/__tests__/body-size.test.d.ts +0 -2
  84. package/dist/http/__tests__/body-size.test.d.ts.map +0 -1
  85. package/dist/http/__tests__/body-size.test.js +0 -24
  86. package/dist/http/__tests__/body-size.test.js.map +0 -1
  87. package/dist/http/__tests__/route-classifier.test.d.ts +0 -2
  88. package/dist/http/__tests__/route-classifier.test.d.ts.map +0 -1
  89. package/dist/http/__tests__/route-classifier.test.js +0 -54
  90. package/dist/http/__tests__/route-classifier.test.js.map +0 -1
  91. package/dist/http/__tests__/safe-redirect.test.d.ts +0 -2
  92. package/dist/http/__tests__/safe-redirect.test.d.ts.map +0 -1
  93. package/dist/http/__tests__/safe-redirect.test.js +0 -44
  94. package/dist/http/__tests__/safe-redirect.test.js.map +0 -1
  95. package/dist/http/__tests__/security-headers.test.d.ts +0 -2
  96. package/dist/http/__tests__/security-headers.test.d.ts.map +0 -1
  97. package/dist/http/__tests__/security-headers.test.js +0 -24
  98. package/dist/http/__tests__/security-headers.test.js.map +0 -1
  99. package/dist/ops/__tests__/semver.test.d.ts +0 -2
  100. package/dist/ops/__tests__/semver.test.d.ts.map +0 -1
  101. package/dist/ops/__tests__/semver.test.js +0 -38
  102. package/dist/ops/__tests__/semver.test.js.map +0 -1
  103. package/dist/providers/__tests__/create-selva-providers.test.d.ts +0 -7
  104. package/dist/providers/__tests__/create-selva-providers.test.d.ts.map +0 -1
  105. package/dist/providers/__tests__/create-selva-providers.test.js +0 -135
  106. package/dist/providers/__tests__/create-selva-providers.test.js.map +0 -1
  107. package/dist/tokens/__tests__/token-codec.test.d.ts +0 -2
  108. package/dist/tokens/__tests__/token-codec.test.d.ts.map +0 -1
  109. package/dist/tokens/__tests__/token-codec.test.js +0 -50
  110. package/dist/tokens/__tests__/token-codec.test.js.map +0 -1
  111. package/src/access/__tests__/project-access-input.test.ts +0 -175
  112. package/src/access/index.ts +0 -9
  113. package/src/access/project-access-input.ts +0 -145
  114. package/src/compute/__tests__/client-cache.test.ts +0 -224
  115. package/src/compute/__tests__/rate-limit.test.ts +0 -106
  116. package/src/compute/__tests__/remote-definition.test.ts +0 -140
  117. package/src/compute/__tests__/safe-url.test.ts +0 -72
  118. package/src/compute/__tests__/solve-pipeline.test.ts +0 -341
  119. package/src/compute/__tests__/transform-input.test.ts +0 -162
  120. package/src/compute/client-cache.ts +0 -300
  121. package/src/compute/index.ts +0 -48
  122. package/src/compute/limits.ts +0 -159
  123. package/src/compute/rate-limit.ts +0 -110
  124. package/src/compute/remote-definition.ts +0 -149
  125. package/src/compute/safe-url.ts +0 -186
  126. package/src/compute/solve-pipeline.ts +0 -339
  127. package/src/compute/transform-input.ts +0 -66
  128. package/src/definitions/__tests__/load-for-render.test.ts +0 -244
  129. package/src/definitions/__tests__/schema-extraction.test.ts +0 -137
  130. package/src/definitions/definition-service.ts +0 -243
  131. package/src/definitions/index.ts +0 -22
  132. package/src/definitions/load-for-render.ts +0 -272
  133. package/src/definitions/schema-extraction.ts +0 -117
  134. package/src/errors/SentryErrorReporter.ts +0 -88
  135. package/src/errors/index.ts +0 -3
  136. package/src/http/__tests__/body-size.test.ts +0 -27
  137. package/src/http/__tests__/route-classifier.test.ts +0 -60
  138. package/src/http/__tests__/safe-redirect.test.ts +0 -47
  139. package/src/http/__tests__/security-headers.test.ts +0 -29
  140. package/src/http/body-size.ts +0 -24
  141. package/src/http/index.ts +0 -10
  142. package/src/http/redirect.ts +0 -16
  143. package/src/http/route-classifier.ts +0 -74
  144. package/src/http/security-headers.ts +0 -42
  145. package/src/index.ts +0 -27
  146. package/src/ops/__tests__/semver.test.ts +0 -42
  147. package/src/ops/index.ts +0 -3
  148. package/src/ops/semver.ts +0 -60
  149. package/src/providers/__tests__/create-selva-providers.test.ts +0 -172
  150. package/src/providers/__tests__/fixtures/override-config.mjs +0 -8
  151. package/src/providers/create-selva-providers.ts +0 -241
  152. package/src/providers/index.ts +0 -12
  153. package/src/tokens/__tests__/token-codec.test.ts +0 -63
  154. package/src/tokens/index.ts +0 -8
  155. package/src/tokens/token-codec.ts +0 -86
@@ -1,196 +0,0 @@
1
- /**
2
- * Tests for `createDefinitionLoader` (K4) — version resolution, error
3
- * classification, and the ADR 0005 schema-staleness behavior: a cached schema
4
- * is used only at the app's current format version; anything else re-extracts
5
- * from compute and persists back (best-effort, current-version only).
6
- */
7
- import { describe, it, expect, vi, beforeEach } from 'vitest';
8
- import { UI_SCHEMA_VERSION } from '@selvajs/schemas';
9
- import { createDefinitionLoader, DefinitionLoadError } from '../load-for-render.js';
10
- const ctx = { userId: 'user-1' };
11
- function uiSchema(version, inputs = []) {
12
- return {
13
- id: 'schema-1',
14
- name: 'Test',
15
- schemaVersion: version,
16
- inputs,
17
- outputs: [],
18
- layout: { type: 'tabbed', tabs: [] }
19
- };
20
- }
21
- const record = {
22
- guid: 'def-1',
23
- projectId: 'proj-1',
24
- computeServerId: null,
25
- liveVersionId: 'v-live',
26
- draftVersionId: 'v-draft'
27
- };
28
- function version(overrides = {}) {
29
- return {
30
- id: 'v-live',
31
- definitionId: 'def-1',
32
- versionNumber: 1,
33
- fileExt: 'gh',
34
- fileKey: 'definitions/def-1/versions/v1.gh',
35
- uploadedBy: 'user-1',
36
- uploadedAt: '2026-07-01T00:00:00Z',
37
- ...overrides
38
- };
39
- }
40
- const computeServer = { id: 'srv-1', serverUrl: 'http://c.example' };
41
- function makeDeps(overrides = {}) {
42
- const getIO = vi.fn(async () => ({ inputs: [{ id: 'a', default: 42 }], outputs: [] }));
43
- const deps = {
44
- storage: { get: vi.fn(async () => new Uint8Array([1, 2, 3])) },
45
- definitions: {
46
- getVersion: vi.fn(async () => version()),
47
- setVersionSchema: vi.fn(async () => { })
48
- },
49
- projects: { getProject: vi.fn(async () => ({ id: 'proj-1', orgId: 'org-1' })) },
50
- resolveServer: vi.fn(async () => computeServer),
51
- getClient: vi.fn(async () => ({ client: { getIO, getRawIO: vi.fn() } })),
52
- fetchSchema: vi.fn(async () => uiSchema(UI_SCHEMA_VERSION, [{ id: 'a' }])),
53
- onWarn: vi.fn(),
54
- ...overrides
55
- };
56
- return {
57
- deps: deps,
58
- mocks: deps,
59
- getIO
60
- };
61
- }
62
- async function flushMicrotasks() {
63
- await new Promise((resolve) => setTimeout(resolve, 0));
64
- }
65
- describe('schema cache staleness (ADR 0005)', () => {
66
- it('uses the cached schema when its version matches, without re-extracting or persisting', async () => {
67
- const cached = uiSchema(UI_SCHEMA_VERSION, [{ id: 'a' }]);
68
- const { deps, mocks } = makeDeps();
69
- mocks.definitions.getVersion.mockResolvedValue(version({ schema: cached }));
70
- const result = await createDefinitionLoader(deps)(ctx, record, 'live');
71
- expect(mocks.fetchSchema).not.toHaveBeenCalled();
72
- expect(mocks.definitions.setVersionSchema).not.toHaveBeenCalled();
73
- // Compute defaults are merged into the cached schema's inputs.
74
- expect(result.schema.inputs[0].default).toBe(42);
75
- });
76
- it('re-extracts and persists when the cached schema is at an older format version', async () => {
77
- const { deps, mocks } = makeDeps();
78
- mocks.definitions.getVersion.mockResolvedValue(version({ schema: uiSchema('2.10.0') }));
79
- await createDefinitionLoader(deps)(ctx, record, 'live');
80
- await flushMicrotasks();
81
- expect(mocks.fetchSchema).toHaveBeenCalledTimes(1);
82
- expect(mocks.definitions.setVersionSchema).toHaveBeenCalledWith(ctx, 'v-live', expect.objectContaining({ schemaVersion: UI_SCHEMA_VERSION }));
83
- });
84
- it('re-extracts and persists when no schema is cached (pre-caching row)', async () => {
85
- const { deps, mocks } = makeDeps();
86
- mocks.definitions.getVersion.mockResolvedValue(version({ schema: undefined }));
87
- await createDefinitionLoader(deps)(ctx, record, 'live');
88
- await flushMicrotasks();
89
- expect(mocks.fetchSchema).toHaveBeenCalledTimes(1);
90
- expect(mocks.definitions.setVersionSchema).toHaveBeenCalledTimes(1);
91
- });
92
- it('does NOT persist a re-extracted schema that is still not at the current version', async () => {
93
- // Compute plugin behind the app: re-extraction yields an older format.
94
- const { deps, mocks } = makeDeps({
95
- fetchSchema: vi.fn(async () => uiSchema('2.10.0'))
96
- });
97
- mocks.definitions.getVersion.mockResolvedValue(version({ schema: undefined }));
98
- const result = await createDefinitionLoader(deps)(ctx, record, 'live');
99
- await flushMicrotasks();
100
- expect(mocks.definitions.setVersionSchema).not.toHaveBeenCalled();
101
- // The older schema still renders (older shapes only lack optional additions).
102
- expect(result.schema.schemaVersion).toBe('2.10.0');
103
- });
104
- it('a failed persist warns but does not fail the render', async () => {
105
- const { deps, mocks } = makeDeps();
106
- mocks.definitions.getVersion.mockResolvedValue(version({ schema: undefined }));
107
- mocks.definitions.setVersionSchema.mockRejectedValue(new Error('RLS: not allowed'));
108
- const result = await createDefinitionLoader(deps)(ctx, record, 'live');
109
- await flushMicrotasks();
110
- expect(result.schema.schemaVersion).toBe(UI_SCHEMA_VERSION);
111
- expect(mocks.onWarn).toHaveBeenCalledWith(expect.stringContaining('cache refresh failed'));
112
- });
113
- });
114
- describe('version resolution', () => {
115
- it('resolves the draft pointer for the draft channel', async () => {
116
- const { deps, mocks } = makeDeps();
117
- mocks.definitions.getVersion.mockResolvedValue(version({ id: 'v-draft' }));
118
- await createDefinitionLoader(deps)(ctx, record, 'draft');
119
- expect(mocks.definitions.getVersion).toHaveBeenCalledWith(ctx, 'v-draft');
120
- });
121
- it('an explicit versionId wins over the channel pointer', async () => {
122
- const { deps, mocks } = makeDeps();
123
- mocks.definitions.getVersion.mockResolvedValue(version({ id: 'v-7' }));
124
- await createDefinitionLoader(deps)(ctx, record, 'live', 'v-7');
125
- expect(mocks.definitions.getVersion).toHaveBeenCalledWith(ctx, 'v-7');
126
- });
127
- it("rejects a version that belongs to another definition ('data')", async () => {
128
- const { deps, mocks } = makeDeps();
129
- mocks.definitions.getVersion.mockResolvedValue(version({ definitionId: 'other-def' }));
130
- await expect(createDefinitionLoader(deps)(ctx, record, 'live')).rejects.toMatchObject({
131
- name: 'DefinitionLoadError',
132
- kind: 'data'
133
- });
134
- });
135
- });
136
- describe('error classification', () => {
137
- it("no pointer for the channel → 'data'", async () => {
138
- const { deps } = makeDeps();
139
- const bare = { ...record, liveVersionId: null };
140
- await expect(createDefinitionLoader(deps)(ctx, bare, 'live')).rejects.toMatchObject({
141
- kind: 'data'
142
- });
143
- });
144
- it("missing blob → 'data'", async () => {
145
- const { deps, mocks } = makeDeps();
146
- mocks.storage.get.mockResolvedValue(null);
147
- await expect(createDefinitionLoader(deps)(ctx, record, 'live')).rejects.toMatchObject({
148
- kind: 'data'
149
- });
150
- });
151
- it("unresolvable compute server → 'missing-config'", async () => {
152
- const { deps, mocks } = makeDeps();
153
- mocks.resolveServer.mockRejectedValue(new Error('none visible'));
154
- await expect(createDefinitionLoader(deps)(ctx, record, 'live')).rejects.toMatchObject({
155
- kind: 'missing-config'
156
- });
157
- });
158
- it("client connect failure → 'connect'", async () => {
159
- const { deps, mocks } = makeDeps();
160
- mocks.getClient.mockRejectedValue(new Error('ECONNREFUSED'));
161
- await expect(createDefinitionLoader(deps)(ctx, record, 'live')).rejects.toMatchObject({
162
- kind: 'connect'
163
- });
164
- });
165
- it("IO/schema phase failure → 'schema'", async () => {
166
- const { deps, mocks } = makeDeps({
167
- fetchSchema: vi.fn(async () => {
168
- throw new Error('no Schema output');
169
- })
170
- });
171
- mocks.definitions.getVersion.mockResolvedValue(version({ schema: undefined }));
172
- const err = await createDefinitionLoader(deps)(ctx, record, 'live').catch((e) => e);
173
- expect(err).toBeInstanceOf(DefinitionLoadError);
174
- expect(err.kind).toBe('schema');
175
- });
176
- });
177
- describe('compute default merging', () => {
178
- beforeEach(() => vi.clearAllMocks());
179
- it('converts Color defaults to hex', async () => {
180
- const { deps, mocks } = makeDeps({
181
- getClient: vi.fn(async () => ({
182
- client: {
183
- getIO: vi.fn(async () => ({
184
- inputs: [{ id: 'col', paramType: 'Color', default: '255,128,0' }],
185
- outputs: []
186
- })),
187
- getRawIO: vi.fn()
188
- }
189
- }))
190
- });
191
- mocks.definitions.getVersion.mockResolvedValue(version({ schema: uiSchema(UI_SCHEMA_VERSION, [{ id: 'col' }]) }));
192
- const result = await createDefinitionLoader(deps)(ctx, record, 'live');
193
- expect(result.schema.inputs[0].default).toBe('#ff8000');
194
- });
195
- });
196
- //# sourceMappingURL=load-for-render.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"load-for-render.test.js","sourceRoot":"","sources":["../../../src/definitions/__tests__/load-for-render.test.ts"],"names":[],"mappings":"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"}
@@ -1,11 +0,0 @@
1
- /**
2
- * Tests for the compute-schema extraction gate (K4 / ADR 0005).
3
- *
4
- * `fetch` is stubbed per test to script the compute `/grasshopper/schema`
5
- * response. The version-compat gate (`assertSupportedSchemaVersion`) is also
6
- * exercised directly: newer-than-supported must throw 'unsupported', while
7
- * older / missing versions pass (compute's C# migrator emits its own current
8
- * version; older shapes only lack optional additions).
9
- */
10
- export {};
11
- //# sourceMappingURL=schema-extraction.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema-extraction.test.d.ts","sourceRoot":"","sources":["../../../src/definitions/__tests__/schema-extraction.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -1,115 +0,0 @@
1
- /**
2
- * Tests for the compute-schema extraction gate (K4 / ADR 0005).
3
- *
4
- * `fetch` is stubbed per test to script the compute `/grasshopper/schema`
5
- * response. The version-compat gate (`assertSupportedSchemaVersion`) is also
6
- * exercised directly: newer-than-supported must throw 'unsupported', while
7
- * older / missing versions pass (compute's C# migrator emits its own current
8
- * version; older shapes only lack optional additions).
9
- */
10
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
11
- import { UI_SCHEMA_VERSION } from '@selvajs/schemas';
12
- import { fetchSchemaFromCompute, assertSupportedSchemaVersion, SchemaExtractionError } from '../schema-extraction.js';
13
- function schema(version) {
14
- return {
15
- id: 'schema-1',
16
- name: 'Test',
17
- ...(version !== undefined && { schemaVersion: version }),
18
- inputs: [],
19
- outputs: [],
20
- layout: { type: 'tabbed', tabs: [] }
21
- };
22
- }
23
- function bump(version, part) {
24
- const nums = version.split('.').map(Number);
25
- nums[part] += 1;
26
- return nums.join('.');
27
- }
28
- const server = {
29
- id: 'srv-1',
30
- serverUrl: 'http://compute.example.com',
31
- apiKey: 'secret'
32
- };
33
- describe('assertSupportedSchemaVersion', () => {
34
- it('passes the current version', () => {
35
- expect(() => assertSupportedSchemaVersion(schema(UI_SCHEMA_VERSION))).not.toThrow();
36
- });
37
- it('passes older versions (older shapes only lack optional additions)', () => {
38
- expect(() => assertSupportedSchemaVersion(schema('1.0.0'))).not.toThrow();
39
- expect(() => assertSupportedSchemaVersion(schema('2.0.0'))).not.toThrow();
40
- });
41
- it('passes a schema without a version (pre-2.12.0 plugin)', () => {
42
- expect(() => assertSupportedSchemaVersion(schema())).not.toThrow();
43
- });
44
- it.each([
45
- ['major', 0],
46
- ['minor', 1],
47
- ['patch', 2]
48
- ])('throws unsupported for a newer %s version', (_label, part) => {
49
- const newer = bump(UI_SCHEMA_VERSION, part);
50
- try {
51
- assertSupportedSchemaVersion(schema(newer));
52
- expect.unreachable('should have thrown');
53
- }
54
- catch (err) {
55
- expect(err).toBeInstanceOf(SchemaExtractionError);
56
- expect(err.kind).toBe('unsupported');
57
- expect(err.message).toContain(newer);
58
- expect(err.message).toContain(UI_SCHEMA_VERSION);
59
- }
60
- });
61
- it('passes an unparseable version string (fail open — invalid is not "newer")', () => {
62
- expect(() => assertSupportedSchemaVersion(schema('abc'))).not.toThrow();
63
- });
64
- });
65
- describe('fetchSchemaFromCompute', () => {
66
- let fetchMock;
67
- beforeEach(() => {
68
- fetchMock = vi.fn();
69
- vi.stubGlobal('fetch', fetchMock);
70
- });
71
- afterEach(() => {
72
- vi.unstubAllGlobals();
73
- });
74
- function computeResponse(schemas) {
75
- // Compute wraps results with PascalCase keys.
76
- return new Response(JSON.stringify([{ FileName: 'definition.gh', Schemas: schemas }]), {
77
- status: 200,
78
- headers: { 'content-type': 'application/json' }
79
- });
80
- }
81
- it('extracts the first schema and sends the API key header', async () => {
82
- fetchMock.mockResolvedValue(computeResponse([schema(UI_SCHEMA_VERSION)]));
83
- const result = await fetchSchemaFromCompute(new Uint8Array([1]), server);
84
- expect(result.id).toBe('schema-1');
85
- const [url, init] = fetchMock.mock.calls[0];
86
- expect(url).toBe('http://compute.example.com/grasshopper/schema');
87
- expect(init.headers['RhinoComputeKey']).toBe('secret');
88
- });
89
- it('throws unreachable when the network request fails', async () => {
90
- fetchMock.mockRejectedValue(new Error('ECONNREFUSED'));
91
- await expect(fetchSchemaFromCompute(new Uint8Array([1]), server)).rejects.toMatchObject({
92
- name: 'SchemaExtractionError',
93
- kind: 'unreachable'
94
- });
95
- });
96
- it('throws unreachable on a non-OK status', async () => {
97
- fetchMock.mockResolvedValue(new Response('nope', { status: 500 }));
98
- await expect(fetchSchemaFromCompute(new Uint8Array([1]), server)).rejects.toMatchObject({
99
- kind: 'unreachable'
100
- });
101
- });
102
- it('throws invalid when the definition yields no schemas', async () => {
103
- fetchMock.mockResolvedValue(computeResponse([]));
104
- await expect(fetchSchemaFromCompute(new Uint8Array([1]), server)).rejects.toMatchObject({
105
- kind: 'invalid'
106
- });
107
- });
108
- it('applies the version gate to the extracted schema', async () => {
109
- fetchMock.mockResolvedValue(computeResponse([schema(bump(UI_SCHEMA_VERSION, 1))]));
110
- await expect(fetchSchemaFromCompute(new Uint8Array([1]), server)).rejects.toMatchObject({
111
- kind: 'unsupported'
112
- });
113
- });
114
- });
115
- //# sourceMappingURL=schema-extraction.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema-extraction.test.js","sourceRoot":"","sources":["../../../src/definitions/__tests__/schema-extraction.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=body-size.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"body-size.test.d.ts","sourceRoot":"","sources":["../../../src/http/__tests__/body-size.test.ts"],"names":[],"mappings":""}
@@ -1,24 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { declaredBodySizeExceeds } from '../body-size.js';
3
- function headersWith(contentLength) {
4
- const h = new Headers();
5
- if (contentLength !== undefined)
6
- h.set('content-length', contentLength);
7
- return h;
8
- }
9
- describe('declaredBodySizeExceeds', () => {
10
- it('flags a declared size over the limit', () => {
11
- expect(declaredBodySizeExceeds(headersWith('1001'), 1000)).toBe(true);
12
- });
13
- it('passes a declared size at or under the limit', () => {
14
- expect(declaredBodySizeExceeds(headersWith('1000'), 1000)).toBe(false);
15
- expect(declaredBodySizeExceeds(headersWith('0'), 1000)).toBe(false);
16
- });
17
- it('passes when Content-Length is absent (chunked transfer — global limit is the backstop)', () => {
18
- expect(declaredBodySizeExceeds(headersWith(), 1000)).toBe(false);
19
- });
20
- it('passes a non-numeric Content-Length rather than throwing', () => {
21
- expect(declaredBodySizeExceeds(headersWith('not-a-number'), 1000)).toBe(false);
22
- });
23
- });
24
- //# sourceMappingURL=body-size.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"body-size.test.js","sourceRoot":"","sources":["../../../src/http/__tests__/body-size.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,SAAS,WAAW,CAAC,aAAsB;IAC1C,MAAM,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;IACxB,IAAI,aAAa,KAAK,SAAS;QAAE,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;IACxE,OAAO,CAAC,CAAC;AACV,CAAC;AAED,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,uBAAuB,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACvD,MAAM,CAAC,uBAAuB,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,CAAC,uBAAuB,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wFAAwF,EAAE,GAAG,EAAE;QACjG,MAAM,CAAC,uBAAuB,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QACnE,MAAM,CAAC,uBAAuB,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=route-classifier.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"route-classifier.test.d.ts","sourceRoot":"","sources":["../../../src/http/__tests__/route-classifier.test.ts"],"names":[],"mappings":""}
@@ -1,54 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { createRouteClassifier } from '../route-classifier.js';
3
- // Generic values — the consuming app's actual route policy is pinned by its
4
- // own test suite; these cover the classifier mechanics.
5
- const classifier = createRouteClassifier({
6
- publicPages: ['/', '/login'],
7
- publicPrefixes: ['/auth/', '/logout'],
8
- publicApis: ['/api/health'],
9
- selfGatingPrefix: '/api/files/',
10
- staticPrefixes: ['/_app/', '/favicon/'],
11
- staticPaths: ['/favicon.svg', '/robots.txt']
12
- });
13
- describe('createRouteClassifier', () => {
14
- it('classifies exact pages, API allowlist, prefixes, and self-gating as public', () => {
15
- for (const path of [
16
- '/',
17
- '/login',
18
- '/api/health',
19
- '/auth/oauth/callback',
20
- '/logout',
21
- '/api/files/orgs/abc/logo.webp'
22
- ]) {
23
- expect(classifier.isPublicRoute(path)).toBe(true);
24
- }
25
- });
26
- it('denies by default — unknown routes are gated', () => {
27
- for (const path of ['/library', '/api/projects', '/billing', '/whatever']) {
28
- expect(classifier.isPublicRoute(path)).toBe(false);
29
- }
30
- });
31
- it('exact-match pages do not admit siblings via prefix', () => {
32
- expect(classifier.isPublicRoute('/login-other')).toBe(false);
33
- expect(classifier.isPublicRoute('/api/healthz')).toBe(false);
34
- });
35
- it('self-gating prefix is not a loose match', () => {
36
- expect(classifier.isSelfGatingApiRoute('/api/files/x')).toBe(true);
37
- expect(classifier.isSelfGatingApiRoute('/api/filesX/y')).toBe(false);
38
- expect(classifier.isSelfGatingApiRoute('/api/projects')).toBe(false);
39
- });
40
- it('recognizes static assets by prefix and exact path', () => {
41
- expect(classifier.isStaticAsset('/_app/immutable/x.js')).toBe(true);
42
- expect(classifier.isStaticAsset('/favicon/16.png')).toBe(true);
43
- expect(classifier.isStaticAsset('/robots.txt')).toBe(true);
44
- expect(classifier.isStaticAsset('/favicon-other.png')).toBe(false);
45
- expect(classifier.isStaticAsset('/login')).toBe(false);
46
- });
47
- it('every allowlist is optional — an empty config gates everything', () => {
48
- const closed = createRouteClassifier({});
49
- expect(closed.isPublicRoute('/')).toBe(false);
50
- expect(closed.isStaticAsset('/robots.txt')).toBe(false);
51
- expect(closed.isSelfGatingApiRoute('/api/files/x')).toBe(false);
52
- });
53
- });
54
- //# sourceMappingURL=route-classifier.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"route-classifier.test.js","sourceRoot":"","sources":["../../../src/http/__tests__/route-classifier.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=safe-redirect.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"safe-redirect.test.d.ts","sourceRoot":"","sources":["../../../src/http/__tests__/safe-redirect.test.ts"],"names":[],"mappings":""}
@@ -1,44 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { safeRedirectTarget } from '../redirect.js';
3
- /**
4
- * `safeRedirectTarget` is the post-login redirect validator. The point of
5
- * the function is to reject *exactly* the values that would otherwise
6
- * smuggle an external host into a `redirect(303, …)` call:
7
- * protocol-relative URLs (`//evil.com`) and back-slash variants some
8
- * browsers normalize as a path separator. Each row below is one such case.
9
- */
10
- describe('safeRedirectTarget', () => {
11
- it.each([
12
- ['/foo', '/foo'],
13
- ['/foo/bar', '/foo/bar'],
14
- ['/foo?x=1', '/foo?x=1'],
15
- ['/foo#frag', '/foo#frag'],
16
- ['/a', '/a'] // shortest valid path: `/` + non-`/` char
17
- ])('accepts same-origin path %j → %j', (input, expected) => {
18
- expect(safeRedirectTarget(input, '/fallback')).toBe(expected);
19
- });
20
- it.each([
21
- ['//evil.com', 'protocol-relative URL'],
22
- ['//evil.com/path', 'protocol-relative URL with path'],
23
- ['/\\evil.com', 'back-slash bypass'],
24
- ['https://evil.com', 'absolute URL'],
25
- ['http://evil.com', 'absolute URL'],
26
- ['javascript:alert(1)', 'javascript: scheme'],
27
- ['', 'empty string'],
28
- ['/', 'lone slash (length<2)'],
29
- ['evil.com', 'no leading slash'],
30
- ['./relative', 'relative path']
31
- ])('rejects %j (%s)', (input) => {
32
- expect(safeRedirectTarget(input, '/fallback')).toBe('/fallback');
33
- });
34
- it.each([null, undefined])('rejects %j', (input) => {
35
- expect(safeRedirectTarget(input, '/fallback')).toBe('/fallback');
36
- });
37
- it('passes through arbitrary non-string types as fallback', () => {
38
- // safeRedirectTarget's signature is `string | null | undefined`, but
39
- // some call sites get `unknown` from FormData — make sure we don't
40
- // throw on a stray non-string.
41
- expect(safeRedirectTarget(42, '/fallback')).toBe('/fallback');
42
- });
43
- });
44
- //# sourceMappingURL=safe-redirect.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"safe-redirect.test.js","sourceRoot":"","sources":["../../../src/http/__tests__/safe-redirect.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD;;;;;;GAMG;AACH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,IAAI,CAAC;QACP,CAAC,MAAM,EAAE,MAAM,CAAC;QAChB,CAAC,UAAU,EAAE,UAAU,CAAC;QACxB,CAAC,UAAU,EAAE,UAAU,CAAC;QACxB,CAAC,WAAW,EAAE,WAAW,CAAC;QAC1B,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,0CAA0C;KACvD,CAAC,CAAC,kCAAkC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QAC1D,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC;QACP,CAAC,YAAY,EAAE,uBAAuB,CAAC;QACvC,CAAC,iBAAiB,EAAE,iCAAiC,CAAC;QACtD,CAAC,aAAa,EAAE,mBAAmB,CAAC;QACpC,CAAC,kBAAkB,EAAE,cAAc,CAAC;QACpC,CAAC,iBAAiB,EAAE,cAAc,CAAC;QACnC,CAAC,qBAAqB,EAAE,oBAAoB,CAAC;QAC7C,CAAC,EAAE,EAAE,cAAc,CAAC;QACpB,CAAC,GAAG,EAAE,uBAAuB,CAAC;QAC9B,CAAC,UAAU,EAAE,kBAAkB,CAAC;QAChC,CAAC,YAAY,EAAE,eAAe,CAAC;KAC/B,CAAC,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE;QAC/B,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE;QAClD,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAChE,qEAAqE;QACrE,mEAAmE;QACnE,+BAA+B;QAC/B,MAAM,CAAC,kBAAkB,CAAC,EAAuB,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=security-headers.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"security-headers.test.d.ts","sourceRoot":"","sources":["../../../src/http/__tests__/security-headers.test.ts"],"names":[],"mappings":""}
@@ -1,24 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { applySecurityHeaders } from '../security-headers.js';
3
- describe('applySecurityHeaders', () => {
4
- it('sets the baseline hardening headers and returns the same response', () => {
5
- const response = new Response('ok');
6
- const out = applySecurityHeaders(response, { hsts: false });
7
- expect(out).toBe(response);
8
- expect(out.headers.get('X-Content-Type-Options')).toBe('nosniff');
9
- expect(out.headers.get('Referrer-Policy')).toBe('strict-origin-when-cross-origin');
10
- expect(out.headers.get('Permissions-Policy')).toContain('camera=()');
11
- });
12
- it('sets HSTS only when asked (production)', () => {
13
- const dev = applySecurityHeaders(new Response('ok'), { hsts: false });
14
- expect(dev.headers.get('Strict-Transport-Security')).toBeNull();
15
- const prod = applySecurityHeaders(new Response('ok'), { hsts: true });
16
- expect(prod.headers.get('Strict-Transport-Security')).toBe('max-age=31536000; includeSubDomains');
17
- });
18
- it('never sets CSP or frame headers (iframe embedding is a product requirement)', () => {
19
- const out = applySecurityHeaders(new Response('ok'), { hsts: true });
20
- expect(out.headers.get('Content-Security-Policy')).toBeNull();
21
- expect(out.headers.get('X-Frame-Options')).toBeNull();
22
- });
23
- });
24
- //# sourceMappingURL=security-headers.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"security-headers.test.js","sourceRoot":"","sources":["../../../src/http/__tests__/security-headers.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC5E,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,oBAAoB,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5D,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QACnF,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QACjD,MAAM,GAAG,GAAG,oBAAoB,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACtE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QAEhE,MAAM,IAAI,GAAG,oBAAoB,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACtE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC,CAAC,IAAI,CACzD,qCAAqC,CACrC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACtF,MAAM,GAAG,GAAG,oBAAoB,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC9D,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=semver.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"semver.test.d.ts","sourceRoot":"","sources":["../../../src/ops/__tests__/semver.test.ts"],"names":[],"mappings":""}
@@ -1,38 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { isNewer } from '../semver.js';
3
- describe('isNewer', () => {
4
- it('detects a newer patch / minor / major', () => {
5
- expect(isNewer('4.3.2', '4.3.1')).toBe(true);
6
- expect(isNewer('4.4.0', '4.3.9')).toBe(true);
7
- expect(isNewer('5.0.0', '4.9.9')).toBe(true);
8
- });
9
- it('returns false for same or older versions', () => {
10
- expect(isNewer('4.3.1', '4.3.1')).toBe(false);
11
- expect(isNewer('4.3.0', '4.3.1')).toBe(false);
12
- expect(isNewer('3.9.9', '4.0.0')).toBe(false);
13
- });
14
- it('ignores pre-release suffixes on the stable channel (only stable bumps surface)', () => {
15
- expect(isNewer('4.3.2-beta.1', '4.3.1')).toBe(true);
16
- expect(isNewer('4.3.1-beta.1', '4.3.1')).toBe(false);
17
- // Explicit stable channel matches the default.
18
- expect(isNewer('4.3.1-beta.1', '4.3.1', 'stable')).toBe(false);
19
- });
20
- it('orders pre-releases on the beta channel', () => {
21
- // Successive betas of the same core.
22
- expect(isNewer('4.6.0-beta.2', '4.6.0-beta.1', 'beta')).toBe(true);
23
- expect(isNewer('4.6.0-beta.1', '4.6.0-beta.2', 'beta')).toBe(false);
24
- // A newer core beta beats an older stable.
25
- expect(isNewer('4.6.0-beta.1', '4.5.1', 'beta')).toBe(true);
26
- // Stable of a core outranks any beta of the same core (promotion).
27
- expect(isNewer('4.6.0', '4.6.0-beta.9', 'beta')).toBe(true);
28
- expect(isNewer('4.6.0-beta.9', '4.6.0', 'beta')).toBe(false);
29
- // Reverting to an OLDER stable is NOT "newer" — the channel switch, not
30
- // isNewer, is what makes it actionable.
31
- expect(isNewer('4.5.1', '4.6.0-beta.2', 'beta')).toBe(false);
32
- });
33
- it('falls back to a string compare when unparseable', () => {
34
- expect(isNewer('weird', 'weird')).toBe(false);
35
- expect(isNewer('a', 'b')).toBe(true);
36
- });
37
- });
38
- //# sourceMappingURL=semver.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"semver.test.js","sourceRoot":"","sources":["../../../src/ops/__tests__/semver.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACxB,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gFAAgF,EAAE,GAAG,EAAE;QACzF,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpD,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrD,+CAA+C;QAC/C,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QAClD,qCAAqC;QACrC,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnE,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpE,2CAA2C;QAC3C,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,mEAAmE;QACnE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7D,wEAAwE;QACxE,wCAAwC;QACxC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QAC1D,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -1,7 +0,0 @@
1
- /**
2
- * Tests for `createSelvaProviders` (K5) — registry-driven provider selection,
3
- * lazy memoized instantiation, config parsing (flags/branding/tenancy), the
4
- * solve-metrics duck-type pick, and the external config-path override.
5
- */
6
- export {};
7
- //# sourceMappingURL=create-selva-providers.test.d.ts.map