@milaboratories/pl-middle-layer 1.10.12
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/block_registry/index.d.ts +4 -0
- package/dist/block_registry/index.d.ts.map +1 -0
- package/dist/block_registry/registry.d.ts +37 -0
- package/dist/block_registry/registry.d.ts.map +1 -0
- package/dist/block_registry/registry_spec.d.ts +12 -0
- package/dist/block_registry/registry_spec.d.ts.map +1 -0
- package/dist/block_registry/watcher.d.ts +15 -0
- package/dist/block_registry/watcher.d.ts.map +1 -0
- package/dist/block_registry/well_known_registries.d.ts +4 -0
- package/dist/block_registry/well_known_registries.d.ts.map +1 -0
- package/dist/cfg_render/executor.d.ts +8 -0
- package/dist/cfg_render/executor.d.ts.map +1 -0
- package/dist/cfg_render/operation.d.ts +29 -0
- package/dist/cfg_render/operation.d.ts.map +1 -0
- package/dist/cfg_render/renderer.d.ts +6 -0
- package/dist/cfg_render/renderer.d.ts.map +1 -0
- package/dist/cfg_render/traverse.d.ts +3 -0
- package/dist/cfg_render/traverse.d.ts.map +1 -0
- package/dist/cfg_render/util.d.ts +5 -0
- package/dist/cfg_render/util.d.ts.map +1 -0
- package/dist/dev/index.d.ts +21 -0
- package/dist/dev/index.d.ts.map +1 -0
- package/dist/dev/util.d.ts +3 -0
- package/dist/dev/util.d.ts.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3587 -0
- package/dist/index.mjs.map +1 -0
- package/dist/js_render/context.d.ts +68 -0
- package/dist/js_render/context.d.ts.map +1 -0
- package/dist/js_render/index.d.ts +6 -0
- package/dist/js_render/index.d.ts.map +1 -0
- package/dist/middle_layer/active_cfg.d.ts +6 -0
- package/dist/middle_layer/active_cfg.d.ts.map +1 -0
- package/dist/middle_layer/block.d.ts +9 -0
- package/dist/middle_layer/block.d.ts.map +1 -0
- package/dist/middle_layer/block_ctx.d.ts +20 -0
- package/dist/middle_layer/block_ctx.d.ts.map +1 -0
- package/dist/middle_layer/block_ctx_unsafe.d.ts +16 -0
- package/dist/middle_layer/block_ctx_unsafe.d.ts.map +1 -0
- package/dist/middle_layer/driver_kit.d.ts +31 -0
- package/dist/middle_layer/driver_kit.d.ts.map +1 -0
- package/dist/middle_layer/frontend_path.d.ts +6 -0
- package/dist/middle_layer/frontend_path.d.ts.map +1 -0
- package/dist/middle_layer/index.d.ts +5 -0
- package/dist/middle_layer/index.d.ts.map +1 -0
- package/dist/middle_layer/middle_layer.d.ts +78 -0
- package/dist/middle_layer/middle_layer.d.ts.map +1 -0
- package/dist/middle_layer/navigation_states.d.ts +10 -0
- package/dist/middle_layer/navigation_states.d.ts.map +1 -0
- package/dist/middle_layer/ops.d.ts +64 -0
- package/dist/middle_layer/ops.d.ts.map +1 -0
- package/dist/middle_layer/project.d.ts +110 -0
- package/dist/middle_layer/project.d.ts.map +1 -0
- package/dist/middle_layer/project_list.d.ts +11 -0
- package/dist/middle_layer/project_list.d.ts.map +1 -0
- package/dist/middle_layer/project_overview.d.ts +8 -0
- package/dist/middle_layer/project_overview.d.ts.map +1 -0
- package/dist/middle_layer/render.d.ts +6 -0
- package/dist/middle_layer/render.d.ts.map +1 -0
- package/dist/middle_layer/types.d.ts +11 -0
- package/dist/middle_layer/types.d.ts.map +1 -0
- package/dist/middle_layer/util.d.ts +3 -0
- package/dist/middle_layer/util.d.ts.map +1 -0
- package/dist/model/args.d.ts +12 -0
- package/dist/model/args.d.ts.map +1 -0
- package/dist/model/block_pack.d.ts +8 -0
- package/dist/model/block_pack.d.ts.map +1 -0
- package/dist/model/block_pack_spec.d.ts +40 -0
- package/dist/model/block_pack_spec.d.ts.map +1 -0
- package/dist/model/frontend.d.ts +10 -0
- package/dist/model/frontend.d.ts.map +1 -0
- package/dist/model/index.d.ts +3 -0
- package/dist/model/index.d.ts.map +1 -0
- package/dist/model/project_model.d.ts +67 -0
- package/dist/model/project_model.d.ts.map +1 -0
- package/dist/model/project_model_util.d.ts +29 -0
- package/dist/model/project_model_util.d.ts.map +1 -0
- package/dist/model/template_spec.d.ts +16 -0
- package/dist/model/template_spec.d.ts.map +1 -0
- package/dist/mutator/block-pack/block_pack.d.ts +17 -0
- package/dist/mutator/block-pack/block_pack.d.ts.map +1 -0
- package/dist/mutator/block-pack/frontend.d.ts +4 -0
- package/dist/mutator/block-pack/frontend.d.ts.map +1 -0
- package/dist/mutator/context_export.d.ts +9 -0
- package/dist/mutator/context_export.d.ts.map +1 -0
- package/dist/mutator/project.d.ts +121 -0
- package/dist/mutator/project.d.ts.map +1 -0
- package/dist/mutator/template/render_block.d.ts +32 -0
- package/dist/mutator/template/render_block.d.ts.map +1 -0
- package/dist/mutator/template/render_template.d.ts +12 -0
- package/dist/mutator/template/render_template.d.ts.map +1 -0
- package/dist/mutator/template/template_loading.d.ts +13 -0
- package/dist/mutator/template/template_loading.d.ts.map +1 -0
- package/dist/pool/data.d.ts +24 -0
- package/dist/pool/data.d.ts.map +1 -0
- package/dist/pool/driver.d.ts +22 -0
- package/dist/pool/driver.d.ts.map +1 -0
- package/dist/pool/index.d.ts +3 -0
- package/dist/pool/index.d.ts.map +1 -0
- package/dist/pool/p_object_collection.d.ts +29 -0
- package/dist/pool/p_object_collection.d.ts.map +1 -0
- package/dist/pool/ref_count_pool.d.ts +25 -0
- package/dist/pool/ref_count_pool.d.ts.map +1 -0
- package/dist/pool/result_pool.d.ts +25 -0
- package/dist/pool/result_pool.d.ts.map +1 -0
- package/dist/test/block_packs.d.ts +6 -0
- package/dist/test/block_packs.d.ts.map +1 -0
- package/dist/test/explicit_templates.d.ts +3 -0
- package/dist/test/explicit_templates.d.ts.map +1 -0
- package/dist/test/known_templates.d.ts +6 -0
- package/dist/test/known_templates.d.ts.map +1 -0
- package/package.json +55 -0
- package/src/block_registry/index.ts +3 -0
- package/src/block_registry/registry.test.ts +35 -0
- package/src/block_registry/registry.ts +180 -0
- package/src/block_registry/registry_spec.ts +13 -0
- package/src/block_registry/watcher.ts +72 -0
- package/src/block_registry/well_known_registries.ts +13 -0
- package/src/cfg_render/executor.test.ts +120 -0
- package/src/cfg_render/executor.ts +253 -0
- package/src/cfg_render/operation.ts +38 -0
- package/src/cfg_render/renderer.ts +540 -0
- package/src/cfg_render/traverse.ts +58 -0
- package/src/cfg_render/util.ts +29 -0
- package/src/dev/index.ts +89 -0
- package/src/dev/util.ts +13 -0
- package/src/index.ts +21 -0
- package/src/js_render/context.ts +768 -0
- package/src/js_render/index.ts +41 -0
- package/src/middle_layer/active_cfg.ts +56 -0
- package/src/middle_layer/block.ts +70 -0
- package/src/middle_layer/block_ctx.ts +90 -0
- package/src/middle_layer/block_ctx_unsafe.ts +29 -0
- package/src/middle_layer/driver_kit.ts +107 -0
- package/src/middle_layer/frontend_path.ts +83 -0
- package/src/middle_layer/index.ts +4 -0
- package/src/middle_layer/middle_layer.test.ts +720 -0
- package/src/middle_layer/middle_layer.ts +235 -0
- package/src/middle_layer/navigation_states.ts +48 -0
- package/src/middle_layer/ops.ts +147 -0
- package/src/middle_layer/project.ts +380 -0
- package/src/middle_layer/project_list.ts +59 -0
- package/src/middle_layer/project_overview.ts +220 -0
- package/src/middle_layer/render.test.ts +129 -0
- package/src/middle_layer/render.ts +19 -0
- package/src/middle_layer/types.ts +16 -0
- package/src/middle_layer/util.ts +22 -0
- package/src/model/args.ts +62 -0
- package/src/model/block_pack.ts +8 -0
- package/src/model/block_pack_spec.ts +52 -0
- package/src/model/frontend.ts +10 -0
- package/src/model/index.ts +2 -0
- package/src/model/project_model.test.ts +26 -0
- package/src/model/project_model.ts +142 -0
- package/src/model/project_model_util.test.ts +88 -0
- package/src/model/project_model_util.ts +169 -0
- package/src/model/template_spec.ts +18 -0
- package/src/mutator/block-pack/block_pack.test.ts +53 -0
- package/src/mutator/block-pack/block_pack.ts +187 -0
- package/src/mutator/block-pack/frontend.ts +29 -0
- package/src/mutator/context_export.ts +25 -0
- package/src/mutator/project.test.ts +272 -0
- package/src/mutator/project.ts +1112 -0
- package/src/mutator/template/render_block.ts +91 -0
- package/src/mutator/template/render_template.ts +40 -0
- package/src/mutator/template/template_loading.ts +77 -0
- package/src/mutator/template/template_render.test.ts +272 -0
- package/src/pool/data.ts +239 -0
- package/src/pool/driver.ts +325 -0
- package/src/pool/index.ts +2 -0
- package/src/pool/p_object_collection.ts +122 -0
- package/src/pool/ref_count_pool.ts +76 -0
- package/src/pool/result_pool.ts +284 -0
- package/src/test/block_packs.ts +23 -0
- package/src/test/explicit_templates.ts +8 -0
- package/src/test/known_templates.ts +24 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AnyRef,
|
|
3
|
+
field,
|
|
4
|
+
PlTransaction,
|
|
5
|
+
ResourceRef,
|
|
6
|
+
ResourceType,
|
|
7
|
+
Pl
|
|
8
|
+
} from '@milaboratories/pl-client';
|
|
9
|
+
import { randomUUID } from 'node:crypto';
|
|
10
|
+
import { createRenderTemplate } from './render_template';
|
|
11
|
+
|
|
12
|
+
export const BContextEnd: ResourceType = { name: 'BContextEnd', version: '1' };
|
|
13
|
+
export const BContext: ResourceType = { name: 'BContext', version: '1' };
|
|
14
|
+
export const BContextId = 'id';
|
|
15
|
+
export const BContextParent = 'parent';
|
|
16
|
+
export const BContextMultiParentPrefix = 'parent/';
|
|
17
|
+
|
|
18
|
+
// TODO: add implementation for dual context heavy block.
|
|
19
|
+
// export type BlockType =
|
|
20
|
+
// | 'LightBlock'
|
|
21
|
+
// | 'HeavyBlock'
|
|
22
|
+
// | 'DualContextHeavyBlock';
|
|
23
|
+
// moved to project model ==>>>
|
|
24
|
+
|
|
25
|
+
export type HeavyBlockInputs = {
|
|
26
|
+
args: AnyRef;
|
|
27
|
+
blockId: AnyRef;
|
|
28
|
+
isProduction: AnyRef;
|
|
29
|
+
context: AnyRef;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type HeavyBlockOutputs = {
|
|
33
|
+
context: AnyRef;
|
|
34
|
+
result: AnyRef;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const HeavyBlockOutputNames: (keyof HeavyBlockOutputs)[] = ['context', 'result'];
|
|
38
|
+
|
|
39
|
+
export function createRenderHeavyBlock(
|
|
40
|
+
tx: PlTransaction,
|
|
41
|
+
tpl: AnyRef,
|
|
42
|
+
inputs: HeavyBlockInputs
|
|
43
|
+
): HeavyBlockOutputs {
|
|
44
|
+
return createRenderTemplate(tx, tpl, true, inputs, HeavyBlockOutputNames);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type LightBlockInputs = {
|
|
48
|
+
args: AnyRef;
|
|
49
|
+
blockId: AnyRef;
|
|
50
|
+
stagingContext: AnyRef;
|
|
51
|
+
productionContext: AnyRef;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type LightBlockOutput = {
|
|
55
|
+
result: AnyRef;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const LightBlockOutputNames: (keyof LightBlockOutput)[] = ['result'];
|
|
59
|
+
|
|
60
|
+
export function createRenderLightBlock(
|
|
61
|
+
tx: PlTransaction,
|
|
62
|
+
tpl: ResourceRef,
|
|
63
|
+
inputs: LightBlockInputs
|
|
64
|
+
): LightBlockOutput {
|
|
65
|
+
return createRenderTemplate(tx, tpl, true, inputs, LightBlockOutputNames);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function createBContextEnd(tx: PlTransaction): ResourceRef {
|
|
69
|
+
const ctx = tx.createEphemeral(BContextEnd);
|
|
70
|
+
tx.lock(ctx);
|
|
71
|
+
return ctx;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function createBContextFromUpstreams(tx: PlTransaction, upstreamCtxs: AnyRef[]): AnyRef {
|
|
75
|
+
if (upstreamCtxs.length === 0) return createBContextEnd(tx);
|
|
76
|
+
|
|
77
|
+
if (upstreamCtxs.length === 1) return upstreamCtxs[0];
|
|
78
|
+
|
|
79
|
+
const ctx = tx.createEphemeral(BContext);
|
|
80
|
+
|
|
81
|
+
// setting id
|
|
82
|
+
tx.createField(field(ctx, BContextId), 'Input', Pl.createPlString(tx, randomUUID()));
|
|
83
|
+
|
|
84
|
+
// setting parents
|
|
85
|
+
for (let i = 0; i < upstreamCtxs.length; i++)
|
|
86
|
+
tx.createField(field(ctx, `${BContextMultiParentPrefix}${i}`), 'Input', upstreamCtxs[i]);
|
|
87
|
+
|
|
88
|
+
tx.lock(ctx);
|
|
89
|
+
|
|
90
|
+
return ctx;
|
|
91
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { AnyRef, field, Pl, PlTransaction } from '@milaboratories/pl-client';
|
|
2
|
+
import { ResourceType } from '@platforma-sdk/model';
|
|
3
|
+
|
|
4
|
+
const EphRenderTemplate: ResourceType = {
|
|
5
|
+
name: 'EphRenderTemplate',
|
|
6
|
+
version: '1'
|
|
7
|
+
};
|
|
8
|
+
const RenderTemplate: ResourceType = {
|
|
9
|
+
name: 'RenderTemplate',
|
|
10
|
+
version: '1'
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Creates render template operation, for a given remplate and inputs.
|
|
15
|
+
*
|
|
16
|
+
* @param tx transaction to use during rendering creation
|
|
17
|
+
* @param tpl reference to the template resource (see {@link loadTemplate})
|
|
18
|
+
* @param ephemeral true for ephemeral templates, false for pure templates
|
|
19
|
+
* @param inputs map of inputs pointing to other resources or fields
|
|
20
|
+
* @param outputNames names of the outputs to collect and return from this method
|
|
21
|
+
*/
|
|
22
|
+
export function createRenderTemplate<O extends string>(
|
|
23
|
+
tx: PlTransaction,
|
|
24
|
+
tpl: AnyRef,
|
|
25
|
+
ephemeral: boolean,
|
|
26
|
+
inputs: Pl.PlRecord,
|
|
27
|
+
outputNames: O[]
|
|
28
|
+
): Record<O, AnyRef> {
|
|
29
|
+
if (outputNames.length === 0) throw new Error('Zero output names provided');
|
|
30
|
+
const rId = ephemeral ? tx.createEphemeral(EphRenderTemplate) : tx.createStruct(RenderTemplate);
|
|
31
|
+
|
|
32
|
+
const tplField = field(rId, 'template');
|
|
33
|
+
const inputsField = field(rId, 'inputs');
|
|
34
|
+
|
|
35
|
+
tx.createField(tplField, 'Input', tpl);
|
|
36
|
+
tx.createField(inputsField, 'Input', Pl.createPlMap(tx, inputs, ephemeral));
|
|
37
|
+
tx.lockInputs(rId);
|
|
38
|
+
|
|
39
|
+
return Pl.futureRecord(tx, rId, outputNames, 'Output', 'outputs/');
|
|
40
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { AnyRef, field, Pl, PlTransaction, ResourceType } from '@milaboratories/pl-client';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import {
|
|
4
|
+
ExplicitTemplate,
|
|
5
|
+
TemplateFromRegistry,
|
|
6
|
+
TemplateSpecAny,
|
|
7
|
+
TemplateSpecPrepared
|
|
8
|
+
} from '../../model/template_spec';
|
|
9
|
+
import { assertNever } from '@milaboratories/ts-helpers';
|
|
10
|
+
|
|
11
|
+
//
|
|
12
|
+
// Resource schema
|
|
13
|
+
//
|
|
14
|
+
|
|
15
|
+
export const TengoTemplateGet: ResourceType = { name: 'TengoTemplateGet', version: '1' };
|
|
16
|
+
export const TengoTemplateGetRegistry = 'registry';
|
|
17
|
+
export const TengoTemplateGetTemplateURI = 'templateURI';
|
|
18
|
+
export const TengoTemplateGetTemplate = 'template';
|
|
19
|
+
|
|
20
|
+
export const TengoTemplatePack: ResourceType = { name: 'TengoTemplatePack', version: '1' };
|
|
21
|
+
export const TengoTemplatePackConvert: ResourceType = {
|
|
22
|
+
name: 'TengoTemplatePackConvert',
|
|
23
|
+
version: '1'
|
|
24
|
+
};
|
|
25
|
+
export const TengoTemplatePackConvertTemplatePack = 'templatePack';
|
|
26
|
+
export const TengoTemplatePackConvertTemplate = 'template';
|
|
27
|
+
|
|
28
|
+
export async function prepareTemplateSpec(tpl: TemplateSpecAny): Promise<TemplateSpecPrepared> {
|
|
29
|
+
switch (tpl.type) {
|
|
30
|
+
case 'from-file':
|
|
31
|
+
return {
|
|
32
|
+
type: 'explicit',
|
|
33
|
+
content: await fs.promises.readFile(tpl.path)
|
|
34
|
+
};
|
|
35
|
+
case 'from-registry':
|
|
36
|
+
case 'explicit':
|
|
37
|
+
return tpl;
|
|
38
|
+
default:
|
|
39
|
+
return assertNever(tpl);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function loadTemplateFromRegistry(tx: PlTransaction, spec: TemplateFromRegistry): AnyRef {
|
|
44
|
+
const getTemplate = tx.createStruct(TengoTemplateGet);
|
|
45
|
+
const registry = field(getTemplate, TengoTemplateGetRegistry);
|
|
46
|
+
const uri = field(getTemplate, TengoTemplateGetTemplateURI);
|
|
47
|
+
const templateFromRegistry = field(getTemplate, TengoTemplateGetTemplate);
|
|
48
|
+
|
|
49
|
+
// Note: it has a resource schema, so platforma creates fields by itself.
|
|
50
|
+
|
|
51
|
+
tx.setField(registry, tx.createValue(Pl.JsonString, Buffer.from(JSON.stringify(spec.registry))));
|
|
52
|
+
tx.setField(uri, tx.createValue(Pl.JsonString, Buffer.from(JSON.stringify(spec.path))));
|
|
53
|
+
|
|
54
|
+
return templateFromRegistry;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function loadTemplateFromExplicit(tx: PlTransaction, spec: ExplicitTemplate): AnyRef {
|
|
58
|
+
const templatePack = tx.createValue(TengoTemplatePack, spec.content);
|
|
59
|
+
const templatePackConvert = tx.createStruct(TengoTemplatePackConvert);
|
|
60
|
+
const templatePackField = field(templatePackConvert, TengoTemplatePackConvertTemplatePack);
|
|
61
|
+
const template = field(templatePackConvert, TengoTemplatePackConvertTemplate);
|
|
62
|
+
|
|
63
|
+
tx.setField(templatePackField, templatePack);
|
|
64
|
+
|
|
65
|
+
return template;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function loadTemplate(tx: PlTransaction, spec: TemplateSpecPrepared): AnyRef {
|
|
69
|
+
switch (spec.type) {
|
|
70
|
+
case 'from-registry':
|
|
71
|
+
return loadTemplateFromRegistry(tx, spec);
|
|
72
|
+
case 'explicit':
|
|
73
|
+
return loadTemplateFromExplicit(tx, spec);
|
|
74
|
+
default:
|
|
75
|
+
return assertNever(spec);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AnyRef,
|
|
3
|
+
AnyResourceRef,
|
|
4
|
+
field,
|
|
5
|
+
isNotNullResourceId,
|
|
6
|
+
isNullResourceId,
|
|
7
|
+
PlClient,
|
|
8
|
+
PlTransaction,
|
|
9
|
+
ResourceData,
|
|
10
|
+
ResourceId,
|
|
11
|
+
TestHelpers,
|
|
12
|
+
getField,
|
|
13
|
+
valErr,
|
|
14
|
+
Pl
|
|
15
|
+
} from '@milaboratories/pl-client';
|
|
16
|
+
import { loadTemplate } from './template_loading';
|
|
17
|
+
import { createBContextEnd, createRenderHeavyBlock, HeavyBlockOutputs } from './render_block';
|
|
18
|
+
import { notEmpty, sleep } from '@milaboratories/ts-helpers';
|
|
19
|
+
import { TemplateSpecPrepared } from '../../model/template_spec';
|
|
20
|
+
import {
|
|
21
|
+
TplSpecEnterExplicit,
|
|
22
|
+
TplSpecEnterFromRegistry,
|
|
23
|
+
TplSpecSumExplicit,
|
|
24
|
+
TplSpecSumFromRegistry
|
|
25
|
+
} from '../../test/known_templates';
|
|
26
|
+
import { outputRef } from '../../model/args';
|
|
27
|
+
|
|
28
|
+
describe.each([
|
|
29
|
+
{ name: 'explicit', specEnter: TplSpecEnterExplicit, specSum: TplSpecSumExplicit },
|
|
30
|
+
{ name: 'from registry', specEnter: TplSpecEnterFromRegistry, specSum: TplSpecSumFromRegistry }
|
|
31
|
+
])('test render $name', ({ specEnter, specSum }) => {
|
|
32
|
+
const args: {
|
|
33
|
+
name: string;
|
|
34
|
+
createBlocksFn: (tx: PlTransaction) => Promise<HeavyBlockOutputs>;
|
|
35
|
+
expect: (pl: PlClient, tx: PlTransaction) => Promise<boolean>;
|
|
36
|
+
}[] = [
|
|
37
|
+
{
|
|
38
|
+
name: 'test render template staging',
|
|
39
|
+
createBlocksFn: async (tx) => {
|
|
40
|
+
return createEnterNumbers(tx, specEnter, false, 'block1', createBContextEnd(tx), undefined);
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
expect: async (pl, tx) => {
|
|
44
|
+
const { ctx, result, ok } = await expectResultAndContext(tx, pl.clientRoot);
|
|
45
|
+
if (!ok) return false;
|
|
46
|
+
|
|
47
|
+
expectFields(result!, ['dependsOnBlocks']);
|
|
48
|
+
expectFields(ctx!, ['id', 'parent', 'values/column.spec']);
|
|
49
|
+
expect(await expectData(tx, result!, 'dependsOnBlocks')).toStrictEqual([]);
|
|
50
|
+
expect(await expectData(tx, ctx!, 'values/column.spec')).not.toBeUndefined();
|
|
51
|
+
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'test render template production',
|
|
57
|
+
createBlocksFn: async (tx) => {
|
|
58
|
+
return createEnterNumbers(
|
|
59
|
+
tx,
|
|
60
|
+
specEnter,
|
|
61
|
+
true,
|
|
62
|
+
'block1',
|
|
63
|
+
createBContextEnd(tx),
|
|
64
|
+
[42, 2, 3, 7]
|
|
65
|
+
);
|
|
66
|
+
},
|
|
67
|
+
expect: async (pl, tx) => {
|
|
68
|
+
const { ctx, result, ok } = await expectResultAndContext(tx, pl.clientRoot);
|
|
69
|
+
if (!ok) return false;
|
|
70
|
+
|
|
71
|
+
expectFields(result!, ['dependsOnBlocks']);
|
|
72
|
+
expectFields(ctx!, ['id', 'parent', 'values/column.spec', 'values/column.data']);
|
|
73
|
+
expect(await expectData(tx, result!, 'dependsOnBlocks')).toStrictEqual([]);
|
|
74
|
+
expect(await expectData(tx, ctx!, 'values/column.data')).toStrictEqual([42, 2, 3, 7]);
|
|
75
|
+
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: 'test render chain staging',
|
|
81
|
+
createBlocksFn: async (tx) => {
|
|
82
|
+
const enter1 = createEnterNumbers(
|
|
83
|
+
tx,
|
|
84
|
+
specEnter,
|
|
85
|
+
false,
|
|
86
|
+
'block1',
|
|
87
|
+
createBContextEnd(tx),
|
|
88
|
+
undefined
|
|
89
|
+
);
|
|
90
|
+
const enter2 = createEnterNumbers(
|
|
91
|
+
tx,
|
|
92
|
+
specEnter,
|
|
93
|
+
false,
|
|
94
|
+
'block2',
|
|
95
|
+
enter1.context,
|
|
96
|
+
undefined
|
|
97
|
+
);
|
|
98
|
+
return createSumNumbers(tx, specSum, false, 'block3', enter2.context, undefined);
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
expect: async (pl, tx) => {
|
|
102
|
+
const { ctx, result, ok } = await expectResultAndContext(tx, pl.clientRoot);
|
|
103
|
+
if (!ok) return false;
|
|
104
|
+
|
|
105
|
+
expectFields(result!, ['dependsOnBlocks', 'opts']);
|
|
106
|
+
expectFields(ctx!, ['id', 'parent']);
|
|
107
|
+
expect(await expectData(tx, result!, 'opts')).toStrictEqual([
|
|
108
|
+
{
|
|
109
|
+
label: 'block1 / column',
|
|
110
|
+
ref: { blockId: 'block1', name: 'column' }
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
label: 'block2 / column',
|
|
114
|
+
ref: { blockId: 'block2', name: 'column' }
|
|
115
|
+
}
|
|
116
|
+
]);
|
|
117
|
+
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: 'test render chain production',
|
|
123
|
+
createBlocksFn: async (tx) => {
|
|
124
|
+
const enter1 = createEnterNumbers(tx, specEnter, true, 'block1', createBContextEnd(tx), [
|
|
125
|
+
21
|
|
126
|
+
]);
|
|
127
|
+
const enter2 = createEnterNumbers(tx, specEnter, true, 'block2', enter1.context, [10, 11]);
|
|
128
|
+
return createSumNumbers(tx, specSum, true, 'block3', enter2.context, [
|
|
129
|
+
outputRef('block1', 'column'), //{ blockId: 'block1', name: 'column' },
|
|
130
|
+
outputRef('block2', 'column') //{ blockId: 'block2', name: 'column' }
|
|
131
|
+
]);
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
expect: async (pl, tx) => {
|
|
135
|
+
const { ctx, result, ok } = await expectResultAndContext(tx, pl.clientRoot);
|
|
136
|
+
if (!ok) return false;
|
|
137
|
+
|
|
138
|
+
expectFields(result!, ['dependsOnBlocks', 'sum']);
|
|
139
|
+
expectFields(ctx!, ['id', 'parent']);
|
|
140
|
+
expect(await expectData(tx, result!, 'sum')).toBe(42);
|
|
141
|
+
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
];
|
|
146
|
+
|
|
147
|
+
for (const arg of args) {
|
|
148
|
+
test(
|
|
149
|
+
arg.name,
|
|
150
|
+
async () => {
|
|
151
|
+
await TestHelpers.withTempRoot(async (pl) => {
|
|
152
|
+
const f0 = field(pl.clientRoot, 'result');
|
|
153
|
+
const f1 = field(pl.clientRoot, 'context');
|
|
154
|
+
|
|
155
|
+
await pl.withWriteTx('test', async (tx) => {
|
|
156
|
+
const b = await arg.createBlocksFn(tx);
|
|
157
|
+
tx.createField(f0, 'Dynamic', b.result);
|
|
158
|
+
tx.createField(f1, 'Dynamic', b.context);
|
|
159
|
+
await tx.commit();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
while (true) {
|
|
163
|
+
if (await pl.withReadTx('test', (tx) => arg.expect(pl, tx))) break;
|
|
164
|
+
|
|
165
|
+
await sleep(30);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
},
|
|
169
|
+
5000
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
function createEnterNumbers(
|
|
175
|
+
tx: PlTransaction,
|
|
176
|
+
template: TemplateSpecPrepared,
|
|
177
|
+
isProd: boolean,
|
|
178
|
+
blockIdData: string,
|
|
179
|
+
ctx: AnyRef,
|
|
180
|
+
numbers?: number[]
|
|
181
|
+
) {
|
|
182
|
+
const tpl = loadTemplate(tx, template);
|
|
183
|
+
|
|
184
|
+
const args = tx.createValue(Pl.JsonObject, jsonToData({ numbers: numbers ?? [] }));
|
|
185
|
+
const blockId = tx.createValue(Pl.JsonString, jsonToData(blockIdData));
|
|
186
|
+
const isProduction = Pl.createPlBool(tx, isProd);
|
|
187
|
+
|
|
188
|
+
return createRenderHeavyBlock(tx, tpl, {
|
|
189
|
+
args: args,
|
|
190
|
+
blockId: blockId,
|
|
191
|
+
isProduction: isProduction,
|
|
192
|
+
context: ctx
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
interface Ref {
|
|
197
|
+
blockId: string;
|
|
198
|
+
name: string;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function createSumNumbers(
|
|
202
|
+
tx: PlTransaction,
|
|
203
|
+
template: TemplateSpecPrepared,
|
|
204
|
+
isProd: boolean,
|
|
205
|
+
blockIdData: string,
|
|
206
|
+
ctx: AnyRef,
|
|
207
|
+
sources?: Ref[]
|
|
208
|
+
) {
|
|
209
|
+
const tpl = loadTemplate(tx, template);
|
|
210
|
+
|
|
211
|
+
const args = tx.createValue(Pl.JsonObject, jsonToData({ sources: sources }));
|
|
212
|
+
const blockId = tx.createValue(Pl.JsonString, jsonToData(blockIdData));
|
|
213
|
+
const isProduction = Pl.createPlBool(tx, isProd);
|
|
214
|
+
|
|
215
|
+
return createRenderHeavyBlock(tx, tpl, {
|
|
216
|
+
args: args,
|
|
217
|
+
blockId: blockId,
|
|
218
|
+
isProduction: isProduction,
|
|
219
|
+
context: ctx
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async function expectResultAndContext(
|
|
224
|
+
tx: PlTransaction,
|
|
225
|
+
root: AnyResourceRef
|
|
226
|
+
): Promise<{
|
|
227
|
+
ctx?: ResourceData;
|
|
228
|
+
result?: ResourceData;
|
|
229
|
+
ok: boolean;
|
|
230
|
+
}> {
|
|
231
|
+
const fieldData = await tx.getResourceData(root, true);
|
|
232
|
+
expect(isNullResourceId(fieldData.error)).toBe(true);
|
|
233
|
+
expectFields(fieldData, ['context', 'result']);
|
|
234
|
+
|
|
235
|
+
const ctxField = await valErr(tx, getField(fieldData, 'context'));
|
|
236
|
+
expect(ctxField.error).toHaveLength(0);
|
|
237
|
+
const resultField = await valErr(tx, getField(fieldData, 'result'));
|
|
238
|
+
expect(resultField.error).toHaveLength(0);
|
|
239
|
+
|
|
240
|
+
const ctxId = ctxField.valueId;
|
|
241
|
+
const resultId = resultField.valueId;
|
|
242
|
+
|
|
243
|
+
if (isNullResourceId(ctxId) || isNullResourceId(resultId)) return { ok: false };
|
|
244
|
+
|
|
245
|
+
const result = await tx.getResourceData(resultId, true);
|
|
246
|
+
const ctx = await tx.getResourceData(ctxId, true);
|
|
247
|
+
|
|
248
|
+
if (!result.final || !ctx.final) return { ok: false };
|
|
249
|
+
|
|
250
|
+
return { ctx, result, ok: true };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async function expectResource(tx: PlTransaction, res: ResourceData, fieldName: string) {
|
|
254
|
+
const f = getField(res, fieldName);
|
|
255
|
+
const ve = await valErr(tx, f);
|
|
256
|
+
expect(ve.error).toHaveLength(0);
|
|
257
|
+
expect(isNotNullResourceId(ve.valueId)).toBeTruthy();
|
|
258
|
+
return await tx.getResourceData(ve.valueId as ResourceId, true);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
async function expectData(tx: PlTransaction, result: ResourceData, fieldName: string) {
|
|
262
|
+
return expectResource(tx, result, fieldName).then(resDataToJson);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function expectFields(res: ResourceData, fields: string[]) {
|
|
266
|
+
const names = res.fields.map((f) => f.name);
|
|
267
|
+
expect(names.sort()).toStrictEqual(fields.sort());
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const jsonToData = (data: unknown) => Buffer.from(JSON.stringify(data));
|
|
271
|
+
|
|
272
|
+
const resDataToJson = (res: ResourceData) => JSON.parse(notEmpty(res.data).toString());
|