@astrale-os/sdk 0.6.0-beta.4 → 0.6.0-beta.6

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,5 +1,5 @@
1
- import * as value from '../../../platform/value/index.js';
2
1
  import { acceptStepId } from '../step/index.js';
2
+ import { acceptStepOutput } from '../step/output.js';
3
3
  /** Process-local runner for tests and explicitly non-durable embeddings. */
4
4
  export function createInlineWorkflowRunner() {
5
5
  async function run(workflow, context) {
@@ -37,10 +37,8 @@ function createInlineStep(signal) {
37
37
  started.add(accepted);
38
38
  execution = (async () => {
39
39
  const output = await execute();
40
- if (output === undefined)
41
- return output;
42
40
  try {
43
- return value.accept(output);
41
+ return acceptStepOutput(output);
44
42
  }
45
43
  catch (cause) {
46
44
  throw new TypeError(`Workflow Step ${accepted} output must be portable.`, {
@@ -0,0 +1,2 @@
1
+ /** Capture optional Object fields as absence without changing portable Array or scalar semantics. */
2
+ export declare function acceptStepOutput<Output>(input: Output): Output;
@@ -0,0 +1,73 @@
1
+ import * as value from '../../../platform/value/index.js';
2
+ /** Capture optional Object fields as absence without changing portable Array or scalar semantics. */
3
+ export function acceptStepOutput(input) {
4
+ if (input === undefined)
5
+ return input;
6
+ const captured = new WeakMap();
7
+ const omitted = new WeakMap();
8
+ const pending = [];
9
+ let members = 0;
10
+ function capture(source, depth) {
11
+ if (source === null || typeof source !== 'object')
12
+ return source;
13
+ const retained = captured.get(source);
14
+ if (retained !== undefined)
15
+ return retained;
16
+ if (depth >= value.defaultLimits.maxDepth) {
17
+ throw new value.BoundaryError('VALUE_LIMIT', 'Workflow Step container depth exceeds the portable limit', '');
18
+ }
19
+ const array = Array.isArray(source);
20
+ const snapshot = array ? [] : Object.create(Object.getPrototypeOf(source));
21
+ captured.set(source, snapshot);
22
+ pending.push({ source, snapshot, depth, array });
23
+ return snapshot;
24
+ }
25
+ const snapshot = capture(input, 0);
26
+ for (let index = 0; index < pending.length; index += 1) {
27
+ const { source, snapshot: container, depth, array } = pending[index];
28
+ const descriptors = Object.getOwnPropertyDescriptors(source);
29
+ const keys = Reflect.ownKeys(descriptors);
30
+ // Bound this preparatory capture too; canonical admission subsequently checks each path.
31
+ members += keys.length - (array ? 1 : 0);
32
+ if (members > value.defaultLimits.maxMembers) {
33
+ throw new value.BoundaryError('VALUE_LIMIT', 'Workflow Step member count exceeds the portable limit', '');
34
+ }
35
+ const absent = new Set();
36
+ for (const key of keys) {
37
+ const descriptor = Object.getOwnPropertyDescriptor(descriptors, key)
38
+ .value;
39
+ if ('value' in descriptor) {
40
+ if (!array &&
41
+ typeof key === 'string' &&
42
+ descriptor.enumerable &&
43
+ descriptor.value === undefined) {
44
+ // Validate this member's key, descriptor and budget before interpreting its absence.
45
+ descriptor.value = null;
46
+ absent.add(key);
47
+ }
48
+ else {
49
+ descriptor.value = capture(descriptor.value, depth + 1);
50
+ }
51
+ }
52
+ Object.defineProperty(container, key, descriptor);
53
+ }
54
+ if (absent.size > 0)
55
+ omitted.set(container, absent);
56
+ }
57
+ // The canonical owner still rejects cycles, invalid descriptors/prototypes/keys and lossy values.
58
+ const output = value.accept(snapshot);
59
+ const pruning = [{ snapshot, output }];
60
+ for (let index = 0; index < pruning.length; index += 1) {
61
+ const pair = pruning[index];
62
+ if (pair.output === null || typeof pair.output !== 'object')
63
+ continue;
64
+ const source = pair.snapshot;
65
+ const target = pair.output;
66
+ for (const key of omitted.get(source) ?? [])
67
+ delete target[key];
68
+ for (const key of Object.keys(target)) {
69
+ pruning.push({ snapshot: source[key], output: target[key] });
70
+ }
71
+ }
72
+ return output;
73
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/sdk",
3
- "version": "0.6.0-beta.4",
3
+ "version": "0.6.0-beta.6",
4
4
  "description": "Schema-first SDK for defining, composing, and deploying Astrale domains",
5
5
  "keywords": [
6
6
  "astrale",