@milaboratories/pl-model-common 1.29.0 → 1.31.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.
Files changed (105) hide show
  1. package/dist/bmodel/block_config.d.ts +1 -0
  2. package/dist/bmodel/code.d.ts +1 -0
  3. package/dist/driver_kit.d.ts +1 -1
  4. package/dist/drivers/index.d.ts +7 -7
  5. package/dist/drivers/index.js +2 -2
  6. package/dist/drivers/pframe/data_types.cjs +0 -15
  7. package/dist/drivers/pframe/data_types.cjs.map +1 -1
  8. package/dist/drivers/pframe/data_types.d.ts +14 -60
  9. package/dist/drivers/pframe/data_types.js +1 -13
  10. package/dist/drivers/pframe/data_types.js.map +1 -1
  11. package/dist/drivers/pframe/driver.cjs.map +1 -1
  12. package/dist/drivers/pframe/driver.d.ts +13 -5
  13. package/dist/drivers/pframe/driver.js.map +1 -1
  14. package/dist/drivers/pframe/index.d.ts +6 -6
  15. package/dist/drivers/pframe/index.js +2 -2
  16. package/dist/drivers/pframe/pframe.d.ts +2 -2
  17. package/dist/drivers/pframe/query/query_common.d.ts +2 -2
  18. package/dist/drivers/pframe/query/query_data.d.ts +1 -1
  19. package/dist/drivers/pframe/query/query_spec.d.ts +2 -2
  20. package/dist/drivers/pframe/spec/ids.d.ts +2 -2
  21. package/dist/drivers/pframe/spec/index.d.ts +1 -1
  22. package/dist/drivers/pframe/spec/index.js +1 -1
  23. package/dist/drivers/pframe/spec/selectors.d.ts +1 -1
  24. package/dist/drivers/pframe/spec/spec.cjs +14 -1
  25. package/dist/drivers/pframe/spec/spec.cjs.map +1 -1
  26. package/dist/drivers/pframe/spec/spec.d.ts +7 -1
  27. package/dist/drivers/pframe/spec/spec.js +14 -2
  28. package/dist/drivers/pframe/spec/spec.js.map +1 -1
  29. package/dist/drivers/pframe/spec_driver.d.ts +36 -6
  30. package/dist/drivers/pframe/table_calculate.cjs.map +1 -1
  31. package/dist/drivers/pframe/table_calculate.d.ts +5 -6
  32. package/dist/drivers/pframe/table_calculate.js.map +1 -1
  33. package/dist/drivers/pframe/table_common.d.ts +1 -1
  34. package/dist/drivers/pframe/unique_values.d.ts +2 -2
  35. package/dist/errors.cjs +48 -0
  36. package/dist/errors.cjs.map +1 -1
  37. package/dist/errors.d.ts +25 -1
  38. package/dist/errors.js +37 -1
  39. package/dist/errors.js.map +1 -1
  40. package/dist/flags/block_flags.cjs.map +1 -1
  41. package/dist/flags/block_flags.d.ts +4 -1
  42. package/dist/flags/block_flags.js.map +1 -1
  43. package/dist/flags/flag_utils.d.ts +1 -1
  44. package/dist/flags/index.d.ts +3 -0
  45. package/dist/index.cjs +38 -3
  46. package/dist/index.d.ts +31 -22
  47. package/dist/index.js +12 -4
  48. package/dist/pool/query.d.ts +1 -1
  49. package/dist/pool_entry.cjs +30 -0
  50. package/dist/pool_entry.cjs.map +1 -0
  51. package/dist/pool_entry.d.ts +30 -0
  52. package/dist/pool_entry.js +29 -0
  53. package/dist/pool_entry.js.map +1 -0
  54. package/dist/services/index.cjs +6 -0
  55. package/dist/services/index.d.ts +6 -0
  56. package/dist/services/index.js +6 -0
  57. package/dist/services/service_capabilities.cjs +51 -0
  58. package/dist/services/service_capabilities.cjs.map +1 -0
  59. package/dist/services/service_capabilities.d.ts +33 -0
  60. package/dist/services/service_capabilities.js +46 -0
  61. package/dist/services/service_capabilities.js.map +1 -0
  62. package/dist/services/service_declarations.cjs +17 -0
  63. package/dist/services/service_declarations.cjs.map +1 -0
  64. package/dist/services/service_declarations.d.ts +16 -0
  65. package/dist/services/service_declarations.js +17 -0
  66. package/dist/services/service_declarations.js.map +1 -0
  67. package/dist/services/service_injector_factory.cjs +19 -0
  68. package/dist/services/service_injector_factory.cjs.map +1 -0
  69. package/dist/services/service_injector_factory.d.ts +8 -0
  70. package/dist/services/service_injector_factory.js +18 -0
  71. package/dist/services/service_injector_factory.js.map +1 -0
  72. package/dist/services/service_injectors.cjs +48 -0
  73. package/dist/services/service_injectors.cjs.map +1 -0
  74. package/dist/services/service_injectors.d.ts +23 -0
  75. package/dist/services/service_injectors.js +46 -0
  76. package/dist/services/service_injectors.js.map +1 -0
  77. package/dist/services/service_registry.cjs +52 -0
  78. package/dist/services/service_registry.cjs.map +1 -0
  79. package/dist/services/service_registry.d.ts +25 -0
  80. package/dist/services/service_registry.js +51 -0
  81. package/dist/services/service_registry.js.map +1 -0
  82. package/dist/services/service_types.cjs +30 -0
  83. package/dist/services/service_types.cjs.map +1 -0
  84. package/dist/services/service_types.d.ts +45 -0
  85. package/dist/services/service_types.js +28 -0
  86. package/dist/services/service_types.js.map +1 -0
  87. package/package.json +4 -4
  88. package/src/drivers/pframe/data_types.ts +18 -140
  89. package/src/drivers/pframe/driver.ts +11 -1
  90. package/src/drivers/pframe/spec/spec.ts +16 -2
  91. package/src/drivers/pframe/spec_driver.ts +37 -5
  92. package/src/drivers/pframe/table_calculate.ts +3 -4
  93. package/src/errors.ts +53 -0
  94. package/src/flags/block_flags.ts +5 -2
  95. package/src/index.ts +2 -0
  96. package/src/pool_entry.ts +42 -0
  97. package/src/services/index.ts +5 -0
  98. package/src/services/service_capabilities.test.ts +119 -0
  99. package/src/services/service_capabilities.ts +64 -0
  100. package/src/services/service_declarations.ts +25 -0
  101. package/src/services/service_injector_factory.ts +27 -0
  102. package/src/services/service_injectors.ts +79 -0
  103. package/src/services/service_registry.test.ts +69 -0
  104. package/src/services/service_registry.ts +94 -0
  105. package/src/services/service_types.ts +114 -0
@@ -26,7 +26,7 @@ export type PTableVectorTyped<DataType extends ValueType> = {
26
26
  /** Stored data type */
27
27
  readonly type: DataType;
28
28
 
29
- /** Values for present positions, absent positions have NA values */
29
+ /** Values for present positions */
30
30
  readonly data: PVectorDataTyped<DataType>;
31
31
 
32
32
  /**
@@ -36,15 +36,10 @@ export type PTableVectorTyped<DataType extends ValueType> = {
36
36
  * */
37
37
  readonly isNA?: Uint8Array;
38
38
 
39
- /**
40
- * Encoded bit array marking some elements of this vector as absent,
41
- * call {@link bitSet} to read the data.
42
- * */
43
- readonly absent: Uint8Array;
39
+ /** @deprecated Always empty. Kept for backwards compatibility with old blocks. */
40
+ readonly absent?: Uint8Array;
44
41
  };
45
- /** Table column data in comparison to the data stored in a separate PColumn
46
- * may have some of the values "absent", i.e. as a result of missing record in
47
- * outer join operation. This information is encoded in {@link absent} field. */
42
+ /** Table column data */
48
43
  export type PTableVector = PTableVectorTyped<ValueType>;
49
44
 
50
45
  function isBitSet(bitVector: Uint8Array, offset: number): boolean {
@@ -53,10 +48,6 @@ function isBitSet(bitVector: Uint8Array, offset: number): boolean {
53
48
  return (bitVector[chunkIndex] & mask) > 0;
54
49
  }
55
50
 
56
- function isValueAbsent(vector: PTableVector, row: number): boolean {
57
- return isBitSet(vector.absent, row);
58
- }
59
-
60
51
  function isValueNA(vector: PTableVector, row: number): boolean {
61
52
  if (vector.isNA) return isBitSet(vector.isNA, row);
62
53
 
@@ -81,14 +72,6 @@ function isValueNA(vector: PTableVector, row: number): boolean {
81
72
  }
82
73
  }
83
74
 
84
- export const PTableAbsent = { type: "absent" } as const;
85
- export type PTableAbsent = typeof PTableAbsent;
86
-
87
- /** Type guard for absent value */
88
- export function isPTableAbsent(value: unknown): value is PTableAbsent {
89
- return typeof value === "object" && value !== null && "type" in value && value.type === "absent";
90
- }
91
-
92
75
  export const PTableNA = null;
93
76
  export type PTableNA = typeof PTableNA;
94
77
 
@@ -120,49 +103,21 @@ export type PTableValueDataBranded<DataType extends ValueTypeSupported> = Brande
120
103
  PTableValueData<DataType>,
121
104
  DataType
122
105
  >;
123
- export type PTableValue<
124
- Absent = PTableAbsent,
125
- NA = PTableNA,
126
- DataType extends ValueTypeSupported = ValueTypeSupported,
127
- > = Absent | NA | PTableValueData<DataType>;
106
+ export type PTableValue<NA = PTableNA, DataType extends ValueTypeSupported = ValueTypeSupported> =
107
+ | NA
108
+ | PTableValueData<DataType>;
128
109
  export type PTableValueBranded<
129
- Absent = PTableAbsent,
130
110
  NA = PTableNA,
131
111
  DataType extends ValueTypeSupported = ValueTypeSupported,
132
- > = Absent | NA | PTableValueDataBranded<DataType>;
133
-
134
- export type PTableValueAxis<
135
- Absent = PTableAbsent,
136
- DataType extends ValueTypeSupported = ValueTypeSupported,
137
- > = PTableValue<Absent, never, DataType>;
112
+ > = NA | PTableValueDataBranded<DataType>;
138
113
 
139
- export function isPTableValueAxis<Absent, NA, DataType extends ValueTypeSupported>(
140
- value: PTableValue<Absent, NA, DataType>,
141
- isNA: (value: PTableValue<Absent, NA, DataType>) => value is NA,
142
- ): value is PTableValueAxis<Absent, DataType>;
143
- export function isPTableValueAxis<Absent, DataType extends ValueTypeSupported>(
144
- value: PTableValue<Absent, PTableNA, DataType>,
145
- ): value is PTableValueAxis<Absent, DataType>;
146
- export function isPTableValueAxis<
147
- Absent = PTableAbsent,
148
- NA = PTableNA,
149
- DataType extends ValueTypeSupported = ValueTypeSupported,
150
- >(
151
- value: PTableValue<Absent, NA, DataType>,
152
- isNA?: (value: PTableValue<Absent, NA, DataType>) => value is NA,
153
- ): value is PTableValueAxis<Absent, DataType> {
154
- return !(isNA ? isNA(value) : isPTableNA(value));
155
- }
114
+ export type PTableValueAxis<DataType extends ValueTypeSupported = ValueTypeSupported> =
115
+ PTableValueData<DataType>;
156
116
 
157
- function pTableValueImpl<
158
- FillAbsent = PTableAbsent,
159
- FillNA = PTableNA,
160
- DataType extends ValueType = ValueTypeSupported,
161
- >(
117
+ function pTableValueImpl<FillNA = PTableNA, DataType extends ValueType = ValueTypeSupported>(
162
118
  column: PTableVectorTyped<ValueType>,
163
119
  row: number,
164
120
  options?: {
165
- absent?: FillAbsent;
166
121
  na?: FillNA;
167
122
  dataType?: DataType;
168
123
  },
@@ -181,10 +136,6 @@ function pTableValueImpl<
181
136
  throw Error(`expected column of type ${options.dataType}, got ${valueType}`);
182
137
  }
183
138
 
184
- if (isValueAbsent(column, row)) {
185
- return options?.absent !== undefined ? options.absent : PTableAbsent;
186
- }
187
-
188
139
  if (isValueNA(column, row)) {
189
140
  return options?.na !== undefined ? options.na : PTableNA;
190
141
  }
@@ -208,37 +159,14 @@ function pTableValueImpl<
208
159
  export function pTableValue<DataType extends ValueType>(
209
160
  column: PTableVectorTyped<DataType>,
210
161
  row: number,
211
- ): DataType extends ValueTypeSupported ? PTableValue<PTableAbsent, PTableNA, DataType> : never;
212
- export function pTableValue<FillAbsent, DataType extends ValueType>(
213
- column: PTableVectorTyped<DataType>,
214
- row: number,
215
- options: {
216
- absent: FillAbsent;
217
- },
218
- ): DataType extends ValueTypeSupported ? PTableValue<FillAbsent, PTableNA, DataType> : never;
162
+ ): DataType extends ValueTypeSupported ? PTableValue<PTableNA, DataType> : never;
219
163
  export function pTableValue<FillNA, DataType extends ValueType>(
220
164
  column: PTableVectorTyped<DataType>,
221
165
  row: number,
222
166
  options: {
223
167
  na: FillNA;
224
168
  },
225
- ): DataType extends ValueTypeSupported ? PTableValue<PTableAbsent, FillNA, DataType> : never;
226
- export function pTableValue<FillNA, FillAbsent, DataType extends ValueType>(
227
- column: PTableVectorTyped<DataType>,
228
- row: number,
229
- options: {
230
- absent: FillAbsent;
231
- na: FillNA;
232
- },
233
- ): DataType extends ValueTypeSupported ? PTableValue<FillAbsent, FillNA, DataType> : never;
234
- export function pTableValue<FillAbsent, DataType extends ValueTypeSupported>(
235
- column: PTableVectorTyped<ValueType>,
236
- row: number,
237
- options: {
238
- absent: FillAbsent;
239
- dataType: DataType;
240
- },
241
- ): PTableValue<FillAbsent, PTableNA>;
169
+ ): DataType extends ValueTypeSupported ? PTableValue<FillNA, DataType> : never;
242
170
  export function pTableValue<FillNA, DataType extends ValueTypeSupported>(
243
171
  column: PTableVectorTyped<ValueType>,
244
172
  row: number,
@@ -246,25 +174,11 @@ export function pTableValue<FillNA, DataType extends ValueTypeSupported>(
246
174
  na: FillNA;
247
175
  dataType: DataType;
248
176
  },
249
- ): PTableValue<PTableAbsent, FillNA, DataType>;
250
- export function pTableValue<FillNA, FillAbsent, DataType extends ValueTypeSupported>(
251
- column: PTableVectorTyped<ValueType>,
252
- row: number,
253
- options: {
254
- absent: FillAbsent;
255
- na: FillNA;
256
- dataType: DataType;
257
- },
258
- ): PTableValue<FillAbsent, FillNA, DataType>;
259
- export function pTableValue<
260
- FillAbsent = PTableAbsent,
261
- FillNA = PTableNA,
262
- DataType extends ValueType = ValueTypeSupported,
263
- >(
177
+ ): PTableValue<FillNA, DataType>;
178
+ export function pTableValue<FillNA = PTableNA, DataType extends ValueType = ValueTypeSupported>(
264
179
  column: PTableVectorTyped<ValueType>,
265
180
  row: number,
266
181
  options?: {
267
- absent?: FillAbsent;
268
182
  na?: FillNA;
269
183
  dataType?: DataType;
270
184
  },
@@ -275,39 +189,14 @@ export function pTableValue<
275
189
  export function pTableValueBranded<DataType extends ValueType>(
276
190
  column: PTableVectorTyped<DataType>,
277
191
  row: number,
278
- ): DataType extends ValueTypeSupported
279
- ? PTableValueBranded<PTableAbsent, PTableNA, DataType>
280
- : never;
281
- export function pTableValueBranded<FillAbsent, DataType extends ValueType>(
282
- column: PTableVectorTyped<DataType>,
283
- row: number,
284
- options: {
285
- absent: FillAbsent;
286
- },
287
- ): DataType extends ValueTypeSupported ? PTableValueBranded<FillAbsent, PTableNA, DataType> : never;
192
+ ): DataType extends ValueTypeSupported ? PTableValueBranded<PTableNA, DataType> : never;
288
193
  export function pTableValueBranded<FillNA, DataType extends ValueType>(
289
194
  column: PTableVectorTyped<DataType>,
290
195
  row: number,
291
196
  options: {
292
197
  na: FillNA;
293
198
  },
294
- ): DataType extends ValueTypeSupported ? PTableValueBranded<PTableAbsent, FillNA, DataType> : never;
295
- export function pTableValueBranded<FillNA, FillAbsent, DataType extends ValueType>(
296
- column: PTableVectorTyped<DataType>,
297
- row: number,
298
- options: {
299
- absent: FillAbsent;
300
- na: FillNA;
301
- },
302
- ): DataType extends ValueTypeSupported ? PTableValueBranded<FillAbsent, FillNA, DataType> : never;
303
- export function pTableValueBranded<FillAbsent, DataType extends ValueTypeSupported>(
304
- column: PTableVectorTyped<ValueType>,
305
- row: number,
306
- options: {
307
- absent: FillAbsent;
308
- dataType: DataType;
309
- },
310
- ): PTableValueBranded<FillAbsent, PTableNA>;
199
+ ): DataType extends ValueTypeSupported ? PTableValueBranded<FillNA, DataType> : never;
311
200
  export function pTableValueBranded<FillNA, DataType extends ValueTypeSupported>(
312
201
  column: PTableVectorTyped<ValueType>,
313
202
  row: number,
@@ -315,25 +204,14 @@ export function pTableValueBranded<FillNA, DataType extends ValueTypeSupported>(
315
204
  na: FillNA;
316
205
  dataType: DataType;
317
206
  },
318
- ): PTableValueBranded<PTableAbsent, FillNA, DataType>;
319
- export function pTableValueBranded<FillNA, FillAbsent, DataType extends ValueTypeSupported>(
320
- column: PTableVectorTyped<ValueType>,
321
- row: number,
322
- options: {
323
- absent: FillAbsent;
324
- na: FillNA;
325
- dataType: DataType;
326
- },
327
- ): PTableValueBranded<FillAbsent, FillNA, DataType>;
207
+ ): PTableValueBranded<FillNA, DataType>;
328
208
  export function pTableValueBranded<
329
- FillAbsent = PTableAbsent,
330
209
  FillNA = PTableNA,
331
210
  DataType extends ValueType = ValueTypeSupported,
332
211
  >(
333
212
  column: PTableVectorTyped<ValueType>,
334
213
  row: number,
335
214
  options?: {
336
- absent?: FillAbsent;
337
215
  na?: FillNA;
338
216
  dataType?: DataType;
339
217
  },
@@ -1,6 +1,9 @@
1
1
  import type { Branded } from "../../branding";
2
2
  import type { PTable } from "./table";
3
- import type { PFrame } from "./pframe";
3
+ import type { PFrame, PFrameDef } from "./pframe";
4
+ import type { PColumn } from "./spec/spec";
5
+ import type { PColumnValues, DataInfo } from "./data_info";
6
+ import type { PTableDef, PTableDefV2 } from "./table_calculate";
4
7
  import type { AddParameterToAllMethods } from "./type_util";
5
8
  import type { PTableShape, PTableVector, TableRange } from "./data_types";
6
9
  import type { FindColumnsRequest, FindColumnsResponse } from "./find_columns";
@@ -16,6 +19,13 @@ export type PFrameHandle = Branded<string, "PFrame">;
16
19
  /** PFrame handle */
17
20
  export type PTableHandle = Branded<string, "PTable">;
18
21
 
22
+ /** Model-side PFrame service — creates frames/tables from column definitions. */
23
+ export interface PFrameModelDriver<Col = PColumn<string | PColumnValues | DataInfo<string>>> {
24
+ createPFrame(def: PFrameDef<Col>): PFrameHandle;
25
+ createPTable(def: PTableDef<Col>): PTableHandle;
26
+ createPTableV2(def: PTableDefV2<Col>): PTableHandle;
27
+ }
28
+
19
29
  /** Allows to access main data layer features of platforma */
20
30
  export interface PFrameDriver {
21
31
  //
@@ -508,8 +508,6 @@ export function getNormalizedAxesList(axes: AxisSpec[]): AxisSpecNormalized[] {
508
508
  modifiedAxis.parentAxesSpec = parents.some((p) => p === undefined)
509
509
  ? []
510
510
  : (parents as AxisSpecNormalized[]);
511
-
512
- delete modifiedAxis.annotations?.[Annotation.Parents];
513
511
  }
514
512
  });
515
513
 
@@ -543,6 +541,22 @@ export function getDenormalizedAxesList(axesSpec: AxisSpecNormalized[]): AxisSpe
543
541
  });
544
542
  }
545
543
 
544
+ /**
545
+ * Resolve annotation-based parents (`pl7.app/parents`) to numeric `parentAxes`
546
+ * on a column spec. Returns the spec unchanged if all axes already use numeric
547
+ * indices or have no parent annotations.
548
+ */
549
+ export function resolveAnnotationParents(spec: PColumnSpec): PColumnSpec {
550
+ const hasAnnotationParents = spec.axesSpec.some(
551
+ (axis) => !!readAnnotationJson(axis, Annotation.Parents),
552
+ );
553
+ if (!hasAnnotationParents) return spec;
554
+
555
+ const normalized = getNormalizedAxesList(spec.axesSpec);
556
+ const denormalized = getDenormalizedAxesList(normalized);
557
+ return { ...spec, axesSpec: denormalized };
558
+ }
559
+
546
560
  /** Common type representing spec for all the axes in a column */
547
561
  export type AxesSpec = AxisSpec[];
548
562
 
@@ -1,4 +1,5 @@
1
1
  import type { Branded } from "@milaboratories/helpers";
2
+ import type { PoolEntry } from "../../pool_entry";
2
3
  import type {
3
4
  AxisSpec,
4
5
  AxesSpec,
@@ -10,6 +11,7 @@ import type {
10
11
  ColumnValueType,
11
12
  } from "./spec";
12
13
  import type { PTableColumnId, PTableColumnSpec } from "./table_common";
14
+ import { DataQuery, SpecQuery } from "./query";
13
15
 
14
16
  /** Matches a string value either exactly or by regex pattern */
15
17
  export type StringMatcher =
@@ -144,6 +146,33 @@ export interface DiscoverColumnsResponse {
144
146
  hits: DiscoverColumnsResponseHit[];
145
147
  }
146
148
 
149
+ /** Request for deleting an entry from a given axes integration */
150
+ export interface DeleteColumnRequest {
151
+ /** Already integrated axes with qualifications */
152
+ axes: ColumnAxesWithQualifications[];
153
+ /** Zero based index of the entry to be deleted */
154
+ delete: number;
155
+ }
156
+
157
+ /** Response from delete column */
158
+ export interface DeleteColumnResponse {
159
+ axes: ColumnAxesWithQualifications[];
160
+ }
161
+
162
+ /** Response from evaluating a query against a PFrame. */
163
+ export type EvaluateQueryResponse = {
164
+ /**
165
+ * The table specification describing the structure of the query result,
166
+ * including all axes and columns that will be present in the output.
167
+ */
168
+ tableSpec: PTableColumnSpec[];
169
+ /**
170
+ * The data layer query representation with numeric indices,
171
+ * suitable for execution by the data processing engine.
172
+ */
173
+ dataQuery: DataQuery;
174
+ };
175
+
147
176
  /** Handle to a spec-only PFrame (no data, synchronous operations). */
148
177
  export type SpecFrameHandle = Branded<string, "SpecFrameHandle">;
149
178
 
@@ -155,17 +184,20 @@ export type SpecFrameHandle = Branded<string, "SpecFrameHandle">;
155
184
  * because the underlying WASM PFrame computes results immediately.
156
185
  */
157
186
  export interface PFrameSpecDriver {
158
- /** Create a spec-only PFrame from column specs. Returns a handle. */
159
- createSpecFrame(specs: Record<string, PColumnSpec>): SpecFrameHandle;
187
+ /** Create a spec-only PFrame from column specs. Returns a pool entry with handle and unref. */
188
+ createSpecFrame(specs: Record<string, PColumnSpec>): PoolEntry<SpecFrameHandle>;
160
189
 
161
190
  /** Discover columns compatible with given axes integration. */
162
- specFrameDiscoverColumns(
191
+ discoverColumns(
163
192
  handle: SpecFrameHandle,
164
193
  request: DiscoverColumnsRequest,
165
194
  ): DiscoverColumnsResponse;
166
195
 
167
- /** Dispose a spec frame, freeing WASM resources. */
168
- disposeSpecFrame(handle: SpecFrameHandle): void;
196
+ /** Delete an entry from a given axes integration */
197
+ deleteColumn(handle: SpecFrameHandle, request: DeleteColumnRequest): DeleteColumnResponse;
198
+
199
+ /** Evaluates a query specification against this PFrame */
200
+ evaluateQuery(handle: SpecFrameHandle, request: SpecQuery): EvaluateQueryResponse;
169
201
 
170
202
  /** Expand index-based parentAxes in AxesSpec to resolved AxisId parents in AxesId. */
171
203
  expandAxes(spec: AxesSpec): AxesId;
@@ -85,8 +85,7 @@ export interface InnerJoin<Col> {
85
85
  /**
86
86
  * Defines a join request tree node that will output all records present at
87
87
  * least in one of the child nodes ({@link entries}), values for those PColumns
88
- * that lacks corresponding combinations of axis values will be marked as absent,
89
- * see {@link PTableVector.absent}.
88
+ * that lack corresponding combinations of axis values will be null.
90
89
  * */
91
90
  export interface FullJoin<Col> {
92
91
  /** Node type discriminator */
@@ -100,8 +99,8 @@ export interface FullJoin<Col> {
100
99
  * Defines a join request tree node that will output all records present in
101
100
  * {@link primary} child node, and records from the {@link secondary} nodes will
102
101
  * be added to the output only if present, values for those PColumns from the
103
- * {@link secondary} list, that lacks corresponding combinations of axis values
104
- * will be marked as absent, see {@link PTableVector.absent}.
102
+ * {@link secondary} list, that lack corresponding combinations of axis values
103
+ * will be null.
105
104
  *
106
105
  * This node can be thought as a chain of SQL LEFT JOIN operations starting from
107
106
  * the {@link primary} node and adding {@link secondary} nodes one by one.
package/src/errors.ts CHANGED
@@ -28,6 +28,59 @@ export function isAggregateError(error: unknown): error is AggregateError {
28
28
  return error instanceof Error && error.name === "AggregateError";
29
29
  }
30
30
 
31
+ export class ServiceError extends Error {
32
+ name = "ServiceError";
33
+ }
34
+
35
+ export function isServiceError(error: unknown): error is ServiceError {
36
+ return (
37
+ error instanceof Error &&
38
+ (error.name === "ServiceError" || error.name.startsWith("ServiceError."))
39
+ );
40
+ }
41
+
42
+ export class ServiceInvalidIdError extends ServiceError {
43
+ name = "ServiceError.InvalidId";
44
+ }
45
+
46
+ export function isServiceInvalidIdError(error: unknown): error is ServiceInvalidIdError {
47
+ return error instanceof Error && error.name === "ServiceError.InvalidId";
48
+ }
49
+
50
+ export class ServiceAlreadyRegisteredError extends ServiceError {
51
+ name = "ServiceError.AlreadyRegistered";
52
+ }
53
+
54
+ export function isServiceAlreadyRegisteredError(
55
+ error: unknown,
56
+ ): error is ServiceAlreadyRegisteredError {
57
+ return error instanceof Error && error.name === "ServiceError.AlreadyRegistered";
58
+ }
59
+
60
+ export class ServiceInjectionError extends ServiceError {
61
+ name = "ServiceError.Injection";
62
+ }
63
+
64
+ export function isServiceInjectionError(error: unknown): error is ServiceInjectionError {
65
+ return error instanceof Error && error.name === "ServiceError.Injection";
66
+ }
67
+
68
+ export class ServiceNotRegisteredError extends ServiceError {
69
+ name = "ServiceError.NotRegistered";
70
+ }
71
+
72
+ export function isServiceNotRegisteredError(error: unknown): error is ServiceNotRegisteredError {
73
+ return error instanceof Error && error.name === "ServiceError.NotRegistered";
74
+ }
75
+
76
+ export class ServiceMethodNotFoundError extends ServiceError {
77
+ name = "ServiceError.MethodNotFound";
78
+ }
79
+
80
+ export function isServiceMethodNotFoundError(error: unknown): error is ServiceMethodNotFoundError {
81
+ return error instanceof Error && error.name === "ServiceError.MethodNotFound";
82
+ }
83
+
31
84
  export class PFrameError extends Error {
32
85
  name = "PFrameError";
33
86
  }
@@ -1,3 +1,4 @@
1
+ import type { ServiceRequireFlags } from "../services";
1
2
  import type { ArrayTypeUnion, Assert, Is, IsSubtypeOf } from "./type_utils";
2
3
 
3
4
  /**
@@ -20,7 +21,7 @@ export type BlockCodeKnownFeatureFlags = {
20
21
  readonly requiresModelAPIVersion?: number;
21
22
  readonly requiresUIAPIVersion?: number;
22
23
  readonly requiresCreatePTable?: number;
23
- };
24
+ } & ServiceRequireFlags;
24
25
 
25
26
  export const AllSupportsFeatureFlags = ["supportsLazyState", "supportsPframeQueryRanking"] as const;
26
27
 
@@ -42,9 +43,11 @@ type _KnownFlagsAreValidFlags = Assert<
42
43
 
43
44
  // This check ensures that all keys in BlockConfigV3FeatureFlags are covered in the arrays above.
44
45
  // It will produce a compile-time error if there's a mismatch.
46
+ // Adding a service to Services automatically satisfies this assertion via ServiceRequireFlags.
45
47
  type _AllFlagsAreCovered = Assert<
46
48
  Is<
47
49
  keyof BlockCodeKnownFeatureFlags,
48
- ArrayTypeUnion<typeof AllRequiresFeatureFlags, typeof AllSupportsFeatureFlags>
50
+ | ArrayTypeUnion<typeof AllRequiresFeatureFlags, typeof AllSupportsFeatureFlags>
51
+ | keyof ServiceRequireFlags
49
52
  >
50
53
  >;
package/src/index.ts CHANGED
@@ -18,3 +18,5 @@ export * from "./base64";
18
18
  export * from "./util";
19
19
  export * from "./httpAuth";
20
20
  export * from "./resource_types";
21
+ export * from "./services";
22
+ export * from "./pool_entry";
@@ -0,0 +1,42 @@
1
+ export interface PoolEntry<K extends string = string, R extends {} = {}> extends Disposable {
2
+ /** Resource key, calculated using provided `calculateParamsKey` function */
3
+ readonly key: K;
4
+
5
+ /** Resource itself created by `createNewResource` function */
6
+ readonly resource: R;
7
+
8
+ /**
9
+ * Release the reference. Idempotent.
10
+ * Same as `[Symbol.dispose]()` — provided as a named function
11
+ * for use in callbacks (e.g. `addOnDestroy(entry.unref)`).
12
+ */
13
+ readonly unref: () => void;
14
+ }
15
+
16
+ /**
17
+ * Wraps a PoolEntry for use with `using`. Auto-calls `unref()` at end of scope
18
+ * unless `keep()` is called to transfer ownership to the caller.
19
+ */
20
+ export class PoolEntryGuard<K extends string = string, R extends {} = {}> implements Disposable {
21
+ private kept = false;
22
+
23
+ constructor(readonly entry: PoolEntry<K, R>) {}
24
+
25
+ get key(): K {
26
+ return this.entry.key;
27
+ }
28
+
29
+ get resource(): R {
30
+ return this.entry.resource;
31
+ }
32
+
33
+ /** Disarm the guard — caller takes ownership of the entry. */
34
+ keep(): PoolEntry<K, R> {
35
+ this.kept = true;
36
+ return this.entry;
37
+ }
38
+
39
+ [Symbol.dispose](): void {
40
+ if (!this.kept) this.entry.unref();
41
+ }
42
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./service_types";
2
+ export * from "./service_registry";
3
+ export * from "./service_declarations";
4
+ export * from "./service_capabilities";
5
+ export * from "./service_injectors";
@@ -0,0 +1,119 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import {
3
+ SERVICE_CAPABILITY_FLAGS,
4
+ registerServiceCapabilities,
5
+ resolveRequiredServices,
6
+ getMethodNames,
7
+ isKnownServiceName,
8
+ } from "./service_capabilities";
9
+ import { Services } from "./service_declarations";
10
+
11
+ describe("SERVICE_CAPABILITY_FLAGS", () => {
12
+ it("should have one flag per service", () => {
13
+ expect(SERVICE_CAPABILITY_FLAGS).toHaveLength(Object.keys(Services).length);
14
+ });
15
+
16
+ it("should derive requires* flag names from Services keys", () => {
17
+ for (const key of Object.keys(Services)) {
18
+ expect(SERVICE_CAPABILITY_FLAGS).toContain(`requires${key}`);
19
+ }
20
+ });
21
+ });
22
+
23
+ describe("registerServiceCapabilities", () => {
24
+ it("should call register once per service with (flag, true)", () => {
25
+ const register = vi.fn();
26
+ registerServiceCapabilities(register);
27
+ expect(register).toHaveBeenCalledTimes(Object.keys(Services).length);
28
+ for (const call of register.mock.calls) {
29
+ expect(call[0]).toMatch(/^requires[A-Z]/);
30
+ expect(call[1]).toBe(true);
31
+ }
32
+ });
33
+ });
34
+
35
+ describe("resolveRequiredServices", () => {
36
+ it("should return empty array for undefined flags", () => {
37
+ expect(resolveRequiredServices(undefined)).toEqual([]);
38
+ });
39
+
40
+ it("should return empty array for flags without requires*", () => {
41
+ expect(resolveRequiredServices({ supportsLazyState: true })).toEqual([]);
42
+ });
43
+
44
+ it("should return empty array when requires* is false", () => {
45
+ expect(resolveRequiredServices({ requiresPFrameSpec: false })).toEqual([]);
46
+ });
47
+
48
+ it("should resolve a single required service", () => {
49
+ const result = resolveRequiredServices({ requiresPFrameSpec: true });
50
+ expect(result).toEqual([Services.PFrameSpec]);
51
+ });
52
+
53
+ it("should resolve multiple required services", () => {
54
+ const result = resolveRequiredServices({
55
+ requiresPFrameSpec: true,
56
+ requiresPFrame: true,
57
+ });
58
+ expect(result).toContain(Services.PFrameSpec);
59
+ expect(result).toContain(Services.PFrame);
60
+ expect(result).toHaveLength(2);
61
+ });
62
+
63
+ it("should ignore non-boolean requires* values", () => {
64
+ const result = resolveRequiredServices({
65
+ requiresPFrameSpec: true,
66
+ requiresModelAPIVersion: 2,
67
+ });
68
+ expect(result).toEqual([Services.PFrameSpec]);
69
+ });
70
+ });
71
+
72
+ describe("isKnownServiceName", () => {
73
+ it("should return true for registered service names", () => {
74
+ for (const id of Object.values(Services)) {
75
+ expect(isKnownServiceName(id as string)).toBe(true);
76
+ }
77
+ });
78
+
79
+ it("should return false for unknown names", () => {
80
+ expect(isKnownServiceName("nonexistent")).toBe(false);
81
+ });
82
+ });
83
+
84
+ describe("getMethodNames", () => {
85
+ it("should return own method names", () => {
86
+ const obj = {
87
+ foo() {},
88
+ bar() {},
89
+ baz: 42,
90
+ };
91
+ const names = getMethodNames(obj as any);
92
+ expect(names).toContain("foo");
93
+ expect(names).toContain("bar");
94
+ expect(names).not.toContain("baz");
95
+ });
96
+
97
+ it("should include prototype methods", () => {
98
+ class Base {
99
+ baseMethod() {}
100
+ }
101
+ class Child extends Base {
102
+ childMethod() {}
103
+ }
104
+ const names = getMethodNames(new Child() as any);
105
+ expect(names).toContain("baseMethod");
106
+ expect(names).toContain("childMethod");
107
+ expect(names).not.toContain("constructor");
108
+ });
109
+
110
+ it("should not include getters", () => {
111
+ const obj = Object.create(null, {
112
+ method: { value: () => {}, enumerable: true },
113
+ getter: { get: () => 42, enumerable: true },
114
+ });
115
+ const names = getMethodNames(obj);
116
+ expect(names).toContain("method");
117
+ expect(names).not.toContain("getter");
118
+ });
119
+ });