Skip to content

Commit

Permalink
Extract machine context (#370)
Browse files Browse the repository at this point in the history
* Parse machine context into an object

* changeset

* Parse -> Extract

Co-authored-by: Mateusz Burzyński <[email protected]>

* Use a special handler for parsing root state node to keep extracting context only in the root state node

* Extract lazy context as expression string

* Update packages/machine-extractor/src/__tests__/context.test.ts

Co-authored-by: Mateusz Burzyński <[email protected]>

* Update packages/machine-extractor/src/__tests__/context.test.ts

Co-authored-by: Mateusz Burzyński <[email protected]>

---------

Co-authored-by: Mateusz Burzyński <[email protected]>
  • Loading branch information
farskid and Andarist authored Sep 20, 2023
1 parent ea64a0e commit d885182
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/calm-balloons-ring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@xstate/machine-extractor': minor
---

Extract machine context into an object
91 changes: 91 additions & 0 deletions packages/machine-extractor/src/__tests__/context.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { extractMachinesFromFile } from '..';

describe('Context', () => {
it('Should be able to extract machine context into an object', () => {
const result = extractMachinesFromFile(`
createMachine({
context: {
str: 'some string',
num: 2,
bool: true,
arr: [1,2,3],
obj: {
str: 'some string',
num: 2,
bool: true,
arr: [1,2,3],
obj: {
a: 2
}
}
}
})
`);

expect(result?.machines[0]?.toConfig()).toMatchInlineSnapshot(`
{
"context": {
"arr": [
1,
2,
3,
],
"bool": true,
"num": 2,
"obj": {
"arr": [
1,
2,
3,
],
"bool": true,
"num": 2,
"obj": {
"a": 2,
},
"str": "some string",
},
"str": "some string",
},
}
`);
});

it('Should only account for context on the root node', () => {
const result = extractMachinesFromFile(`
createMachine({
initial: 'a',
states: {
a: {
context: {
foo: 'bar'
}
}
}
})
`);

expect(result?.machines[0]?.toConfig()).toMatchInlineSnapshot(`
{
"initial": "a",
"states": {
"a": {},
},
}
`);
});

it('Should extract lazy context as an expression string', () => {
const result = extractMachinesFromFile(`
createMachine({
context: () => ({})
})
`);

expect(result?.machines[0]?.toConfig()).toMatchInlineSnapshot(`
{
"context": "{{() => ({})}}",
}
`);
});
});
23 changes: 22 additions & 1 deletion packages/machine-extractor/src/toMachineConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,33 @@ const parseStateNode = (
return config;
};

const parseRootStateNode = (
astResult: StateNodeReturn,
opts: ToMachineConfigOptions | undefined,
): ExtractorStateNodeConfig => {
const config: ExtractorMachineConfig = parseStateNode(astResult, opts);
if (t.isObjectExpression(astResult.context?.node)) {
config.context = extractObjectRecursively(
astResult.context!.node,
opts!.fileContent,
);
} else if (astResult.context) {
config.context = toJsonExpressionString(
opts!.fileContent.slice(
astResult.context.node.start!,
astResult.context.node.end!,
),
);
}
return config;
};

export const toMachineConfig = (
result: TMachineCallExpression,
opts?: ToMachineConfigOptions,
): ExtractorMachineConfig | undefined => {
if (!result?.definition) return undefined;
return parseStateNode(result?.definition, opts);
return parseRootStateNode(result?.definition, opts);
};

export const getActionConfig = (
Expand Down
1 change: 1 addition & 0 deletions packages/machine-extractor/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export type ExtractorStateNodeConfig = {
export type ExtractorMachineConfig = ExtractorStateNodeConfig & {
predictableActionArguments?: boolean;
preserveActionOrder?: boolean;
context?: Record<string, any> | JsonExpressionString;
};

export type Location = t.SourceLocation | null;
Expand Down

0 comments on commit d885182

Please sign in to comment.