@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.
- package/LICENSE +21 -0
- package/dist/compute/__tests__/client-cache.test.d.ts +11 -0
- package/dist/compute/__tests__/client-cache.test.d.ts.map +1 -0
- package/dist/compute/__tests__/client-cache.test.js +149 -0
- package/dist/compute/__tests__/client-cache.test.js.map +1 -0
- package/dist/compute/__tests__/rate-limit.test.d.ts +2 -0
- package/dist/compute/__tests__/rate-limit.test.d.ts.map +1 -0
- package/dist/compute/__tests__/rate-limit.test.js +62 -0
- package/dist/compute/__tests__/rate-limit.test.js.map +1 -0
- package/dist/compute/__tests__/remote-definition.test.d.ts +11 -0
- package/dist/compute/__tests__/remote-definition.test.d.ts.map +1 -0
- package/dist/compute/__tests__/remote-definition.test.js +114 -0
- package/dist/compute/__tests__/remote-definition.test.js.map +1 -0
- package/dist/compute/__tests__/safe-url.test.d.ts +2 -0
- package/dist/compute/__tests__/safe-url.test.d.ts.map +1 -0
- package/dist/compute/__tests__/safe-url.test.js +71 -0
- package/dist/compute/__tests__/safe-url.test.js.map +1 -0
- package/dist/compute/__tests__/solve-pipeline.test.d.ts +11 -0
- package/dist/compute/__tests__/solve-pipeline.test.d.ts.map +1 -0
- package/dist/compute/__tests__/solve-pipeline.test.js +245 -0
- package/dist/compute/__tests__/solve-pipeline.test.js.map +1 -0
- package/dist/compute/__tests__/transform-input.test.d.ts +14 -0
- package/dist/compute/__tests__/transform-input.test.d.ts.map +1 -0
- package/dist/compute/__tests__/transform-input.test.js +114 -0
- package/dist/compute/__tests__/transform-input.test.js.map +1 -0
- package/dist/compute/client-cache.d.ts +104 -0
- package/dist/compute/client-cache.d.ts.map +1 -0
- package/dist/compute/client-cache.js +147 -0
- package/dist/compute/client-cache.js.map +1 -0
- package/dist/compute/index.d.ts +8 -0
- package/dist/compute/index.d.ts.map +1 -0
- package/dist/compute/index.js +9 -0
- package/dist/compute/index.js.map +1 -0
- package/dist/compute/limits.d.ts +102 -0
- package/dist/compute/limits.d.ts.map +1 -0
- package/dist/compute/limits.js +76 -0
- package/dist/compute/limits.js.map +1 -0
- package/dist/compute/rate-limit.d.ts +49 -0
- package/dist/compute/rate-limit.d.ts.map +1 -0
- package/dist/compute/rate-limit.js +49 -0
- package/dist/compute/rate-limit.js.map +1 -0
- package/dist/compute/remote-definition.d.ts +53 -0
- package/dist/compute/remote-definition.d.ts.map +1 -0
- package/dist/compute/remote-definition.js +110 -0
- package/dist/compute/remote-definition.js.map +1 -0
- package/dist/compute/safe-url.d.ts +15 -0
- package/dist/compute/safe-url.d.ts.map +1 -0
- package/dist/compute/safe-url.js +195 -0
- package/dist/compute/safe-url.js.map +1 -0
- package/dist/compute/solve-pipeline.d.ts +127 -0
- package/dist/compute/solve-pipeline.d.ts.map +1 -0
- package/dist/compute/solve-pipeline.js +195 -0
- package/dist/compute/solve-pipeline.js.map +1 -0
- package/dist/compute/transform-input.d.ts +20 -0
- package/dist/compute/transform-input.d.ts.map +1 -0
- package/dist/compute/transform-input.js +47 -0
- package/dist/compute/transform-input.js.map +1 -0
- package/dist/definitions/__tests__/load-for-render.test.d.ts +8 -0
- package/dist/definitions/__tests__/load-for-render.test.d.ts.map +1 -0
- package/dist/definitions/__tests__/load-for-render.test.js +196 -0
- package/dist/definitions/__tests__/load-for-render.test.js.map +1 -0
- package/dist/definitions/__tests__/schema-extraction.test.d.ts +11 -0
- package/dist/definitions/__tests__/schema-extraction.test.d.ts.map +1 -0
- package/dist/definitions/__tests__/schema-extraction.test.js +115 -0
- package/dist/definitions/__tests__/schema-extraction.test.js.map +1 -0
- package/dist/definitions/definition-service.d.ts +77 -0
- package/dist/definitions/definition-service.d.ts.map +1 -0
- package/dist/definitions/definition-service.js +184 -0
- package/dist/definitions/definition-service.js.map +1 -0
- package/dist/definitions/index.d.ts +4 -0
- package/dist/definitions/index.d.ts.map +1 -0
- package/dist/definitions/index.js +8 -0
- package/dist/definitions/index.js.map +1 -0
- package/dist/definitions/load-for-render.d.ts +61 -0
- package/dist/definitions/load-for-render.d.ts.map +1 -0
- package/dist/definitions/load-for-render.js +165 -0
- package/dist/definitions/load-for-render.js.map +1 -0
- package/dist/definitions/schema-extraction.d.ts +22 -0
- package/dist/definitions/schema-extraction.d.ts.map +1 -0
- package/dist/definitions/schema-extraction.js +89 -0
- package/dist/definitions/schema-extraction.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/__tests__/create-selva-providers.test.d.ts +7 -0
- package/dist/providers/__tests__/create-selva-providers.test.d.ts.map +1 -0
- package/dist/providers/__tests__/create-selva-providers.test.js +135 -0
- package/dist/providers/__tests__/create-selva-providers.test.js.map +1 -0
- package/dist/providers/create-selva-providers.d.ts +53 -0
- package/dist/providers/create-selva-providers.d.ts.map +1 -0
- package/dist/providers/create-selva-providers.js +152 -0
- package/dist/providers/create-selva-providers.js.map +1 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +6 -0
- package/dist/providers/index.js.map +1 -0
- package/package.json +60 -0
- package/src/compute/__tests__/client-cache.test.ts +164 -0
- package/src/compute/__tests__/rate-limit.test.ts +69 -0
- package/src/compute/__tests__/remote-definition.test.ts +140 -0
- package/src/compute/__tests__/safe-url.test.ts +72 -0
- package/src/compute/__tests__/solve-pipeline.test.ts +294 -0
- package/src/compute/__tests__/transform-input.test.ts +155 -0
- package/src/compute/client-cache.ts +278 -0
- package/src/compute/index.ts +48 -0
- package/src/compute/limits.ts +147 -0
- package/src/compute/rate-limit.ts +83 -0
- package/src/compute/remote-definition.ts +149 -0
- package/src/compute/safe-url.ts +186 -0
- package/src/compute/solve-pipeline.ts +324 -0
- package/src/compute/transform-input.ts +52 -0
- package/src/definitions/__tests__/load-for-render.test.ts +244 -0
- package/src/definitions/__tests__/schema-extraction.test.ts +137 -0
- package/src/definitions/definition-service.ts +243 -0
- package/src/definitions/index.ts +22 -0
- package/src/definitions/load-for-render.ts +272 -0
- package/src/definitions/schema-extraction.ts +117 -0
- package/src/index.ts +18 -0
- package/src/providers/__tests__/create-selva-providers.test.ts +172 -0
- package/src/providers/__tests__/fixtures/override-config.mjs +8 -0
- package/src/providers/create-selva-providers.ts +241 -0
- package/src/providers/index.ts +12 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// Shared compute-schema extraction. One implementation used by:
|
|
2
|
+
// - upload routes (validate-and-cache gate — no upload without a valid schema)
|
|
3
|
+
// - the render path (falls back to live extraction for un-cached or stale
|
|
4
|
+
// versions; see load-for-render.ts and ADR 0005)
|
|
5
|
+
// - the temporary solve-time backfill bridge (see the app's specs/SchemaCaching.md)
|
|
6
|
+
//
|
|
7
|
+
// Extraction IS validation: a `.gh` with no valid "Schema" output, or an
|
|
8
|
+
// unreachable compute server, throws here and the caller rejects the upload.
|
|
9
|
+
import { camelcaseKeys } from '@selvajs/compute/core';
|
|
10
|
+
import { UI_SCHEMA_VERSION } from '@selvajs/schemas';
|
|
11
|
+
/** Thrown when compute is reachable but the definition yields no usable schema. */
|
|
12
|
+
export class SchemaExtractionError extends Error {
|
|
13
|
+
kind;
|
|
14
|
+
constructor(kind, message) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.kind = kind;
|
|
17
|
+
this.name = 'SchemaExtractionError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function parseSemver(version) {
|
|
21
|
+
const m = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
|
|
22
|
+
return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Plugin↔app compat gate: reject a schema emitted by a NEWER plugin than this
|
|
26
|
+
* app was built against — its shape may contain constructs the renderer does
|
|
27
|
+
* not know. Older (or missing) versions pass: the compute-side C# migrator
|
|
28
|
+
* always emits its own current version, and an older shape only lacks
|
|
29
|
+
* optional additions.
|
|
30
|
+
*/
|
|
31
|
+
export function assertSupportedSchemaVersion(schema) {
|
|
32
|
+
const version = schema.schemaVersion;
|
|
33
|
+
if (!version)
|
|
34
|
+
return; // pre-2.12.0 plugin — older than the app, fine
|
|
35
|
+
const extracted = parseSemver(version);
|
|
36
|
+
const supported = parseSemver(UI_SCHEMA_VERSION);
|
|
37
|
+
if (!extracted || !supported)
|
|
38
|
+
return;
|
|
39
|
+
const newer = extracted[0] > supported[0] ||
|
|
40
|
+
(extracted[0] === supported[0] &&
|
|
41
|
+
(extracted[1] > supported[1] ||
|
|
42
|
+
(extracted[1] === supported[1] && extracted[2] > supported[2])));
|
|
43
|
+
if (newer) {
|
|
44
|
+
throw new SchemaExtractionError('unsupported', `This definition was authored with a newer Selva plugin (schema format ${version}); ` +
|
|
45
|
+
`this server supports schema format ≤ ${UI_SCHEMA_VERSION}. Update the server, or ` +
|
|
46
|
+
`re-save the definition with a matching plugin version.`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Fetch the UI schema from Rhino Compute's `/grasshopper/schema` endpoint (no
|
|
51
|
+
* solve required). Throws `SchemaExtractionError` so callers can map to the
|
|
52
|
+
* right HTTP status (503 unreachable / 422 invalid or unsupported).
|
|
53
|
+
*/
|
|
54
|
+
export async function fetchSchemaFromCompute(definitionBytes, server) {
|
|
55
|
+
const schemaUrl = new URL('/grasshopper/schema', server.serverUrl).toString();
|
|
56
|
+
const formData = new FormData();
|
|
57
|
+
const blob = new Blob([new Uint8Array(definitionBytes)], { type: 'application/octet-stream' });
|
|
58
|
+
formData.append('file', blob, 'definition.gh');
|
|
59
|
+
const headers = {};
|
|
60
|
+
if (server.apiKey) {
|
|
61
|
+
headers['RhinoComputeKey'] = server.apiKey;
|
|
62
|
+
}
|
|
63
|
+
let response;
|
|
64
|
+
try {
|
|
65
|
+
response = await fetch(schemaUrl, { method: 'POST', headers, body: formData });
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
throw new SchemaExtractionError('unreachable', `Compute server is unreachable: ${err instanceof Error ? err.message : String(err)}`);
|
|
69
|
+
}
|
|
70
|
+
if (!response.ok) {
|
|
71
|
+
throw new SchemaExtractionError('unreachable', `Schema endpoint returned ${response.status}: ${response.statusText}`);
|
|
72
|
+
}
|
|
73
|
+
// Compute returns [{ FileName, Schemas }] with PascalCase wrapper keys only.
|
|
74
|
+
// The schema contents are already camelCase from our C# serializer, so we only
|
|
75
|
+
// need a shallow camelcase per wrapper to normalize FileName→fileName,
|
|
76
|
+
// Schemas→schemas (shallow camelcaseKeys is a no-op on arrays, so each
|
|
77
|
+
// element is normalized individually). deep:true would mangle user-defined
|
|
78
|
+
// option names (e.g. "Display3d" → "display3d").
|
|
79
|
+
const raw = await response.json();
|
|
80
|
+
const results = (Array.isArray(raw) ? raw : [raw]).map((r) => camelcaseKeys(r));
|
|
81
|
+
const schemas = results.flatMap((r) => r.schemas ?? []);
|
|
82
|
+
if (schemas.length === 0) {
|
|
83
|
+
throw new SchemaExtractionError('invalid', 'No schemas found in definition.\n\n' +
|
|
84
|
+
'In Grasshopper, verify a Context Bake component with the output name "Schema" is present and wired to the solver.');
|
|
85
|
+
}
|
|
86
|
+
assertSupportedSchemaVersion(schemas[0]);
|
|
87
|
+
return schemas[0];
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=schema-extraction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-extraction.js","sourceRoot":"","sources":["../../src/definitions/schema-extraction.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,iFAAiF;AACjF,4EAA4E;AAC5E,qDAAqD;AACrD,sFAAsF;AACtF,EAAE;AACF,yEAAyE;AACzE,6EAA6E;AAE7E,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAiB,MAAM,kBAAkB,CAAC;AAGpE,mFAAmF;AACnF,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAE9B;IADjB,YACiB,IAA+C,EAC/D,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,SAAI,GAAJ,IAAI,CAA2C;QAI/D,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACrC,CAAC;CACD;AAED,SAAS,WAAW,CAAC,OAAe;IACnC,MAAM,CAAC,GAAG,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChD,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,4BAA4B,CAAC,MAAgB;IAC5D,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC;IACrC,IAAI,CAAC,OAAO;QAAE,OAAO,CAAC,+CAA+C;IACrE,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,WAAW,CAAC,iBAAiB,CAAC,CAAC;IACjD,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS;QAAE,OAAO;IACrC,MAAM,KAAK,GACV,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;QAC3B,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC;YAC7B,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;gBAC3B,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,IAAI,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,qBAAqB,CAC9B,aAAa,EACb,yEAAyE,OAAO,KAAK;YACpF,wCAAwC,iBAAiB,0BAA0B;YACnF,wDAAwD,CACzD,CAAC;IACH,CAAC;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC3C,eAA2B,EAC3B,MAA2B;IAE3B,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,qBAAqB,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC;IAE9E,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,UAAU,CAAC,eAAe,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,0BAA0B,EAAE,CAAC,CAAC;IAC/F,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,eAAe,CAAC,CAAC;IAE/C,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,iBAAiB,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IAC5C,CAAC;IAED,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACJ,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAChF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM,IAAI,qBAAqB,CAC9B,aAAa,EACb,kCAAkC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACpF,CAAC;IACH,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QAClB,MAAM,IAAI,qBAAqB,CAC9B,aAAa,EACb,4BAA4B,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE,CACrE,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,+EAA+E;IAC/E,uEAAuE;IACvE,uEAAuE;IACvE,2EAA2E;IAC3E,iDAAiD;IACjD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,CAE3E,CAAC;IACJ,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IAExD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,qBAAqB,CAC9B,SAAS,EACT,qCAAqC;YACpC,mHAAmH,CACpH,CAAC;IACH,CAAC;IAED,4BAA4B,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@selvajs/server` — transport-agnostic compute/solve server building blocks
|
|
3
|
+
* for apps built on the Selva engine.
|
|
4
|
+
*
|
|
5
|
+
* The compute stack (limits, per-key rate limiting, SSRF guard, input
|
|
6
|
+
* transform) that used to live inside the `@selvajs/selva` app, extracted so a
|
|
7
|
+
* consuming app can reuse it instead of copying it. Everything here is
|
|
8
|
+
* env-injected (no ambient `$env` / `process.env`) and framework-agnostic.
|
|
9
|
+
*
|
|
10
|
+
* The full compute subsurface is also available at `@selvajs/server/compute`,
|
|
11
|
+
* the definitions slice (DefinitionService, schema extraction/validation,
|
|
12
|
+
* render loader) at `@selvajs/server/definitions`, and the provider wiring
|
|
13
|
+
* (registry-driven `createSelvaProviders`) at `@selvajs/server/providers`.
|
|
14
|
+
*/
|
|
15
|
+
export * from './compute/index.js';
|
|
16
|
+
export * from './definitions/index.js';
|
|
17
|
+
export * from './providers/index.js';
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@selvajs/server` — transport-agnostic compute/solve server building blocks
|
|
3
|
+
* for apps built on the Selva engine.
|
|
4
|
+
*
|
|
5
|
+
* The compute stack (limits, per-key rate limiting, SSRF guard, input
|
|
6
|
+
* transform) that used to live inside the `@selvajs/selva` app, extracted so a
|
|
7
|
+
* consuming app can reuse it instead of copying it. Everything here is
|
|
8
|
+
* env-injected (no ambient `$env` / `process.env`) and framework-agnostic.
|
|
9
|
+
*
|
|
10
|
+
* The full compute subsurface is also available at `@selvajs/server/compute`,
|
|
11
|
+
* the definitions slice (DefinitionService, schema extraction/validation,
|
|
12
|
+
* render loader) at `@selvajs/server/definitions`, and the provider wiring
|
|
13
|
+
* (registry-driven `createSelvaProviders`) at `@selvajs/server/providers`.
|
|
14
|
+
*/
|
|
15
|
+
export * from './compute/index.js';
|
|
16
|
+
export * from './definitions/index.js';
|
|
17
|
+
export * from './providers/index.js';
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-selva-providers.test.d.ts","sourceRoot":"","sources":["../../../src/providers/__tests__/create-selva-providers.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,135 @@
|
|
|
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
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { createSelvaProviders } from '../create-selva-providers.js';
|
|
9
|
+
class FakeData {
|
|
10
|
+
}
|
|
11
|
+
class FakeStorage {
|
|
12
|
+
}
|
|
13
|
+
function makeRegistry() {
|
|
14
|
+
const authLocal = vi.fn(() => ({ name: 'local-auth' }));
|
|
15
|
+
const authSupabase = vi.fn(() => ({ name: 'supabase-auth' }));
|
|
16
|
+
const dataLocal = vi.fn(() => new FakeData());
|
|
17
|
+
const dataSupabase = vi.fn(() => new FakeData());
|
|
18
|
+
const storageLocal = vi.fn(() => new FakeStorage());
|
|
19
|
+
const registry = {
|
|
20
|
+
auth: { local: authLocal, supabase: authSupabase },
|
|
21
|
+
data: { local: dataLocal, supabase: dataSupabase },
|
|
22
|
+
storage: { local: storageLocal }
|
|
23
|
+
};
|
|
24
|
+
return { registry, authLocal, authSupabase, dataLocal, dataSupabase, storageLocal };
|
|
25
|
+
}
|
|
26
|
+
const noBoot = { onBoot: () => { } };
|
|
27
|
+
describe('registry selection', () => {
|
|
28
|
+
it('falls back to "local" for every slot when env is empty', async () => {
|
|
29
|
+
const { registry, authLocal, dataLocal, storageLocal } = makeRegistry();
|
|
30
|
+
const runtime = await createSelvaProviders({}, { registry, ...noBoot });
|
|
31
|
+
runtime.resolve();
|
|
32
|
+
expect(authLocal).toHaveBeenCalledTimes(1);
|
|
33
|
+
expect(dataLocal).toHaveBeenCalledTimes(1);
|
|
34
|
+
expect(storageLocal).toHaveBeenCalledTimes(1);
|
|
35
|
+
});
|
|
36
|
+
it('honors SELVA_*_PROVIDER env choices, case-insensitively', async () => {
|
|
37
|
+
const { registry, authSupabase, dataSupabase } = makeRegistry();
|
|
38
|
+
const runtime = await createSelvaProviders({ SELVA_AUTH_PROVIDER: 'Supabase', SELVA_DATA_PROVIDER: 'SUPABASE' }, { registry, ...noBoot });
|
|
39
|
+
runtime.resolve();
|
|
40
|
+
expect(authSupabase).toHaveBeenCalledTimes(1);
|
|
41
|
+
expect(dataSupabase).toHaveBeenCalledTimes(1);
|
|
42
|
+
});
|
|
43
|
+
it('honors the defaults option over the built-in "local"', async () => {
|
|
44
|
+
const { registry, authSupabase } = makeRegistry();
|
|
45
|
+
const runtime = await createSelvaProviders({}, { registry, defaults: { auth: 'supabase' }, ...noBoot });
|
|
46
|
+
runtime.resolve();
|
|
47
|
+
expect(authSupabase).toHaveBeenCalledTimes(1);
|
|
48
|
+
});
|
|
49
|
+
it('rejects an unknown choice, listing the registered names', async () => {
|
|
50
|
+
const { registry } = makeRegistry();
|
|
51
|
+
const runtime = await createSelvaProviders({ SELVA_AUTH_PROVIDER: 'okta' }, { registry, ...noBoot });
|
|
52
|
+
expect(() => runtime.resolve()).toThrow(/SELVA_AUTH_PROVIDER="okta".*local \| supabase/);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
describe('laziness and memoization', () => {
|
|
56
|
+
it('does not instantiate providers until resolve() is called', async () => {
|
|
57
|
+
const { registry, authLocal } = makeRegistry();
|
|
58
|
+
await createSelvaProviders({}, { registry, ...noBoot });
|
|
59
|
+
expect(authLocal).not.toHaveBeenCalled();
|
|
60
|
+
});
|
|
61
|
+
it('instantiates once and logs the boot summary once across repeated resolves', async () => {
|
|
62
|
+
const { registry, authLocal } = makeRegistry();
|
|
63
|
+
const onBoot = vi.fn();
|
|
64
|
+
const runtime = await createSelvaProviders({}, { registry, onBoot });
|
|
65
|
+
runtime.resolve();
|
|
66
|
+
runtime.resolve();
|
|
67
|
+
runtime.flag('ENABLE_SHARING');
|
|
68
|
+
expect(authLocal).toHaveBeenCalledTimes(1);
|
|
69
|
+
expect(onBoot).toHaveBeenCalledTimes(1);
|
|
70
|
+
expect(onBoot.mock.calls[0][0]).toContain('auth=local-auth');
|
|
71
|
+
expect(onBoot.mock.calls[0][0]).toContain('data=FakeData');
|
|
72
|
+
expect(onBoot.mock.calls[0][0]).toContain('tenancy=single');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe('config parsing', () => {
|
|
76
|
+
it('parses flags from SELVA_FLAG_* (omitted → false)', async () => {
|
|
77
|
+
const { registry } = makeRegistry();
|
|
78
|
+
const runtime = await createSelvaProviders({ SELVA_FLAG_ENABLE_SHARING: 'true', SELVA_FLAG_ALLOW_ORG_CREATION: 'no' }, { registry, ...noBoot });
|
|
79
|
+
expect(runtime.flag('ENABLE_SHARING')).toBe(true);
|
|
80
|
+
expect(runtime.flag('ALLOW_ORG_CREATION')).toBe(false);
|
|
81
|
+
expect(runtime.flag('ALLOW_CROSS_ORG_PUBLIC')).toBe(false);
|
|
82
|
+
});
|
|
83
|
+
it('parses tenancy and rejects unknown values', async () => {
|
|
84
|
+
const { registry } = makeRegistry();
|
|
85
|
+
const multi = await createSelvaProviders({ SELVA_TENANCY: 'multi' }, { registry, ...noBoot });
|
|
86
|
+
expect(multi.tenancy()).toBe('multi');
|
|
87
|
+
const bad = await createSelvaProviders({ SELVA_TENANCY: 'galactic' }, { registry, ...noBoot });
|
|
88
|
+
expect(() => bad.tenancy()).toThrow(/SELVA_TENANCY="galactic"/);
|
|
89
|
+
});
|
|
90
|
+
it('brands with defaults; copyright falls back to the overridden name', async () => {
|
|
91
|
+
const { registry } = makeRegistry();
|
|
92
|
+
const plain = await createSelvaProviders({}, { registry, ...noBoot });
|
|
93
|
+
expect(plain.branding().name).toBe('Selva');
|
|
94
|
+
expect(plain.branding().copyrightName).toBe('Selva');
|
|
95
|
+
expect(plain.branding().tagline).toBeTruthy();
|
|
96
|
+
const branded = await createSelvaProviders({ SELVA_BRAND_NAME: ' Acme ' }, { registry, ...noBoot });
|
|
97
|
+
expect(branded.branding().name).toBe('Acme');
|
|
98
|
+
expect(branded.branding().copyrightName).toBe('Acme');
|
|
99
|
+
expect(branded.branding().description).toContain('Acme');
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe('solve metric sink', () => {
|
|
103
|
+
it('falls back to a noop sink when the data provider has no solveMetrics', async () => {
|
|
104
|
+
const { registry } = makeRegistry();
|
|
105
|
+
const runtime = await createSelvaProviders({}, { registry, ...noBoot });
|
|
106
|
+
const sink = runtime.solveMetricSink();
|
|
107
|
+
expect(typeof sink.record).toBe('function');
|
|
108
|
+
expect(runtime.solveMetricSink()).toBe(sink); // memoized
|
|
109
|
+
});
|
|
110
|
+
it('reuses a duck-typed solveMetrics sink carried by the data provider', async () => {
|
|
111
|
+
const { registry } = makeRegistry();
|
|
112
|
+
const carried = { record: vi.fn() };
|
|
113
|
+
registry.data.local = vi.fn(() => ({ solveMetrics: carried }));
|
|
114
|
+
const runtime = await createSelvaProviders({}, { registry, ...noBoot });
|
|
115
|
+
expect(runtime.solveMetricSink()).toBe(carried);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
describe('config-path override', () => {
|
|
119
|
+
it('loads the module default export and hands it the env', async () => {
|
|
120
|
+
const { registry, authLocal } = makeRegistry();
|
|
121
|
+
const configPath = fileURLToPath(new URL('./fixtures/override-config.mjs', import.meta.url));
|
|
122
|
+
const runtime = await createSelvaProviders({ OVERRIDE_MARKER: 'hello' }, { registry, configPath, ...noBoot });
|
|
123
|
+
const config = runtime.resolve();
|
|
124
|
+
expect(config.auth.name).toBe('override-auth');
|
|
125
|
+
expect(config.data.marker).toBe('hello');
|
|
126
|
+
expect(runtime.tenancy()).toBe('multi');
|
|
127
|
+
// The registry is bypassed entirely.
|
|
128
|
+
expect(authLocal).not.toHaveBeenCalled();
|
|
129
|
+
});
|
|
130
|
+
it('rejects at load time when the path does not exist', async () => {
|
|
131
|
+
const { registry } = makeRegistry();
|
|
132
|
+
await expect(createSelvaProviders({}, { registry, configPath: './does-not-exist.js', ...noBoot })).rejects.toThrow(/does-not-exist\.js/);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
//# sourceMappingURL=create-selva-providers.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-selva-providers.test.js","sourceRoot":"","sources":["../../../src/providers/__tests__/create-selva-providers.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { IAuthProvider, IDataProvider, IStorageProvider, ISolveMetricSink, SelvaBranding, SelvaConfig, SelvaFlags, TenancyMode } from '@selvajs/platform';
|
|
2
|
+
import { type EnvRecord } from '../compute/limits.js';
|
|
3
|
+
export type ProviderFactory<T> = (env: EnvRecord) => T;
|
|
4
|
+
/**
|
|
5
|
+
* The provider implementations available to this deployment, keyed by the
|
|
6
|
+
* (lowercase) choice name used in `SELVA_AUTH_PROVIDER` / `SELVA_DATA_PROVIDER`
|
|
7
|
+
* / `SELVA_STORAGE_PROVIDER`.
|
|
8
|
+
*/
|
|
9
|
+
export interface ProviderRegistry {
|
|
10
|
+
auth: Record<string, ProviderFactory<IAuthProvider>>;
|
|
11
|
+
data: Record<string, ProviderFactory<IDataProvider>>;
|
|
12
|
+
storage: Record<string, ProviderFactory<IStorageProvider>>;
|
|
13
|
+
}
|
|
14
|
+
export interface CreateSelvaProvidersOptions {
|
|
15
|
+
registry: ProviderRegistry;
|
|
16
|
+
/** Fallback choice per slot when the env var is unset. Default: `'local'`. */
|
|
17
|
+
defaults?: Partial<Record<'auth' | 'data' | 'storage', string>>;
|
|
18
|
+
/**
|
|
19
|
+
* Path to an external `selva.config.js` override (absolute or CWD-relative).
|
|
20
|
+
* Pass `env.SELVA_CONFIG_PATH` through; when set, the module's default
|
|
21
|
+
* export (a `SelvaConfig` or factory) replaces the env-driven wiring.
|
|
22
|
+
*/
|
|
23
|
+
configPath?: string;
|
|
24
|
+
/** Boot-summary sink, called once on first `resolve()`. Default: `console.info`. */
|
|
25
|
+
onBoot?: (summary: string) => void;
|
|
26
|
+
}
|
|
27
|
+
export interface SelvaProviderRuntime {
|
|
28
|
+
/**
|
|
29
|
+
* Memoized provider wiring. The first call instantiates providers from env
|
|
30
|
+
* (and may throw if required secrets are missing); subsequent calls return
|
|
31
|
+
* the cached config. Never call at build time — provider `fromEnv`
|
|
32
|
+
* factories validate required secrets.
|
|
33
|
+
*/
|
|
34
|
+
resolve(): SelvaConfig;
|
|
35
|
+
tenancy(): TenancyMode;
|
|
36
|
+
/** Resolved branding — every field defaulted so the UI never null-checks. */
|
|
37
|
+
branding(): Required<SelvaBranding>;
|
|
38
|
+
/** Safe flag accessor — omitted flags resolve to false. */
|
|
39
|
+
flag(name: keyof SelvaFlags): boolean;
|
|
40
|
+
/** Per-solve timing sink; `NoopSolveMetricSink` when the config omits one. */
|
|
41
|
+
solveMetricSink(): ISolveMetricSink;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Build the provider runtime. Loading the *config source* (default factory,
|
|
45
|
+
* or the `configPath` override module) happens here and is cheap and
|
|
46
|
+
* secret-free — a factory is just a function. The factory is NOT invoked:
|
|
47
|
+
* that runs the registry's `fromEnv` factories, which validate required
|
|
48
|
+
* secrets, and doing it at import/build time would make merely building the
|
|
49
|
+
* app require a full runtime env. Provider instantiation is deferred to the
|
|
50
|
+
* first `resolve()`.
|
|
51
|
+
*/
|
|
52
|
+
export declare function createSelvaProviders(env: EnvRecord, options: CreateSelvaProvidersOptions): Promise<SelvaProviderRuntime>;
|
|
53
|
+
//# sourceMappingURL=create-selva-providers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-selva-providers.d.ts","sourceRoot":"","sources":["../../src/providers/create-selva-providers.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EACX,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,WAAW,EAEX,UAAU,EACV,WAAW,EACX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEhE,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,KAAK,CAAC,CAAC;AAEvD;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,aAAa,CAAC,CAAC,CAAC;IACrD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,aAAa,CAAC,CAAC,CAAC;IACrD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,gBAAgB,CAAC,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,GAAG,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IAChE;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oFAAoF;IACpF,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,oBAAoB;IACpC;;;;;OAKG;IACH,OAAO,IAAI,WAAW,CAAC;IACvB,OAAO,IAAI,WAAW,CAAC;IACvB,6EAA6E;IAC7E,QAAQ,IAAI,QAAQ,CAAC,aAAa,CAAC,CAAC;IACpC,2DAA2D;IAC3D,IAAI,CAAC,IAAI,EAAE,MAAM,UAAU,GAAG,OAAO,CAAC;IACtC,8EAA8E;IAC9E,eAAe,IAAI,gBAAgB,CAAC;CACpC;AAkGD;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACzC,GAAG,EAAE,SAAS,EACd,OAAO,EAAE,2BAA2B,GAClC,OAAO,CAAC,oBAAoB,CAAC,CAkD/B"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// Configurable provider wiring (K5) — the reusable core of the app's
|
|
2
|
+
// composition root, extracted so any app built on the engine gets the same
|
|
3
|
+
// env-driven provider selection, `selva.config.js` override hook, and lazy
|
|
4
|
+
// instantiation without copying it.
|
|
5
|
+
//
|
|
6
|
+
// The provider IMPLEMENTATIONS are not bundled: the caller passes a
|
|
7
|
+
// `ProviderRegistry` mapping choice names (the `SELVA_*_PROVIDER` env values)
|
|
8
|
+
// to `fromEnv`-style factories. That keeps this package free of dependencies
|
|
9
|
+
// on `@selvajs/local-provider` / `@selvajs/supabase-provider` — a consuming
|
|
10
|
+
// app registers exactly the providers it ships.
|
|
11
|
+
//
|
|
12
|
+
// Two wiring modes (unchanged from the app):
|
|
13
|
+
//
|
|
14
|
+
// Default — providers are picked from env vars (SELVA_AUTH_PROVIDER etc.)
|
|
15
|
+
// via the registry. New deployments need only a .env file.
|
|
16
|
+
//
|
|
17
|
+
// Override — pass `configPath` (e.g. env.SELVA_CONFIG_PATH) pointing at an
|
|
18
|
+
// external `selva.config.js` (absolute or CWD-relative). It is loaded
|
|
19
|
+
// dynamically at boot and replaces the env-driven wiring entirely. The path
|
|
20
|
+
// must resolve to an actual `.js` file — there's no TS compiler at runtime.
|
|
21
|
+
import { pathToFileURL } from 'node:url';
|
|
22
|
+
import { resolve as resolvePath } from 'node:path';
|
|
23
|
+
import { existsSync } from 'node:fs';
|
|
24
|
+
import { isFlagEnabled, NoopSolveMetricSink } from '@selvajs/platform';
|
|
25
|
+
import { readBool } from '../compute/limits.js';
|
|
26
|
+
// Every SelvaFlags key, mapped from `SELVA_FLAG_<KEY>`. The `satisfies` +
|
|
27
|
+
// exhaustiveness check below make adding a platform flag without listing it
|
|
28
|
+
// here a compile error.
|
|
29
|
+
const FLAG_KEYS = [
|
|
30
|
+
'ALLOW_CROSS_ORG_PUBLIC',
|
|
31
|
+
'ALLOW_ORG_COMPUTE_OVERRIDE',
|
|
32
|
+
'ALLOW_ORG_CREATION',
|
|
33
|
+
'ENABLE_PLATFORM_PROJECTS',
|
|
34
|
+
'ENABLE_SHARING'
|
|
35
|
+
];
|
|
36
|
+
const _allFlagsListed = true;
|
|
37
|
+
function pick(env, envVar, slot, fallback) {
|
|
38
|
+
const choice = (env[envVar] ?? fallback).toLowerCase();
|
|
39
|
+
const factory = slot[choice];
|
|
40
|
+
if (!factory) {
|
|
41
|
+
throw new Error(`Unknown ${envVar}="${choice}". Expected: ${Object.keys(slot).join(' | ')}.`);
|
|
42
|
+
}
|
|
43
|
+
return factory(env);
|
|
44
|
+
}
|
|
45
|
+
function pickTenancy(env) {
|
|
46
|
+
const choice = (env.SELVA_TENANCY ?? 'single').toLowerCase();
|
|
47
|
+
if (choice !== 'single' && choice !== 'multi') {
|
|
48
|
+
throw new Error(`Unknown SELVA_TENANCY="${choice}". Expected: single | multi.`);
|
|
49
|
+
}
|
|
50
|
+
return choice;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Per-solve metric sink. Supabase's data provider carries a `solveMetrics`
|
|
54
|
+
* sink built from its own client bundle — reuse it so timings persist
|
|
55
|
+
* automatically. Backends without a metrics table leave it undefined, which
|
|
56
|
+
* falls back to `NoopSolveMetricSink` in `solveMetricSink()`.
|
|
57
|
+
*/
|
|
58
|
+
function pickSolveMetrics(data) {
|
|
59
|
+
const candidate = data.solveMetrics;
|
|
60
|
+
if (candidate && typeof candidate.record === 'function') {
|
|
61
|
+
return candidate;
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
function buildDefaultFactory(options) {
|
|
66
|
+
const { registry, defaults } = options;
|
|
67
|
+
return (env) => {
|
|
68
|
+
const data = pick(env, 'SELVA_DATA_PROVIDER', registry.data, defaults?.data ?? 'local');
|
|
69
|
+
return {
|
|
70
|
+
tenancy: pickTenancy(env),
|
|
71
|
+
flags: Object.fromEntries(FLAG_KEYS.map((key) => [key, readBool(env, `SELVA_FLAG_${key}`, false)])),
|
|
72
|
+
branding: {
|
|
73
|
+
name: env.SELVA_BRAND_NAME,
|
|
74
|
+
copyrightName: env.SELVA_BRAND_COPYRIGHT_NAME,
|
|
75
|
+
tagline: env.SELVA_BRAND_TAGLINE,
|
|
76
|
+
description: env.SELVA_BRAND_DESCRIPTION
|
|
77
|
+
},
|
|
78
|
+
auth: pick(env, 'SELVA_AUTH_PROVIDER', registry.auth, defaults?.auth ?? 'local'),
|
|
79
|
+
data,
|
|
80
|
+
storage: pick(env, 'SELVA_STORAGE_PROVIDER', registry.storage, defaults?.storage ?? 'local'),
|
|
81
|
+
solveMetrics: pickSolveMetrics(data)
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
async function loadConfigSource(options) {
|
|
86
|
+
if (!options.configPath) {
|
|
87
|
+
return buildDefaultFactory(options);
|
|
88
|
+
}
|
|
89
|
+
const abs = resolvePath(process.cwd(), options.configPath);
|
|
90
|
+
if (!existsSync(abs)) {
|
|
91
|
+
throw new Error(`Config override path ${options.configPath} resolved to ${abs} which does not exist.`);
|
|
92
|
+
}
|
|
93
|
+
// Dynamic specifier — a bundler must not pre-resolve this at build time,
|
|
94
|
+
// hence @vite-ignore. pathToFileURL keeps Windows absolute paths valid as
|
|
95
|
+
// ESM specifiers.
|
|
96
|
+
const mod = (await import(/* @vite-ignore */ pathToFileURL(abs).href));
|
|
97
|
+
return mod.default;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Build the provider runtime. Loading the *config source* (default factory,
|
|
101
|
+
* or the `configPath` override module) happens here and is cheap and
|
|
102
|
+
* secret-free — a factory is just a function. The factory is NOT invoked:
|
|
103
|
+
* that runs the registry's `fromEnv` factories, which validate required
|
|
104
|
+
* secrets, and doing it at import/build time would make merely building the
|
|
105
|
+
* app require a full runtime env. Provider instantiation is deferred to the
|
|
106
|
+
* first `resolve()`.
|
|
107
|
+
*/
|
|
108
|
+
export async function createSelvaProviders(env, options) {
|
|
109
|
+
const raw = await loadConfigSource(options);
|
|
110
|
+
const onBoot = options.onBoot ?? console.info;
|
|
111
|
+
let config;
|
|
112
|
+
let solveMetricSink;
|
|
113
|
+
function resolve() {
|
|
114
|
+
if (config)
|
|
115
|
+
return config;
|
|
116
|
+
config = typeof raw === 'function' ? raw(env) : raw;
|
|
117
|
+
// One-line boot summary so operators can confirm at a glance what got
|
|
118
|
+
// wired without grepping env vars or reading the config file. Provider
|
|
119
|
+
// names come from the IAuthProvider.name field; data/storage adapters
|
|
120
|
+
// don't expose a name, so we infer from the constructor.
|
|
121
|
+
onBoot(`[selva] providers wired: ` +
|
|
122
|
+
`auth=${config.auth.name} ` +
|
|
123
|
+
`data=${config.data.constructor.name} ` +
|
|
124
|
+
`storage=${config.storage.constructor.name} ` +
|
|
125
|
+
`tenancy=${config.tenancy ?? 'single'}` +
|
|
126
|
+
(options.configPath ? ` config=${options.configPath}` : ''));
|
|
127
|
+
return config;
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
resolve,
|
|
131
|
+
tenancy: () => resolve().tenancy ?? 'single',
|
|
132
|
+
branding: () => {
|
|
133
|
+
const brand = resolve().branding ?? {};
|
|
134
|
+
const name = brand.name?.trim() || 'Selva';
|
|
135
|
+
return {
|
|
136
|
+
name,
|
|
137
|
+
copyrightName: brand.copyrightName?.trim() || name,
|
|
138
|
+
tagline: brand.tagline?.trim() || 'Turn Grasshopper definitions into tools anyone can use.',
|
|
139
|
+
description: brand.description?.trim() ||
|
|
140
|
+
`Build and deploy interactive web applications powered by Grasshopper definitions with ${name}.`
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
flag: (name) => isFlagEnabled(resolve(), name),
|
|
144
|
+
solveMetricSink: () => {
|
|
145
|
+
if (!solveMetricSink) {
|
|
146
|
+
solveMetricSink = resolve().solveMetrics ?? new NoopSolveMetricSink();
|
|
147
|
+
}
|
|
148
|
+
return solveMetricSink;
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=create-selva-providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-selva-providers.js","sourceRoot":"","sources":["../../src/providers/create-selva-providers.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,2EAA2E;AAC3E,2EAA2E;AAC3E,oCAAoC;AACpC,EAAE;AACF,oEAAoE;AACpE,8EAA8E;AAC9E,6EAA6E;AAC7E,4EAA4E;AAC5E,gDAAgD;AAChD,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,4EAA4E;AAC5E,6DAA6D;AAC7D,EAAE;AACF,6EAA6E;AAC7E,wEAAwE;AACxE,8EAA8E;AAC9E,8EAA8E;AAE9E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAYrC,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAkB,MAAM,sBAAsB,CAAC;AA8ChE,0EAA0E;AAC1E,4EAA4E;AAC5E,wBAAwB;AACxB,MAAM,SAAS,GAAG;IACjB,wBAAwB;IACxB,4BAA4B;IAC5B,oBAAoB;IACpB,0BAA0B;IAC1B,gBAAgB;CACiC,CAAC;AAKnD,MAAM,eAAe,GAAmB,IAAI,CAAC;AAE7C,SAAS,IAAI,CACZ,GAAc,EACd,MAAc,EACd,IAAwC,EACxC,QAAgB;IAEhB,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,WAAW,MAAM,KAAK,MAAM,gBAAgB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/F,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC;AAED,SAAS,WAAW,CAAC,GAAc;IAClC,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,aAAa,IAAI,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IAC7D,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,0BAA0B,MAAM,8BAA8B,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAS,gBAAgB,CAAC,IAAmB;IAC5C,MAAM,SAAS,GAAI,IAAmC,CAAC,YAAY,CAAC;IACpE,IAAI,SAAS,IAAI,OAAQ,SAAkC,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACnF,OAAO,SAA6B,CAAC;IACtC,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAoC;IAChE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IACvC,OAAO,CAAC,GAAG,EAAE,EAAE;QACd,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,qBAAqB,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,IAAI,OAAO,CAAC,CAAC;QACxF,OAAO;YACN,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC;YACzB,KAAK,EAAE,MAAM,CAAC,WAAW,CACxB,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CACxE;YACD,QAAQ,EAAE;gBACT,IAAI,EAAE,GAAG,CAAC,gBAAgB;gBAC1B,aAAa,EAAE,GAAG,CAAC,0BAA0B;gBAC7C,OAAO,EAAE,GAAG,CAAC,mBAAmB;gBAChC,WAAW,EAAE,GAAG,CAAC,uBAAuB;aACxC;YACD,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,qBAAqB,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,IAAI,OAAO,CAAC;YAChF,IAAI;YACJ,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,wBAAwB,EAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,IAAI,OAAO,CAAC;YAC5F,YAAY,EAAE,gBAAgB,CAAC,IAAI,CAAC;SACpC,CAAC;IACH,CAAC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC9B,OAAoC;IAEpC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QACzB,OAAO,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IACD,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACd,wBAAwB,OAAO,CAAC,UAAU,gBAAgB,GAAG,wBAAwB,CACrF,CAAC;IACH,CAAC;IACD,yEAAyE;IACzE,0EAA0E;IAC1E,kBAAkB;IAClB,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,kBAAkB,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAEpE,CAAC;IACF,OAAO,GAAG,CAAC,OAAO,CAAC;AACpB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACzC,GAAc,EACd,OAAoC;IAEpC,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAE9C,IAAI,MAA+B,CAAC;IACpC,IAAI,eAA6C,CAAC;IAElD,SAAS,OAAO;QACf,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAC1B,MAAM,GAAG,OAAO,GAAG,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAEpD,sEAAsE;QACtE,uEAAuE;QACvE,sEAAsE;QACtE,yDAAyD;QACzD,MAAM,CACL,2BAA2B;YAC1B,QAAQ,MAAM,CAAC,IAAI,CAAC,IAAI,GAAG;YAC3B,QAAQ,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,GAAG;YACvC,WAAW,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,GAAG;YAC7C,WAAW,MAAM,CAAC,OAAO,IAAI,QAAQ,EAAE;YACvC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC5D,CAAC;QAEF,OAAO,MAAM,CAAC;IACf,CAAC;IAED,OAAO;QACN,OAAO;QACP,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,OAAO,IAAI,QAAQ;QAC5C,QAAQ,EAAE,GAAG,EAAE;YACd,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC,QAAQ,IAAI,EAAE,CAAC;YACvC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC;YAC3C,OAAO;gBACN,IAAI;gBACJ,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,IAAI;gBAClD,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,yDAAyD;gBAC3F,WAAW,EACV,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE;oBACzB,yFAAyF,IAAI,GAAG;aACjG,CAAC;QACH,CAAC;QACD,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC;QAC9C,eAAe,EAAE,GAAG,EAAE;YACrB,IAAI,CAAC,eAAe,EAAE,CAAC;gBACtB,eAAe,GAAG,OAAO,EAAE,CAAC,YAAY,IAAI,IAAI,mBAAmB,EAAE,CAAC;YACvE,CAAC;YACD,OAAO,eAAe,CAAC;QACxB,CAAC;KACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAKA,OAAO,EACN,oBAAoB,EACpB,KAAK,2BAA2B,EAChC,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Configurable provider wiring — env-driven provider selection over a
|
|
2
|
+
// caller-supplied registry, `selva.config.js` override hook, lazy memoized
|
|
3
|
+
// instantiation. The app keeps its own getters (services, error reporting) as
|
|
4
|
+
// its composition root; this is the reusable core underneath.
|
|
5
|
+
export { createSelvaProviders } from './create-selva-providers.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,2EAA2E;AAC3E,8EAA8E;AAC9E,8DAA8D;AAE9D,OAAO,EACN,oBAAoB,EAKpB,MAAM,6BAA6B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@selvajs/server",
|
|
3
|
+
"version": "0.2.0-beta.1",
|
|
4
|
+
"description": "Transport-agnostic compute/solve/definitions server building blocks for apps built on the Selva engine (limits, rate limiting, SSRF guard, input transform, solve pipeline, definition service + render loader)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/VektorNode/selva.git",
|
|
12
|
+
"directory": "packages/server"
|
|
13
|
+
},
|
|
14
|
+
"type": "module",
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"source": "./src/index.ts",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"import": "./dist/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./compute": {
|
|
24
|
+
"source": "./src/compute/index.ts",
|
|
25
|
+
"types": "./dist/compute/index.d.ts",
|
|
26
|
+
"import": "./dist/compute/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./definitions": {
|
|
29
|
+
"source": "./src/definitions/index.ts",
|
|
30
|
+
"types": "./dist/definitions/index.d.ts",
|
|
31
|
+
"import": "./dist/definitions/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./providers": {
|
|
34
|
+
"source": "./src/providers/index.ts",
|
|
35
|
+
"types": "./dist/providers/index.d.ts",
|
|
36
|
+
"import": "./dist/providers/index.js"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"src"
|
|
42
|
+
],
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@selvajs/compute": "^3.1.0-beta.3",
|
|
45
|
+
"@selvajs/platform": "0.14.3-beta.0",
|
|
46
|
+
"@selvajs/schemas": "4.7.0-beta.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "^22.19.17",
|
|
50
|
+
"typescript": "^5.9.3",
|
|
51
|
+
"vitest": "^3.2.6"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "tsc",
|
|
55
|
+
"dev": "tsc --watch",
|
|
56
|
+
"type-check": "tsc --noEmit",
|
|
57
|
+
"test": "vitest run",
|
|
58
|
+
"test:watch": "vitest"
|
|
59
|
+
}
|
|
60
|
+
}
|