@milaboratories/pf-spec-driver 1.2.6 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/pframe_pool.cjs.map +1 -1
- package/dist/pframe_pool.js.map +1 -1
- package/dist/spec_driver.cjs +21 -0
- package/dist/spec_driver.cjs.map +1 -1
- package/dist/spec_driver.d.ts +3 -1
- package/dist/spec_driver.d.ts.map +1 -1
- package/dist/spec_driver.js +22 -1
- package/dist/spec_driver.js.map +1 -1
- package/package.json +7 -7
- package/src/pframe_pool.ts +3 -3
- package/src/spec_driver.test.ts +107 -1
- package/src/spec_driver.ts +31 -0
package/dist/pframe_pool.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pframe_pool.cjs","names":["RefCountPoolBase","logPFrames","PFrameDriverError"],"sources":["../src/pframe_pool.ts"],"sourcesContent":["import {\n PFrameDriverError,\n PColumnSpec,\n SpecFrameHandle,\n stringifyJson,\n canonicalizeJson,\n} from \"@milaboratories/pl-model-common\";\nimport { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport { MiLogger, RefCountPoolBase } from \"@milaboratories/helpers\";\nimport { logPFrames } from \"./logging\";\nimport { createPFrame } from \"@milaboratories/pframes-rs-wasm\";\nimport { blake3 } from \"@noble/hashes/blake3.js\";\nimport { bytesToHex } from \"@noble/hashes/utils.js\";\n\nexport class PFramePool extends RefCountPoolBase<\n Record<string, PColumnSpec>,\n SpecFrameHandle,\n PFrameInternal.
|
|
1
|
+
{"version":3,"file":"pframe_pool.cjs","names":["RefCountPoolBase","logPFrames","PFrameDriverError"],"sources":["../src/pframe_pool.ts"],"sourcesContent":["import {\n PFrameDriverError,\n PColumnSpec,\n SpecFrameHandle,\n stringifyJson,\n canonicalizeJson,\n} from \"@milaboratories/pl-model-common\";\nimport { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport { MiLogger, RefCountPoolBase } from \"@milaboratories/helpers\";\nimport { logPFrames } from \"./logging\";\nimport { createPFrame } from \"@milaboratories/pframes-rs-wasm\";\nimport { blake3 } from \"@noble/hashes/blake3.js\";\nimport { bytesToHex } from \"@noble/hashes/utils.js\";\n\nexport class PFramePool extends RefCountPoolBase<\n Record<string, PColumnSpec>,\n SpecFrameHandle,\n PFrameInternal.PFrameWasmV3\n> {\n constructor(private readonly logger: MiLogger) {\n super();\n }\n\n protected calculateParamsKey(params: Record<string, PColumnSpec>): SpecFrameHandle {\n return bytesToHex(\n blake3(new TextEncoder().encode(canonicalizeJson(params))),\n ) as SpecFrameHandle;\n }\n\n protected createNewResource(\n params: Record<string, PColumnSpec>,\n key: SpecFrameHandle,\n ): PFrameInternal.PFrameWasmV3 {\n if (logPFrames()) {\n this.logger.info(`Creating SpecFrame for handle = ${key}, columns: ` + stringifyJson(params));\n }\n return createPFrame(params);\n }\n\n public getByKey(key: SpecFrameHandle): PFrameInternal.PFrameWasmV3 {\n const resource = super.tryGetByKey(key);\n if (!resource) {\n const error = new PFrameDriverError(`Invalid SpecFrame handle`);\n error.cause = new Error(`SpecFrame with handle ${key} not found`);\n throw error;\n }\n return resource;\n }\n}\n"],"mappings":";;;;;;;AAcA,IAAa,aAAb,cAAgCA,wBAAAA,iBAI9B;CACA,YAAY,QAAmC;AAC7C,SAAO;AADoB,OAAA,SAAA;;CAI7B,mBAA6B,QAAsD;AACjF,UAAA,GAAA,uBAAA,aAAA,GAAA,wBAAA,QACS,IAAI,aAAa,CAAC,QAAA,GAAA,gCAAA,kBAAwB,OAAO,CAAC,CAAC,CAC3D;;CAGH,kBACE,QACA,KAC6B;AAC7B,MAAIC,gBAAAA,YAAY,CACd,MAAK,OAAO,KAAK,mCAAmC,IAAI,gBAAA,GAAA,gCAAA,eAA6B,OAAO,CAAC;AAE/F,UAAA,GAAA,gCAAA,cAAoB,OAAO;;CAG7B,SAAgB,KAAmD;EACjE,MAAM,WAAW,MAAM,YAAY,IAAI;AACvC,MAAI,CAAC,UAAU;GACb,MAAM,QAAQ,IAAIC,gCAAAA,kBAAkB,2BAA2B;AAC/D,SAAM,wBAAQ,IAAI,MAAM,yBAAyB,IAAI,YAAY;AACjE,SAAM;;AAER,SAAO"}
|
package/dist/pframe_pool.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pframe_pool.js","names":[],"sources":["../src/pframe_pool.ts"],"sourcesContent":["import {\n PFrameDriverError,\n PColumnSpec,\n SpecFrameHandle,\n stringifyJson,\n canonicalizeJson,\n} from \"@milaboratories/pl-model-common\";\nimport { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport { MiLogger, RefCountPoolBase } from \"@milaboratories/helpers\";\nimport { logPFrames } from \"./logging\";\nimport { createPFrame } from \"@milaboratories/pframes-rs-wasm\";\nimport { blake3 } from \"@noble/hashes/blake3.js\";\nimport { bytesToHex } from \"@noble/hashes/utils.js\";\n\nexport class PFramePool extends RefCountPoolBase<\n Record<string, PColumnSpec>,\n SpecFrameHandle,\n PFrameInternal.
|
|
1
|
+
{"version":3,"file":"pframe_pool.js","names":[],"sources":["../src/pframe_pool.ts"],"sourcesContent":["import {\n PFrameDriverError,\n PColumnSpec,\n SpecFrameHandle,\n stringifyJson,\n canonicalizeJson,\n} from \"@milaboratories/pl-model-common\";\nimport { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport { MiLogger, RefCountPoolBase } from \"@milaboratories/helpers\";\nimport { logPFrames } from \"./logging\";\nimport { createPFrame } from \"@milaboratories/pframes-rs-wasm\";\nimport { blake3 } from \"@noble/hashes/blake3.js\";\nimport { bytesToHex } from \"@noble/hashes/utils.js\";\n\nexport class PFramePool extends RefCountPoolBase<\n Record<string, PColumnSpec>,\n SpecFrameHandle,\n PFrameInternal.PFrameWasmV3\n> {\n constructor(private readonly logger: MiLogger) {\n super();\n }\n\n protected calculateParamsKey(params: Record<string, PColumnSpec>): SpecFrameHandle {\n return bytesToHex(\n blake3(new TextEncoder().encode(canonicalizeJson(params))),\n ) as SpecFrameHandle;\n }\n\n protected createNewResource(\n params: Record<string, PColumnSpec>,\n key: SpecFrameHandle,\n ): PFrameInternal.PFrameWasmV3 {\n if (logPFrames()) {\n this.logger.info(`Creating SpecFrame for handle = ${key}, columns: ` + stringifyJson(params));\n }\n return createPFrame(params);\n }\n\n public getByKey(key: SpecFrameHandle): PFrameInternal.PFrameWasmV3 {\n const resource = super.tryGetByKey(key);\n if (!resource) {\n const error = new PFrameDriverError(`Invalid SpecFrame handle`);\n error.cause = new Error(`SpecFrame with handle ${key} not found`);\n throw error;\n }\n return resource;\n }\n}\n"],"mappings":";;;;;;;AAcA,IAAa,aAAb,cAAgC,iBAI9B;CACA,YAAY,QAAmC;AAC7C,SAAO;AADoB,OAAA,SAAA;;CAI7B,mBAA6B,QAAsD;AACjF,SAAO,WACL,OAAO,IAAI,aAAa,CAAC,OAAO,iBAAiB,OAAO,CAAC,CAAC,CAC3D;;CAGH,kBACE,QACA,KAC6B;AAC7B,MAAI,YAAY,CACd,MAAK,OAAO,KAAK,mCAAmC,IAAI,eAAe,cAAc,OAAO,CAAC;AAE/F,SAAO,aAAa,OAAO;;CAG7B,SAAgB,KAAmD;EACjE,MAAM,WAAW,MAAM,YAAY,IAAI;AACvC,MAAI,CAAC,UAAU;GACb,MAAM,QAAQ,IAAI,kBAAkB,2BAA2B;AAC/D,SAAM,wBAAQ,IAAI,MAAM,yBAAyB,IAAI,YAAY;AACjE,SAAM;;AAER,SAAO"}
|
package/dist/spec_driver.cjs
CHANGED
|
@@ -28,6 +28,27 @@ var SpecDriver = class {
|
|
|
28
28
|
throw error;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
+
listColumns(handle) {
|
|
32
|
+
const pframe = this.frames.getByKey(handle);
|
|
33
|
+
try {
|
|
34
|
+
if (require_logging.logPFrames()) this.logger.info(`listColumns: handle = ${handle}`);
|
|
35
|
+
return pframe.listColumns();
|
|
36
|
+
} catch (err) {
|
|
37
|
+
const error = new _milaboratories_pl_model_common.PFrameSpecDriverError(`listColumns failed`);
|
|
38
|
+
error.cause = /* @__PURE__ */ new Error(`handle: ${handle}, error:\n${(0, _milaboratories_pl_model_common.ensureError)(err)}`);
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
buildQuery(input) {
|
|
43
|
+
try {
|
|
44
|
+
if (require_logging.logPFrames()) this.logger.info(`buildQuery: input: ${JSON.stringify(input)}`);
|
|
45
|
+
return (0, _milaboratories_pframes_rs_wasm.buildQuery)(input);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
const error = new _milaboratories_pl_model_common.PFrameSpecDriverError(`buildQuery failed`);
|
|
48
|
+
error.cause = /* @__PURE__ */ new Error(`input: ${JSON.stringify(input)}, error:\n${(0, _milaboratories_pl_model_common.ensureError)(err)}`);
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
31
52
|
discoverColumns(handle, request) {
|
|
32
53
|
const pframe = this.frames.getByKey(handle);
|
|
33
54
|
try {
|
package/dist/spec_driver.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec_driver.cjs","names":["ConsoleLoggerAdapter","PFramePool","ValueType","logPFrames","PFrameSpecDriverError"],"sources":["../src/spec_driver.ts"],"sourcesContent":["import {\n expandAxes,\n collapseAxes,\n findAxis,\n findTableColumn,\n} from \"@milaboratories/pframes-rs-wasm\";\nimport type {\n AxesId,\n AxesSpec,\n PColumnSpec,\n PFrameSpecDriver,\n PTableColumnId,\n PTableColumnSpec,\n SingleAxisSelector,\n SpecFrameHandle,\n PoolEntry,\n DiscoverColumnsRequest,\n DiscoverColumnsResponse,\n DeleteColumnRequest,\n DeleteColumnResponse,\n EvaluateQueryResponse,\n SpecQuery,\n} from \"@milaboratories/pl-model-common\";\nimport {\n PFrameSpecDriverError,\n ValueType,\n ensureError,\n resolveAnnotationParents,\n} from \"@milaboratories/pl-model-common\";\nimport { type MiLogger, ConsoleLoggerAdapter } from \"@milaboratories/helpers\";\nimport { PFramePool } from \"./pframe_pool\";\nimport { logPFrames } from \"./logging\";\n\n/**\n * Manages spec-only PFrame instances (WASM) with handle-based lifecycle.\n *\n * All operations are synchronous — WASM computes results immediately.\n */\nexport class SpecDriver implements PFrameSpecDriver, AsyncDisposable {\n private readonly logger: MiLogger;\n private readonly frames: PFramePool;\n\n public constructor(options?: { logger?: MiLogger }) {\n this.logger = options?.logger ?? new ConsoleLoggerAdapter();\n this.frames = new PFramePool(this.logger);\n }\n\n createSpecFrame(specs: Record<string, PColumnSpec>): PoolEntry<SpecFrameHandle> {\n const ValueTypes = new Set(Object.values(ValueType));\n const filtered = Object.fromEntries(\n Object.entries(specs)\n .filter(([, spec]) => ValueTypes.has(spec.valueType))\n .map(([id, spec]) => [id, resolveAnnotationParents(spec)]),\n );\n try {\n if (logPFrames()) {\n this.logger.info(`createSpecFrame: ${Object.keys(filtered).length} columns`);\n }\n return this.frames.acquire(filtered);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`createSpecFrame failed`);\n error.cause = ensureError(err);\n throw error;\n }\n }\n\n discoverColumns(\n handle: SpecFrameHandle,\n request: DiscoverColumnsRequest,\n ): DiscoverColumnsResponse {\n const pframe = this.frames.getByKey(handle);\n try {\n if (logPFrames()) {\n this.logger.info(\n `discoverColumns: handle = ${handle}, request: ${JSON.stringify(request)}`,\n );\n }\n const result = pframe.discoverColumns(request);\n return result;\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`discoverColumns failed`);\n error.cause = new Error(\n `handle: ${handle}, ` +\n `request: ${JSON.stringify(request)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n deleteColumn(handle: SpecFrameHandle, request: DeleteColumnRequest): DeleteColumnResponse {\n const pframe = this.frames.getByKey(handle);\n try {\n if (logPFrames()) {\n this.logger.info(`deleteColumn: handle = ${handle}, request: ${JSON.stringify(request)}`);\n }\n const result = {\n axes: pframe.deleteColumns({ columns: request.axes, delete: request.delete }).columns,\n };\n return result;\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`deleteColumn failed`);\n error.cause = new Error(\n `handle: ${handle}, ` +\n `request: ${JSON.stringify(request)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n evaluateQuery(handle: SpecFrameHandle, request: SpecQuery): EvaluateQueryResponse {\n const pframe = this.frames.getByKey(handle);\n try {\n if (logPFrames()) {\n this.logger.info(`evaluateQuery: handle = ${handle}, request: ${JSON.stringify(request)}`);\n }\n const result = pframe.evaluateQuery(request);\n return result;\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`evaluateQuery failed`);\n error.cause = new Error(\n `handle: ${handle}, ` +\n `request: ${JSON.stringify(request)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n expandAxes(spec: AxesSpec): AxesId {\n try {\n return expandAxes(spec);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`expandAxes failed`);\n error.cause = new Error(`spec: ${JSON.stringify(spec)}, ` + `error:\\n${ensureError(err)}`);\n throw error;\n }\n }\n\n collapseAxes(ids: AxesId): AxesSpec {\n try {\n return collapseAxes(ids);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`collapseAxes failed`);\n error.cause = new Error(`ids: ${JSON.stringify(ids)}, ` + `error:\\n${ensureError(err)}`);\n throw error;\n }\n }\n\n findAxis(spec: AxesSpec, selector: SingleAxisSelector): number {\n try {\n return findAxis(spec, selector);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`findAxis failed`);\n error.cause = new Error(\n `spec: ${JSON.stringify(spec)}, ` +\n `selector: ${JSON.stringify(selector)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n findTableColumn(tableSpec: PTableColumnSpec[], selector: PTableColumnId): number {\n try {\n return findTableColumn(tableSpec, selector);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`findTableColumn failed`);\n error.cause = new Error(\n `selector: ${JSON.stringify(selector)}, ` + `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n async dispose(): Promise<void> {\n await this.frames.dispose();\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.dispose();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"spec_driver.cjs","names":["ConsoleLoggerAdapter","PFramePool","ValueType","logPFrames","PFrameSpecDriverError"],"sources":["../src/spec_driver.ts"],"sourcesContent":["import {\n buildQuery,\n expandAxes,\n collapseAxes,\n findAxis,\n findTableColumn,\n} from \"@milaboratories/pframes-rs-wasm\";\nimport type {\n AxesId,\n AxesSpec,\n BuildQueryInput,\n PColumnInfo,\n PColumnSpec,\n PFrameSpecDriver,\n PTableColumnId,\n PTableColumnSpec,\n SingleAxisSelector,\n SpecFrameHandle,\n SpecQueryJoinEntry,\n PoolEntry,\n DiscoverColumnsRequest,\n DiscoverColumnsResponse,\n DeleteColumnRequest,\n DeleteColumnResponse,\n EvaluateQueryResponse,\n SpecQuery,\n} from \"@milaboratories/pl-model-common\";\nimport {\n PFrameSpecDriverError,\n ValueType,\n ensureError,\n resolveAnnotationParents,\n} from \"@milaboratories/pl-model-common\";\nimport { type MiLogger, ConsoleLoggerAdapter } from \"@milaboratories/helpers\";\nimport { PFramePool } from \"./pframe_pool\";\nimport { logPFrames } from \"./logging\";\n\n/**\n * Manages spec-only PFrame instances (WASM) with handle-based lifecycle.\n *\n * All operations are synchronous — WASM computes results immediately.\n */\nexport class SpecDriver implements PFrameSpecDriver, AsyncDisposable {\n private readonly logger: MiLogger;\n private readonly frames: PFramePool;\n\n public constructor(options?: { logger?: MiLogger }) {\n this.logger = options?.logger ?? new ConsoleLoggerAdapter();\n this.frames = new PFramePool(this.logger);\n }\n\n createSpecFrame(specs: Record<string, PColumnSpec>): PoolEntry<SpecFrameHandle> {\n const ValueTypes = new Set(Object.values(ValueType));\n const filtered = Object.fromEntries(\n Object.entries(specs)\n .filter(([, spec]) => ValueTypes.has(spec.valueType))\n .map(([id, spec]) => [id, resolveAnnotationParents(spec)]),\n );\n try {\n if (logPFrames()) {\n this.logger.info(`createSpecFrame: ${Object.keys(filtered).length} columns`);\n }\n return this.frames.acquire(filtered);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`createSpecFrame failed`);\n error.cause = ensureError(err);\n throw error;\n }\n }\n\n listColumns(handle: SpecFrameHandle): PColumnInfo[] {\n const pframe = this.frames.getByKey(handle);\n try {\n if (logPFrames()) {\n this.logger.info(`listColumns: handle = ${handle}`);\n }\n return pframe.listColumns();\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`listColumns failed`);\n error.cause = new Error(`handle: ${handle}, ` + `error:\\n${ensureError(err)}`);\n throw error;\n }\n }\n\n buildQuery(input: BuildQueryInput): SpecQueryJoinEntry {\n try {\n if (logPFrames()) {\n this.logger.info(`buildQuery: input: ${JSON.stringify(input)}`);\n }\n return buildQuery(input);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`buildQuery failed`);\n error.cause = new Error(`input: ${JSON.stringify(input)}, ` + `error:\\n${ensureError(err)}`);\n throw error;\n }\n }\n\n discoverColumns(\n handle: SpecFrameHandle,\n request: DiscoverColumnsRequest,\n ): DiscoverColumnsResponse {\n const pframe = this.frames.getByKey(handle);\n try {\n if (logPFrames()) {\n this.logger.info(\n `discoverColumns: handle = ${handle}, request: ${JSON.stringify(request)}`,\n );\n }\n const result = pframe.discoverColumns(request);\n return result;\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`discoverColumns failed`);\n error.cause = new Error(\n `handle: ${handle}, ` +\n `request: ${JSON.stringify(request)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n deleteColumn(handle: SpecFrameHandle, request: DeleteColumnRequest): DeleteColumnResponse {\n const pframe = this.frames.getByKey(handle);\n try {\n if (logPFrames()) {\n this.logger.info(`deleteColumn: handle = ${handle}, request: ${JSON.stringify(request)}`);\n }\n const result = {\n axes: pframe.deleteColumns({ columns: request.axes, delete: request.delete }).columns,\n };\n return result;\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`deleteColumn failed`);\n error.cause = new Error(\n `handle: ${handle}, ` +\n `request: ${JSON.stringify(request)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n evaluateQuery(handle: SpecFrameHandle, request: SpecQuery): EvaluateQueryResponse {\n const pframe = this.frames.getByKey(handle);\n try {\n if (logPFrames()) {\n this.logger.info(`evaluateQuery: handle = ${handle}, request: ${JSON.stringify(request)}`);\n }\n const result = pframe.evaluateQuery(request);\n return result;\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`evaluateQuery failed`);\n error.cause = new Error(\n `handle: ${handle}, ` +\n `request: ${JSON.stringify(request)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n expandAxes(spec: AxesSpec): AxesId {\n try {\n return expandAxes(spec);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`expandAxes failed`);\n error.cause = new Error(`spec: ${JSON.stringify(spec)}, ` + `error:\\n${ensureError(err)}`);\n throw error;\n }\n }\n\n collapseAxes(ids: AxesId): AxesSpec {\n try {\n return collapseAxes(ids);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`collapseAxes failed`);\n error.cause = new Error(`ids: ${JSON.stringify(ids)}, ` + `error:\\n${ensureError(err)}`);\n throw error;\n }\n }\n\n findAxis(spec: AxesSpec, selector: SingleAxisSelector): number {\n try {\n return findAxis(spec, selector);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`findAxis failed`);\n error.cause = new Error(\n `spec: ${JSON.stringify(spec)}, ` +\n `selector: ${JSON.stringify(selector)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n findTableColumn(tableSpec: PTableColumnSpec[], selector: PTableColumnId): number {\n try {\n return findTableColumn(tableSpec, selector);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`findTableColumn failed`);\n error.cause = new Error(\n `selector: ${JSON.stringify(selector)}, ` + `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n async dispose(): Promise<void> {\n await this.frames.dispose();\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.dispose();\n }\n}\n"],"mappings":"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"}
|
package/dist/spec_driver.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AxesId, AxesSpec, DeleteColumnRequest, DeleteColumnResponse, DiscoverColumnsRequest, DiscoverColumnsResponse, EvaluateQueryResponse, PColumnSpec, PFrameSpecDriver, PTableColumnId, PTableColumnSpec, PoolEntry, SingleAxisSelector, SpecFrameHandle, SpecQuery } from "@milaboratories/pl-model-common";
|
|
1
|
+
import { AxesId, AxesSpec, BuildQueryInput, DeleteColumnRequest, DeleteColumnResponse, DiscoverColumnsRequest, DiscoverColumnsResponse, EvaluateQueryResponse, PColumnInfo, PColumnSpec, PFrameSpecDriver, PTableColumnId, PTableColumnSpec, PoolEntry, SingleAxisSelector, SpecFrameHandle, SpecQuery, SpecQueryJoinEntry } from "@milaboratories/pl-model-common";
|
|
2
2
|
import { MiLogger } from "@milaboratories/helpers";
|
|
3
3
|
|
|
4
4
|
//#region src/spec_driver.d.ts
|
|
@@ -14,6 +14,8 @@ declare class SpecDriver implements PFrameSpecDriver, AsyncDisposable {
|
|
|
14
14
|
logger?: MiLogger;
|
|
15
15
|
});
|
|
16
16
|
createSpecFrame(specs: Record<string, PColumnSpec>): PoolEntry<SpecFrameHandle>;
|
|
17
|
+
listColumns(handle: SpecFrameHandle): PColumnInfo[];
|
|
18
|
+
buildQuery(input: BuildQueryInput): SpecQueryJoinEntry;
|
|
17
19
|
discoverColumns(handle: SpecFrameHandle, request: DiscoverColumnsRequest): DiscoverColumnsResponse;
|
|
18
20
|
deleteColumn(handle: SpecFrameHandle, request: DeleteColumnRequest): DeleteColumnResponse;
|
|
19
21
|
evaluateQuery(handle: SpecFrameHandle, request: SpecQuery): EvaluateQueryResponse;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec_driver.d.ts","names":[],"sources":["../src/spec_driver.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"spec_driver.d.ts","names":[],"sources":["../src/spec_driver.ts"],"mappings":";;;;;;AA0CA;;;cAAa,UAAA,YAAsB,gBAAA,EAAkB,eAAA;EAAA,iBAClC,MAAA;EAAA,iBACA,MAAA;cAEE,OAAA;IAAY,MAAA,GAAS,QAAA;EAAA;EAKxC,eAAA,CAAgB,KAAA,EAAO,MAAA,SAAe,WAAA,IAAe,SAAA,CAAU,eAAA;EAmB/D,WAAA,CAAY,MAAA,EAAQ,eAAA,GAAkB,WAAA;EActC,UAAA,CAAW,KAAA,EAAO,eAAA,GAAkB,kBAAA;EAapC,eAAA,CACE,MAAA,EAAQ,eAAA,EACR,OAAA,EAAS,sBAAA,GACR,uBAAA;EAqBH,YAAA,CAAa,MAAA,EAAQ,eAAA,EAAiB,OAAA,EAAS,mBAAA,GAAsB,oBAAA;EAqBrE,aAAA,CAAc,MAAA,EAAQ,eAAA,EAAiB,OAAA,EAAS,SAAA,GAAY,qBAAA;EAmB5D,UAAA,CAAW,IAAA,EAAM,QAAA,GAAW,MAAA;EAU5B,YAAA,CAAa,GAAA,EAAK,MAAA,GAAS,QAAA;EAU3B,QAAA,CAAS,IAAA,EAAM,QAAA,EAAU,QAAA,EAAU,kBAAA;EAcnC,eAAA,CAAgB,SAAA,EAAW,gBAAA,IAAoB,QAAA,EAAU,cAAA;EAYnD,OAAA,CAAA,GAAW,OAAA;EAAA,CAIV,MAAA,CAAO,YAAA,KAAiB,OAAA;AAAA"}
|
package/dist/spec_driver.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { logPFrames } from "./logging.js";
|
|
2
2
|
import { PFramePool } from "./pframe_pool.js";
|
|
3
|
-
import { collapseAxes, expandAxes, findAxis, findTableColumn } from "@milaboratories/pframes-rs-wasm";
|
|
3
|
+
import { buildQuery, collapseAxes, expandAxes, findAxis, findTableColumn } from "@milaboratories/pframes-rs-wasm";
|
|
4
4
|
import { PFrameSpecDriverError, ValueType, ensureError, resolveAnnotationParents } from "@milaboratories/pl-model-common";
|
|
5
5
|
import { ConsoleLoggerAdapter } from "@milaboratories/helpers";
|
|
6
6
|
//#region src/spec_driver.ts
|
|
@@ -28,6 +28,27 @@ var SpecDriver = class {
|
|
|
28
28
|
throw error;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
+
listColumns(handle) {
|
|
32
|
+
const pframe = this.frames.getByKey(handle);
|
|
33
|
+
try {
|
|
34
|
+
if (logPFrames()) this.logger.info(`listColumns: handle = ${handle}`);
|
|
35
|
+
return pframe.listColumns();
|
|
36
|
+
} catch (err) {
|
|
37
|
+
const error = new PFrameSpecDriverError(`listColumns failed`);
|
|
38
|
+
error.cause = /* @__PURE__ */ new Error(`handle: ${handle}, error:\n${ensureError(err)}`);
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
buildQuery(input) {
|
|
43
|
+
try {
|
|
44
|
+
if (logPFrames()) this.logger.info(`buildQuery: input: ${JSON.stringify(input)}`);
|
|
45
|
+
return buildQuery(input);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
const error = new PFrameSpecDriverError(`buildQuery failed`);
|
|
48
|
+
error.cause = /* @__PURE__ */ new Error(`input: ${JSON.stringify(input)}, error:\n${ensureError(err)}`);
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
31
52
|
discoverColumns(handle, request) {
|
|
32
53
|
const pframe = this.frames.getByKey(handle);
|
|
33
54
|
try {
|
package/dist/spec_driver.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec_driver.js","names":[],"sources":["../src/spec_driver.ts"],"sourcesContent":["import {\n expandAxes,\n collapseAxes,\n findAxis,\n findTableColumn,\n} from \"@milaboratories/pframes-rs-wasm\";\nimport type {\n AxesId,\n AxesSpec,\n PColumnSpec,\n PFrameSpecDriver,\n PTableColumnId,\n PTableColumnSpec,\n SingleAxisSelector,\n SpecFrameHandle,\n PoolEntry,\n DiscoverColumnsRequest,\n DiscoverColumnsResponse,\n DeleteColumnRequest,\n DeleteColumnResponse,\n EvaluateQueryResponse,\n SpecQuery,\n} from \"@milaboratories/pl-model-common\";\nimport {\n PFrameSpecDriverError,\n ValueType,\n ensureError,\n resolveAnnotationParents,\n} from \"@milaboratories/pl-model-common\";\nimport { type MiLogger, ConsoleLoggerAdapter } from \"@milaboratories/helpers\";\nimport { PFramePool } from \"./pframe_pool\";\nimport { logPFrames } from \"./logging\";\n\n/**\n * Manages spec-only PFrame instances (WASM) with handle-based lifecycle.\n *\n * All operations are synchronous — WASM computes results immediately.\n */\nexport class SpecDriver implements PFrameSpecDriver, AsyncDisposable {\n private readonly logger: MiLogger;\n private readonly frames: PFramePool;\n\n public constructor(options?: { logger?: MiLogger }) {\n this.logger = options?.logger ?? new ConsoleLoggerAdapter();\n this.frames = new PFramePool(this.logger);\n }\n\n createSpecFrame(specs: Record<string, PColumnSpec>): PoolEntry<SpecFrameHandle> {\n const ValueTypes = new Set(Object.values(ValueType));\n const filtered = Object.fromEntries(\n Object.entries(specs)\n .filter(([, spec]) => ValueTypes.has(spec.valueType))\n .map(([id, spec]) => [id, resolveAnnotationParents(spec)]),\n );\n try {\n if (logPFrames()) {\n this.logger.info(`createSpecFrame: ${Object.keys(filtered).length} columns`);\n }\n return this.frames.acquire(filtered);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`createSpecFrame failed`);\n error.cause = ensureError(err);\n throw error;\n }\n }\n\n discoverColumns(\n handle: SpecFrameHandle,\n request: DiscoverColumnsRequest,\n ): DiscoverColumnsResponse {\n const pframe = this.frames.getByKey(handle);\n try {\n if (logPFrames()) {\n this.logger.info(\n `discoverColumns: handle = ${handle}, request: ${JSON.stringify(request)}`,\n );\n }\n const result = pframe.discoverColumns(request);\n return result;\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`discoverColumns failed`);\n error.cause = new Error(\n `handle: ${handle}, ` +\n `request: ${JSON.stringify(request)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n deleteColumn(handle: SpecFrameHandle, request: DeleteColumnRequest): DeleteColumnResponse {\n const pframe = this.frames.getByKey(handle);\n try {\n if (logPFrames()) {\n this.logger.info(`deleteColumn: handle = ${handle}, request: ${JSON.stringify(request)}`);\n }\n const result = {\n axes: pframe.deleteColumns({ columns: request.axes, delete: request.delete }).columns,\n };\n return result;\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`deleteColumn failed`);\n error.cause = new Error(\n `handle: ${handle}, ` +\n `request: ${JSON.stringify(request)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n evaluateQuery(handle: SpecFrameHandle, request: SpecQuery): EvaluateQueryResponse {\n const pframe = this.frames.getByKey(handle);\n try {\n if (logPFrames()) {\n this.logger.info(`evaluateQuery: handle = ${handle}, request: ${JSON.stringify(request)}`);\n }\n const result = pframe.evaluateQuery(request);\n return result;\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`evaluateQuery failed`);\n error.cause = new Error(\n `handle: ${handle}, ` +\n `request: ${JSON.stringify(request)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n expandAxes(spec: AxesSpec): AxesId {\n try {\n return expandAxes(spec);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`expandAxes failed`);\n error.cause = new Error(`spec: ${JSON.stringify(spec)}, ` + `error:\\n${ensureError(err)}`);\n throw error;\n }\n }\n\n collapseAxes(ids: AxesId): AxesSpec {\n try {\n return collapseAxes(ids);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`collapseAxes failed`);\n error.cause = new Error(`ids: ${JSON.stringify(ids)}, ` + `error:\\n${ensureError(err)}`);\n throw error;\n }\n }\n\n findAxis(spec: AxesSpec, selector: SingleAxisSelector): number {\n try {\n return findAxis(spec, selector);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`findAxis failed`);\n error.cause = new Error(\n `spec: ${JSON.stringify(spec)}, ` +\n `selector: ${JSON.stringify(selector)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n findTableColumn(tableSpec: PTableColumnSpec[], selector: PTableColumnId): number {\n try {\n return findTableColumn(tableSpec, selector);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`findTableColumn failed`);\n error.cause = new Error(\n `selector: ${JSON.stringify(selector)}, ` + `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n async dispose(): Promise<void> {\n await this.frames.dispose();\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.dispose();\n }\n}\n"],"mappings":";;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"spec_driver.js","names":[],"sources":["../src/spec_driver.ts"],"sourcesContent":["import {\n buildQuery,\n expandAxes,\n collapseAxes,\n findAxis,\n findTableColumn,\n} from \"@milaboratories/pframes-rs-wasm\";\nimport type {\n AxesId,\n AxesSpec,\n BuildQueryInput,\n PColumnInfo,\n PColumnSpec,\n PFrameSpecDriver,\n PTableColumnId,\n PTableColumnSpec,\n SingleAxisSelector,\n SpecFrameHandle,\n SpecQueryJoinEntry,\n PoolEntry,\n DiscoverColumnsRequest,\n DiscoverColumnsResponse,\n DeleteColumnRequest,\n DeleteColumnResponse,\n EvaluateQueryResponse,\n SpecQuery,\n} from \"@milaboratories/pl-model-common\";\nimport {\n PFrameSpecDriverError,\n ValueType,\n ensureError,\n resolveAnnotationParents,\n} from \"@milaboratories/pl-model-common\";\nimport { type MiLogger, ConsoleLoggerAdapter } from \"@milaboratories/helpers\";\nimport { PFramePool } from \"./pframe_pool\";\nimport { logPFrames } from \"./logging\";\n\n/**\n * Manages spec-only PFrame instances (WASM) with handle-based lifecycle.\n *\n * All operations are synchronous — WASM computes results immediately.\n */\nexport class SpecDriver implements PFrameSpecDriver, AsyncDisposable {\n private readonly logger: MiLogger;\n private readonly frames: PFramePool;\n\n public constructor(options?: { logger?: MiLogger }) {\n this.logger = options?.logger ?? new ConsoleLoggerAdapter();\n this.frames = new PFramePool(this.logger);\n }\n\n createSpecFrame(specs: Record<string, PColumnSpec>): PoolEntry<SpecFrameHandle> {\n const ValueTypes = new Set(Object.values(ValueType));\n const filtered = Object.fromEntries(\n Object.entries(specs)\n .filter(([, spec]) => ValueTypes.has(spec.valueType))\n .map(([id, spec]) => [id, resolveAnnotationParents(spec)]),\n );\n try {\n if (logPFrames()) {\n this.logger.info(`createSpecFrame: ${Object.keys(filtered).length} columns`);\n }\n return this.frames.acquire(filtered);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`createSpecFrame failed`);\n error.cause = ensureError(err);\n throw error;\n }\n }\n\n listColumns(handle: SpecFrameHandle): PColumnInfo[] {\n const pframe = this.frames.getByKey(handle);\n try {\n if (logPFrames()) {\n this.logger.info(`listColumns: handle = ${handle}`);\n }\n return pframe.listColumns();\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`listColumns failed`);\n error.cause = new Error(`handle: ${handle}, ` + `error:\\n${ensureError(err)}`);\n throw error;\n }\n }\n\n buildQuery(input: BuildQueryInput): SpecQueryJoinEntry {\n try {\n if (logPFrames()) {\n this.logger.info(`buildQuery: input: ${JSON.stringify(input)}`);\n }\n return buildQuery(input);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`buildQuery failed`);\n error.cause = new Error(`input: ${JSON.stringify(input)}, ` + `error:\\n${ensureError(err)}`);\n throw error;\n }\n }\n\n discoverColumns(\n handle: SpecFrameHandle,\n request: DiscoverColumnsRequest,\n ): DiscoverColumnsResponse {\n const pframe = this.frames.getByKey(handle);\n try {\n if (logPFrames()) {\n this.logger.info(\n `discoverColumns: handle = ${handle}, request: ${JSON.stringify(request)}`,\n );\n }\n const result = pframe.discoverColumns(request);\n return result;\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`discoverColumns failed`);\n error.cause = new Error(\n `handle: ${handle}, ` +\n `request: ${JSON.stringify(request)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n deleteColumn(handle: SpecFrameHandle, request: DeleteColumnRequest): DeleteColumnResponse {\n const pframe = this.frames.getByKey(handle);\n try {\n if (logPFrames()) {\n this.logger.info(`deleteColumn: handle = ${handle}, request: ${JSON.stringify(request)}`);\n }\n const result = {\n axes: pframe.deleteColumns({ columns: request.axes, delete: request.delete }).columns,\n };\n return result;\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`deleteColumn failed`);\n error.cause = new Error(\n `handle: ${handle}, ` +\n `request: ${JSON.stringify(request)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n evaluateQuery(handle: SpecFrameHandle, request: SpecQuery): EvaluateQueryResponse {\n const pframe = this.frames.getByKey(handle);\n try {\n if (logPFrames()) {\n this.logger.info(`evaluateQuery: handle = ${handle}, request: ${JSON.stringify(request)}`);\n }\n const result = pframe.evaluateQuery(request);\n return result;\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`evaluateQuery failed`);\n error.cause = new Error(\n `handle: ${handle}, ` +\n `request: ${JSON.stringify(request)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n expandAxes(spec: AxesSpec): AxesId {\n try {\n return expandAxes(spec);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`expandAxes failed`);\n error.cause = new Error(`spec: ${JSON.stringify(spec)}, ` + `error:\\n${ensureError(err)}`);\n throw error;\n }\n }\n\n collapseAxes(ids: AxesId): AxesSpec {\n try {\n return collapseAxes(ids);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`collapseAxes failed`);\n error.cause = new Error(`ids: ${JSON.stringify(ids)}, ` + `error:\\n${ensureError(err)}`);\n throw error;\n }\n }\n\n findAxis(spec: AxesSpec, selector: SingleAxisSelector): number {\n try {\n return findAxis(spec, selector);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`findAxis failed`);\n error.cause = new Error(\n `spec: ${JSON.stringify(spec)}, ` +\n `selector: ${JSON.stringify(selector)}, ` +\n `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n findTableColumn(tableSpec: PTableColumnSpec[], selector: PTableColumnId): number {\n try {\n return findTableColumn(tableSpec, selector);\n } catch (err: unknown) {\n const error = new PFrameSpecDriverError(`findTableColumn failed`);\n error.cause = new Error(\n `selector: ${JSON.stringify(selector)}, ` + `error:\\n${ensureError(err)}`,\n );\n throw error;\n }\n }\n\n async dispose(): Promise<void> {\n await this.frames.dispose();\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.dispose();\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milaboratories/pf-spec-driver",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "PSpecDriver implementation: spec-only PFrame operations via WASM",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -20,19 +20,19 @@
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@milaboratories/pframes-rs-wasm": "1.1.
|
|
23
|
+
"@milaboratories/pframes-rs-wasm": "1.1.26",
|
|
24
24
|
"@noble/hashes": "^2.0.1",
|
|
25
|
-
"@milaboratories/
|
|
26
|
-
"@milaboratories/pl-model-middle-layer": "1.
|
|
27
|
-
"@milaboratories/
|
|
25
|
+
"@milaboratories/helpers": "1.14.1",
|
|
26
|
+
"@milaboratories/pl-model-middle-layer": "1.18.1",
|
|
27
|
+
"@milaboratories/pl-model-common": "1.33.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@vitest/coverage-istanbul": "^4.1.3",
|
|
31
31
|
"typescript": "~5.9.3",
|
|
32
32
|
"vitest": "^4.1.3",
|
|
33
33
|
"@milaboratories/build-configs": "2.0.0",
|
|
34
|
-
"@milaboratories/ts-
|
|
35
|
-
"@milaboratories/ts-
|
|
34
|
+
"@milaboratories/ts-builder": "1.3.2",
|
|
35
|
+
"@milaboratories/ts-configs": "1.2.3"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "ts-builder build --target node",
|
package/src/pframe_pool.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { bytesToHex } from "@noble/hashes/utils.js";
|
|
|
15
15
|
export class PFramePool extends RefCountPoolBase<
|
|
16
16
|
Record<string, PColumnSpec>,
|
|
17
17
|
SpecFrameHandle,
|
|
18
|
-
PFrameInternal.
|
|
18
|
+
PFrameInternal.PFrameWasmV3
|
|
19
19
|
> {
|
|
20
20
|
constructor(private readonly logger: MiLogger) {
|
|
21
21
|
super();
|
|
@@ -30,14 +30,14 @@ export class PFramePool extends RefCountPoolBase<
|
|
|
30
30
|
protected createNewResource(
|
|
31
31
|
params: Record<string, PColumnSpec>,
|
|
32
32
|
key: SpecFrameHandle,
|
|
33
|
-
): PFrameInternal.
|
|
33
|
+
): PFrameInternal.PFrameWasmV3 {
|
|
34
34
|
if (logPFrames()) {
|
|
35
35
|
this.logger.info(`Creating SpecFrame for handle = ${key}, columns: ` + stringifyJson(params));
|
|
36
36
|
}
|
|
37
37
|
return createPFrame(params);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
public getByKey(key: SpecFrameHandle): PFrameInternal.
|
|
40
|
+
public getByKey(key: SpecFrameHandle): PFrameInternal.PFrameWasmV3 {
|
|
41
41
|
const resource = super.tryGetByKey(key);
|
|
42
42
|
if (!resource) {
|
|
43
43
|
const error = new PFrameDriverError(`Invalid SpecFrame handle`);
|
package/src/spec_driver.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AxisSpec, PColumnSpec } from "@milaboratories/pl-model-common";
|
|
1
|
+
import type { AxisSpec, PColumnSpec, PObjectId } from "@milaboratories/pl-model-common";
|
|
2
2
|
import { describe, expect, test } from "vitest";
|
|
3
3
|
import { SpecDriver } from "./spec_driver";
|
|
4
4
|
|
|
@@ -199,4 +199,110 @@ describe("SpecDriver", () => {
|
|
|
199
199
|
expect(linkedNames).toContain("description");
|
|
200
200
|
expect(linkedNames).toContain("priority");
|
|
201
201
|
});
|
|
202
|
+
|
|
203
|
+
test("listColumns returns all registered columns", async () => {
|
|
204
|
+
await using driver = new SpecDriver();
|
|
205
|
+
const { key: handle } = driver.createSpecFrame({
|
|
206
|
+
col1: createSpec("col1"),
|
|
207
|
+
col2: createSpec("col2"),
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
const columns = driver.listColumns(handle);
|
|
211
|
+
|
|
212
|
+
const ids = columns.map((c) => c.columnId).sort();
|
|
213
|
+
expect(ids).toEqual(["col1", "col2"]);
|
|
214
|
+
for (const c of columns) {
|
|
215
|
+
expect(c.hasData).toBe(false);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
test("buildQuery wraps a bare column with no path (no handle needed)", async () => {
|
|
220
|
+
await using driver = new SpecDriver();
|
|
221
|
+
const columnId = "c1" as PObjectId;
|
|
222
|
+
|
|
223
|
+
const entry = driver.buildQuery({ version: "v1", column: columnId });
|
|
224
|
+
|
|
225
|
+
expect(entry.entry).toEqual({ type: "column", column: columnId });
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test("discoverColumns: parallel linkers with cd-disambiguated one-side axes yield 4 variants", async () => {
|
|
229
|
+
// Port of pframes-rs-spec case 42: trunk [a1] reaches hit [a3, a2] through
|
|
230
|
+
// each of two parallel linkers whose one-side exposes a2[cd=d:1] and
|
|
231
|
+
// a2[cd=d:2]. Expected: 2 path entries x 2 cd variants = 4 total variants.
|
|
232
|
+
await using driver = new SpecDriver();
|
|
233
|
+
|
|
234
|
+
const linkerAxes: AxisSpec[] = [
|
|
235
|
+
{ type: "Int", name: "a3" } as AxisSpec,
|
|
236
|
+
{
|
|
237
|
+
type: "Int",
|
|
238
|
+
name: "a2",
|
|
239
|
+
parentAxes: [0],
|
|
240
|
+
contextDomain: { d: "1" },
|
|
241
|
+
} as AxisSpec,
|
|
242
|
+
{
|
|
243
|
+
type: "Int",
|
|
244
|
+
name: "a2",
|
|
245
|
+
parentAxes: [0],
|
|
246
|
+
contextDomain: { d: "2" },
|
|
247
|
+
} as AxisSpec,
|
|
248
|
+
{ type: "Int", name: "a1" } as AxisSpec,
|
|
249
|
+
];
|
|
250
|
+
const lClosest: PColumnSpec = {
|
|
251
|
+
kind: "PColumn",
|
|
252
|
+
name: "linker",
|
|
253
|
+
valueType: "Int",
|
|
254
|
+
axesSpec: linkerAxes,
|
|
255
|
+
domain: { algo: "closest" },
|
|
256
|
+
annotations: { "pl7.app/isLinkerColumn": "true" },
|
|
257
|
+
} as PColumnSpec;
|
|
258
|
+
const lFuel: PColumnSpec = {
|
|
259
|
+
kind: "PColumn",
|
|
260
|
+
name: "linker",
|
|
261
|
+
valueType: "Int",
|
|
262
|
+
axesSpec: linkerAxes,
|
|
263
|
+
domain: { algo: "fuelOpt" },
|
|
264
|
+
annotations: { "pl7.app/isLinkerColumn": "true" },
|
|
265
|
+
} as PColumnSpec;
|
|
266
|
+
const hitSpec: PColumnSpec = {
|
|
267
|
+
kind: "PColumn",
|
|
268
|
+
name: "hit",
|
|
269
|
+
valueType: "Int",
|
|
270
|
+
axesSpec: [
|
|
271
|
+
{ type: "Int", name: "a3" } as AxisSpec,
|
|
272
|
+
{ type: "Int", name: "a2", parentAxes: [0] } as AxisSpec,
|
|
273
|
+
],
|
|
274
|
+
annotations: {},
|
|
275
|
+
} as PColumnSpec;
|
|
276
|
+
|
|
277
|
+
const { key: handle } = driver.createSpecFrame({
|
|
278
|
+
l_closest: lClosest,
|
|
279
|
+
l_fuel: lFuel,
|
|
280
|
+
hit: hitSpec,
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
const response = driver.discoverColumns(handle, {
|
|
284
|
+
axes: [{ axesSpec: [{ type: "Int", name: "a1" } as AxisSpec], qualifications: [] }],
|
|
285
|
+
maxHops: 1,
|
|
286
|
+
constraints: {
|
|
287
|
+
allowFloatingSourceAxes: true,
|
|
288
|
+
allowFloatingHitAxes: false,
|
|
289
|
+
allowSourceQualifications: false,
|
|
290
|
+
allowHitQualifications: true,
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
expect(response.hits).toHaveLength(2);
|
|
295
|
+
const paths = response.hits
|
|
296
|
+
.map((h) => h.path.map((s) => (s.type === "linker" ? s.linker.columnId : s.filter.columnId)))
|
|
297
|
+
.sort();
|
|
298
|
+
expect(paths).toEqual([["l_closest"], ["l_fuel"]]);
|
|
299
|
+
for (const hit of response.hits) {
|
|
300
|
+
expect(hit.hit.spec.name).toBe("hit");
|
|
301
|
+
expect(hit.mappingVariants).toHaveLength(2);
|
|
302
|
+
const cdValues = hit.mappingVariants
|
|
303
|
+
.map((v) => v.qualifications.forHit[0]?.contextDomain?.d)
|
|
304
|
+
.sort();
|
|
305
|
+
expect(cdValues).toEqual(["1", "2"]);
|
|
306
|
+
}
|
|
307
|
+
});
|
|
202
308
|
});
|
package/src/spec_driver.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
buildQuery,
|
|
2
3
|
expandAxes,
|
|
3
4
|
collapseAxes,
|
|
4
5
|
findAxis,
|
|
@@ -7,12 +8,15 @@ import {
|
|
|
7
8
|
import type {
|
|
8
9
|
AxesId,
|
|
9
10
|
AxesSpec,
|
|
11
|
+
BuildQueryInput,
|
|
12
|
+
PColumnInfo,
|
|
10
13
|
PColumnSpec,
|
|
11
14
|
PFrameSpecDriver,
|
|
12
15
|
PTableColumnId,
|
|
13
16
|
PTableColumnSpec,
|
|
14
17
|
SingleAxisSelector,
|
|
15
18
|
SpecFrameHandle,
|
|
19
|
+
SpecQueryJoinEntry,
|
|
16
20
|
PoolEntry,
|
|
17
21
|
DiscoverColumnsRequest,
|
|
18
22
|
DiscoverColumnsResponse,
|
|
@@ -64,6 +68,33 @@ export class SpecDriver implements PFrameSpecDriver, AsyncDisposable {
|
|
|
64
68
|
}
|
|
65
69
|
}
|
|
66
70
|
|
|
71
|
+
listColumns(handle: SpecFrameHandle): PColumnInfo[] {
|
|
72
|
+
const pframe = this.frames.getByKey(handle);
|
|
73
|
+
try {
|
|
74
|
+
if (logPFrames()) {
|
|
75
|
+
this.logger.info(`listColumns: handle = ${handle}`);
|
|
76
|
+
}
|
|
77
|
+
return pframe.listColumns();
|
|
78
|
+
} catch (err: unknown) {
|
|
79
|
+
const error = new PFrameSpecDriverError(`listColumns failed`);
|
|
80
|
+
error.cause = new Error(`handle: ${handle}, ` + `error:\n${ensureError(err)}`);
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
buildQuery(input: BuildQueryInput): SpecQueryJoinEntry {
|
|
86
|
+
try {
|
|
87
|
+
if (logPFrames()) {
|
|
88
|
+
this.logger.info(`buildQuery: input: ${JSON.stringify(input)}`);
|
|
89
|
+
}
|
|
90
|
+
return buildQuery(input);
|
|
91
|
+
} catch (err: unknown) {
|
|
92
|
+
const error = new PFrameSpecDriverError(`buildQuery failed`);
|
|
93
|
+
error.cause = new Error(`input: ${JSON.stringify(input)}, ` + `error:\n${ensureError(err)}`);
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
67
98
|
discoverColumns(
|
|
68
99
|
handle: SpecFrameHandle,
|
|
69
100
|
request: DiscoverColumnsRequest,
|