@cratis/scene.engine 3.7.0 → 4.0.0
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/ActionDispatcher.ts +87 -0
- package/buildStarterProfile.ts +2 -2
- package/dist/cjs/buildStarterProfile.js.map +1 -1
- package/dist/cjs/index.js +9 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/resolveBehaviors.js +104 -0
- package/dist/cjs/resolveBehaviors.js.map +1 -0
- package/dist/cjs/runActions.js +219 -0
- package/dist/cjs/runActions.js.map +1 -0
- package/dist/esm/ActionDispatcher.d.ts +27 -0
- package/dist/esm/ActionDispatcher.d.ts.map +1 -0
- package/dist/esm/ActionDispatcher.js +2 -0
- package/dist/esm/ActionDispatcher.js.map +1 -0
- package/dist/esm/buildStarterProfile.d.ts +2 -2
- package/dist/esm/buildStarterProfile.d.ts.map +1 -1
- package/dist/esm/buildStarterProfile.js.map +1 -1
- package/dist/esm/for_resolveBehaviors/when_resolving_additive_attachments.d.ts +2 -0
- package/dist/esm/for_resolveBehaviors/when_resolving_additive_attachments.d.ts.map +1 -0
- package/dist/esm/for_resolveBehaviors/when_resolving_additive_attachments.js +68 -0
- package/dist/esm/for_resolveBehaviors/when_resolving_additive_attachments.js.map +1 -0
- package/dist/esm/for_runActions/given/a_recording_dispatcher.d.ts +21 -0
- package/dist/esm/for_runActions/given/a_recording_dispatcher.d.ts.map +1 -0
- package/dist/esm/for_runActions/given/a_recording_dispatcher.js +45 -0
- package/dist/esm/for_runActions/given/a_recording_dispatcher.js.map +1 -0
- package/dist/esm/for_runActions/when_running_a_sequence_of_actions.d.ts +2 -0
- package/dist/esm/for_runActions/when_running_a_sequence_of_actions.d.ts.map +1 -0
- package/dist/esm/for_runActions/when_running_a_sequence_of_actions.js +126 -0
- package/dist/esm/for_runActions/when_running_a_sequence_of_actions.js.map +1 -0
- package/dist/esm/for_runActions/when_running_against_the_shared_fixture_corpus.d.ts +2 -0
- package/dist/esm/for_runActions/when_running_against_the_shared_fixture_corpus.d.ts.map +1 -0
- package/dist/esm/for_runActions/when_running_against_the_shared_fixture_corpus.js +61 -0
- package/dist/esm/for_runActions/when_running_against_the_shared_fixture_corpus.js.map +1 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/resolveBehaviors.d.ts +16 -0
- package/dist/esm/resolveBehaviors.d.ts.map +1 -0
- package/dist/esm/resolveBehaviors.js +99 -0
- package/dist/esm/resolveBehaviors.js.map +1 -0
- package/dist/esm/runActions.d.ts +26 -0
- package/dist/esm/runActions.d.ts.map +1 -0
- package/dist/esm/runActions.js +215 -0
- package/dist/esm/runActions.js.map +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/for_resolveBehaviors/when_resolving_additive_attachments.ts +100 -0
- package/for_runActions/given/a_recording_dispatcher.ts +72 -0
- package/for_runActions/when_running_a_sequence_of_actions.ts +226 -0
- package/for_runActions/when_running_against_the_shared_fixture_corpus.ts +124 -0
- package/index.ts +3 -0
- package/package.json +3 -3
- package/resolveBehaviors.ts +137 -0
- package/runActions.ts +284 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { InteractionActionKind, InteractionTriggerKind } from '@cratis/scene.model';
|
|
2
|
+
import { resolveApplicationTriggerBehaviors, resolveBehaviors } from '../resolveBehaviors';
|
|
3
|
+
const behavior = (name, kind, order) => ({
|
|
4
|
+
name,
|
|
5
|
+
order,
|
|
6
|
+
bindings: [
|
|
7
|
+
{
|
|
8
|
+
trigger: { kind },
|
|
9
|
+
actions: [{ kind: InteractionActionKind.RefreshQuery, query: name ?? 'inline' }],
|
|
10
|
+
},
|
|
11
|
+
],
|
|
12
|
+
});
|
|
13
|
+
describe('when resolving additive attachments', () => {
|
|
14
|
+
const attachments = [
|
|
15
|
+
{ level: 'layout', behaviors: [behavior('LayoutWide', InteractionTriggerKind.Click)] },
|
|
16
|
+
{ level: 'module', behaviors: [behavior('ModuleWide', InteractionTriggerKind.Click)] },
|
|
17
|
+
{ level: 'element', behaviors: [behavior(undefined, InteractionTriggerKind.Click)] },
|
|
18
|
+
];
|
|
19
|
+
it('should run every matching attachment rather than only the most specific', () => {
|
|
20
|
+
const resolved = resolveBehaviors(attachments, InteractionTriggerKind.Click);
|
|
21
|
+
resolved.should.have.lengthOf(3);
|
|
22
|
+
});
|
|
23
|
+
it('should run the outermost attachment first', () => {
|
|
24
|
+
const resolved = resolveBehaviors(attachments, InteractionTriggerKind.Click);
|
|
25
|
+
resolved.map(candidate => candidate.level).should.eql(['layout', 'module', 'element']);
|
|
26
|
+
});
|
|
27
|
+
it('should keep an inline behavior anonymous', () => {
|
|
28
|
+
const resolved = resolveBehaviors(attachments, InteractionTriggerKind.Click);
|
|
29
|
+
(resolved[2].behaviorName === undefined).should.be.true;
|
|
30
|
+
});
|
|
31
|
+
it('should ignore bindings for a different trigger', () => {
|
|
32
|
+
const resolved = resolveBehaviors([{ level: 'element', behaviors: [behavior('OnSubmitOnly', InteractionTriggerKind.Submit)] }], InteractionTriggerKind.Click);
|
|
33
|
+
resolved.should.be.empty;
|
|
34
|
+
});
|
|
35
|
+
it('should let an explicit order win over position', () => {
|
|
36
|
+
const resolved = resolveBehaviors([
|
|
37
|
+
{ level: 'layout', behaviors: [behavior('LayoutWide', InteractionTriggerKind.Click)] },
|
|
38
|
+
{ level: 'element', behaviors: [behavior('RunsFirst', InteractionTriggerKind.Click, 1)] },
|
|
39
|
+
], InteractionTriggerKind.Click);
|
|
40
|
+
resolved.map(candidate => candidate.behaviorName).should.eql(['RunsFirst', 'LayoutWide']);
|
|
41
|
+
});
|
|
42
|
+
it('should order deterministically across repeated resolutions', () => {
|
|
43
|
+
const once = resolveBehaviors(attachments, InteractionTriggerKind.Click).map(c => c.level);
|
|
44
|
+
const twice = resolveBehaviors(attachments, InteractionTriggerKind.Click).map(c => c.level);
|
|
45
|
+
once.should.eql(twice);
|
|
46
|
+
});
|
|
47
|
+
it('should resolve a named application trigger separately from the built-in kinds', () => {
|
|
48
|
+
const resolved = resolveApplicationTriggerBehaviors([
|
|
49
|
+
{
|
|
50
|
+
level: 'screen',
|
|
51
|
+
behaviors: [
|
|
52
|
+
{
|
|
53
|
+
name: undefined,
|
|
54
|
+
bindings: [
|
|
55
|
+
{ trigger: { triggerName: 'InvoiceImported' }, actions: [] },
|
|
56
|
+
{ trigger: { triggerName: 'SomethingElse' }, actions: [] },
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
], 'InvoiceImported');
|
|
62
|
+
resolved.should.have.lengthOf(1);
|
|
63
|
+
});
|
|
64
|
+
it('should tolerate an attachment with no behaviors at all', () => {
|
|
65
|
+
resolveBehaviors([{ level: 'element', behaviors: [] }], InteractionTriggerKind.Click).should.be.empty;
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
//# sourceMappingURL=when_resolving_additive_attachments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"when_resolving_additive_attachments.js","sourceRoot":"","sources":["../../../for_resolveBehaviors/when_resolving_additive_attachments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { NotificationLevel } from '@cratis/scene.model';
|
|
2
|
+
import { ActionDispatcher, CommandOutcome, DialogOutcome } from '../../ActionDispatcher';
|
|
3
|
+
import { InteractionContext } from '../../runActions';
|
|
4
|
+
export declare class RecordingDispatcher implements ActionDispatcher {
|
|
5
|
+
readonly calls: string[];
|
|
6
|
+
commandSucceeds: boolean;
|
|
7
|
+
dialogConfirmed: boolean;
|
|
8
|
+
confirmAnswer: boolean;
|
|
9
|
+
executeCommand(command: string, args: Record<string, unknown>): Promise<CommandOutcome>;
|
|
10
|
+
navigate(screen: string): void;
|
|
11
|
+
navigateBack(): void;
|
|
12
|
+
openDialog(dialogTemplate: string, args: Record<string, unknown>): Promise<DialogOutcome>;
|
|
13
|
+
closeDialog(): void;
|
|
14
|
+
refreshQuery(query: string): Promise<void>;
|
|
15
|
+
setState(target: string, value: unknown): void;
|
|
16
|
+
notify(level: NotificationLevel, message: string): void;
|
|
17
|
+
confirm(message: string): Promise<boolean>;
|
|
18
|
+
raise(trigger: string): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export declare const pathEchoingContext: InteractionContext;
|
|
21
|
+
//# sourceMappingURL=a_recording_dispatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a_recording_dispatcher.d.ts","sourceRoot":"","sources":["../../../../for_runActions/given/a_recording_dispatcher.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqB,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAQtD,qBAAa,mBAAoB,YAAW,gBAAgB;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAM;IAE9B,eAAe,UAAQ;IACvB,eAAe,UAAQ;IACvB,aAAa,UAAQ;IAEf,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CAK5F;IAED,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAE7B;IAED,YAAY,IAAI,IAAI,CAEnB;IAEK,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAG9F;IAED,WAAW,IAAI,IAAI,CAElB;IAEK,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;IAED,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAE7C;IAED,MAAM,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAEtD;IAEK,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAG/C;IAEK,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1C;CACJ;AAKD,eAAO,MAAM,kBAAkB,EAAE,kBAEhC,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export class RecordingDispatcher {
|
|
2
|
+
calls = [];
|
|
3
|
+
commandSucceeds = true;
|
|
4
|
+
dialogConfirmed = true;
|
|
5
|
+
confirmAnswer = true;
|
|
6
|
+
async executeCommand(command, args) {
|
|
7
|
+
this.calls.push(`executeCommand:${command}:${JSON.stringify(args)}`);
|
|
8
|
+
return this.commandSucceeds
|
|
9
|
+
? { isSuccess: true }
|
|
10
|
+
: { isSuccess: false, validationErrors: [{ member: 'amount', message: 'Must be positive' }] };
|
|
11
|
+
}
|
|
12
|
+
navigate(screen) {
|
|
13
|
+
this.calls.push(`navigate:${screen}`);
|
|
14
|
+
}
|
|
15
|
+
navigateBack() {
|
|
16
|
+
this.calls.push('navigateBack');
|
|
17
|
+
}
|
|
18
|
+
async openDialog(dialogTemplate, args) {
|
|
19
|
+
this.calls.push(`openDialog:${dialogTemplate}:${JSON.stringify(args)}`);
|
|
20
|
+
return { isConfirmed: this.dialogConfirmed, result: 'the-result' };
|
|
21
|
+
}
|
|
22
|
+
closeDialog() {
|
|
23
|
+
this.calls.push('closeDialog');
|
|
24
|
+
}
|
|
25
|
+
async refreshQuery(query) {
|
|
26
|
+
this.calls.push(`refreshQuery:${query}`);
|
|
27
|
+
}
|
|
28
|
+
setState(target, value) {
|
|
29
|
+
this.calls.push(`setState:${target}:${String(value)}`);
|
|
30
|
+
}
|
|
31
|
+
notify(level, message) {
|
|
32
|
+
this.calls.push(`notify:${level}:${message}`);
|
|
33
|
+
}
|
|
34
|
+
async confirm(message) {
|
|
35
|
+
this.calls.push(`confirm:${message}`);
|
|
36
|
+
return this.confirmAnswer;
|
|
37
|
+
}
|
|
38
|
+
async raise(trigger) {
|
|
39
|
+
this.calls.push(`raise:${trigger}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export const pathEchoingContext = {
|
|
43
|
+
resolve: (binding) => `<${binding.path}>`,
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=a_recording_dispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a_recording_dispatcher.js","sourceRoot":"","sources":["../../../../for_runActions/given/a_recording_dispatcher.ts"],"names":[],"mappings":"AAaA,MAAM,OAAO,mBAAmB;IACnB,KAAK,GAAa,EAAE,CAAC;IAE9B,eAAe,GAAG,IAAI,CAAC;IACvB,eAAe,GAAG,IAAI,CAAC;IACvB,aAAa,GAAG,IAAI,CAAC;IAErB,KAAK,CAAC,cAAc,CAAC,OAAe,EAAE,IAA6B;QAC/D,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrE,OAAO,IAAI,CAAC,eAAe;YACvB,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE;YACrB,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,EAAE,CAAC;IACtG,CAAC;IAED,QAAQ,CAAC,MAAc;QACnB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,YAAY;QACR,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,cAAsB,EAAE,IAA6B;QAClE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,cAAc,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxE,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IACvE,CAAC;IAED,WAAW;QACP,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAa;QAC5B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,KAAK,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,QAAQ,CAAC,MAAc,EAAE,KAAc;QACnC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,CAAC,KAAwB,EAAE,OAAe;QAC5C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,IAAI,OAAO,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAe;QACzB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC,aAAa,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,OAAe;QACvB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;IACxC,CAAC;CACJ;AAKD,MAAM,CAAC,MAAM,kBAAkB,GAAuB;IAClD,OAAO,EAAE,CAAC,OAA0B,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,IAAI,GAAG;CAC/D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"when_running_a_sequence_of_actions.d.ts","sourceRoot":"","sources":["../../../for_runActions/when_running_a_sequence_of_actions.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { InteractionActionKind, NotificationLevel } from '@cratis/scene.model';
|
|
2
|
+
import { InteractionStop, runActions } from '../runActions';
|
|
3
|
+
import { pathEchoingContext, RecordingDispatcher } from './given/a_recording_dispatcher';
|
|
4
|
+
const action = (kind, extra = {}) => ({ kind, ...extra });
|
|
5
|
+
describe('when running a sequence of actions', () => {
|
|
6
|
+
it('should run them in the order they were declared', async () => {
|
|
7
|
+
const dispatcher = new RecordingDispatcher();
|
|
8
|
+
await runActions([
|
|
9
|
+
action(InteractionActionKind.RefreshQuery, { query: 'Invoices' }),
|
|
10
|
+
action(InteractionActionKind.Notify, { level: NotificationLevel.Info, message: { text: 'Done' } }),
|
|
11
|
+
], dispatcher, pathEchoingContext);
|
|
12
|
+
dispatcher.calls.should.eql(['refreshQuery:Invoices', 'notify:Info:Done']);
|
|
13
|
+
});
|
|
14
|
+
it('should resolve an action\'s arguments through the binding resolver', async () => {
|
|
15
|
+
const dispatcher = new RecordingDispatcher();
|
|
16
|
+
await runActions([
|
|
17
|
+
action(InteractionActionKind.ExecuteCommand, {
|
|
18
|
+
command: 'CancelInvoice',
|
|
19
|
+
arguments: [{ name: 'invoiceId', value: { path: 'item.invoiceId' } }],
|
|
20
|
+
}),
|
|
21
|
+
], dispatcher, pathEchoingContext);
|
|
22
|
+
dispatcher.calls.should.eql(['executeCommand:CancelInvoice:{"invoiceId":"<item.invoiceId>"}']);
|
|
23
|
+
});
|
|
24
|
+
it('should take the success branch when a command succeeds', async () => {
|
|
25
|
+
const dispatcher = new RecordingDispatcher();
|
|
26
|
+
const run = await runActions([
|
|
27
|
+
action(InteractionActionKind.ExecuteCommand, {
|
|
28
|
+
command: 'RegisterInvoice',
|
|
29
|
+
onSuccess: [action(InteractionActionKind.CloseDialog)],
|
|
30
|
+
onFailure: [action(InteractionActionKind.Notify, { level: NotificationLevel.Error, message: { text: 'Failed' } })],
|
|
31
|
+
}),
|
|
32
|
+
], dispatcher, pathEchoingContext);
|
|
33
|
+
dispatcher.calls.should.eql(['executeCommand:RegisterInvoice:{}', 'closeDialog']);
|
|
34
|
+
run.stop.should.equal(InteractionStop.Completed);
|
|
35
|
+
});
|
|
36
|
+
it('should take the failure branch when a command fails', async () => {
|
|
37
|
+
const dispatcher = new RecordingDispatcher();
|
|
38
|
+
dispatcher.commandSucceeds = false;
|
|
39
|
+
await runActions([
|
|
40
|
+
action(InteractionActionKind.ExecuteCommand, {
|
|
41
|
+
command: 'RegisterInvoice',
|
|
42
|
+
onSuccess: [action(InteractionActionKind.CloseDialog)],
|
|
43
|
+
onFailure: [action(InteractionActionKind.Notify, { level: NotificationLevel.Error, message: { text: 'Failed' } })],
|
|
44
|
+
}),
|
|
45
|
+
], dispatcher, pathEchoingContext);
|
|
46
|
+
dispatcher.calls.should.eql(['executeCommand:RegisterInvoice:{}', 'notify:Error:Failed']);
|
|
47
|
+
});
|
|
48
|
+
it('should stop the sequence when a confirm is declined', async () => {
|
|
49
|
+
const dispatcher = new RecordingDispatcher();
|
|
50
|
+
dispatcher.confirmAnswer = false;
|
|
51
|
+
const run = await runActions([
|
|
52
|
+
action(InteractionActionKind.Confirm, {
|
|
53
|
+
message: { text: 'Are you sure?' },
|
|
54
|
+
onSuccess: [action(InteractionActionKind.ExecuteCommand, { command: 'CancelInvoice' })],
|
|
55
|
+
}),
|
|
56
|
+
action(InteractionActionKind.Notify, { level: NotificationLevel.Info, message: { text: 'Cancelled' } }),
|
|
57
|
+
], dispatcher, pathEchoingContext);
|
|
58
|
+
dispatcher.calls.should.eql(['confirm:Are you sure?']);
|
|
59
|
+
run.stop.should.equal(InteractionStop.Declined);
|
|
60
|
+
});
|
|
61
|
+
it('should run the gated actions when a confirm is accepted', async () => {
|
|
62
|
+
const dispatcher = new RecordingDispatcher();
|
|
63
|
+
await runActions([
|
|
64
|
+
action(InteractionActionKind.Confirm, {
|
|
65
|
+
message: { text: 'Are you sure?' },
|
|
66
|
+
onSuccess: [action(InteractionActionKind.ExecuteCommand, { command: 'CancelInvoice' })],
|
|
67
|
+
}),
|
|
68
|
+
], dispatcher, pathEchoingContext);
|
|
69
|
+
dispatcher.calls.should.eql(['confirm:Are you sure?', 'executeCommand:CancelInvoice:{}']);
|
|
70
|
+
});
|
|
71
|
+
it('should stop the sequence after a navigation', async () => {
|
|
72
|
+
const dispatcher = new RecordingDispatcher();
|
|
73
|
+
const run = await runActions([
|
|
74
|
+
action(InteractionActionKind.Navigate, { screen: 'InvoiceList' }),
|
|
75
|
+
action(InteractionActionKind.Notify, { level: NotificationLevel.Info, message: { text: 'Never runs' } }),
|
|
76
|
+
], dispatcher, pathEchoingContext);
|
|
77
|
+
dispatcher.calls.should.eql(['navigate:InvoiceList']);
|
|
78
|
+
run.stop.should.equal(InteractionStop.Navigated);
|
|
79
|
+
});
|
|
80
|
+
it('should stop the sequence after navigating back', async () => {
|
|
81
|
+
const dispatcher = new RecordingDispatcher();
|
|
82
|
+
const run = await runActions([action(InteractionActionKind.NavigateBack), action(InteractionActionKind.CloseDialog)], dispatcher, pathEchoingContext);
|
|
83
|
+
dispatcher.calls.should.eql(['navigateBack']);
|
|
84
|
+
run.stop.should.equal(InteractionStop.Navigated);
|
|
85
|
+
});
|
|
86
|
+
it('should run a dialog\'s result continuation after it closes', async () => {
|
|
87
|
+
const dispatcher = new RecordingDispatcher();
|
|
88
|
+
await runActions([
|
|
89
|
+
action(InteractionActionKind.OpenDialog, {
|
|
90
|
+
dialogTemplate: 'InvoiceDetails',
|
|
91
|
+
arguments: [{ name: 'invoiceId', value: { path: 'item.invoiceId' } }],
|
|
92
|
+
onResult: [action(InteractionActionKind.RefreshQuery, { query: 'Invoices' })],
|
|
93
|
+
}),
|
|
94
|
+
], dispatcher, pathEchoingContext);
|
|
95
|
+
dispatcher.calls.should.eql([
|
|
96
|
+
'openDialog:InvoiceDetails:{"invoiceId":"<item.invoiceId>"}',
|
|
97
|
+
'refreshQuery:Invoices',
|
|
98
|
+
]);
|
|
99
|
+
});
|
|
100
|
+
it('should resolve a message from a binding when it has one', async () => {
|
|
101
|
+
const dispatcher = new RecordingDispatcher();
|
|
102
|
+
await runActions([action(InteractionActionKind.Notify, { level: NotificationLevel.Info, message: { binding: { path: 'state.message' } } })], dispatcher, pathEchoingContext);
|
|
103
|
+
dispatcher.calls.should.eql(['notify:Info:<state.message>']);
|
|
104
|
+
});
|
|
105
|
+
it('should localize a message given a strings key', async () => {
|
|
106
|
+
const dispatcher = new RecordingDispatcher();
|
|
107
|
+
await runActions([action(InteractionActionKind.Notify, { level: NotificationLevel.Info, message: { stringsKey: 'invoiceRegistered' } })], dispatcher, { resolve: () => undefined, localize: key => `localized(${key})` });
|
|
108
|
+
dispatcher.calls.should.eql(['notify:Info:localized(invoiceRegistered)']);
|
|
109
|
+
});
|
|
110
|
+
it('should report an action kind it does not know instead of ignoring it', async () => {
|
|
111
|
+
const dispatcher = new RecordingDispatcher();
|
|
112
|
+
const run = await runActions([action('SomethingFromALaterVersion')], dispatcher, pathEchoingContext);
|
|
113
|
+
dispatcher.calls.should.be.empty;
|
|
114
|
+
run.stop.should.equal(InteractionStop.Reported);
|
|
115
|
+
run.findings.should.have.lengthOf(1);
|
|
116
|
+
run.findings[0].kind.should.equal('unknownAction');
|
|
117
|
+
run.findings[0].detail.should.contain('SomethingFromALaterVersion');
|
|
118
|
+
});
|
|
119
|
+
it('should report a message binding that resolved to nothing', async () => {
|
|
120
|
+
const dispatcher = new RecordingDispatcher();
|
|
121
|
+
const run = await runActions([action(InteractionActionKind.Confirm, { message: { binding: { path: 'state.missing' } } })], dispatcher, { resolve: () => undefined });
|
|
122
|
+
run.findings[0].kind.should.equal('unresolvedMessage');
|
|
123
|
+
run.findings[0].detail.should.contain('state.missing');
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
//# sourceMappingURL=when_running_a_sequence_of_actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"when_running_a_sequence_of_actions.js","sourceRoot":"","sources":["../../../for_runActions/when_running_a_sequence_of_actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"when_running_against_the_shared_fixture_corpus.d.ts","sourceRoot":"","sources":["../../../for_runActions/when_running_against_the_shared_fixture_corpus.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { InteractionActionKind, InteractionTriggerKind, NotificationLevel } from '@cratis/scene.model';
|
|
4
|
+
import { resolveBehaviors } from '../resolveBehaviors';
|
|
5
|
+
import { InteractionStop, runActions } from '../runActions';
|
|
6
|
+
import { pathEchoingContext, RecordingDispatcher } from './given/a_recording_dispatcher';
|
|
7
|
+
const manifestPath = join(import.meta.dirname, '..', '..', '..', '..', 'interaction-fixtures.json');
|
|
8
|
+
const corpus = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
9
|
+
function attachment(fixture) {
|
|
10
|
+
return {
|
|
11
|
+
level: fixture.level,
|
|
12
|
+
depth: fixture.depth,
|
|
13
|
+
behaviors: fixture.behaviors.map(behavior => ({
|
|
14
|
+
name: behavior.name ?? undefined,
|
|
15
|
+
order: behavior.order,
|
|
16
|
+
bindings: [
|
|
17
|
+
{
|
|
18
|
+
trigger: { kind: InteractionTriggerKind[behavior.trigger] },
|
|
19
|
+
actions: [],
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
})),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function action(fixture) {
|
|
26
|
+
return {
|
|
27
|
+
kind: InteractionActionKind[fixture.kind] ?? fixture.kind,
|
|
28
|
+
command: fixture.command,
|
|
29
|
+
query: fixture.query,
|
|
30
|
+
screen: fixture.screen,
|
|
31
|
+
dialogTemplate: fixture.dialogTemplate,
|
|
32
|
+
level: fixture.level === undefined ? undefined : NotificationLevel[fixture.level],
|
|
33
|
+
message: fixture.text === undefined ? undefined : { text: fixture.text },
|
|
34
|
+
onSuccess: (fixture.onSuccess ?? []).map(action),
|
|
35
|
+
onFailure: (fixture.onFailure ?? []).map(action),
|
|
36
|
+
onResult: (fixture.onResult ?? []).map(action),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function callsWithoutArguments(calls) {
|
|
40
|
+
return calls.map(call => call.replace(/:\{.*\}$/, ''));
|
|
41
|
+
}
|
|
42
|
+
describe('when running against the shared fixture corpus', () => {
|
|
43
|
+
for (const fixture of corpus.resolutionCases) {
|
|
44
|
+
it(`should resolve the case where ${fixture.name}`, () => {
|
|
45
|
+
const resolved = resolveBehaviors(fixture.attachments.map(attachment), InteractionTriggerKind[fixture.trigger]);
|
|
46
|
+
resolved.map(candidate => candidate.behaviorName ?? null).should.eql(fixture.expected);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
for (const fixture of corpus.sequencingCases) {
|
|
50
|
+
it(`should sequence the case where ${fixture.name}`, async () => {
|
|
51
|
+
const dispatcher = new RecordingDispatcher();
|
|
52
|
+
dispatcher.commandSucceeds = fixture.commandSucceeds;
|
|
53
|
+
dispatcher.confirmAnswer = fixture.confirmAnswer;
|
|
54
|
+
const run = await runActions(fixture.actions.map(action), dispatcher, pathEchoingContext);
|
|
55
|
+
callsWithoutArguments(dispatcher.calls).should.eql(fixture.expectedCalls);
|
|
56
|
+
run.stop.should.equal(InteractionStop[fixture.expectedStop]);
|
|
57
|
+
run.findings.map(finding => finding.kind).should.eql(fixture.expectedFindings ?? []);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
//# sourceMappingURL=when_running_against_the_shared_fixture_corpus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"when_running_against_the_shared_fixture_corpus.js","sourceRoot":"","sources":["../../../for_runActions/when_running_against_the_shared_fixture_corpus.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAqB,qBAAqB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC1H,OAAO,EAAsB,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAiDzF,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,2BAA2B,CAAC,CAAC;AACpG,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAkB,CAAC;AAEhF,SAAS,UAAU,CAAC,OAA0B;IAC1C,OAAO;QACH,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAC1C,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,SAAS;YAChC,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,QAAQ,EAAE;gBACN;oBACI,OAAO,EAAE,EAAE,IAAI,EAAE,sBAAsB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAW;oBACpE,OAAO,EAAE,EAAE;iBACd;aACJ;SACJ,CAAC,CAAC;KACN,CAAC;AACN,CAAC;AAED,SAAS,MAAM,CAAC,OAAsB;IAClC,OAAO;QACH,IAAI,EAAE,qBAAqB,CAAC,OAAO,CAAC,IAA0C,CAAC,IAAI,OAAO,CAAC,IAAI;QAC/F,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,KAAK,EAAE,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC;QACjF,OAAO,EAAE,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;QACxE,SAAS,EAAE,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;QAChD,SAAS,EAAE,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;QAChD,QAAQ,EAAE,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;KAC5B,CAAC;AAC3B,CAAC;AAID,SAAS,qBAAqB,CAAC,KAAe;IAC1C,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,QAAQ,CAAC,gDAAgD,EAAE,GAAG,EAAE;IAC5D,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QAC3C,EAAE,CAAC,iCAAiC,OAAO,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE;YACrD,MAAM,QAAQ,GAAG,gBAAgB,CAC7B,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,EACnC,sBAAsB,CAAC,OAAO,CAAC,OAAO,CAAC,CAC1C,CAAC;YAEF,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC3F,CAAC,CAAC,CAAC;IACP,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QAC3C,EAAE,CAAC,kCAAkC,OAAO,CAAC,IAAI,EAAE,EAAE,KAAK,IAAI,EAAE;YAC5D,MAAM,UAAU,GAAG,IAAI,mBAAmB,EAAE,CAAC;YAC7C,UAAU,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;YACrD,UAAU,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;YAEjD,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAC;YAE1F,qBAAqB,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YAC1E,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;YAC7D,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;QACzF,CAAC,CAAC,CAAC;IACP,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -19,4 +19,7 @@ export * from './packageCatalog';
|
|
|
19
19
|
export * from './resolveScreenTemplates';
|
|
20
20
|
export * from './buildStarterProfile';
|
|
21
21
|
export * from './incompatibleStarterThemes';
|
|
22
|
+
export * from './ActionDispatcher';
|
|
23
|
+
export * from './runActions';
|
|
24
|
+
export * from './resolveBehaviors';
|
|
22
25
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAGA,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAGA,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC"}
|
package/dist/esm/index.js
CHANGED
|
@@ -16,4 +16,6 @@ export { availablePackagesFor, baseComponentLibraries, componentsForPackages, pa
|
|
|
16
16
|
export { isScreenTemplateResolutionValid, resolveScreenTemplates } from './resolveScreenTemplates.js';
|
|
17
17
|
export { buildStarterProfile } from './buildStarterProfile.js';
|
|
18
18
|
export { incompatibleStarterThemes } from './incompatibleStarterThemes.js';
|
|
19
|
+
export { InteractionStop, runActions, runBindings } from './runActions.js';
|
|
20
|
+
export { resolveApplicationTriggerBehaviors, resolveBehaviors, resolveEventBehaviors, resolveIntervalBehaviors } from './resolveBehaviors.js';
|
|
19
21
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Behavior, InteractionBinding, InteractionTriggerKind } from '@cratis/scene.model';
|
|
2
|
+
export interface BehaviorAttachment {
|
|
3
|
+
level: string;
|
|
4
|
+
behaviors: Behavior[];
|
|
5
|
+
depth?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ResolvedBinding {
|
|
8
|
+
level: string;
|
|
9
|
+
behaviorName?: string;
|
|
10
|
+
binding: InteractionBinding;
|
|
11
|
+
}
|
|
12
|
+
export declare function resolveBehaviors(attachments: BehaviorAttachment[], kind: InteractionTriggerKind): ResolvedBinding[];
|
|
13
|
+
export declare function resolveApplicationTriggerBehaviors(attachments: BehaviorAttachment[], triggerName: string): ResolvedBinding[];
|
|
14
|
+
export declare function resolveEventBehaviors(attachments: BehaviorAttachment[], eventName: string): ResolvedBinding[];
|
|
15
|
+
export declare function resolveIntervalBehaviors(attachments: BehaviorAttachment[]): ResolvedBinding[];
|
|
16
|
+
//# sourceMappingURL=resolveBehaviors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveBehaviors.d.ts","sourceRoot":"","sources":["../../resolveBehaviors.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAsB,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAQ/G,MAAM,WAAW,kBAAkB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,QAAQ,EAAE,CAAC;IAStB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAKD,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,kBAAkB,CAAC;CAC/B;AAyBD,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,kBAAkB,EAAE,EAAE,IAAI,EAAE,sBAAsB,GAAG,eAAe,EAAE,CAgCnH;AASD,wBAAgB,kCAAkC,CAAC,WAAW,EAAE,kBAAkB,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,eAAe,EAAE,CAE5H;AASD,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,kBAAkB,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CAE7G;AAQD,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,kBAAkB,EAAE,GAAG,eAAe,EAAE,CAE7F"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
/**
|
|
4
|
+
* Whether the trigger is the built-in kind asked for.
|
|
5
|
+
*/ function isKind(trigger, kind) {
|
|
6
|
+
return trigger.kind === kind;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Collects the bindings that respond to a built-in interaction kind, in the order they run.
|
|
10
|
+
*
|
|
11
|
+
* Attachments are **additive**: a behavior on a template and a behavior on an element both run, rather than the
|
|
12
|
+
* more specific one replacing the less specific one. The order is outermost attachment first, declaration order
|
|
13
|
+
* within a level, and any behavior that declares an `order` sorts by it.
|
|
14
|
+
*
|
|
15
|
+
* The additive rule is what lets a module say 'confirm every destructive action' without every screen beneath it
|
|
16
|
+
* having to cooperate - but it also means the order has to be deterministic, or the same document behaves
|
|
17
|
+
* differently between runs. That is why this is a pure function over an ordered list rather than something
|
|
18
|
+
* assembled while rendering.
|
|
19
|
+
*
|
|
20
|
+
* @param attachments The attachment levels, outermost first.
|
|
21
|
+
* @param kind The built-in interaction kind that occurred.
|
|
22
|
+
* @returns The bindings to run, in order.
|
|
23
|
+
*/ function resolveBehaviors(attachments, kind) {
|
|
24
|
+
const resolved = [];
|
|
25
|
+
attachments.forEach((attachment, level)=>{
|
|
26
|
+
let declaration = 0;
|
|
27
|
+
for (const behavior of attachment.behaviors ?? []){
|
|
28
|
+
for (const binding of behavior.bindings ?? []){
|
|
29
|
+
if (!isKind(binding.trigger, kind)) continue;
|
|
30
|
+
resolved.push({
|
|
31
|
+
entry: {
|
|
32
|
+
level: attachment.level,
|
|
33
|
+
behaviorName: behavior.name,
|
|
34
|
+
binding
|
|
35
|
+
},
|
|
36
|
+
level: attachment.depth ?? level,
|
|
37
|
+
declaration: declaration++,
|
|
38
|
+
order: behavior.order
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
// An explicit order wins over position; everything else keeps the order it was written in. Sorting is
|
|
44
|
+
// stable on (order, level, declaration) so the result never depends on the sort implementation.
|
|
45
|
+
return resolved.sort((left, right)=>{
|
|
46
|
+
if (left.order !== right.order) {
|
|
47
|
+
if (left.order === undefined) return 1;
|
|
48
|
+
if (right.order === undefined) return -1;
|
|
49
|
+
return left.order - right.order;
|
|
50
|
+
}
|
|
51
|
+
return left.level !== right.level ? left.level - right.level : left.declaration - right.declaration;
|
|
52
|
+
}).map((candidate)=>candidate.entry);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Collects the bindings that respond to a named application trigger firing.
|
|
56
|
+
*
|
|
57
|
+
* @param attachments The attachment levels, outermost first.
|
|
58
|
+
* @param triggerName The application trigger that fired.
|
|
59
|
+
* @returns The bindings to run, in order.
|
|
60
|
+
*/ function resolveApplicationTriggerBehaviors(attachments, triggerName) {
|
|
61
|
+
return collect(attachments, (trigger)=>trigger.triggerName === triggerName);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Collects the bindings that respond to a modeled domain event being observed.
|
|
65
|
+
*
|
|
66
|
+
* @param attachments The attachment levels, outermost first.
|
|
67
|
+
* @param eventName The event that was observed.
|
|
68
|
+
* @returns The bindings to run, in order.
|
|
69
|
+
*/ function resolveEventBehaviors(attachments, eventName) {
|
|
70
|
+
return collect(attachments, (trigger)=>trigger.eventName === eventName);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Collects every interval binding, so a host can schedule them.
|
|
74
|
+
*
|
|
75
|
+
* @param attachments The attachment levels, outermost first.
|
|
76
|
+
* @returns The interval bindings, in order.
|
|
77
|
+
*/ function resolveIntervalBehaviors(attachments) {
|
|
78
|
+
return collect(attachments, (trigger)=>typeof trigger.seconds === 'number');
|
|
79
|
+
}
|
|
80
|
+
function collect(attachments, matches) {
|
|
81
|
+
const resolved = [];
|
|
82
|
+
for (const attachment of attachments){
|
|
83
|
+
for (const behavior of attachment.behaviors ?? []){
|
|
84
|
+
for (const binding of behavior.bindings ?? []){
|
|
85
|
+
if (matches(binding.trigger)) {
|
|
86
|
+
resolved.push({
|
|
87
|
+
level: attachment.level,
|
|
88
|
+
behaviorName: behavior.name,
|
|
89
|
+
binding
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return resolved;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export { resolveApplicationTriggerBehaviors, resolveBehaviors, resolveEventBehaviors, resolveIntervalBehaviors };
|
|
99
|
+
//# sourceMappingURL=resolveBehaviors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveBehaviors.js","sources":["../../resolveBehaviors.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Behavior, InteractionBinding, InteractionTrigger, InteractionTriggerKind } from '@cratis/scene.model';\n\n/**\n * One level of the containment tree a behavior can be attached to, outermost first.\n *\n * Named rather than positional so a finding can say *where* a behavior came from - 'the module's behavior ran\n * before the element's' is only a useful thing to report if the level has a name.\n */\nexport interface BehaviorAttachment {\n level: string;\n behaviors: Behavior[];\n\n /**\n * How deeply nested this attachment is, with 0 the outermost.\n *\n * Optional, defaulting to the position in the list. Stating it explicitly is what lets a caller assemble the\n * list in whatever order is convenient - walking a tree upwards from the element, for instance - without the\n * resolved order silently depending on that choice.\n */\n depth?: number;\n}\n\n/**\n * One binding to run, with the attachment it came from.\n */\nexport interface ResolvedBinding {\n level: string;\n behaviorName?: string;\n binding: InteractionBinding;\n}\n\n/**\n * Whether the trigger is the built-in kind asked for.\n */\nfunction isKind(trigger: InteractionTrigger, kind: InteractionTriggerKind): boolean {\n return (trigger as { kind?: InteractionTriggerKind }).kind === kind;\n}\n\n/**\n * Collects the bindings that respond to a built-in interaction kind, in the order they run.\n *\n * Attachments are **additive**: a behavior on a template and a behavior on an element both run, rather than the\n * more specific one replacing the less specific one. The order is outermost attachment first, declaration order\n * within a level, and any behavior that declares an `order` sorts by it.\n *\n * The additive rule is what lets a module say 'confirm every destructive action' without every screen beneath it\n * having to cooperate - but it also means the order has to be deterministic, or the same document behaves\n * differently between runs. That is why this is a pure function over an ordered list rather than something\n * assembled while rendering.\n *\n * @param attachments The attachment levels, outermost first.\n * @param kind The built-in interaction kind that occurred.\n * @returns The bindings to run, in order.\n */\nexport function resolveBehaviors(attachments: BehaviorAttachment[], kind: InteractionTriggerKind): ResolvedBinding[] {\n const resolved: { entry: ResolvedBinding; level: number; declaration: number; order?: number }[] = [];\n\n attachments.forEach((attachment, level) => {\n let declaration = 0;\n for (const behavior of (attachment.behaviors ?? [])) {\n for (const binding of (behavior.bindings ?? [])) {\n if (!isKind(binding.trigger, kind)) continue;\n\n resolved.push({\n entry: { level: attachment.level, behaviorName: behavior.name, binding },\n level: attachment.depth ?? level,\n declaration: declaration++,\n order: behavior.order,\n });\n }\n }\n });\n\n // An explicit order wins over position; everything else keeps the order it was written in. Sorting is\n // stable on (order, level, declaration) so the result never depends on the sort implementation.\n return resolved\n .sort((left, right) => {\n if (left.order !== right.order) {\n if (left.order === undefined) return 1;\n if (right.order === undefined) return -1;\n return left.order - right.order;\n }\n\n return left.level !== right.level ? left.level - right.level : left.declaration - right.declaration;\n })\n .map(candidate => candidate.entry);\n}\n\n/**\n * Collects the bindings that respond to a named application trigger firing.\n *\n * @param attachments The attachment levels, outermost first.\n * @param triggerName The application trigger that fired.\n * @returns The bindings to run, in order.\n */\nexport function resolveApplicationTriggerBehaviors(attachments: BehaviorAttachment[], triggerName: string): ResolvedBinding[] {\n return collect(attachments, trigger => (trigger as { triggerName?: string }).triggerName === triggerName);\n}\n\n/**\n * Collects the bindings that respond to a modeled domain event being observed.\n *\n * @param attachments The attachment levels, outermost first.\n * @param eventName The event that was observed.\n * @returns The bindings to run, in order.\n */\nexport function resolveEventBehaviors(attachments: BehaviorAttachment[], eventName: string): ResolvedBinding[] {\n return collect(attachments, trigger => (trigger as { eventName?: string }).eventName === eventName);\n}\n\n/**\n * Collects every interval binding, so a host can schedule them.\n *\n * @param attachments The attachment levels, outermost first.\n * @returns The interval bindings, in order.\n */\nexport function resolveIntervalBehaviors(attachments: BehaviorAttachment[]): ResolvedBinding[] {\n return collect(attachments, trigger => typeof (trigger as { seconds?: number }).seconds === 'number');\n}\n\nfunction collect(attachments: BehaviorAttachment[], matches: (trigger: InteractionTrigger) => boolean): ResolvedBinding[] {\n const resolved: ResolvedBinding[] = [];\n for (const attachment of attachments) {\n for (const behavior of (attachment.behaviors ?? [])) {\n for (const binding of (behavior.bindings ?? [])) {\n if (matches(binding.trigger)) {\n resolved.push({ level: attachment.level, behaviorName: behavior.name, binding });\n }\n }\n }\n }\n\n return resolved;\n}\n"],"names":["isKind","trigger","kind","resolveBehaviors","attachments","resolved","forEach","attachment","level","declaration","behavior","behaviors","binding","bindings","push","entry","behaviorName","name","depth","order","sort","left","right","undefined","map","candidate","resolveApplicationTriggerBehaviors","triggerName","collect","resolveEventBehaviors","eventName","resolveIntervalBehaviors","seconds","matches"],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ResolvedBinding } from './resolveBehaviors';
|
|
2
|
+
import { InteractionAction } from '@cratis/scene.model';
|
|
3
|
+
import { ActionDispatcher } from './ActionDispatcher';
|
|
4
|
+
import { BindingResolver } from './BindingResolver';
|
|
5
|
+
export declare enum InteractionStop {
|
|
6
|
+
Completed = "Completed",
|
|
7
|
+
Declined = "Declined",
|
|
8
|
+
Navigated = "Navigated",
|
|
9
|
+
Reported = "Reported"
|
|
10
|
+
}
|
|
11
|
+
export interface InteractionFinding {
|
|
12
|
+
kind: 'unknownAction' | 'unresolvedMessage' | 'unresolvedCondition';
|
|
13
|
+
detail: string;
|
|
14
|
+
}
|
|
15
|
+
export interface InteractionRun {
|
|
16
|
+
stop: InteractionStop;
|
|
17
|
+
findings: InteractionFinding[];
|
|
18
|
+
ran: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface InteractionContext {
|
|
21
|
+
resolve: BindingResolver;
|
|
22
|
+
localize?: (key: string) => string;
|
|
23
|
+
}
|
|
24
|
+
export declare function runActions(actions: InteractionAction[], dispatcher: ActionDispatcher, context: InteractionContext): Promise<InteractionRun>;
|
|
25
|
+
export declare function runBindings(bindings: ResolvedBinding[], dispatcher: ActionDispatcher, context: InteractionContext): Promise<InteractionRun>;
|
|
26
|
+
//# sourceMappingURL=runActions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runActions.d.ts","sourceRoot":"","sources":["../../runActions.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAGH,iBAAiB,EAUpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAKpD,oBAAY,eAAe;IAEvB,SAAS,cAAc;IAGvB,QAAQ,aAAa;IAGrB,SAAS,cAAc;IAGvB,QAAQ,aAAa;CACxB;AAQD,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,eAAe,GAAG,mBAAmB,GAAG,qBAAqB,CAAC;IACpE,MAAM,EAAE,MAAM,CAAC;CAClB;AAKD,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAE/B,GAAG,EAAE,MAAM,EAAE,CAAC;CACjB;AAKD,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,eAAe,CAAC;IAEzB,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;CACtC;AA+DD,wBAAsB,UAAU,CAC5B,OAAO,EAAE,iBAAiB,EAAE,EAC5B,UAAU,EAAE,gBAAgB,EAC5B,OAAO,EAAE,kBAAkB,GAC5B,OAAO,CAAC,cAAc,CAAC,CAIzB;AA+GD,wBAAsB,WAAW,CAC7B,QAAQ,EAAE,eAAe,EAAE,EAC3B,UAAU,EAAE,gBAAgB,EAC5B,OAAO,EAAE,kBAAkB,GAC5B,OAAO,CAAC,cAAc,CAAC,CAczB"}
|