@granular-software/sdk 0.4.12 → 0.4.13
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/cli/index.js +124 -0
- package/dist/index.d.mts +121 -1
- package/dist/index.d.ts +121 -1
- package/dist/index.js +319 -66
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +318 -67
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import * as Automerge from '@automerge/automerge';
|
|
2
|
+
import { normalizeEffectBehaviorSummary } from '@granular-software/metamodel-effect-behaviors';
|
|
3
|
+
import { DEFAULT_METAMODEL_PACKAGES } from '@granular-software/metamodel-preset-default';
|
|
2
4
|
|
|
3
5
|
var __create = Object.create;
|
|
4
6
|
var __defProp = Object.defineProperty;
|
|
@@ -5383,6 +5385,123 @@ function resolveApiUrl(explicitApiUrl, mode) {
|
|
|
5383
5385
|
}
|
|
5384
5386
|
return resolveEndpointMode(mode) === "local" ? LOCAL_API_URL : PRODUCTION_API_URL;
|
|
5385
5387
|
}
|
|
5388
|
+
function computeEffectKey(effect) {
|
|
5389
|
+
const attachedClass = effect.className?.trim();
|
|
5390
|
+
if (!attachedClass) {
|
|
5391
|
+
return `global:${effect.name}`;
|
|
5392
|
+
}
|
|
5393
|
+
return effect.static ? `class:${attachedClass}:static:${effect.name}` : `class:${attachedClass}:instance:${effect.name}`;
|
|
5394
|
+
}
|
|
5395
|
+
function normalizeEffectBehaviors(value) {
|
|
5396
|
+
return normalizeEffectBehaviorSummary(
|
|
5397
|
+
value
|
|
5398
|
+
) || {};
|
|
5399
|
+
}
|
|
5400
|
+
function resolveInvocationMode(context) {
|
|
5401
|
+
const mode = context?.invocation?.mode;
|
|
5402
|
+
if (mode === "dryRun" || mode === "reverse") {
|
|
5403
|
+
return mode;
|
|
5404
|
+
}
|
|
5405
|
+
return "execute";
|
|
5406
|
+
}
|
|
5407
|
+
function resolveReverseEffect(effectMap, currentEffect, request, behaviors) {
|
|
5408
|
+
const explicitReverseHandler = request.context?.invocation?.reverseHandler?.trim();
|
|
5409
|
+
const configuredReverseHandler = behaviors.reverse?.handler?.trim();
|
|
5410
|
+
const reverseHandler = explicitReverseHandler || configuredReverseHandler;
|
|
5411
|
+
if (!reverseHandler) {
|
|
5412
|
+
return void 0;
|
|
5413
|
+
}
|
|
5414
|
+
if (reverseHandler.includes(":")) {
|
|
5415
|
+
return effectMap.get(reverseHandler);
|
|
5416
|
+
}
|
|
5417
|
+
const directMatch = effectMap.get(reverseHandler);
|
|
5418
|
+
if (directMatch) {
|
|
5419
|
+
return directMatch;
|
|
5420
|
+
}
|
|
5421
|
+
const candidateKeys = [
|
|
5422
|
+
computeEffectKey({
|
|
5423
|
+
name: reverseHandler,
|
|
5424
|
+
className: currentEffect.className,
|
|
5425
|
+
static: currentEffect.static
|
|
5426
|
+
}),
|
|
5427
|
+
computeEffectKey({
|
|
5428
|
+
name: reverseHandler
|
|
5429
|
+
})
|
|
5430
|
+
];
|
|
5431
|
+
for (const candidateKey of candidateKeys) {
|
|
5432
|
+
const candidate = effectMap.get(candidateKey);
|
|
5433
|
+
if (candidate) {
|
|
5434
|
+
return candidate;
|
|
5435
|
+
}
|
|
5436
|
+
}
|
|
5437
|
+
return void 0;
|
|
5438
|
+
}
|
|
5439
|
+
function resolveHandlerForMode(effectMap, effect, request) {
|
|
5440
|
+
const behaviors = normalizeEffectBehaviors(request.context?.behaviors || effect.metamodels || void 0);
|
|
5441
|
+
const mode = resolveInvocationMode(request.context);
|
|
5442
|
+
if (mode === "dryRun") {
|
|
5443
|
+
if (effect.dryRunHandler) {
|
|
5444
|
+
return { effect, mode, handler: effect.dryRunHandler };
|
|
5445
|
+
}
|
|
5446
|
+
if (behaviors.dryRun?.enabled) {
|
|
5447
|
+
return { effect, mode, handler: effect.handler };
|
|
5448
|
+
}
|
|
5449
|
+
throw new Error(`Dry run is not supported for ${request.effectKey}`);
|
|
5450
|
+
}
|
|
5451
|
+
if (mode === "reverse") {
|
|
5452
|
+
if (effect.reverseHandler) {
|
|
5453
|
+
return { effect, mode, handler: effect.reverseHandler };
|
|
5454
|
+
}
|
|
5455
|
+
const reverseEffect = resolveReverseEffect(effectMap, effect, request, behaviors);
|
|
5456
|
+
if (reverseEffect) {
|
|
5457
|
+
return {
|
|
5458
|
+
effect: reverseEffect,
|
|
5459
|
+
mode,
|
|
5460
|
+
handler: reverseEffect.reverseHandler || reverseEffect.handler
|
|
5461
|
+
};
|
|
5462
|
+
}
|
|
5463
|
+
throw new Error(`Reverse execution is not supported for ${request.effectKey}`);
|
|
5464
|
+
}
|
|
5465
|
+
return { effect, mode, handler: effect.handler };
|
|
5466
|
+
}
|
|
5467
|
+
async function invokeRegisteredEffect(effectMap, request) {
|
|
5468
|
+
const effect = effectMap.get(request.effectKey);
|
|
5469
|
+
if (!effect) {
|
|
5470
|
+
throw new Error(`Effect handler not found: ${request.effectKey}`);
|
|
5471
|
+
}
|
|
5472
|
+
const resolved = resolveHandlerForMode(effectMap, effect, request);
|
|
5473
|
+
const context = {
|
|
5474
|
+
...request.context || {},
|
|
5475
|
+
behaviors: normalizeEffectBehaviors(request.context?.behaviors || effect.metamodels || void 0),
|
|
5476
|
+
invocation: {
|
|
5477
|
+
mode: resolved.mode,
|
|
5478
|
+
sourceEffectKey: request.effectKey,
|
|
5479
|
+
sourceEffectName: request.effectName,
|
|
5480
|
+
...request.context?.invocation?.reverseHandler ? { reverseHandler: request.context.invocation.reverseHandler } : {}
|
|
5481
|
+
}
|
|
5482
|
+
};
|
|
5483
|
+
if (resolved.effect.className && !resolved.effect.static && request.input && typeof request.input === "object" && "_objectId" in request.input) {
|
|
5484
|
+
const { _objectId, ...rest } = request.input;
|
|
5485
|
+
return resolved.handler(_objectId, rest, context);
|
|
5486
|
+
}
|
|
5487
|
+
return resolved.handler(request.input, context);
|
|
5488
|
+
}
|
|
5489
|
+
function buildFieldMetamodelMutations(fieldPath, spec) {
|
|
5490
|
+
return DEFAULT_METAMODEL_PACKAGES.flatMap(
|
|
5491
|
+
(pkg) => pkg.manifest?.buildFieldMutations?.(fieldPath, spec) || []
|
|
5492
|
+
);
|
|
5493
|
+
}
|
|
5494
|
+
function buildModelMetamodelMutations(modelPath, spec) {
|
|
5495
|
+
return DEFAULT_METAMODEL_PACKAGES.flatMap(
|
|
5496
|
+
(pkg) => pkg.manifest?.buildModelMutations?.(modelPath, spec) || []
|
|
5497
|
+
);
|
|
5498
|
+
}
|
|
5499
|
+
function buildEffectMetamodelMutations(toolPath, spec) {
|
|
5500
|
+
if (!spec) return [];
|
|
5501
|
+
return DEFAULT_METAMODEL_PACKAGES.flatMap(
|
|
5502
|
+
(pkg) => pkg.manifest?.buildEffectMutations?.(toolPath, spec) || []
|
|
5503
|
+
);
|
|
5504
|
+
}
|
|
5386
5505
|
|
|
5387
5506
|
// src/client.ts
|
|
5388
5507
|
var STANDARD_MODULES_OPERATIONS = [
|
|
@@ -5398,7 +5517,7 @@ var STANDARD_MODULES_OPERATIONS = [
|
|
|
5398
5517
|
var BUILTIN_MODULES = {
|
|
5399
5518
|
"standard_modules": STANDARD_MODULES_OPERATIONS
|
|
5400
5519
|
};
|
|
5401
|
-
function
|
|
5520
|
+
function computeEffectKey2(effect) {
|
|
5402
5521
|
const attachedClass = effect.className?.trim();
|
|
5403
5522
|
if (!attachedClass) {
|
|
5404
5523
|
return `global:${effect.name}`;
|
|
@@ -5975,6 +6094,87 @@ var Environment = class extends Session {
|
|
|
5975
6094
|
}
|
|
5976
6095
|
return ref;
|
|
5977
6096
|
}
|
|
6097
|
+
async _runGraphql(query, label) {
|
|
6098
|
+
const result = await this.graphql(query);
|
|
6099
|
+
if (result.errors?.length) {
|
|
6100
|
+
throw new Error(`${label}: ${result.errors[0].message}`);
|
|
6101
|
+
}
|
|
6102
|
+
return result.data;
|
|
6103
|
+
}
|
|
6104
|
+
async _applyFieldMetamodels(fieldPath, spec) {
|
|
6105
|
+
for (const mutation of buildFieldMetamodelMutations(fieldPath, spec)) {
|
|
6106
|
+
await this._runGraphql(mutation.query, mutation.label);
|
|
6107
|
+
}
|
|
6108
|
+
}
|
|
6109
|
+
async _applyModelMetamodels(modelPath, op) {
|
|
6110
|
+
for (const mutation of buildModelMetamodelMutations(modelPath, op)) {
|
|
6111
|
+
await this._runGraphql(mutation.query, mutation.label);
|
|
6112
|
+
}
|
|
6113
|
+
}
|
|
6114
|
+
async _ensureWorkspaceToolsRoot() {
|
|
6115
|
+
await this._runGraphql(
|
|
6116
|
+
`mutation { create_model(path: "workspace", label: "workspace") { model { path } } }`,
|
|
6117
|
+
"ensure workspace"
|
|
6118
|
+
).catch((error) => {
|
|
6119
|
+
if (!error.message.includes("already exists")) throw error;
|
|
6120
|
+
});
|
|
6121
|
+
await this._runGraphql(
|
|
6122
|
+
`mutation { at(path: "workspace") { create_submodel(subpath: "tools", label: "Tools") { model { path } } } }`,
|
|
6123
|
+
"ensure workspace:tools"
|
|
6124
|
+
).catch((error) => {
|
|
6125
|
+
if (!error.message.includes("already exists")) throw error;
|
|
6126
|
+
});
|
|
6127
|
+
await this._runGraphql(
|
|
6128
|
+
`mutation { at(path: "workspace:tools") { create_submodel(subpath: "declared", label: "Declared") { model { path } } } }`,
|
|
6129
|
+
"ensure workspace:tools:declared"
|
|
6130
|
+
).catch((error) => {
|
|
6131
|
+
if (!error.message.includes("already exists")) throw error;
|
|
6132
|
+
});
|
|
6133
|
+
}
|
|
6134
|
+
async _storeEffectSchemas(toolPath, effect) {
|
|
6135
|
+
await this._runGraphql(
|
|
6136
|
+
`mutation { at(path: ${JSON.stringify(toolPath)}) { create_submodel(subpath: "inputSchema", label: "inputSchema") { set_string_value(value: ${JSON.stringify(JSON.stringify(effect.inputSchema))}) { done } } } }`,
|
|
6137
|
+
`store inputSchema on ${toolPath}`
|
|
6138
|
+
).catch((error) => {
|
|
6139
|
+
if (!error.message.includes("already exists")) throw error;
|
|
6140
|
+
});
|
|
6141
|
+
if (effect.outputSchema) {
|
|
6142
|
+
await this._runGraphql(
|
|
6143
|
+
`mutation { at(path: ${JSON.stringify(toolPath)}) { create_submodel(subpath: "outputSchema", label: "outputSchema") { set_string_value(value: ${JSON.stringify(JSON.stringify(effect.outputSchema))}) { done } } } }`,
|
|
6144
|
+
`store outputSchema on ${toolPath}`
|
|
6145
|
+
).catch((error) => {
|
|
6146
|
+
if (!error.message.includes("already exists")) throw error;
|
|
6147
|
+
});
|
|
6148
|
+
}
|
|
6149
|
+
}
|
|
6150
|
+
async _applyEffectMetamodels(toolPath, metamodels) {
|
|
6151
|
+
for (const mutation of buildEffectMetamodelMutations(toolPath, metamodels)) {
|
|
6152
|
+
await this._runGraphql(mutation.query, mutation.label);
|
|
6153
|
+
}
|
|
6154
|
+
}
|
|
6155
|
+
async _applyEffectDeclaration(effect, aliasMap) {
|
|
6156
|
+
let containerPath = "workspace:tools:declared";
|
|
6157
|
+
if (effect.attachedClass) {
|
|
6158
|
+
containerPath = this._resolveAlias(effect.attachedClass, aliasMap);
|
|
6159
|
+
} else {
|
|
6160
|
+
await this._ensureWorkspaceToolsRoot();
|
|
6161
|
+
}
|
|
6162
|
+
await this._runGraphql(
|
|
6163
|
+
`mutation { at(path: ${JSON.stringify(containerPath)}) { create_submodel(subpath: ${JSON.stringify(effect.name)}, label: ${JSON.stringify(effect.name)}) { model { path } } } }`,
|
|
6164
|
+
`create effect model ${containerPath}:${effect.name}`
|
|
6165
|
+
).catch((error) => {
|
|
6166
|
+
if (!error.message.includes("already exists")) throw error;
|
|
6167
|
+
});
|
|
6168
|
+
const toolPath = `${containerPath}:${effect.name}`;
|
|
6169
|
+
if (effect.description) {
|
|
6170
|
+
await this._runGraphql(
|
|
6171
|
+
`mutation { at(path: ${JSON.stringify(toolPath)}) { set_description(description: ${JSON.stringify(effect.description)}) { done } } }`,
|
|
6172
|
+
`set effect description on ${toolPath}`
|
|
6173
|
+
);
|
|
6174
|
+
}
|
|
6175
|
+
await this._storeEffectSchemas(toolPath, effect);
|
|
6176
|
+
await this._applyEffectMetamodels(toolPath, effect.metamodels);
|
|
6177
|
+
}
|
|
5978
6178
|
/**
|
|
5979
6179
|
* Apply a single manifest operation via GraphQL
|
|
5980
6180
|
*/
|
|
@@ -5997,24 +6197,32 @@ var Environment = class extends Session {
|
|
|
5997
6197
|
const extendsRef = op.extends ? this._resolveAlias(op.extends, aliasMap) : void 0;
|
|
5998
6198
|
const instanceOfRef = op.instanceOf ? this._resolveAlias(op.instanceOf, aliasMap) : void 0;
|
|
5999
6199
|
if (extendsRef) {
|
|
6000
|
-
await this.
|
|
6001
|
-
`mutation { create_model(path: "${op.create}", label: "${label}") { model { path } } }
|
|
6200
|
+
await this._runGraphql(
|
|
6201
|
+
`mutation { create_model(path: "${op.create}", label: "${label}") { model { path } } }`,
|
|
6202
|
+
`create model ${op.create}`
|
|
6002
6203
|
);
|
|
6003
|
-
await this.
|
|
6004
|
-
`mutation { at(path: "${op.create}") { add_superclass(superclass: "${extendsRef}") { model { path } } } }
|
|
6204
|
+
await this._runGraphql(
|
|
6205
|
+
`mutation { at(path: "${op.create}") { add_superclass(superclass: "${extendsRef}") { model { path } } } }`,
|
|
6206
|
+
`add superclass ${extendsRef} to ${op.create}`
|
|
6005
6207
|
);
|
|
6006
6208
|
} else if (instanceOfRef) {
|
|
6007
|
-
await this.
|
|
6008
|
-
`mutation { at(path: "${instanceOfRef}") { instantiate(path: "${op.create}", label: "${label}") { model { path } } } }
|
|
6209
|
+
await this._runGraphql(
|
|
6210
|
+
`mutation { at(path: "${instanceOfRef}") { instantiate(path: "${op.create}", label: "${label}") { model { path } } } }`,
|
|
6211
|
+
`instantiate ${op.create} from ${instanceOfRef}`
|
|
6009
6212
|
);
|
|
6010
6213
|
} else {
|
|
6011
|
-
await this.
|
|
6012
|
-
`mutation { create_model(path: "${op.create}", label: "${label}") { model { path } } }
|
|
6214
|
+
await this._runGraphql(
|
|
6215
|
+
`mutation { create_model(path: "${op.create}", label: "${label}") { model { path } } }`,
|
|
6216
|
+
`create model ${op.create}`
|
|
6013
6217
|
);
|
|
6014
6218
|
}
|
|
6015
6219
|
if (op.has) {
|
|
6016
6220
|
await this._applyFields(op.create, op.has);
|
|
6017
6221
|
}
|
|
6222
|
+
await this._applyModelMetamodels(op.create, op);
|
|
6223
|
+
if (op.withEffect) {
|
|
6224
|
+
await this._applyEffectDeclaration(op.withEffect, aliasMap);
|
|
6225
|
+
}
|
|
6018
6226
|
return;
|
|
6019
6227
|
}
|
|
6020
6228
|
if (op.on) {
|
|
@@ -6022,8 +6230,15 @@ var Environment = class extends Session {
|
|
|
6022
6230
|
if (op.has) {
|
|
6023
6231
|
await this._applyFields(target, op.has);
|
|
6024
6232
|
}
|
|
6233
|
+
await this._applyModelMetamodels(target, op);
|
|
6234
|
+
if (op.withEffect) {
|
|
6235
|
+
await this._applyEffectDeclaration(op.withEffect, aliasMap);
|
|
6236
|
+
}
|
|
6025
6237
|
return;
|
|
6026
6238
|
}
|
|
6239
|
+
if (op.withEffect) {
|
|
6240
|
+
await this._applyEffectDeclaration(op.withEffect, aliasMap);
|
|
6241
|
+
}
|
|
6027
6242
|
}
|
|
6028
6243
|
/**
|
|
6029
6244
|
* Apply field definitions (has) to a model via GraphQL
|
|
@@ -6031,81 +6246,91 @@ var Environment = class extends Session {
|
|
|
6031
6246
|
async _applyFields(modelPath, fields) {
|
|
6032
6247
|
for (const [fieldName, spec] of Object.entries(fields)) {
|
|
6033
6248
|
const fieldLabel = fieldName.charAt(0).toUpperCase() + fieldName.slice(1);
|
|
6034
|
-
await this.
|
|
6249
|
+
await this._runGraphql(
|
|
6035
6250
|
`mutation {
|
|
6036
|
-
at(path:
|
|
6037
|
-
create_submodel(subpath:
|
|
6251
|
+
at(path: ${JSON.stringify(modelPath)}) {
|
|
6252
|
+
create_submodel(subpath: ${JSON.stringify(fieldName)}, label: ${JSON.stringify(fieldLabel)}) {
|
|
6038
6253
|
model { path }
|
|
6039
6254
|
}
|
|
6040
6255
|
}
|
|
6041
|
-
}
|
|
6042
|
-
|
|
6256
|
+
}`,
|
|
6257
|
+
`create field ${modelPath}.${fieldName}`
|
|
6258
|
+
).catch((error) => {
|
|
6259
|
+
if (!error.message.includes("already exists")) throw error;
|
|
6260
|
+
});
|
|
6043
6261
|
if (spec.type) {
|
|
6044
|
-
await this.
|
|
6262
|
+
await this._runGraphql(
|
|
6045
6263
|
`mutation {
|
|
6046
|
-
at(path:
|
|
6047
|
-
at(submodel:
|
|
6048
|
-
add_prototype(prototype:
|
|
6264
|
+
at(path: ${JSON.stringify(modelPath)}) {
|
|
6265
|
+
at(submodel: ${JSON.stringify(fieldName)}) {
|
|
6266
|
+
add_prototype(prototype: ${JSON.stringify(spec.type)}) { done }
|
|
6049
6267
|
}
|
|
6050
6268
|
}
|
|
6051
|
-
}
|
|
6269
|
+
}`,
|
|
6270
|
+
`set prototype on ${modelPath}:${fieldName}`
|
|
6052
6271
|
);
|
|
6053
6272
|
}
|
|
6054
6273
|
if (spec.description) {
|
|
6055
|
-
await this.
|
|
6274
|
+
await this._runGraphql(
|
|
6056
6275
|
`mutation {
|
|
6057
|
-
at(path:
|
|
6058
|
-
at(submodel:
|
|
6059
|
-
set_description(description:
|
|
6276
|
+
at(path: ${JSON.stringify(modelPath)}) {
|
|
6277
|
+
at(submodel: ${JSON.stringify(fieldName)}) {
|
|
6278
|
+
set_description(description: ${JSON.stringify(spec.description)}) { done }
|
|
6060
6279
|
}
|
|
6061
6280
|
}
|
|
6062
|
-
}
|
|
6281
|
+
}`,
|
|
6282
|
+
`set description on ${modelPath}:${fieldName}`
|
|
6063
6283
|
);
|
|
6064
6284
|
}
|
|
6065
6285
|
if (spec.value !== void 0 && spec.value !== null) {
|
|
6066
6286
|
if (typeof spec.value === "string") {
|
|
6067
|
-
await this.
|
|
6287
|
+
await this._runGraphql(
|
|
6068
6288
|
`mutation {
|
|
6069
|
-
at(path:
|
|
6070
|
-
at(submodel:
|
|
6071
|
-
set_string_value(value:
|
|
6289
|
+
at(path: ${JSON.stringify(modelPath)}) {
|
|
6290
|
+
at(submodel: ${JSON.stringify(fieldName)}) {
|
|
6291
|
+
set_string_value(value: ${JSON.stringify(spec.value)}) { done }
|
|
6072
6292
|
}
|
|
6073
6293
|
}
|
|
6074
|
-
}
|
|
6294
|
+
}`,
|
|
6295
|
+
`set string value on ${modelPath}:${fieldName}`
|
|
6075
6296
|
);
|
|
6076
6297
|
} else if (typeof spec.value === "number") {
|
|
6077
|
-
await this.
|
|
6298
|
+
await this._runGraphql(
|
|
6078
6299
|
`mutation {
|
|
6079
|
-
at(path:
|
|
6080
|
-
at(submodel:
|
|
6300
|
+
at(path: ${JSON.stringify(modelPath)}) {
|
|
6301
|
+
at(submodel: ${JSON.stringify(fieldName)}) {
|
|
6081
6302
|
set_number_value(value: ${spec.value}) { done }
|
|
6082
6303
|
}
|
|
6083
6304
|
}
|
|
6084
|
-
}
|
|
6305
|
+
}`,
|
|
6306
|
+
`set number value on ${modelPath}:${fieldName}`
|
|
6085
6307
|
);
|
|
6086
6308
|
} else if (typeof spec.value === "boolean") {
|
|
6087
|
-
await this.
|
|
6309
|
+
await this._runGraphql(
|
|
6088
6310
|
`mutation {
|
|
6089
|
-
at(path:
|
|
6090
|
-
at(submodel:
|
|
6311
|
+
at(path: ${JSON.stringify(modelPath)}) {
|
|
6312
|
+
at(submodel: ${JSON.stringify(fieldName)}) {
|
|
6091
6313
|
set_boolean_value(value: ${spec.value}) { done }
|
|
6092
6314
|
}
|
|
6093
6315
|
}
|
|
6094
|
-
}
|
|
6316
|
+
}`,
|
|
6317
|
+
`set boolean value on ${modelPath}:${fieldName}`
|
|
6095
6318
|
);
|
|
6096
6319
|
}
|
|
6097
6320
|
}
|
|
6098
6321
|
if (spec.ref) {
|
|
6099
|
-
await this.
|
|
6322
|
+
await this._runGraphql(
|
|
6100
6323
|
`mutation {
|
|
6101
|
-
at(path:
|
|
6102
|
-
at(submodel:
|
|
6103
|
-
set_reference(reference:
|
|
6324
|
+
at(path: ${JSON.stringify(modelPath)}) {
|
|
6325
|
+
at(submodel: ${JSON.stringify(fieldName)}) {
|
|
6326
|
+
set_reference(reference: ${JSON.stringify(spec.ref)}) { done }
|
|
6104
6327
|
}
|
|
6105
6328
|
}
|
|
6106
|
-
}
|
|
6329
|
+
}`,
|
|
6330
|
+
`set reference on ${modelPath}:${fieldName}`
|
|
6107
6331
|
);
|
|
6108
6332
|
}
|
|
6333
|
+
await this._applyFieldMetamodels(`${modelPath}:${fieldName}`, spec);
|
|
6109
6334
|
if (spec.has) {
|
|
6110
6335
|
await this._applyFields(`${modelPath}:${fieldName}`, spec.has);
|
|
6111
6336
|
}
|
|
@@ -6445,7 +6670,7 @@ var Granular = class {
|
|
|
6445
6670
|
}
|
|
6446
6671
|
serializeEffect(effect) {
|
|
6447
6672
|
return {
|
|
6448
|
-
effectKey:
|
|
6673
|
+
effectKey: computeEffectKey2(effect),
|
|
6449
6674
|
name: effect.name,
|
|
6450
6675
|
description: effect.description,
|
|
6451
6676
|
inputSchema: effect.inputSchema,
|
|
@@ -6481,23 +6706,54 @@ var Granular = class {
|
|
|
6481
6706
|
const host = await this.ensureSandboxEffectHost(sandboxId);
|
|
6482
6707
|
await this.publishSandboxEffectCatalog(host);
|
|
6483
6708
|
}
|
|
6484
|
-
|
|
6485
|
-
if (host.
|
|
6486
|
-
|
|
6709
|
+
recoverEffectHost(host, error) {
|
|
6710
|
+
if (host.recovering) {
|
|
6711
|
+
return;
|
|
6712
|
+
}
|
|
6713
|
+
if (this.sandboxEffectHosts.get(host.sandboxId) !== host) {
|
|
6714
|
+
return;
|
|
6487
6715
|
}
|
|
6488
|
-
host.
|
|
6716
|
+
host.recovering = true;
|
|
6717
|
+
this.stopEffectHostHeartbeat(host);
|
|
6718
|
+
this.sandboxEffectHosts.delete(host.sandboxId);
|
|
6719
|
+
try {
|
|
6720
|
+
host.wsClient.disconnect();
|
|
6721
|
+
} catch (disconnectError) {
|
|
6489
6722
|
console.warn(
|
|
6490
|
-
`[Granular]
|
|
6491
|
-
|
|
6723
|
+
`[Granular] Failed to disconnect stale effect host for sandbox ${host.sandboxId}:`,
|
|
6724
|
+
disconnectError
|
|
6492
6725
|
);
|
|
6726
|
+
}
|
|
6727
|
+
void this.ensureSandboxEffectHost(host.sandboxId).catch((reconnectError) => {
|
|
6728
|
+
console.error(
|
|
6729
|
+
`[Granular] Failed to recover effect host for sandbox ${host.sandboxId} after heartbeat failure:`,
|
|
6730
|
+
reconnectError
|
|
6731
|
+
);
|
|
6732
|
+
console.error("[Granular] Original heartbeat failure:", error);
|
|
6493
6733
|
});
|
|
6494
|
-
|
|
6734
|
+
}
|
|
6735
|
+
startEffectHostHeartbeat(host) {
|
|
6736
|
+
if (host.heartbeatTimer) {
|
|
6737
|
+
clearInterval(host.heartbeatTimer);
|
|
6738
|
+
}
|
|
6739
|
+
host.heartbeatInFlight = false;
|
|
6740
|
+
const sendHeartbeat = (failureLabel, recoverOnFailure) => {
|
|
6741
|
+
if (host.heartbeatInFlight || host.recovering) {
|
|
6742
|
+
return;
|
|
6743
|
+
}
|
|
6744
|
+
host.heartbeatInFlight = true;
|
|
6495
6745
|
host.wsClient.call("client.heartbeat", {}).catch((error) => {
|
|
6496
|
-
console.warn(
|
|
6497
|
-
|
|
6498
|
-
error
|
|
6499
|
-
|
|
6746
|
+
console.warn(`${failureLabel} ${host.sandboxId}:`, error);
|
|
6747
|
+
if (recoverOnFailure) {
|
|
6748
|
+
this.recoverEffectHost(host, error);
|
|
6749
|
+
}
|
|
6750
|
+
}).finally(() => {
|
|
6751
|
+
host.heartbeatInFlight = false;
|
|
6500
6752
|
});
|
|
6753
|
+
};
|
|
6754
|
+
sendHeartbeat("[Granular] Initial effect host heartbeat failed for sandbox", false);
|
|
6755
|
+
host.heartbeatTimer = setInterval(() => {
|
|
6756
|
+
sendHeartbeat("[Granular] Effect host heartbeat failed for sandbox", true);
|
|
6501
6757
|
}, 1e4);
|
|
6502
6758
|
}
|
|
6503
6759
|
stopEffectHostHeartbeat(host) {
|
|
@@ -6506,6 +6762,7 @@ var Granular = class {
|
|
|
6506
6762
|
}
|
|
6507
6763
|
clearInterval(host.heartbeatTimer);
|
|
6508
6764
|
host.heartbeatTimer = null;
|
|
6765
|
+
host.heartbeatInFlight = false;
|
|
6509
6766
|
}
|
|
6510
6767
|
async synchronizeEffectHost(host) {
|
|
6511
6768
|
await host.wsClient.call("client.hello", {
|
|
@@ -6541,19 +6798,13 @@ var Granular = class {
|
|
|
6541
6798
|
effectClientId,
|
|
6542
6799
|
clientId,
|
|
6543
6800
|
wsClient,
|
|
6544
|
-
heartbeatTimer: null
|
|
6801
|
+
heartbeatTimer: null,
|
|
6802
|
+
heartbeatInFlight: false,
|
|
6803
|
+
recovering: false
|
|
6545
6804
|
};
|
|
6546
6805
|
wsClient.registerRpcHandler("effect.invoke", async (params) => {
|
|
6547
6806
|
const request = params;
|
|
6548
|
-
|
|
6549
|
-
if (!effect) {
|
|
6550
|
-
throw new Error(`Effect handler not found: ${request.effectKey}`);
|
|
6551
|
-
}
|
|
6552
|
-
if (effect.className && !effect.static && request.input && typeof request.input === "object" && "_objectId" in request.input) {
|
|
6553
|
-
const { _objectId, ...rest } = request.input;
|
|
6554
|
-
return effect.handler(_objectId, rest, request.context);
|
|
6555
|
-
}
|
|
6556
|
-
return effect.handler(request.input, request.context);
|
|
6807
|
+
return invokeRegisteredEffect(this.getSandboxEffectMap(sandboxId), request);
|
|
6557
6808
|
});
|
|
6558
6809
|
wsClient.on("open", () => {
|
|
6559
6810
|
void this.synchronizeEffectHost(host).catch((error) => {
|
|
@@ -6596,7 +6847,7 @@ var Granular = class {
|
|
|
6596
6847
|
async registerEffect(sandboxNameOrId, effect) {
|
|
6597
6848
|
const sandbox = await this.findOrCreateSandbox(sandboxNameOrId);
|
|
6598
6849
|
const sandboxId = sandbox.sandboxId;
|
|
6599
|
-
this.getSandboxEffectMap(sandboxId).set(
|
|
6850
|
+
this.getSandboxEffectMap(sandboxId).set(computeEffectKey2(effect), effect);
|
|
6600
6851
|
await this.syncSandboxEffectCatalog(sandboxId);
|
|
6601
6852
|
}
|
|
6602
6853
|
/**
|
|
@@ -6609,7 +6860,7 @@ var Granular = class {
|
|
|
6609
6860
|
const sandboxId = sandbox.sandboxId;
|
|
6610
6861
|
const map = this.getSandboxEffectMap(sandboxId);
|
|
6611
6862
|
for (const effect of effects) {
|
|
6612
|
-
map.set(
|
|
6863
|
+
map.set(computeEffectKey2(effect), effect);
|
|
6613
6864
|
}
|
|
6614
6865
|
await this.syncSandboxEffectCatalog(sandboxId);
|
|
6615
6866
|
}
|
|
@@ -6886,6 +7137,6 @@ var Granular = class {
|
|
|
6886
7137
|
}
|
|
6887
7138
|
};
|
|
6888
7139
|
|
|
6889
|
-
export { Environment, Granular, Session, WSClient };
|
|
7140
|
+
export { Environment, Granular, Session, WSClient, invokeRegisteredEffect, normalizeEffectBehaviors };
|
|
6890
7141
|
//# sourceMappingURL=index.mjs.map
|
|
6891
7142
|
//# sourceMappingURL=index.mjs.map
|