@milaboratories/pl-middle-layer 1.18.1 → 1.19.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.
@@ -1 +1 @@
1
- {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/pool/driver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EAAE,kBAAkB,EAAgB,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAA2B,MAAM,4BAA4B,CAAC;AACpF,OAAO,EACL,yBAAyB,EACzB,0BAA0B,EAC1B,kBAAkB,EAClB,mBAAmB,EAEnB,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,IAAI,eAAe,EAC/B,OAAO,EAEP,SAAS,EACT,SAAS,EACT,SAAS,EAKV,MAAM,sBAAsB,CAAC;AAqH9B,qBAAa,YAAa,YAAW,eAAe;IAOtC,OAAO,CAAC,QAAQ,CAAC,UAAU;IANvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyD;IACjF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsE;IAC9F,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA+B;IAChE,0FAA0F;IAC1F,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA8B;gBAEpC,UAAU,EAAE,cAAc;IAmDhD,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,kBAAkB,CAAC,EAAE,GAAG,EAAE,aAAa,GAAG,YAAY;IAQlF,YAAY,CACjB,GAAG,EAAE,SAAS,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,EAC3C,GAAG,EAAE,aAAa,GACjB,YAAY;IAYF,WAAW,CACtB,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,mBAAmB,CAAC;IAiBlB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAM9E,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAM9D,kBAAkB,CAC7B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,GAC5C,OAAO,CAAC,0BAA0B,CAAC;IA6BzB,eAAe,CAC1B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,oBAAoB,CAAC;IAanB,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAKpD,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAK1D,OAAO,CAClB,MAAM,EAAE,YAAY,EACpB,aAAa,EAAE,MAAM,EAAE,EACvB,KAAK,CAAC,EAAE,UAAU,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC;CAM3B;AA+CD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAI/E"}
1
+ {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/pool/driver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EAAE,kBAAkB,EAAgB,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAA2B,MAAM,4BAA4B,CAAC;AACpF,OAAO,EACL,yBAAyB,EACzB,0BAA0B,EAC1B,kBAAkB,EAClB,mBAAmB,EAEnB,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,IAAI,eAAe,EAC/B,OAAO,EAEP,SAAS,EACT,SAAS,EACT,SAAS,EAKV,MAAM,sBAAsB,CAAC;AAqH9B,qBAAa,YAAa,YAAW,eAAe;IAOtC,OAAO,CAAC,QAAQ,CAAC,UAAU;IANvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyD;IACjF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsE;IAC9F,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA+B;IAChE,0FAA0F;IAC1F,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA8B;gBAEpC,UAAU,EAAE,cAAc;IAoDhD,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,kBAAkB,CAAC,EAAE,GAAG,EAAE,aAAa,GAAG,YAAY;IAQlF,YAAY,CACjB,GAAG,EAAE,SAAS,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,EAC3C,GAAG,EAAE,aAAa,GACjB,YAAY;IAYF,WAAW,CACtB,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,mBAAmB,CAAC;IAiBlB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAM9E,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAM9D,kBAAkB,CAC7B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,GAC5C,OAAO,CAAC,0BAA0B,CAAC;IA6BzB,eAAe,CAC1B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,oBAAoB,CAAC;IAanB,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAKpD,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAK1D,OAAO,CAClB,MAAM,EAAE,YAAY,EACpB,aAAa,EAAE,MAAM,EAAE,EACvB,KAAK,CAAC,EAAE,UAAU,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC;CAM3B;AA+CD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAI/E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milaboratories/pl-middle-layer",
3
- "version": "1.18.1",
3
+ "version": "1.19.1",
4
4
  "description": "Pl Middle Layer",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.js",
@@ -28,19 +28,19 @@
28
28
  "utility-types": "^3.11.0",
29
29
  "yaml": "^2.6.1",
30
30
  "zod": "^3.23.8",
31
- "@milaboratories/computable": "^2.3.2",
32
31
  "@milaboratories/resolve-helper": "^1.0.2",
33
- "@platforma-sdk/block-tools": "^2.3.30",
34
- "@milaboratories/pl-client": "^2.6.1",
32
+ "@milaboratories/pl-client": "^2.6.3",
33
+ "@platforma-sdk/block-tools": "^2.4.1",
35
34
  "@milaboratories/pl-model-common": "^1.8.0",
36
- "@milaboratories/pl-drivers": "^1.3.25",
37
- "@milaboratories/pl-model-middle-layer": "^1.5.13",
38
- "@milaboratories/pl-tree": "^1.4.16",
35
+ "@milaboratories/pl-drivers": "^1.4.0",
36
+ "@milaboratories/pl-tree": "^1.4.18",
37
+ "@milaboratories/pl-model-middle-layer": "^1.6.0",
39
38
  "@platforma-sdk/model": "^1.14.1",
40
- "@milaboratories/ts-helpers": "^1.1.1",
41
- "@milaboratories/pl-config": "^1.3.1",
39
+ "@milaboratories/computable": "^2.3.3",
42
40
  "@platforma-sdk/workflow-tengo": "2.5.0",
43
- "@milaboratories/pl-local": "^1.8.0"
41
+ "@milaboratories/ts-helpers": "^1.1.2",
42
+ "@milaboratories/pl-config": "^1.3.2",
43
+ "@milaboratories/pl-local": "^1.8.1"
44
44
  },
45
45
  "devDependencies": {
46
46
  "typescript": "~5.5.4",
@@ -13,11 +13,15 @@ import { LegacyDevBlockPackFiles } from '../dev_env';
13
13
  import { tryLoadPackDescription } from '@platforma-sdk/block-tools';
14
14
  import { V2RegistryProvider } from './registry-v2-provider';
15
15
  import {
16
+ AnyChannel,
16
17
  BlockPackListing,
17
18
  BlockPackOverview,
18
19
  RegistryEntry,
19
- RegistryStatus
20
+ RegistryStatus,
21
+ SingleBlockPackOverview,
22
+ StableChannel
20
23
  } from '@milaboratories/pl-model-middle-layer';
24
+ import { version } from 'node:process';
21
25
 
22
26
  async function getFileContent(path: string) {
23
27
  try {
@@ -88,8 +92,7 @@ export class BlockPackRegistry {
88
92
  name: pkg,
89
93
  version: latestVersion
90
94
  };
91
- result.push({
92
- registryId: regEntry.id,
95
+ const latestOverview: SingleBlockPackOverview = {
93
96
  id,
94
97
  meta: {
95
98
  title: latestMeta['title'] ?? 'No title',
@@ -103,17 +106,36 @@ export class BlockPackRegistry {
103
106
  type: 'from-registry-v1',
104
107
  id,
105
108
  registryUrl: regSpec.url
109
+ }
110
+ };
111
+ result.push({
112
+ registryId: regEntry.id,
113
+ id,
114
+ latestByChannel: {
115
+ [AnyChannel]: latestOverview,
116
+ [StableChannel]: latestOverview
106
117
  },
107
- otherVersions: overviewEntry.allVersions
118
+ allVersions: overviewEntry.allVersions.map((v) => ({ version: v, channels: [] }))
108
119
  });
109
120
  }
110
121
  return result;
111
122
 
112
123
  case 'remote-v2':
113
- return (await this.v2Provider.getRegistry(regSpec.url).listBlockPacks()).map((e) => ({
114
- ...e,
115
- registryId: regEntry.id
116
- }));
124
+ return (await this.v2Provider.getRegistry(regSpec.url).listBlockPacks()).map((e) =>
125
+ e.latestByChannel[StableChannel]
126
+ ? {
127
+ ...e,
128
+ registryId: regEntry.id
129
+ }
130
+ : {
131
+ ...e,
132
+ latestByChannel: {
133
+ ...e.latestByChannel,
134
+ [StableChannel]: e.latestByChannel[AnyChannel]
135
+ },
136
+ registryId: regEntry.id
137
+ }
138
+ );
117
139
 
118
140
  case 'local-dev':
119
141
  for (const entry of await fs.promises.readdir(regSpec.path, { withFileTypes: true })) {
@@ -134,8 +156,7 @@ export class BlockPackRegistry {
134
156
  version: 'DEV'
135
157
  };
136
158
 
137
- result.push({
138
- registryId: regEntry.id,
159
+ const latestOverview: SingleBlockPackOverview = {
139
160
  id,
140
161
  meta: {
141
162
  title: (config.meta['title'] as string) ?? 'No title',
@@ -149,33 +170,51 @@ export class BlockPackRegistry {
149
170
  type: 'dev-v2',
150
171
  folder: devPath,
151
172
  mtime
173
+ }
174
+ };
175
+
176
+ result.push({
177
+ registryId: regEntry.id,
178
+ id,
179
+ latestByChannel: {
180
+ [AnyChannel]: latestOverview,
181
+ [StableChannel]: latestOverview
152
182
  },
153
- otherVersions: []
183
+ allVersions: []
154
184
  });
155
185
  } else {
156
186
  let actualDevPath = devPath;
157
187
  let v2Description = await tryLoadPackDescription(actualDevPath);
158
-
188
+
159
189
  if (v2Description === undefined)
160
190
  // iterating over expected subfolder names where block developer may put root block-pack package
161
191
  for (const bpSubfolder of ['block', 'meta']) {
162
- actualDevPath = path.join(devPath, bpSubfolder)
192
+ actualDevPath = path.join(devPath, bpSubfolder);
163
193
  v2Description = await tryLoadPackDescription(actualDevPath);
164
194
  if (v2Description !== undefined) break;
165
195
  }
166
196
 
167
197
  if (v2Description !== undefined) {
168
198
  const mtime = await getDevV2PacketMtime(v2Description);
169
- result.push({
170
- registryId: regEntry.id,
199
+
200
+ const latestOverview: SingleBlockPackOverview = {
171
201
  id: v2Description.id,
172
202
  meta: await BlockPackMetaEmbedAbsoluteBytes.parseAsync(v2Description.meta),
173
203
  spec: {
174
204
  type: 'dev-v2',
175
- folder: actualDevPath,
205
+ folder: devPath,
176
206
  mtime
207
+ }
208
+ };
209
+
210
+ result.push({
211
+ registryId: regEntry.id,
212
+ id: v2Description.id,
213
+ latestByChannel: {
214
+ [AnyChannel]: latestOverview,
215
+ [StableChannel]: latestOverview
177
216
  },
178
- otherVersions: []
217
+ allVersions: []
179
218
  });
180
219
  }
181
220
  }
@@ -1,5 +1,12 @@
1
1
  import { PollComputablePool, PollPoolOps } from '@milaboratories/computable';
2
- import { blockPackIdEquals, BlockPackSpec } from '@milaboratories/pl-model-middle-layer';
2
+ import {
3
+ AnyChannel,
4
+ BlockPackFromRegistryV2,
5
+ blockPackIdEquals,
6
+ blockPackIdToString,
7
+ BlockPackSpec,
8
+ StableChannel
9
+ } from '@milaboratories/pl-model-middle-layer';
3
10
  import { Dispatcher } from 'undici';
4
11
  import { getDevV1PacketMtime, getDevV2PacketMtime } from './registry';
5
12
  import { tryLoadPackDescription } from '@platforma-sdk/block-tools';
@@ -72,7 +79,35 @@ export class BlockUpdateWatcher extends PollComputablePool<
72
79
  case 'from-registry-v2': {
73
80
  try {
74
81
  const registry = this.registryProvider.getRegistry(req.registryUrl);
75
- const spec = (await registry.getOverviewForSpec(req.id))?.spec;
82
+ let spec: BlockPackSpec | undefined;
83
+
84
+ if (req.channel === undefined) {
85
+ const a1 = await registry.getLatestOverview(req.id, StableChannel);
86
+ if (a1) spec = a1.spec;
87
+ else {
88
+ // forcing update from non-existent channel to stable
89
+ const a2 = await registry.getLatestOverview(req.id, AnyChannel);
90
+ if (a2 === undefined) {
91
+ this.logger.error(`No any channel record for ${blockPackIdToString(req.id)}`);
92
+ return undefined;
93
+ }
94
+ spec = { ...(a2.spec as BlockPackFromRegistryV2), channel: StableChannel };
95
+ }
96
+ } else {
97
+ const a1 = await registry.getLatestOverview(req.id, req.channel);
98
+ if (a1) spec = a1.spec;
99
+ else if(req.channel === StableChannel) {
100
+ // we were not able to find a stable package because there are none for the block pack yet
101
+ const a2 = await registry.getLatestOverview(req.id, AnyChannel);
102
+ if (a2 === undefined) {
103
+ this.logger.error(`No any channel record for ${blockPackIdToString(req.id)}`);
104
+ return undefined;
105
+ }
106
+ // providing "any" channel package as a substitute and marking it as stable
107
+ spec = { ...(a2.spec as BlockPackFromRegistryV2), channel: StableChannel };
108
+ }
109
+ }
110
+
76
111
  if (spec?.type !== 'from-registry-v2') throw new Error('Unexpected');
77
112
  if (blockPackIdEquals(spec.id, req.id)) return undefined;
78
113
 
@@ -1,7 +1,58 @@
1
- import { test, expect } from '@jest/globals';
2
- import { awaitBlockDone, withMl } from './middle_layer.test';
3
- import { getQuickJS, Scope, shouldInterruptAfterDeadline } from 'quickjs-emscripten';
1
+ import { expect, test } from '@jest/globals';
4
2
  import * as tp from 'node:timers/promises';
3
+ import path from 'path';
4
+ import { getQuickJS, Scope, shouldInterruptAfterDeadline } from 'quickjs-emscripten';
5
+ import { randomUUID } from 'node:crypto';
6
+ import { MiddleLayer } from './middle_layer';
7
+ import { PlClient, TestHelpers } from '@milaboratories/pl-client';
8
+ import { Project } from './project';
9
+
10
+ export async function withMl(
11
+ cb: (ml: MiddleLayer, workFolder: string) => Promise<void>
12
+ ): Promise<void> {
13
+ const workFolder = path.resolve(`work/${randomUUID()}`);
14
+
15
+ await TestHelpers.withTempRoot(async (pl: PlClient) => {
16
+ const ml = await MiddleLayer.init(pl, workFolder, {
17
+ defaultTreeOptions: { pollingInterval: 250, stopPollingDelay: 500 },
18
+ devBlockUpdateRecheckInterval: 300,
19
+ localSecret: MiddleLayer.generateLocalSecret(),
20
+ localProjections: [], // TODO must be different with local pl
21
+ openFileDialogCallback: () => {
22
+ throw new Error('Not implemented.');
23
+ }
24
+ });
25
+ try {
26
+ await cb(ml, workFolder);
27
+ } finally {
28
+ await ml.close();
29
+ }
30
+ });
31
+ }
32
+
33
+ export async function awaitBlockDone(prj: Project, blockId: string, timeout: number = 2000) {
34
+ const abortSignal = AbortSignal.timeout(timeout);
35
+ const overview = prj.overview;
36
+ const state = prj.getBlockState(blockId);
37
+ // const stateAndOverview = Computable.make(() => ({ overview, state: undefined }));
38
+ while (true) {
39
+ // const {
40
+ // overview: overviewSnapshot,
41
+ // state: stateSnapshot
42
+ // } = await stateAndOverview.getValue();
43
+ const overviewSnapshot = (await overview.getValue())!;
44
+ const blockOverview = overviewSnapshot.blocks.find((b) => b.id == blockId);
45
+ if (blockOverview === undefined) throw new Error(`Blocks not found: ${blockId}`);
46
+ if (blockOverview.outputErrors) return;
47
+ if (blockOverview.calculationStatus === 'Done') return;
48
+ try {
49
+ await overview.awaitChange(abortSignal);
50
+ } catch (e: any) {
51
+ console.dir(await state.getValue(), { depth: 5 });
52
+ throw new Error('Aborted.', { cause: e });
53
+ }
54
+ }
55
+ }
5
56
 
6
57
  test('test JS render enter numbers', async () => {
7
58
  await withMl(async (ml) => {
@@ -162,6 +162,7 @@ export class PFrameDriver implements SdkPFrameDriver {
162
162
  const concurrencyLimiter = new ConcurrencyLimitingExecutor(1);
163
163
  this.blobContentCache = blobContentCache;
164
164
  this.concurrencyLimiter = concurrencyLimiter;
165
+
165
166
  this.pFrames = new (class extends RefCountResourcePool<InternalPFrameData, PFrameHolder> {
166
167
  constructor(private readonly blobDriver: DownloadDriver) {
167
168
  super();