@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.
Files changed (65) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +10 -11
  3. package/dist/getWebComponentMap.js +1 -1
  4. package/dist/getWebComponentMap.js.map +1 -1
  5. package/dist/graph/augment.js +0 -3
  6. package/dist/graph/augment.js.map +1 -1
  7. package/dist/graph/build.d.ts +2 -2
  8. package/dist/graph/build.js +7 -8
  9. package/dist/graph/build.js.map +1 -1
  10. package/dist/graph/module.d.ts +6 -9
  11. package/dist/graph/module.js +54 -123
  12. package/dist/graph/module.js.map +1 -1
  13. package/dist/graph/serialize.d.ts +2 -2
  14. package/dist/graph/serialize.js +2 -2
  15. package/dist/graph/serialize.js.map +1 -1
  16. package/dist/graph/test-helpers.d.ts +0 -13
  17. package/dist/graph/test-helpers.js +0 -10
  18. package/dist/graph/test-helpers.js.map +1 -1
  19. package/dist/graph/traverse.d.ts +3 -3
  20. package/dist/graph/traverse.js +19 -349
  21. package/dist/graph/traverse.js.map +1 -1
  22. package/dist/index.d.ts +3 -3
  23. package/dist/index.js +4 -6
  24. package/dist/index.js.map +1 -1
  25. package/dist/toSourceCode.d.ts +1 -4
  26. package/dist/toSourceCode.js +8 -52
  27. package/dist/toSourceCode.js.map +1 -1
  28. package/dist/tsconfig.tsbuildinfo +1 -1
  29. package/dist/types.d.ts +21 -78
  30. package/dist/types.js.map +1 -1
  31. package/dist/utils/index.d.ts +0 -3
  32. package/dist/utils/index.js +0 -18
  33. package/dist/utils/index.js.map +1 -1
  34. package/docs/how-it-works.md +9 -10
  35. package/fixtures/skeleton/app/views/layouts/application.liquid +13 -0
  36. package/fixtures/skeleton/app/views/pages/index.liquid +5 -0
  37. package/fixtures/skeleton/app/views/partials/header.liquid +3 -0
  38. package/fixtures/skeleton/app/views/partials/parent.liquid +1 -1
  39. package/package.json +5 -5
  40. package/src/getWebComponentMap.ts +1 -1
  41. package/src/graph/augment.ts +1 -13
  42. package/src/graph/build.spec.ts +33 -173
  43. package/src/graph/build.ts +11 -14
  44. package/src/graph/module.ts +60 -144
  45. package/src/graph/serialize.spec.ts +22 -29
  46. package/src/graph/serialize.ts +2 -2
  47. package/src/graph/test-helpers.ts +1 -18
  48. package/src/graph/traverse.ts +31 -504
  49. package/src/index.ts +3 -3
  50. package/src/toSourceCode.ts +14 -55
  51. package/src/types.ts +23 -100
  52. package/src/utils/index.ts +0 -24
  53. package/fixtures/skeleton/blocks/_private.liquid +0 -1
  54. package/fixtures/skeleton/blocks/_static.liquid +0 -10
  55. package/fixtures/skeleton/blocks/group.liquid +0 -27
  56. package/fixtures/skeleton/blocks/render-static.liquid +0 -22
  57. package/fixtures/skeleton/blocks/text.liquid +0 -14
  58. package/fixtures/skeleton/jsconfig.json +0 -9
  59. package/fixtures/skeleton/layout/theme.liquid +0 -14
  60. package/fixtures/skeleton/sections/custom-section.liquid +0 -6
  61. package/fixtures/skeleton/sections/header-group.json +0 -36
  62. package/fixtures/skeleton/sections/header.liquid +0 -1
  63. package/fixtures/skeleton/templates/index.json +0 -20
  64. /package/fixtures/skeleton/assets/{theme.css → app.css} +0 -0
  65. /package/fixtures/skeleton/assets/{theme.js → app.js} +0 -0
@@ -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
- CssModule,
4
- ImageModule,
5
- JavaScriptModule,
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<ThemeGraph> to cache modules so that if the theme graph
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
- * ThemeGraph (no need for a `visited` property on modules, etc.)
25
+ * AppGraph (no need for a `visited` property on modules, etc.)
31
26
  */
32
- const ModuleCache: WeakMap<ThemeGraph, Map<string, ThemeModule>> = new WeakMap();
27
+ const ModuleCache: WeakMap<AppGraph, Map<string, AppModule>> = new WeakMap();
33
28
 
34
- export function getModule(themeGraph: ThemeGraph, uri: UriString): ThemeModule | undefined {
35
- const cache = getCache(themeGraph);
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, themeGraph.rootUri);
35
+ const relativePath = path.relative(uri, appGraph.rootUri);
41
36
 
42
37
  switch (true) {
43
- case relativePath.startsWith('assets'): {
44
- return getAssetModule(themeGraph, path.basename(uri));
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
- export function getTemplateModule(themeGraph: ThemeGraph, uri: UriString): ThemeModule {
77
- const extension = extname(uri);
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
- export function getThemeBlockModule(themeGraph: ThemeGraph, blockType: string): LiquidModule {
106
- const uri = path.join(themeGraph.rootUri, 'blocks', `${blockType}.liquid`);
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
- export function getSectionGroupModule(
128
- themeGraph: ThemeGraph,
129
- sectionGroupType: string,
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
- let type: ModuleType | undefined = undefined;
148
-
149
- if (SUPPORTED_ASSET_IMAGE_EXTENSIONS.includes(extension)) {
150
- type = ModuleType.Image;
151
- } else if (extension === 'js') {
152
- type = ModuleType.JavaScript;
153
- } else if (extension === 'css') {
154
- type = ModuleType.Css;
155
- } else if (extension === 'svg') {
156
- type = ModuleType.Svg;
157
- }
158
-
159
- if (!type) {
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(themeGraph, {
164
- type,
71
+ return module(appGraph, {
72
+ type: ModuleType.Asset,
165
73
  kind: 'unused',
166
74
  dependencies: [],
167
75
  references: [],
168
- uri: path.join(themeGraph.rootUri, 'assets', asset),
76
+ uri: path.join(appGraph.rootUri, 'assets', asset),
169
77
  });
170
78
  }
171
79
 
172
- export function getPartialModule(themeGraph: ThemeGraph, partial: string): LiquidModule {
173
- const uri = path.join(themeGraph.rootUri, 'app/views/partials', `${partial}.liquid`);
174
- return module(themeGraph, {
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
- themeGraph: ThemeGraph,
185
- layoutName: string | false | undefined = 'theme',
92
+ appGraph: AppGraph,
93
+ layoutUri: string | false | undefined,
186
94
  ): LiquidModule | undefined {
187
- if (layoutName === false) return undefined;
188
- if (layoutName === undefined) layoutName = 'theme';
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: 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(themeGraph: ThemeGraph): Map<string, ThemeModule> {
200
- if (!ModuleCache.has(themeGraph)) {
201
- ModuleCache.set(themeGraph, new Map());
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(themeGraph)!;
119
+ return ModuleCache.get(appGraph)!;
204
120
  }
205
121
 
206
- function module<T extends ThemeModule>(themeGraph: ThemeGraph, mod: T): T {
207
- const cache = getCache(themeGraph);
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 { ThemeGraph } from '../types';
4
- import { getSectionModule, getPartialModule, getTemplateModule } from './module';
5
- import { serializeThemeGraph } from './serialize';
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: serializeThemeGraph', () => {
8
+ describe('Unit: serializeAppGraph', () => {
9
9
  it('serialize the graph', () => {
10
- const rootUri = 'file:///theme';
10
+ const rootUri = 'file:///app';
11
11
  const p = (part: string) => pathUtils.join(rootUri, part);
12
- const graph: ThemeGraph = {
12
+ const graph: AppGraph = {
13
13
  entryPoints: [],
14
14
  modules: {},
15
15
  rootUri,
16
16
  };
17
17
 
18
- const template = getTemplateModule(graph, p('templates/index.json'));
19
- const customSection = getSectionModule(graph, 'custom-section');
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
- const section2 = getSectionModule(graph, 'section2');
27
- bind(template, section2, { sourceRange: [20, 25] });
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 = [template];
30
- [template, customSection, section2, parentPartial, childPartial].forEach((module) => {
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 } = serializeThemeGraph(graph);
35
- expect(nodes).toHaveLength(5);
36
- expect(edges).toHaveLength(4);
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: 'file:///theme/templates/index.json', range: [0, 5] },
41
- target: { uri: 'file:///theme/sections/custom-section.liquid' },
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: 'file:///theme/app/views/partials/parent.liquid', range: [20, 25] },
51
- target: { uri: 'file:///theme/app/views/partials/child.liquid' },
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: 'file:///theme/templates/index.json', range: [20, 25] },
56
- target: { uri: 'file:///theme/sections/section2.liquid' },
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
  ]),
@@ -1,6 +1,6 @@
1
- import { SerializableEdge, SerializableGraph, SerializableNode, ThemeGraph } from '../types';
1
+ import { SerializableEdge, SerializableGraph, SerializableNode, AppGraph } from '../types';
2
2
 
3
- export function serializeThemeGraph(graph: ThemeGraph): SerializableGraph {
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),