@auto-engineer/narrative 0.11.12 → 0.11.14
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +22 -0
- package/dist/src/commands/export-schema-helper.js +1 -2
- package/dist/src/commands/export-schema-helper.js.map +1 -1
- package/dist/src/data-narrative-builders.d.ts +7 -5
- package/dist/src/data-narrative-builders.d.ts.map +1 -1
- package/dist/src/data-narrative-builders.js +19 -1
- package/dist/src/data-narrative-builders.js.map +1 -1
- package/dist/src/getNarratives.cache.specs.d.ts +2 -0
- package/dist/src/getNarratives.cache.specs.d.ts.map +1 -0
- package/dist/src/{getFlows.cache.specs.js → getNarratives.cache.specs.js} +1 -1
- package/dist/src/getNarratives.cache.specs.js.map +1 -0
- package/dist/src/getNarratives.specs.js +233 -19
- package/dist/src/getNarratives.specs.js.map +1 -1
- package/dist/src/model-to-narrative.specs.d.ts +2 -0
- package/dist/src/model-to-narrative.specs.d.ts.map +1 -0
- package/dist/src/{model-to-flow.specs.js → model-to-narrative.specs.js} +594 -2
- package/dist/src/model-to-narrative.specs.js.map +1 -0
- package/dist/src/narrative-context.d.ts.map +1 -1
- package/dist/src/narrative-context.js +0 -1
- package/dist/src/narrative-context.js.map +1 -1
- package/dist/src/narrative.d.ts +1 -0
- package/dist/src/narrative.d.ts.map +1 -1
- package/dist/src/narrative.js +11 -0
- package/dist/src/narrative.js.map +1 -1
- package/dist/src/samples/mixed-given-types.narrative.js +0 -1
- package/dist/src/samples/mixed-given-types.narrative.js.map +1 -1
- package/dist/src/samples/questionnaires.narrative.js +0 -2
- package/dist/src/samples/questionnaires.narrative.js.map +1 -1
- package/dist/src/schema.d.ts +2253 -2054
- package/dist/src/schema.d.ts.map +1 -1
- package/dist/src/schema.js +9 -1
- package/dist/src/schema.js.map +1 -1
- package/dist/src/transformers/model-to-narrative/generators/flow.d.ts.map +1 -1
- package/dist/src/transformers/model-to-narrative/generators/flow.js +49 -12
- package/dist/src/transformers/model-to-narrative/generators/flow.js.map +1 -1
- package/dist/src/transformers/model-to-narrative/generators/gwt.d.ts.map +1 -1
- package/dist/src/transformers/model-to-narrative/generators/gwt.js +32 -8
- package/dist/src/transformers/model-to-narrative/generators/gwt.js.map +1 -1
- package/dist/src/transformers/narrative-to-model/debug.d.ts.map +1 -1
- package/dist/src/transformers/narrative-to-model/debug.js +1 -1
- package/dist/src/transformers/narrative-to-model/debug.js.map +1 -1
- package/dist/src/types.d.ts +6 -8
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/src/commands/export-schema-helper.ts +1 -2
- package/src/data-narrative-builders.ts +41 -9
- package/src/getNarratives.specs.ts +266 -20
- package/src/{model-to-flow.specs.ts → model-to-narrative.specs.ts} +609 -1
- package/src/narrative-context.ts +0 -1
- package/src/narrative.ts +16 -1
- package/src/samples/mixed-given-types.narrative.ts +0 -1
- package/src/samples/questionnaires.narrative.ts +0 -2
- package/src/schema.ts +13 -1
- package/src/transformers/model-to-narrative/generators/flow.ts +85 -26
- package/src/transformers/model-to-narrative/generators/gwt.ts +44 -9
- package/src/transformers/narrative-to-model/debug.ts +1 -1
- package/src/types.ts +7 -9
- package/dist/src/getFlows.cache.specs.d.ts +0 -2
- package/dist/src/getFlows.cache.specs.d.ts.map +0 -1
- package/dist/src/getFlows.cache.specs.js.map +0 -1
- package/dist/src/model-to-flow.specs.d.ts +0 -2
- package/dist/src/model-to-flow.specs.d.ts.map +0 -1
- package/dist/src/model-to-flow.specs.js.map +0 -1
- /package/src/{getFlows.cache.specs.ts → getNarratives.cache.specs.ts} +0 -0
|
@@ -489,7 +489,9 @@ narrative('Test Flow with IDs', 'FLOW-123', () => {
|
|
|
489
489
|
should('allow filtering');
|
|
490
490
|
});
|
|
491
491
|
})
|
|
492
|
-
.server(() => {
|
|
492
|
+
.server(() => {
|
|
493
|
+
specs('Product data specs', () => {});
|
|
494
|
+
});
|
|
493
495
|
});
|
|
494
496
|
`);
|
|
495
497
|
});
|
|
@@ -1782,5 +1784,595 @@ narrative('Response Analytics', () => {
|
|
|
1782
1784
|
});
|
|
1783
1785
|
`);
|
|
1784
1786
|
});
|
|
1787
|
+
it('should omit .when({}) when given has multiple items and when is empty', async () => {
|
|
1788
|
+
const modelWithEmptyWhen = {
|
|
1789
|
+
variant: 'specs',
|
|
1790
|
+
narratives: [
|
|
1791
|
+
{
|
|
1792
|
+
name: 'Todo List Summary',
|
|
1793
|
+
id: 'TODO-001',
|
|
1794
|
+
slices: [
|
|
1795
|
+
{
|
|
1796
|
+
name: 'views completion summary',
|
|
1797
|
+
id: 'SUMMARY-001',
|
|
1798
|
+
type: 'query',
|
|
1799
|
+
client: {
|
|
1800
|
+
description: 'Summary view client',
|
|
1801
|
+
},
|
|
1802
|
+
server: {
|
|
1803
|
+
description: 'Summary calculation server',
|
|
1804
|
+
specs: {
|
|
1805
|
+
name: 'Summary Statistics',
|
|
1806
|
+
rules: [
|
|
1807
|
+
{
|
|
1808
|
+
id: 'RULE-SUMMARY',
|
|
1809
|
+
description: 'summary shows overall todo list statistics',
|
|
1810
|
+
examples: [
|
|
1811
|
+
{
|
|
1812
|
+
description: 'calculates summary from multiple todos',
|
|
1813
|
+
given: [
|
|
1814
|
+
{
|
|
1815
|
+
eventRef: 'TodoAdded',
|
|
1816
|
+
exampleData: {
|
|
1817
|
+
todoId: 'todo-001',
|
|
1818
|
+
description: 'Buy groceries',
|
|
1819
|
+
status: 'pending',
|
|
1820
|
+
addedAt: new Date('2030-01-01T09:00:00.000Z'),
|
|
1821
|
+
},
|
|
1822
|
+
},
|
|
1823
|
+
{
|
|
1824
|
+
eventRef: 'TodoAdded',
|
|
1825
|
+
exampleData: {
|
|
1826
|
+
todoId: 'todo-002',
|
|
1827
|
+
description: 'Write report',
|
|
1828
|
+
status: 'pending',
|
|
1829
|
+
addedAt: new Date('2030-01-01T09:10:00.000Z'),
|
|
1830
|
+
},
|
|
1831
|
+
},
|
|
1832
|
+
{
|
|
1833
|
+
eventRef: 'TodoMarkedInProgress',
|
|
1834
|
+
exampleData: {
|
|
1835
|
+
todoId: 'todo-001',
|
|
1836
|
+
markedAt: new Date('2030-01-01T10:00:00.000Z'),
|
|
1837
|
+
},
|
|
1838
|
+
},
|
|
1839
|
+
{
|
|
1840
|
+
eventRef: 'TodoMarkedComplete',
|
|
1841
|
+
exampleData: {
|
|
1842
|
+
todoId: 'todo-002',
|
|
1843
|
+
completedAt: new Date('2030-01-01T11:00:00.000Z'),
|
|
1844
|
+
},
|
|
1845
|
+
},
|
|
1846
|
+
],
|
|
1847
|
+
when: {
|
|
1848
|
+
eventRef: '',
|
|
1849
|
+
exampleData: {},
|
|
1850
|
+
},
|
|
1851
|
+
then: [
|
|
1852
|
+
{
|
|
1853
|
+
stateRef: 'TodoListSummary',
|
|
1854
|
+
exampleData: {
|
|
1855
|
+
summaryId: 'main-summary',
|
|
1856
|
+
totalTodos: 2,
|
|
1857
|
+
pendingCount: 0,
|
|
1858
|
+
inProgressCount: 1,
|
|
1859
|
+
completedCount: 1,
|
|
1860
|
+
completionPercentage: 50,
|
|
1861
|
+
},
|
|
1862
|
+
},
|
|
1863
|
+
],
|
|
1864
|
+
},
|
|
1865
|
+
],
|
|
1866
|
+
},
|
|
1867
|
+
],
|
|
1868
|
+
},
|
|
1869
|
+
},
|
|
1870
|
+
},
|
|
1871
|
+
],
|
|
1872
|
+
},
|
|
1873
|
+
],
|
|
1874
|
+
messages: [
|
|
1875
|
+
{
|
|
1876
|
+
type: 'event',
|
|
1877
|
+
name: 'TodoAdded',
|
|
1878
|
+
fields: [
|
|
1879
|
+
{ name: 'todoId', type: 'string', required: true },
|
|
1880
|
+
{ name: 'description', type: 'string', required: true },
|
|
1881
|
+
{ name: 'status', type: 'string', required: true },
|
|
1882
|
+
{ name: 'addedAt', type: 'Date', required: true },
|
|
1883
|
+
],
|
|
1884
|
+
source: 'internal',
|
|
1885
|
+
metadata: { version: 1 },
|
|
1886
|
+
},
|
|
1887
|
+
{
|
|
1888
|
+
type: 'event',
|
|
1889
|
+
name: 'TodoMarkedInProgress',
|
|
1890
|
+
fields: [
|
|
1891
|
+
{ name: 'todoId', type: 'string', required: true },
|
|
1892
|
+
{ name: 'markedAt', type: 'Date', required: true },
|
|
1893
|
+
],
|
|
1894
|
+
source: 'internal',
|
|
1895
|
+
metadata: { version: 1 },
|
|
1896
|
+
},
|
|
1897
|
+
{
|
|
1898
|
+
type: 'event',
|
|
1899
|
+
name: 'TodoMarkedComplete',
|
|
1900
|
+
fields: [
|
|
1901
|
+
{ name: 'todoId', type: 'string', required: true },
|
|
1902
|
+
{ name: 'completedAt', type: 'Date', required: true },
|
|
1903
|
+
],
|
|
1904
|
+
source: 'internal',
|
|
1905
|
+
metadata: { version: 1 },
|
|
1906
|
+
},
|
|
1907
|
+
{
|
|
1908
|
+
type: 'state',
|
|
1909
|
+
name: 'TodoListSummary',
|
|
1910
|
+
fields: [
|
|
1911
|
+
{ name: 'summaryId', type: 'string', required: true },
|
|
1912
|
+
{ name: 'totalTodos', type: 'number', required: true },
|
|
1913
|
+
{ name: 'pendingCount', type: 'number', required: true },
|
|
1914
|
+
{ name: 'inProgressCount', type: 'number', required: true },
|
|
1915
|
+
{ name: 'completedCount', type: 'number', required: true },
|
|
1916
|
+
{ name: 'completionPercentage', type: 'number', required: true },
|
|
1917
|
+
],
|
|
1918
|
+
metadata: { version: 1 },
|
|
1919
|
+
},
|
|
1920
|
+
],
|
|
1921
|
+
integrations: [],
|
|
1922
|
+
};
|
|
1923
|
+
const code = await modelToNarrative(modelWithEmptyWhen);
|
|
1924
|
+
expect(code).toEqual(`import { example, narrative, query, rule, specs } from '@auto-engineer/narrative';
|
|
1925
|
+
import type { Event, State } from '@auto-engineer/narrative';
|
|
1926
|
+
type TodoAdded = Event<
|
|
1927
|
+
'TodoAdded',
|
|
1928
|
+
{
|
|
1929
|
+
todoId: string;
|
|
1930
|
+
description: string;
|
|
1931
|
+
status: string;
|
|
1932
|
+
addedAt: Date;
|
|
1933
|
+
}
|
|
1934
|
+
>;
|
|
1935
|
+
type TodoMarkedInProgress = Event<
|
|
1936
|
+
'TodoMarkedInProgress',
|
|
1937
|
+
{
|
|
1938
|
+
todoId: string;
|
|
1939
|
+
markedAt: Date;
|
|
1940
|
+
}
|
|
1941
|
+
>;
|
|
1942
|
+
type TodoMarkedComplete = Event<
|
|
1943
|
+
'TodoMarkedComplete',
|
|
1944
|
+
{
|
|
1945
|
+
todoId: string;
|
|
1946
|
+
completedAt: Date;
|
|
1947
|
+
}
|
|
1948
|
+
>;
|
|
1949
|
+
type TodoListSummary = State<
|
|
1950
|
+
'TodoListSummary',
|
|
1951
|
+
{
|
|
1952
|
+
summaryId: string;
|
|
1953
|
+
totalTodos: number;
|
|
1954
|
+
pendingCount: number;
|
|
1955
|
+
inProgressCount: number;
|
|
1956
|
+
completedCount: number;
|
|
1957
|
+
completionPercentage: number;
|
|
1958
|
+
}
|
|
1959
|
+
>;
|
|
1960
|
+
narrative('Todo List Summary', 'TODO-001', () => {
|
|
1961
|
+
query('views completion summary', 'SUMMARY-001').server(() => {
|
|
1962
|
+
specs('Summary Statistics', () => {
|
|
1963
|
+
rule('summary shows overall todo list statistics', 'RULE-SUMMARY', () => {
|
|
1964
|
+
example('calculates summary from multiple todos')
|
|
1965
|
+
.given<TodoAdded>({
|
|
1966
|
+
todoId: 'todo-001',
|
|
1967
|
+
description: 'Buy groceries',
|
|
1968
|
+
status: 'pending',
|
|
1969
|
+
addedAt: new Date('2030-01-01T09:00:00.000Z'),
|
|
1970
|
+
})
|
|
1971
|
+
.and<TodoAdded>({
|
|
1972
|
+
todoId: 'todo-002',
|
|
1973
|
+
description: 'Write report',
|
|
1974
|
+
status: 'pending',
|
|
1975
|
+
addedAt: new Date('2030-01-01T09:10:00.000Z'),
|
|
1976
|
+
})
|
|
1977
|
+
.and<TodoMarkedInProgress>({ todoId: 'todo-001', markedAt: new Date('2030-01-01T10:00:00.000Z') })
|
|
1978
|
+
.and<TodoMarkedComplete>({ todoId: 'todo-002', completedAt: new Date('2030-01-01T11:00:00.000Z') })
|
|
1979
|
+
.then<TodoListSummary>({
|
|
1980
|
+
summaryId: 'main-summary',
|
|
1981
|
+
totalTodos: 2,
|
|
1982
|
+
pendingCount: 0,
|
|
1983
|
+
inProgressCount: 1,
|
|
1984
|
+
completedCount: 1,
|
|
1985
|
+
completionPercentage: 50,
|
|
1986
|
+
});
|
|
1987
|
+
});
|
|
1988
|
+
});
|
|
1989
|
+
});
|
|
1990
|
+
});
|
|
1991
|
+
`);
|
|
1992
|
+
expect(code).not.toContain('.when({})');
|
|
1993
|
+
expect(code).not.toContain('.when<');
|
|
1994
|
+
});
|
|
1995
|
+
describe('projection DSL generation', () => {
|
|
1996
|
+
it('should generate fromSingletonProjection for singleton projections', async () => {
|
|
1997
|
+
const modelWithSingletonProjection = {
|
|
1998
|
+
variant: 'specs',
|
|
1999
|
+
narratives: [
|
|
2000
|
+
{
|
|
2001
|
+
name: 'Todo Summary Flow',
|
|
2002
|
+
id: 'TODO-SUMMARY',
|
|
2003
|
+
slices: [
|
|
2004
|
+
{
|
|
2005
|
+
name: 'views todo summary',
|
|
2006
|
+
id: 'SUMMARY-SLICE',
|
|
2007
|
+
type: 'query',
|
|
2008
|
+
client: {
|
|
2009
|
+
description: 'Summary client',
|
|
2010
|
+
},
|
|
2011
|
+
server: {
|
|
2012
|
+
description: 'Summary server',
|
|
2013
|
+
data: [
|
|
2014
|
+
{
|
|
2015
|
+
target: {
|
|
2016
|
+
type: 'State',
|
|
2017
|
+
name: 'TodoListSummary',
|
|
2018
|
+
},
|
|
2019
|
+
origin: {
|
|
2020
|
+
type: 'projection',
|
|
2021
|
+
name: 'TodoSummary',
|
|
2022
|
+
singleton: true,
|
|
2023
|
+
},
|
|
2024
|
+
},
|
|
2025
|
+
],
|
|
2026
|
+
specs: {
|
|
2027
|
+
name: 'Summary Rules',
|
|
2028
|
+
rules: [],
|
|
2029
|
+
},
|
|
2030
|
+
},
|
|
2031
|
+
},
|
|
2032
|
+
],
|
|
2033
|
+
},
|
|
2034
|
+
],
|
|
2035
|
+
messages: [
|
|
2036
|
+
{
|
|
2037
|
+
type: 'state',
|
|
2038
|
+
name: 'TodoListSummary',
|
|
2039
|
+
fields: [
|
|
2040
|
+
{ name: 'summaryId', type: 'string', required: true },
|
|
2041
|
+
{ name: 'totalTodos', type: 'number', required: true },
|
|
2042
|
+
],
|
|
2043
|
+
metadata: { version: 1 },
|
|
2044
|
+
},
|
|
2045
|
+
],
|
|
2046
|
+
integrations: [],
|
|
2047
|
+
};
|
|
2048
|
+
const code = await modelToNarrative(modelWithSingletonProjection);
|
|
2049
|
+
expect(code).toEqual(`import { data, narrative, query, source, specs } from '@auto-engineer/narrative';
|
|
2050
|
+
import type { State } from '@auto-engineer/narrative';
|
|
2051
|
+
type TodoListSummary = State<
|
|
2052
|
+
'TodoListSummary',
|
|
2053
|
+
{
|
|
2054
|
+
summaryId: string;
|
|
2055
|
+
totalTodos: number;
|
|
2056
|
+
}
|
|
2057
|
+
>;
|
|
2058
|
+
narrative('Todo Summary Flow', 'TODO-SUMMARY', () => {
|
|
2059
|
+
query('views todo summary', 'SUMMARY-SLICE').server(() => {
|
|
2060
|
+
data([source().state('TodoListSummary').fromSingletonProjection('TodoSummary')]);
|
|
2061
|
+
specs('Summary Rules', () => {});
|
|
2062
|
+
});
|
|
2063
|
+
});
|
|
2064
|
+
`);
|
|
2065
|
+
});
|
|
2066
|
+
it('should generate fromProjection with single idField for regular projections', async () => {
|
|
2067
|
+
const modelWithRegularProjection = {
|
|
2068
|
+
variant: 'specs',
|
|
2069
|
+
narratives: [
|
|
2070
|
+
{
|
|
2071
|
+
name: 'Todo Flow',
|
|
2072
|
+
id: 'TODO-FLOW',
|
|
2073
|
+
slices: [
|
|
2074
|
+
{
|
|
2075
|
+
name: 'views todo',
|
|
2076
|
+
id: 'TODO-SLICE',
|
|
2077
|
+
type: 'query',
|
|
2078
|
+
client: {
|
|
2079
|
+
description: 'Todo client',
|
|
2080
|
+
},
|
|
2081
|
+
server: {
|
|
2082
|
+
description: 'Todo server',
|
|
2083
|
+
data: [
|
|
2084
|
+
{
|
|
2085
|
+
target: {
|
|
2086
|
+
type: 'State',
|
|
2087
|
+
name: 'TodoState',
|
|
2088
|
+
},
|
|
2089
|
+
origin: {
|
|
2090
|
+
type: 'projection',
|
|
2091
|
+
name: 'Todos',
|
|
2092
|
+
idField: 'todoId',
|
|
2093
|
+
},
|
|
2094
|
+
},
|
|
2095
|
+
],
|
|
2096
|
+
specs: {
|
|
2097
|
+
name: 'Todo Rules',
|
|
2098
|
+
rules: [],
|
|
2099
|
+
},
|
|
2100
|
+
},
|
|
2101
|
+
},
|
|
2102
|
+
],
|
|
2103
|
+
},
|
|
2104
|
+
],
|
|
2105
|
+
messages: [
|
|
2106
|
+
{
|
|
2107
|
+
type: 'state',
|
|
2108
|
+
name: 'TodoState',
|
|
2109
|
+
fields: [
|
|
2110
|
+
{ name: 'todoId', type: 'string', required: true },
|
|
2111
|
+
{ name: 'description', type: 'string', required: true },
|
|
2112
|
+
],
|
|
2113
|
+
metadata: { version: 1 },
|
|
2114
|
+
},
|
|
2115
|
+
],
|
|
2116
|
+
integrations: [],
|
|
2117
|
+
};
|
|
2118
|
+
const code = await modelToNarrative(modelWithRegularProjection);
|
|
2119
|
+
expect(code).toEqual(`import { data, narrative, query, source, specs } from '@auto-engineer/narrative';
|
|
2120
|
+
import type { State } from '@auto-engineer/narrative';
|
|
2121
|
+
type TodoState = State<
|
|
2122
|
+
'TodoState',
|
|
2123
|
+
{
|
|
2124
|
+
todoId: string;
|
|
2125
|
+
description: string;
|
|
2126
|
+
}
|
|
2127
|
+
>;
|
|
2128
|
+
narrative('Todo Flow', 'TODO-FLOW', () => {
|
|
2129
|
+
query('views todo', 'TODO-SLICE').server(() => {
|
|
2130
|
+
data([source().state('TodoState').fromProjection('Todos', 'todoId')]);
|
|
2131
|
+
specs('Todo Rules', () => {});
|
|
2132
|
+
});
|
|
2133
|
+
});
|
|
2134
|
+
`);
|
|
2135
|
+
});
|
|
2136
|
+
it('should generate fromCompositeProjection with array idField for composite key projections', async () => {
|
|
2137
|
+
const modelWithCompositeProjection = {
|
|
2138
|
+
variant: 'specs',
|
|
2139
|
+
narratives: [
|
|
2140
|
+
{
|
|
2141
|
+
name: 'User Project Flow',
|
|
2142
|
+
id: 'USER-PROJECT-FLOW',
|
|
2143
|
+
slices: [
|
|
2144
|
+
{
|
|
2145
|
+
name: 'views user project',
|
|
2146
|
+
id: 'USER-PROJECT-SLICE',
|
|
2147
|
+
type: 'query',
|
|
2148
|
+
client: {
|
|
2149
|
+
description: 'User project client',
|
|
2150
|
+
},
|
|
2151
|
+
server: {
|
|
2152
|
+
description: 'User project server',
|
|
2153
|
+
data: [
|
|
2154
|
+
{
|
|
2155
|
+
target: {
|
|
2156
|
+
type: 'State',
|
|
2157
|
+
name: 'UserProjectState',
|
|
2158
|
+
},
|
|
2159
|
+
origin: {
|
|
2160
|
+
type: 'projection',
|
|
2161
|
+
name: 'UserProjects',
|
|
2162
|
+
idField: ['userId', 'projectId'],
|
|
2163
|
+
},
|
|
2164
|
+
},
|
|
2165
|
+
],
|
|
2166
|
+
specs: {
|
|
2167
|
+
name: 'User Project Rules',
|
|
2168
|
+
rules: [],
|
|
2169
|
+
},
|
|
2170
|
+
},
|
|
2171
|
+
},
|
|
2172
|
+
],
|
|
2173
|
+
},
|
|
2174
|
+
],
|
|
2175
|
+
messages: [
|
|
2176
|
+
{
|
|
2177
|
+
type: 'state',
|
|
2178
|
+
name: 'UserProjectState',
|
|
2179
|
+
fields: [
|
|
2180
|
+
{ name: 'userId', type: 'string', required: true },
|
|
2181
|
+
{ name: 'projectId', type: 'string', required: true },
|
|
2182
|
+
{ name: 'role', type: 'string', required: true },
|
|
2183
|
+
],
|
|
2184
|
+
metadata: { version: 1 },
|
|
2185
|
+
},
|
|
2186
|
+
],
|
|
2187
|
+
integrations: [],
|
|
2188
|
+
};
|
|
2189
|
+
const code = await modelToNarrative(modelWithCompositeProjection);
|
|
2190
|
+
expect(code).toEqual(`import { data, narrative, query, source, specs } from '@auto-engineer/narrative';
|
|
2191
|
+
import type { State } from '@auto-engineer/narrative';
|
|
2192
|
+
type UserProjectState = State<
|
|
2193
|
+
'UserProjectState',
|
|
2194
|
+
{
|
|
2195
|
+
userId: string;
|
|
2196
|
+
projectId: string;
|
|
2197
|
+
role: string;
|
|
2198
|
+
}
|
|
2199
|
+
>;
|
|
2200
|
+
narrative('User Project Flow', 'USER-PROJECT-FLOW', () => {
|
|
2201
|
+
query('views user project', 'USER-PROJECT-SLICE').server(() => {
|
|
2202
|
+
data([source().state('UserProjectState').fromCompositeProjection('UserProjects', ['userId', 'projectId'])]);
|
|
2203
|
+
specs('User Project Rules', () => {});
|
|
2204
|
+
});
|
|
2205
|
+
});
|
|
2206
|
+
`);
|
|
2207
|
+
});
|
|
2208
|
+
it('should generate all three projection types in a single narrative', async () => {
|
|
2209
|
+
const modelWithAllProjectionTypes = {
|
|
2210
|
+
variant: 'specs',
|
|
2211
|
+
narratives: [
|
|
2212
|
+
{
|
|
2213
|
+
name: 'All Projection Types',
|
|
2214
|
+
id: 'ALL-PROJ',
|
|
2215
|
+
slices: [
|
|
2216
|
+
{
|
|
2217
|
+
name: 'views summary',
|
|
2218
|
+
id: 'SUMMARY-SLICE',
|
|
2219
|
+
type: 'query',
|
|
2220
|
+
client: {
|
|
2221
|
+
description: 'Summary client',
|
|
2222
|
+
},
|
|
2223
|
+
server: {
|
|
2224
|
+
description: 'Summary server',
|
|
2225
|
+
data: [
|
|
2226
|
+
{
|
|
2227
|
+
target: {
|
|
2228
|
+
type: 'State',
|
|
2229
|
+
name: 'TodoListSummary',
|
|
2230
|
+
},
|
|
2231
|
+
origin: {
|
|
2232
|
+
type: 'projection',
|
|
2233
|
+
name: 'TodoSummary',
|
|
2234
|
+
singleton: true,
|
|
2235
|
+
},
|
|
2236
|
+
},
|
|
2237
|
+
],
|
|
2238
|
+
specs: {
|
|
2239
|
+
name: 'Summary Rules',
|
|
2240
|
+
rules: [],
|
|
2241
|
+
},
|
|
2242
|
+
},
|
|
2243
|
+
},
|
|
2244
|
+
{
|
|
2245
|
+
name: 'views todo',
|
|
2246
|
+
id: 'TODO-SLICE',
|
|
2247
|
+
type: 'query',
|
|
2248
|
+
client: {
|
|
2249
|
+
description: 'Todo client',
|
|
2250
|
+
},
|
|
2251
|
+
server: {
|
|
2252
|
+
description: 'Todo server',
|
|
2253
|
+
data: [
|
|
2254
|
+
{
|
|
2255
|
+
target: {
|
|
2256
|
+
type: 'State',
|
|
2257
|
+
name: 'TodoState',
|
|
2258
|
+
},
|
|
2259
|
+
origin: {
|
|
2260
|
+
type: 'projection',
|
|
2261
|
+
name: 'Todos',
|
|
2262
|
+
idField: 'todoId',
|
|
2263
|
+
},
|
|
2264
|
+
},
|
|
2265
|
+
],
|
|
2266
|
+
specs: {
|
|
2267
|
+
name: 'Todo Rules',
|
|
2268
|
+
rules: [],
|
|
2269
|
+
},
|
|
2270
|
+
},
|
|
2271
|
+
},
|
|
2272
|
+
{
|
|
2273
|
+
name: 'views user project todos',
|
|
2274
|
+
id: 'USER-PROJECT-SLICE',
|
|
2275
|
+
type: 'query',
|
|
2276
|
+
client: {
|
|
2277
|
+
description: 'User project client',
|
|
2278
|
+
},
|
|
2279
|
+
server: {
|
|
2280
|
+
description: 'User project server',
|
|
2281
|
+
data: [
|
|
2282
|
+
{
|
|
2283
|
+
target: {
|
|
2284
|
+
type: 'State',
|
|
2285
|
+
name: 'UserProjectTodos',
|
|
2286
|
+
},
|
|
2287
|
+
origin: {
|
|
2288
|
+
type: 'projection',
|
|
2289
|
+
name: 'UserProjectTodos',
|
|
2290
|
+
idField: ['userId', 'projectId'],
|
|
2291
|
+
},
|
|
2292
|
+
},
|
|
2293
|
+
],
|
|
2294
|
+
specs: {
|
|
2295
|
+
name: 'User Project Rules',
|
|
2296
|
+
rules: [],
|
|
2297
|
+
},
|
|
2298
|
+
},
|
|
2299
|
+
},
|
|
2300
|
+
],
|
|
2301
|
+
},
|
|
2302
|
+
],
|
|
2303
|
+
messages: [
|
|
2304
|
+
{
|
|
2305
|
+
type: 'state',
|
|
2306
|
+
name: 'TodoListSummary',
|
|
2307
|
+
fields: [
|
|
2308
|
+
{ name: 'summaryId', type: 'string', required: true },
|
|
2309
|
+
{ name: 'totalTodos', type: 'number', required: true },
|
|
2310
|
+
],
|
|
2311
|
+
metadata: { version: 1 },
|
|
2312
|
+
},
|
|
2313
|
+
{
|
|
2314
|
+
type: 'state',
|
|
2315
|
+
name: 'TodoState',
|
|
2316
|
+
fields: [
|
|
2317
|
+
{ name: 'todoId', type: 'string', required: true },
|
|
2318
|
+
{ name: 'description', type: 'string', required: true },
|
|
2319
|
+
],
|
|
2320
|
+
metadata: { version: 1 },
|
|
2321
|
+
},
|
|
2322
|
+
{
|
|
2323
|
+
type: 'state',
|
|
2324
|
+
name: 'UserProjectTodos',
|
|
2325
|
+
fields: [
|
|
2326
|
+
{ name: 'userId', type: 'string', required: true },
|
|
2327
|
+
{ name: 'projectId', type: 'string', required: true },
|
|
2328
|
+
{ name: 'todos', type: 'Array<string>', required: true },
|
|
2329
|
+
],
|
|
2330
|
+
metadata: { version: 1 },
|
|
2331
|
+
},
|
|
2332
|
+
],
|
|
2333
|
+
integrations: [],
|
|
2334
|
+
};
|
|
2335
|
+
const code = await modelToNarrative(modelWithAllProjectionTypes);
|
|
2336
|
+
expect(code).toEqual(`import { data, narrative, query, source, specs } from '@auto-engineer/narrative';
|
|
2337
|
+
import type { State } from '@auto-engineer/narrative';
|
|
2338
|
+
type TodoListSummary = State<
|
|
2339
|
+
'TodoListSummary',
|
|
2340
|
+
{
|
|
2341
|
+
summaryId: string;
|
|
2342
|
+
totalTodos: number;
|
|
2343
|
+
}
|
|
2344
|
+
>;
|
|
2345
|
+
type TodoState = State<
|
|
2346
|
+
'TodoState',
|
|
2347
|
+
{
|
|
2348
|
+
todoId: string;
|
|
2349
|
+
description: string;
|
|
2350
|
+
}
|
|
2351
|
+
>;
|
|
2352
|
+
type UserProjectTodos = State<
|
|
2353
|
+
'UserProjectTodos',
|
|
2354
|
+
{
|
|
2355
|
+
userId: string;
|
|
2356
|
+
projectId: string;
|
|
2357
|
+
todos: string[];
|
|
2358
|
+
}
|
|
2359
|
+
>;
|
|
2360
|
+
narrative('All Projection Types', 'ALL-PROJ', () => {
|
|
2361
|
+
query('views summary', 'SUMMARY-SLICE').server(() => {
|
|
2362
|
+
data([source().state('TodoListSummary').fromSingletonProjection('TodoSummary')]);
|
|
2363
|
+
specs('Summary Rules', () => {});
|
|
2364
|
+
});
|
|
2365
|
+
query('views todo', 'TODO-SLICE').server(() => {
|
|
2366
|
+
data([source().state('TodoState').fromProjection('Todos', 'todoId')]);
|
|
2367
|
+
specs('Todo Rules', () => {});
|
|
2368
|
+
});
|
|
2369
|
+
query('views user project todos', 'USER-PROJECT-SLICE').server(() => {
|
|
2370
|
+
data([source().state('UserProjectTodos').fromCompositeProjection('UserProjectTodos', ['userId', 'projectId'])]);
|
|
2371
|
+
specs('User Project Rules', () => {});
|
|
2372
|
+
});
|
|
2373
|
+
});
|
|
2374
|
+
`);
|
|
2375
|
+
});
|
|
2376
|
+
});
|
|
1785
2377
|
});
|
|
1786
|
-
//# sourceMappingURL=model-to-
|
|
2378
|
+
//# sourceMappingURL=model-to-narrative.specs.js.map
|