@platformos/platformos-graph 0.0.7 → 0.0.9
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/CHANGELOG.md +18 -0
- package/README.md +10 -11
- package/dist/getWebComponentMap.js +1 -1
- package/dist/getWebComponentMap.js.map +1 -1
- package/dist/graph/augment.js +0 -3
- package/dist/graph/augment.js.map +1 -1
- package/dist/graph/build.d.ts +2 -2
- package/dist/graph/build.js +7 -8
- package/dist/graph/build.js.map +1 -1
- package/dist/graph/module.d.ts +6 -9
- package/dist/graph/module.js +54 -123
- package/dist/graph/module.js.map +1 -1
- package/dist/graph/serialize.d.ts +2 -2
- package/dist/graph/serialize.js +2 -2
- package/dist/graph/serialize.js.map +1 -1
- package/dist/graph/test-helpers.d.ts +0 -13
- package/dist/graph/test-helpers.js +0 -10
- package/dist/graph/test-helpers.js.map +1 -1
- package/dist/graph/traverse.d.ts +3 -3
- package/dist/graph/traverse.js +19 -349
- package/dist/graph/traverse.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -6
- package/dist/index.js.map +1 -1
- package/dist/toSourceCode.d.ts +1 -4
- package/dist/toSourceCode.js +8 -52
- package/dist/toSourceCode.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +21 -78
- package/dist/types.js.map +1 -1
- package/dist/utils/index.d.ts +0 -3
- package/dist/utils/index.js +0 -18
- package/dist/utils/index.js.map +1 -1
- package/docs/how-it-works.md +9 -10
- package/fixtures/skeleton/app/views/layouts/application.liquid +13 -0
- package/fixtures/skeleton/app/views/pages/index.liquid +5 -0
- package/fixtures/skeleton/app/views/partials/header.liquid +3 -0
- package/fixtures/skeleton/app/views/partials/parent.liquid +1 -1
- package/package.json +5 -5
- package/src/getWebComponentMap.ts +1 -1
- package/src/graph/augment.ts +1 -13
- package/src/graph/build.spec.ts +33 -173
- package/src/graph/build.ts +11 -14
- package/src/graph/module.ts +60 -144
- package/src/graph/serialize.spec.ts +22 -29
- package/src/graph/serialize.ts +2 -2
- package/src/graph/test-helpers.ts +1 -18
- package/src/graph/traverse.ts +31 -504
- package/src/index.ts +3 -3
- package/src/toSourceCode.ts +14 -55
- package/src/types.ts +23 -100
- package/src/utils/index.ts +0 -24
- package/fixtures/skeleton/blocks/_private.liquid +0 -1
- package/fixtures/skeleton/blocks/_static.liquid +0 -10
- package/fixtures/skeleton/blocks/group.liquid +0 -27
- package/fixtures/skeleton/blocks/render-static.liquid +0 -22
- package/fixtures/skeleton/blocks/text.liquid +0 -14
- package/fixtures/skeleton/jsconfig.json +0 -9
- package/fixtures/skeleton/layout/theme.liquid +0 -14
- package/fixtures/skeleton/sections/custom-section.liquid +0 -6
- package/fixtures/skeleton/sections/header-group.json +0 -36
- package/fixtures/skeleton/sections/header.liquid +0 -1
- package/fixtures/skeleton/templates/index.json +0 -20
- /package/fixtures/skeleton/assets/{theme.css → app.css} +0 -0
- /package/fixtures/skeleton/assets/{theme.js → app.js} +0 -0
package/src/graph/module.ts
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
import { path, UriString } from '@platformos/platformos-check-common';
|
|
1
|
+
import { isLayout, isPage, isPartial, path, UriString } from '@platformos/platformos-check-common';
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
JsonModule,
|
|
7
|
-
JsonModuleKind,
|
|
3
|
+
AssetModule,
|
|
4
|
+
AppGraph,
|
|
5
|
+
AppModule,
|
|
8
6
|
LiquidModule,
|
|
9
7
|
LiquidModuleKind,
|
|
10
8
|
ModuleType,
|
|
11
9
|
SUPPORTED_ASSET_IMAGE_EXTENSIONS,
|
|
12
|
-
SvgModule,
|
|
13
|
-
ThemeGraph,
|
|
14
|
-
ThemeModule,
|
|
15
10
|
} from '../types';
|
|
16
11
|
import { extname } from '../utils';
|
|
17
12
|
|
|
@@ -23,155 +18,68 @@ import { extname } from '../utils';
|
|
|
23
18
|
* graphs' modules record), we want to avoid creating two different module objects
|
|
24
19
|
* that represent the same file.
|
|
25
20
|
*
|
|
26
|
-
* We're using a WeakMap<
|
|
21
|
+
* We're using a WeakMap<AppGraph> to cache modules so that if the app graph
|
|
27
22
|
* gets garbage collected, the module cache will also be garbage collected.
|
|
28
23
|
*
|
|
29
24
|
* This allows us to have a module cache without changing the API of the
|
|
30
|
-
*
|
|
25
|
+
* AppGraph (no need for a `visited` property on modules, etc.)
|
|
31
26
|
*/
|
|
32
|
-
const ModuleCache: WeakMap<
|
|
27
|
+
const ModuleCache: WeakMap<AppGraph, Map<string, AppModule>> = new WeakMap();
|
|
33
28
|
|
|
34
|
-
export function getModule(
|
|
35
|
-
const cache = getCache(
|
|
29
|
+
export function getModule(appGraph: AppGraph, uri: UriString): AppModule | undefined {
|
|
30
|
+
const cache = getCache(appGraph);
|
|
36
31
|
if (cache.has(uri)) {
|
|
37
32
|
return cache.get(uri)!;
|
|
38
33
|
}
|
|
39
34
|
|
|
40
|
-
const relativePath = path.relative(uri,
|
|
35
|
+
const relativePath = path.relative(uri, appGraph.rootUri);
|
|
41
36
|
|
|
42
37
|
switch (true) {
|
|
43
|
-
case
|
|
44
|
-
return
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
case relativePath.startsWith('blocks'): {
|
|
48
|
-
return getThemeBlockModule(themeGraph, path.basename(uri, '.liquid'));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
case relativePath.startsWith('layout'): {
|
|
52
|
-
return getLayoutModule(themeGraph, path.basename(uri, '.liquid'));
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
case relativePath.startsWith('sections'): {
|
|
56
|
-
if (relativePath.endsWith('.json')) {
|
|
57
|
-
return getSectionGroupModule(themeGraph, path.basename(uri, '.json'));
|
|
58
|
-
}
|
|
59
|
-
return getSectionModule(themeGraph, path.basename(uri, '.liquid'));
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
case relativePath.includes('/views/partials') || relativePath.includes('/lib/'): {
|
|
63
|
-
return getPartialModule(themeGraph, path.basename(uri, '.liquid'));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
case relativePath.startsWith('snippets'): {
|
|
67
|
-
return getPartialModule(themeGraph, path.basename(uri, '.liquid'));
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
case relativePath.startsWith('templates'): {
|
|
71
|
-
return getTemplateModule(themeGraph, uri);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
38
|
+
case isLayout(uri):
|
|
39
|
+
return getLayoutModule(appGraph, uri);
|
|
75
40
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
switch (extension) {
|
|
79
|
-
case 'json': {
|
|
80
|
-
return module(themeGraph, {
|
|
81
|
-
type: ModuleType.Json,
|
|
82
|
-
kind: JsonModuleKind.Template,
|
|
83
|
-
dependencies: [],
|
|
84
|
-
references: [],
|
|
85
|
-
uri: uri,
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
case 'liquid': {
|
|
90
|
-
return module(themeGraph, {
|
|
91
|
-
type: ModuleType.Liquid,
|
|
92
|
-
kind: LiquidModuleKind.Template,
|
|
93
|
-
dependencies: [],
|
|
94
|
-
references: [],
|
|
95
|
-
uri: uri,
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
default: {
|
|
100
|
-
throw new Error(`Unknown template type for ${uri}`);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
41
|
+
case isPage(uri):
|
|
42
|
+
return getPageModule(appGraph, uri);
|
|
104
43
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
return module(themeGraph, {
|
|
108
|
-
type: ModuleType.Liquid,
|
|
109
|
-
kind: LiquidModuleKind.Block,
|
|
110
|
-
dependencies: [],
|
|
111
|
-
references: [],
|
|
112
|
-
uri,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export function getSectionModule(themeGraph: ThemeGraph, sectionType: string): LiquidModule {
|
|
117
|
-
const uri = path.join(themeGraph.rootUri, 'sections', `${sectionType}.liquid`);
|
|
118
|
-
return module(themeGraph, {
|
|
119
|
-
type: ModuleType.Liquid,
|
|
120
|
-
kind: LiquidModuleKind.Section,
|
|
121
|
-
dependencies: [],
|
|
122
|
-
references: [],
|
|
123
|
-
uri,
|
|
124
|
-
});
|
|
125
|
-
}
|
|
44
|
+
case isPartial(uri):
|
|
45
|
+
return getPartialModule(appGraph, path.basename(uri, '.liquid'));
|
|
126
46
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
): JsonModule {
|
|
131
|
-
const uri = path.join(themeGraph.rootUri, 'sections', `${sectionGroupType}.json`);
|
|
132
|
-
return module(themeGraph, {
|
|
133
|
-
type: ModuleType.Json,
|
|
134
|
-
kind: JsonModuleKind.SectionGroup,
|
|
135
|
-
dependencies: [],
|
|
136
|
-
references: [],
|
|
137
|
-
uri,
|
|
138
|
-
});
|
|
47
|
+
case relativePath.startsWith('assets') || relativePath.startsWith('modules'):
|
|
48
|
+
return getAssetModule(appGraph, path.basename(uri));
|
|
49
|
+
}
|
|
139
50
|
}
|
|
140
51
|
|
|
141
|
-
export function getAssetModule(
|
|
142
|
-
themeGraph: ThemeGraph,
|
|
143
|
-
asset: string,
|
|
144
|
-
): JavaScriptModule | CssModule | SvgModule | ImageModule | undefined {
|
|
52
|
+
export function getAssetModule(appGraph: AppGraph, asset: string): AssetModule | undefined {
|
|
145
53
|
const extension = extname(asset);
|
|
146
54
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (!
|
|
55
|
+
const SUPPORTED_ASSET_EXTENSIONS = [
|
|
56
|
+
...SUPPORTED_ASSET_IMAGE_EXTENSIONS,
|
|
57
|
+
'js',
|
|
58
|
+
'css',
|
|
59
|
+
'svg',
|
|
60
|
+
'pdf',
|
|
61
|
+
'woff',
|
|
62
|
+
'woff2',
|
|
63
|
+
'ttf',
|
|
64
|
+
'eot',
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
if (!SUPPORTED_ASSET_EXTENSIONS.includes(extension)) {
|
|
160
68
|
return undefined;
|
|
161
69
|
}
|
|
162
70
|
|
|
163
|
-
return module(
|
|
164
|
-
type,
|
|
71
|
+
return module(appGraph, {
|
|
72
|
+
type: ModuleType.Asset,
|
|
165
73
|
kind: 'unused',
|
|
166
74
|
dependencies: [],
|
|
167
75
|
references: [],
|
|
168
|
-
uri: path.join(
|
|
76
|
+
uri: path.join(appGraph.rootUri, 'assets', asset),
|
|
169
77
|
});
|
|
170
78
|
}
|
|
171
79
|
|
|
172
|
-
export function getPartialModule(
|
|
173
|
-
const uri = path.join(
|
|
174
|
-
return module(
|
|
80
|
+
export function getPartialModule(appGraph: AppGraph, partial: string): LiquidModule {
|
|
81
|
+
const uri = path.join(appGraph.rootUri, 'app/views/partials', `${partial}.liquid`);
|
|
82
|
+
return module(appGraph, {
|
|
175
83
|
type: ModuleType.Liquid,
|
|
176
84
|
kind: LiquidModuleKind.Partial,
|
|
177
85
|
uri: uri,
|
|
@@ -181,30 +89,38 @@ export function getPartialModule(themeGraph: ThemeGraph, partial: string): Liqui
|
|
|
181
89
|
}
|
|
182
90
|
|
|
183
91
|
export function getLayoutModule(
|
|
184
|
-
|
|
185
|
-
|
|
92
|
+
appGraph: AppGraph,
|
|
93
|
+
layoutUri: string | false | undefined,
|
|
186
94
|
): LiquidModule | undefined {
|
|
187
|
-
if (
|
|
188
|
-
|
|
189
|
-
const uri = path.join(themeGraph.rootUri, 'layout', `${layoutName}.liquid`);
|
|
190
|
-
return module(themeGraph, {
|
|
95
|
+
if (!layoutUri) return undefined;
|
|
96
|
+
return module(appGraph, {
|
|
191
97
|
type: ModuleType.Liquid,
|
|
192
98
|
kind: LiquidModuleKind.Layout,
|
|
193
|
-
uri:
|
|
99
|
+
uri: layoutUri,
|
|
100
|
+
dependencies: [],
|
|
101
|
+
references: [],
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function getPageModule(appGraph: AppGraph, pageUri: string): LiquidModule {
|
|
106
|
+
return module(appGraph, {
|
|
107
|
+
type: ModuleType.Liquid,
|
|
108
|
+
kind: LiquidModuleKind.Page,
|
|
109
|
+
uri: pageUri,
|
|
194
110
|
dependencies: [],
|
|
195
111
|
references: [],
|
|
196
112
|
});
|
|
197
113
|
}
|
|
198
114
|
|
|
199
|
-
function getCache(
|
|
200
|
-
if (!ModuleCache.has(
|
|
201
|
-
ModuleCache.set(
|
|
115
|
+
function getCache(appGraph: AppGraph): Map<string, AppModule> {
|
|
116
|
+
if (!ModuleCache.has(appGraph)) {
|
|
117
|
+
ModuleCache.set(appGraph, new Map());
|
|
202
118
|
}
|
|
203
|
-
return ModuleCache.get(
|
|
119
|
+
return ModuleCache.get(appGraph)!;
|
|
204
120
|
}
|
|
205
121
|
|
|
206
|
-
function module<T extends
|
|
207
|
-
const cache = getCache(
|
|
122
|
+
function module<T extends AppModule>(appGraph: AppGraph, mod: T): T {
|
|
123
|
+
const cache = getCache(appGraph);
|
|
208
124
|
if (!cache.has(mod.uri)) {
|
|
209
125
|
cache.set(mod.uri, mod);
|
|
210
126
|
}
|
|
@@ -1,59 +1,52 @@
|
|
|
1
1
|
import { path as pathUtils } from '@platformos/platformos-check-common';
|
|
2
2
|
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { AppGraph } from '../types';
|
|
4
|
+
import { getLayoutModule, getPartialModule } from './module';
|
|
5
|
+
import { serializeAppGraph } from './serialize';
|
|
6
6
|
import { bind } from './traverse';
|
|
7
7
|
|
|
8
|
-
describe('Unit:
|
|
8
|
+
describe('Unit: serializeAppGraph', () => {
|
|
9
9
|
it('serialize the graph', () => {
|
|
10
|
-
const rootUri = 'file:///
|
|
10
|
+
const rootUri = 'file:///app';
|
|
11
11
|
const p = (part: string) => pathUtils.join(rootUri, part);
|
|
12
|
-
const graph:
|
|
12
|
+
const graph: AppGraph = {
|
|
13
13
|
entryPoints: [],
|
|
14
14
|
modules: {},
|
|
15
15
|
rootUri,
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
const
|
|
19
|
-
const
|
|
18
|
+
const layout = getLayoutModule(graph, p('app/views/layouts/application.liquid'))!;
|
|
19
|
+
const headerPartial = getPartialModule(graph, 'header');
|
|
20
20
|
const parentPartial = getPartialModule(graph, 'parent');
|
|
21
21
|
const childPartial = getPartialModule(graph, 'child');
|
|
22
|
-
bind(template, customSection, { sourceRange: [0, 5] });
|
|
23
|
-
bind(customSection, parentPartial, { sourceRange: [10, 15] });
|
|
24
|
-
bind(parentPartial, childPartial, { sourceRange: [20, 25] });
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
bind(
|
|
23
|
+
bind(layout, headerPartial, { sourceRange: [0, 5] });
|
|
24
|
+
bind(layout, parentPartial, { sourceRange: [10, 15] });
|
|
25
|
+
bind(parentPartial, childPartial, { sourceRange: [20, 25] });
|
|
28
26
|
|
|
29
|
-
graph.entryPoints = [
|
|
30
|
-
[
|
|
27
|
+
graph.entryPoints = [layout];
|
|
28
|
+
[layout, headerPartial, parentPartial, childPartial].forEach((module) => {
|
|
31
29
|
graph.modules[module.uri] = module;
|
|
32
30
|
});
|
|
33
31
|
|
|
34
|
-
const { nodes, edges } =
|
|
35
|
-
expect(nodes).toHaveLength(
|
|
36
|
-
expect(edges).toHaveLength(
|
|
32
|
+
const { nodes, edges } = serializeAppGraph(graph);
|
|
33
|
+
expect(nodes).toHaveLength(4);
|
|
34
|
+
expect(edges).toHaveLength(3);
|
|
37
35
|
expect(edges).toEqual(
|
|
38
36
|
expect.arrayContaining([
|
|
39
37
|
{
|
|
40
|
-
source: { uri: '
|
|
41
|
-
target: { uri: '
|
|
42
|
-
type: 'direct',
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
source: { uri: 'file:///theme/sections/custom-section.liquid', range: [10, 15] },
|
|
46
|
-
target: { uri: 'file:///theme/app/views/partials/parent.liquid' },
|
|
38
|
+
source: { uri: p('app/views/layouts/application.liquid'), range: [0, 5] },
|
|
39
|
+
target: { uri: p('app/views/partials/header.liquid') },
|
|
47
40
|
type: 'direct',
|
|
48
41
|
},
|
|
49
42
|
{
|
|
50
|
-
source: { uri: '
|
|
51
|
-
target: { uri: '
|
|
43
|
+
source: { uri: p('app/views/layouts/application.liquid'), range: [10, 15] },
|
|
44
|
+
target: { uri: p('app/views/partials/parent.liquid') },
|
|
52
45
|
type: 'direct',
|
|
53
46
|
},
|
|
54
47
|
{
|
|
55
|
-
source: { uri: '
|
|
56
|
-
target: { uri: '
|
|
48
|
+
source: { uri: p('app/views/partials/parent.liquid'), range: [20, 25] },
|
|
49
|
+
target: { uri: p('app/views/partials/child.liquid') },
|
|
57
50
|
type: 'direct',
|
|
58
51
|
},
|
|
59
52
|
]),
|
package/src/graph/serialize.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { SerializableEdge, SerializableGraph, SerializableNode,
|
|
1
|
+
import { SerializableEdge, SerializableGraph, SerializableNode, AppGraph } from '../types';
|
|
2
2
|
|
|
3
|
-
export function
|
|
3
|
+
export function serializeAppGraph(graph: AppGraph): SerializableGraph {
|
|
4
4
|
const nodes: SerializableNode[] = Object.values(graph.modules).map((module) => ({
|
|
5
5
|
uri: module.uri,
|
|
6
6
|
type: module.type,
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
LiquidSourceCode,
|
|
3
|
-
memoize,
|
|
4
|
-
path as pathUtils,
|
|
5
|
-
SectionSchema,
|
|
6
|
-
ThemeBlockSchema,
|
|
7
|
-
toSchema,
|
|
8
|
-
} from '@platformos/platformos-check-common';
|
|
1
|
+
import { memoize, path as pathUtils } from '@platformos/platformos-check-common';
|
|
9
2
|
import { AbstractFileSystem } from '@platformos/platformos-common';
|
|
10
3
|
import { NodeFileSystem } from '@platformos/platformos-check-node';
|
|
11
4
|
import { vi } from 'vitest';
|
|
@@ -28,16 +21,6 @@ export async function getDependencies(rootUri: string, fs: AbstractFileSystem =
|
|
|
28
21
|
const getSourceCode = makeGetSourceCode(fs);
|
|
29
22
|
const deps = {
|
|
30
23
|
fs,
|
|
31
|
-
getSectionSchema: memoize(async (name: string) => {
|
|
32
|
-
const uri = pathUtils.join(skeleton, 'sections', `${name}.liquid`);
|
|
33
|
-
const sourceCode = (await getSourceCode(uri)) as LiquidSourceCode;
|
|
34
|
-
return (await toSchema('theme', uri, sourceCode, async () => true)) as SectionSchema;
|
|
35
|
-
}, identity),
|
|
36
|
-
getBlockSchema: memoize(async (name: string) => {
|
|
37
|
-
const uri = pathUtils.join(skeleton, 'blocks', `${name}.liquid`);
|
|
38
|
-
const sourceCode = (await getSourceCode(uri)) as LiquidSourceCode;
|
|
39
|
-
return (await toSchema('theme', uri, sourceCode, async () => true)) as ThemeBlockSchema;
|
|
40
|
-
}, identity),
|
|
41
24
|
getSourceCode,
|
|
42
25
|
getWebComponentDefinitionReference: (customElementName: string) =>
|
|
43
26
|
webComponentDefs.get(customElementName),
|