@platformos/platformos-graph 0.0.19 → 0.1.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.
Files changed (141) hide show
  1. package/CHANGELOG.md +516 -0
  2. package/bin/platformos-graph +21 -81
  3. package/dist/cache-probes.spec.d.ts +1 -0
  4. package/dist/cache-probes.spec.js +62 -0
  5. package/dist/cache-probes.spec.js.map +1 -0
  6. package/dist/cli.d.ts +46 -0
  7. package/dist/cli.js +131 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/cli.spec.d.ts +1 -0
  10. package/dist/cli.spec.js +235 -0
  11. package/dist/cli.spec.js.map +1 -0
  12. package/dist/graph/app-index-resolution.spec.d.ts +1 -0
  13. package/dist/graph/app-index-resolution.spec.js +167 -0
  14. package/dist/graph/app-index-resolution.spec.js.map +1 -0
  15. package/dist/graph/asset-resolution.spec.d.ts +1 -0
  16. package/dist/graph/asset-resolution.spec.js +64 -0
  17. package/dist/graph/asset-resolution.spec.js.map +1 -0
  18. package/dist/graph/augment.js +3 -1
  19. package/dist/graph/augment.js.map +1 -1
  20. package/dist/graph/build.d.ts +15 -2
  21. package/dist/graph/build.js +54 -12
  22. package/dist/graph/build.js.map +1 -1
  23. package/dist/graph/build.spec.d.ts +1 -0
  24. package/dist/graph/build.spec.js +138 -0
  25. package/dist/graph/build.spec.js.map +1 -0
  26. package/dist/graph/edge-sources.d.ts +28 -0
  27. package/dist/graph/edge-sources.js +43 -0
  28. package/dist/graph/edge-sources.js.map +1 -0
  29. package/dist/graph/edge-sources.spec.d.ts +1 -0
  30. package/dist/graph/edge-sources.spec.js +125 -0
  31. package/dist/graph/edge-sources.spec.js.map +1 -0
  32. package/dist/graph/extract.spec.d.ts +1 -0
  33. package/dist/graph/extract.spec.js +163 -0
  34. package/dist/graph/extract.spec.js.map +1 -0
  35. package/dist/graph/module.d.ts +70 -2
  36. package/dist/graph/module.js +164 -29
  37. package/dist/graph/module.js.map +1 -1
  38. package/dist/graph/module.spec.d.ts +1 -0
  39. package/dist/graph/module.spec.js +74 -0
  40. package/dist/graph/module.spec.js.map +1 -0
  41. package/dist/graph/query.d.ts +72 -0
  42. package/dist/graph/query.js +140 -0
  43. package/dist/graph/query.js.map +1 -0
  44. package/dist/graph/query.spec.d.ts +1 -0
  45. package/dist/graph/query.spec.js +209 -0
  46. package/dist/graph/query.spec.js.map +1 -0
  47. package/dist/graph/serialize.spec.d.ts +1 -0
  48. package/dist/graph/serialize.spec.js +50 -0
  49. package/dist/graph/serialize.spec.js.map +1 -0
  50. package/dist/graph/structural.spec.d.ts +1 -0
  51. package/dist/graph/structural.spec.js +146 -0
  52. package/dist/graph/structural.spec.js.map +1 -0
  53. package/dist/graph/test-helpers.d.ts +2 -3
  54. package/dist/graph/test-helpers.js +5 -9
  55. package/dist/graph/test-helpers.js.map +1 -1
  56. package/dist/graph/traverse-edges.spec.d.ts +1 -0
  57. package/dist/graph/traverse-edges.spec.js +337 -0
  58. package/dist/graph/traverse-edges.spec.js.map +1 -0
  59. package/dist/graph/traverse.d.ts +63 -4
  60. package/dist/graph/traverse.js +364 -49
  61. package/dist/graph/traverse.js.map +1 -1
  62. package/dist/index.d.ts +5 -1
  63. package/dist/index.js +21 -4
  64. package/dist/index.js.map +1 -1
  65. package/dist/parsers.d.ts +35 -0
  66. package/dist/parsers.js +72 -0
  67. package/dist/parsers.js.map +1 -0
  68. package/dist/parsers.spec.d.ts +1 -0
  69. package/dist/parsers.spec.js +70 -0
  70. package/dist/parsers.spec.js.map +1 -0
  71. package/dist/toSourceCode.d.ts +14 -2
  72. package/dist/toSourceCode.js +23 -19
  73. package/dist/toSourceCode.js.map +1 -1
  74. package/dist/tsconfig.tsbuildinfo +1 -1
  75. package/dist/types.d.ts +114 -20
  76. package/dist/types.js.map +1 -1
  77. package/dist/utils/index.d.ts +1 -1
  78. package/fixtures/asset-edges/app/assets/logo.css +1 -0
  79. package/fixtures/asset-edges/app/assets/site/app.js +1 -0
  80. package/fixtures/asset-edges/app/views/pages/index.liquid +3 -0
  81. package/fixtures/background-edges/app/views/pages/broken.liquid +3 -0
  82. package/fixtures/background-edges/app/views/pages/index.liquid +3 -0
  83. package/fixtures/background-edges/app/views/partials/jobs/notify.liquid +3 -0
  84. package/fixtures/function-edges/app/lib/queries/list.liquid +3 -0
  85. package/fixtures/function-edges/app/views/pages/broken.liquid +3 -0
  86. package/fixtures/function-edges/app/views/pages/index.liquid +3 -0
  87. package/fixtures/graphql-edges/app/graphql/blog_posts/find.graphql +10 -0
  88. package/fixtures/graphql-edges/app/views/pages/broken.liquid +3 -0
  89. package/fixtures/graphql-edges/app/views/pages/index.liquid +3 -0
  90. package/fixtures/graphql-table/app/graphql/with_table.graphql +5 -0
  91. package/fixtures/graphql-table/app/graphql/without_table.graphql +3 -0
  92. package/fixtures/graphql-table/app/views/pages/index.liquid +4 -0
  93. package/fixtures/include-edges/app/views/pages/index.liquid +1 -0
  94. package/fixtures/include-edges/app/views/partials/shared/header.liquid +1 -0
  95. package/fixtures/layout-edges/app/views/layouts/theme.liquid +4 -0
  96. package/fixtures/layout-edges/app/views/pages/broken.liquid +5 -0
  97. package/fixtures/layout-edges/app/views/pages/index.liquid +5 -0
  98. package/fixtures/module-edges/app/views/pages/index.liquid +4 -0
  99. package/fixtures/module-edges/modules/my_module/public/lib/queries/get.liquid +3 -0
  100. package/fixtures/module-edges/modules/my_module/public/views/partials/card.liquid +1 -0
  101. package/fixtures/schema-nodes/app/schema/blog_post.yml +6 -0
  102. package/fixtures/schema-nodes/app/schema/no_name.yml +3 -0
  103. package/fixtures/schema-nodes/app/views/pages/index.liquid +1 -0
  104. package/fixtures/skeleton/app/assets/app.js +1 -0
  105. package/fixtures/skeleton/app/views/partials/child.liquid +2 -4
  106. package/fixtures/skeleton/app/views/partials/parent.liquid +2 -4
  107. package/fixtures/structural/app/views/pages/about.liquid +1 -0
  108. package/fixtures/structural/app/views/pages/blog/show.liquid +4 -0
  109. package/fixtures/structural/app/views/pages/index.liquid +6 -0
  110. package/fixtures/structural/app/views/pages/rich.liquid +8 -0
  111. package/fixtures/structural/app/views/partials/card.liquid +1 -0
  112. package/fixtures/structural/app/views/partials/documented.liquid +5 -0
  113. package/package.json +7 -5
  114. package/src/cli.spec.ts +271 -0
  115. package/src/cli.ts +167 -0
  116. package/src/graph/augment.ts +4 -2
  117. package/src/graph/build.spec.ts +888 -9
  118. package/src/graph/build.ts +68 -17
  119. package/src/graph/edge-sources.spec.ts +125 -0
  120. package/src/graph/edge-sources.ts +49 -0
  121. package/src/graph/module.spec.ts +168 -0
  122. package/src/graph/module.ts +167 -33
  123. package/src/graph/query.spec.ts +260 -0
  124. package/src/graph/query.ts +154 -0
  125. package/src/graph/serialize.spec.ts +4 -4
  126. package/src/graph/test-helpers.ts +5 -12
  127. package/src/graph/traverse.spec.ts +278 -0
  128. package/src/graph/traverse.ts +423 -54
  129. package/src/index.ts +16 -1
  130. package/src/parsers.spec.ts +85 -0
  131. package/src/parsers.ts +75 -0
  132. package/src/toSourceCode.ts +26 -26
  133. package/src/types.ts +120 -23
  134. package/src/utils/index.ts +1 -1
  135. package/bin/jsconfig.json +0 -18
  136. package/dist/getWebComponentMap.d.ts +0 -10
  137. package/dist/getWebComponentMap.js +0 -66
  138. package/dist/getWebComponentMap.js.map +0 -1
  139. package/fixtures/skeleton/assets/app.js +0 -7
  140. package/src/getWebComponentMap.ts +0 -81
  141. /package/fixtures/skeleton/{assets → app/assets}/app.css +0 -0
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * The graph resolves `{% render %}` / `{% function %}` / `{% graphql %}` / `layout:`
5
+ * targets through `IDependencies.app`'s index when it is given one.
6
+ *
7
+ * Two things are pinned, and they pull in opposite directions:
8
+ *
9
+ * 1. COST. With an app, a name is answered from the O(1) index and the build lists no
10
+ * directory at all — except for assets, which never use the index by design.
11
+ * 2. ANSWER. The graph must be IDENTICAL with the app, without it, and with an app whose
12
+ * index is only partly populated. The index is a shortcut through `findOrLocate`, not
13
+ * a second resolution rule, so every arm here compares whole graphs.
14
+ *
15
+ * The no-app arm is the control for the cost claim: it shows these very lookups DO cost
16
+ * listings when nothing can answer them, so "no directories listed" is caused by the
17
+ * index rather than by a fixture with nothing to resolve.
18
+ */
19
+ const platformos_check_common_1 = require("@platformos/platformos-check-common");
20
+ const platformos_common_1 = require("@platformos/platformos-common");
21
+ const platformos_check_node_1 = require("@platformos/platformos-check-node");
22
+ const vitest_1 = require("vitest");
23
+ const index_1 = require("../index");
24
+ const utils_1 = require("../utils");
25
+ const test_helpers_1 = require("./test-helpers");
26
+ const moduleEdges = platformos_check_common_1.path.join(test_helpers_1.fixturesRoot, 'module-edges');
27
+ /** The real filesystem, with every directory listing recorded. */
28
+ function recordingFs() {
29
+ const listedDirectories = [];
30
+ const fs = {
31
+ stat: (uri) => platformos_check_node_1.NodeFileSystem.stat(uri),
32
+ readFile: (uri) => platformos_check_node_1.NodeFileSystem.readFile(uri),
33
+ readDirectory: (uri) => {
34
+ listedDirectories.push(uri);
35
+ return platformos_check_node_1.NodeFileSystem.readDirectory(uri);
36
+ },
37
+ };
38
+ return { fs, listedDirectories };
39
+ }
40
+ /** Every source file under the root, classified — the app the language server holds. */
41
+ async function wholeApp(rootUri, fs) {
42
+ return platformos_common_1.App.fromPaths(rootUri, await (0, platformos_common_1.walkAppSourceFiles)(fs, rootUri), fs);
43
+ }
44
+ /** An app that knows the entry points and nothing else, so every target is an index MISS. */
45
+ async function pagesOnlyApp(rootUri, fs) {
46
+ const whole = await wholeApp(rootUri, fs);
47
+ return platformos_common_1.App.fromPaths(rootUri, whole.pages().map((file) => file.uri), fs);
48
+ }
49
+ /**
50
+ * Build the fixture's graph from its pages and layouts, recording what it touched.
51
+ *
52
+ * `entryPoints` are passed explicitly — a discovering build walks the project first, and
53
+ * those listings would swamp the ones under test. The scope is the same one
54
+ * `buildAppGraph` would have discovered for these fixtures.
55
+ */
56
+ async function buildRecording(rootUri, makeApp) {
57
+ const { fs, listedDirectories } = recordingFs();
58
+ const entryPointsApp = await wholeApp(rootUri, fs);
59
+ const entryPoints = [...entryPointsApp.pages(), ...entryPointsApp.layouts()].map((file) => file.uri);
60
+ const app = makeApp ? await makeApp(rootUri, fs) : undefined;
61
+ const sourcesRead = [];
62
+ const getSourceCode = (0, test_helpers_1.makeGetSourceCode)(fs);
63
+ // Everything above is fixture setup — the walks it performed are not what is measured.
64
+ listedDirectories.length = 0;
65
+ const graph = await (0, index_1.buildAppGraph)(rootUri, {
66
+ fs,
67
+ app,
68
+ getSourceCode: (uri) => {
69
+ sourcesRead.push(uri);
70
+ return getSourceCode(uri);
71
+ },
72
+ }, entryPoints);
73
+ return {
74
+ graph,
75
+ // SORTED, not in call order: entry points are traversed concurrently, so which
76
+ // lookup reaches the filesystem first is a scheduling detail. WHICH directories a
77
+ // build has to list is the claim.
78
+ listedDirectories: (0, utils_1.unique)(listedDirectories).sort(),
79
+ sourcesRead: (0, utils_1.unique)(sourcesRead).sort(),
80
+ };
81
+ }
82
+ const dir = (rootUri, relative) => platformos_check_common_1.path.join(rootUri, ...relative.split('/'));
83
+ const referenceKey = (reference) => [
84
+ reference.source.uri,
85
+ reference.source.range?.join(':') ?? '',
86
+ reference.kind,
87
+ reference.type,
88
+ ].join('|');
89
+ /**
90
+ * The graph with every node's REVERSE index (`references`) in a stable order.
91
+ *
92
+ * A node's dependents are appended as each caller finishes traversing, and entry points
93
+ * are traversed concurrently — so their order tracks how long each resolution took,
94
+ * which is precisely what an index changes. `dependencies` are deliberately NOT sorted:
95
+ * those come from one file's visit in source order, so a difference there would be a
96
+ * real one and must still fail.
97
+ */
98
+ function canonical(graph) {
99
+ const sortReferences = (module) => ({
100
+ ...module,
101
+ references: [...module.references].sort((a, b) => referenceKey(a).localeCompare(referenceKey(b))),
102
+ });
103
+ return {
104
+ ...graph,
105
+ entryPoints: graph.entryPoints.map(sortReferences),
106
+ modules: Object.fromEntries(Object.entries(graph.modules).map(([uri, module]) => [uri, sortReferences(module)])),
107
+ };
108
+ }
109
+ (0, vitest_1.describe)('a graph build over a project with an App index', () => {
110
+ let indexed;
111
+ let unindexed;
112
+ let partialIndex;
113
+ (0, vitest_1.beforeAll)(async () => {
114
+ indexed = await buildRecording(test_helpers_1.skeleton, wholeApp);
115
+ unindexed = await buildRecording(test_helpers_1.skeleton);
116
+ partialIndex = await buildRecording(test_helpers_1.skeleton, pagesOnlyApp);
117
+ });
118
+ (0, vitest_1.it)('lists no directory but the asset one, because the index answers every name', () => {
119
+ // `app/assets` is here on purpose: `findOrLocate` never indexes an asset, since
120
+ // nothing reads one and the only question is whether it still exists on disk.
121
+ (0, vitest_1.expect)(indexed.listedDirectories).toEqual([dir(test_helpers_1.skeleton, 'app/assets')]);
122
+ });
123
+ (0, vitest_1.it)('lists a directory per candidate when there is no index to answer from', () => {
124
+ (0, vitest_1.expect)(unindexed.listedDirectories).toEqual([
125
+ dir(test_helpers_1.skeleton, 'app/assets'),
126
+ dir(test_helpers_1.skeleton, 'app/views/layouts'),
127
+ dir(test_helpers_1.skeleton, 'app/views/partials'),
128
+ ]);
129
+ });
130
+ (0, vitest_1.it)('builds the same graph with the index as without it', () => {
131
+ (0, vitest_1.expect)(canonical(indexed.graph)).toEqual(canonical(unindexed.graph));
132
+ });
133
+ (0, vitest_1.it)('falls back to the filesystem for a name the index does not hold', () => {
134
+ (0, vitest_1.expect)(canonical(partialIndex.graph)).toEqual(canonical(unindexed.graph));
135
+ // And the miss really was a miss: the partial and layout directories were listed,
136
+ // so the equality above is not an app that quietly answered everything.
137
+ (0, vitest_1.expect)(partialIndex.listedDirectories).toEqual(unindexed.listedDirectories);
138
+ });
139
+ (0, vitest_1.it)('never asks for an asset source code, only for the files it traverses', () => {
140
+ // An Asset node is a leaf whose only fact is existence (an `fs.stat`), so `app.js`
141
+ // and `app.css` are absent here — which is why an App backing a graph needs no
142
+ // `.js`/image parsers. Every Liquid file in the fixture IS read: the absence above
143
+ // is about assets, not about a build that read nothing.
144
+ (0, vitest_1.expect)(indexed.sourcesRead).toEqual([
145
+ platformos_check_common_1.path.join(test_helpers_1.skeleton, 'app', 'views', 'layouts', 'application.liquid'),
146
+ platformos_check_common_1.path.join(test_helpers_1.skeleton, 'app', 'views', 'pages', 'index.liquid'),
147
+ platformos_check_common_1.path.join(test_helpers_1.skeleton, 'app', 'views', 'partials', 'child.liquid'),
148
+ platformos_check_common_1.path.join(test_helpers_1.skeleton, 'app', 'views', 'partials', 'header.liquid'),
149
+ platformos_check_common_1.path.join(test_helpers_1.skeleton, 'app', 'views', 'partials', 'parent.liquid'),
150
+ ].sort());
151
+ });
152
+ });
153
+ (0, vitest_1.describe)('a module-prefixed name resolved through an App index', () => {
154
+ let indexed;
155
+ let unindexed;
156
+ (0, vitest_1.beforeAll)(async () => {
157
+ indexed = await buildRecording(moduleEdges, wholeApp);
158
+ unindexed = await buildRecording(moduleEdges);
159
+ });
160
+ (0, vitest_1.it)('costs no listing at all — this fixture has no assets to except', () => {
161
+ (0, vitest_1.expect)(indexed.listedDirectories).toEqual([]);
162
+ });
163
+ (0, vitest_1.it)('resolves `modules/my_module/…` to the same files the candidate walk finds', () => {
164
+ (0, vitest_1.expect)(canonical(indexed.graph)).toEqual(canonical(unindexed.graph));
165
+ });
166
+ });
167
+ //# sourceMappingURL=app-index-resolution.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-index-resolution.spec.js","sourceRoot":"","sources":["../../src/graph/app-index-resolution.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const platformos_common_1 = require("@platformos/platformos-common");
4
+ const vitest_1 = require("vitest");
5
+ const vscode_uri_1 = require("vscode-uri");
6
+ const module_1 = require("./module");
7
+ const ROOT = 'file:///project';
8
+ const emptyGraph = () => ({ rootUri: ROOT, entryPoints: [], modules: {} });
9
+ /**
10
+ * Assets follow exactly the same placement rules as every other platformOS file type:
11
+ * `app/assets/` or `modules/<name>/{public,private}/assets/`. Resolution goes through
12
+ * platformos-common, so the graph cannot disagree with `DocumentsLocator` about where
13
+ * `{{ 'app.js' | asset_url }}` points.
14
+ */
15
+ (0, vitest_1.describe)('asset reference resolution', () => {
16
+ (0, vitest_1.it)("resolves 'app.js' to app/assets/app.js", () => {
17
+ (0, vitest_1.expect)((0, module_1.getAssetModule)(emptyGraph(), 'app.js').uri).toBe(`${ROOT}/app/assets/app.js`);
18
+ });
19
+ (0, vitest_1.it)('keeps a subdirectory instead of collapsing to a basename', () => {
20
+ (0, vitest_1.expect)((0, module_1.getAssetModule)(emptyGraph(), 'styles/theme.css').uri).toBe(`${ROOT}/app/assets/styles/theme.css`);
21
+ });
22
+ (0, vitest_1.it)('routes a modules/<name>/ reference into that module, not into app/assets', () => {
23
+ (0, vitest_1.expect)((0, module_1.getAssetModule)(emptyGraph(), 'modules/admin/app.css').uri).toBe(`${ROOT}/app/modules/admin/public/assets/app.css`);
24
+ });
25
+ (0, vitest_1.it)('ignores a reference with an extension no asset uses', () => {
26
+ (0, vitest_1.expect)((0, module_1.getAssetModule)(emptyGraph(), 'notes.txt')).toBe(undefined);
27
+ });
28
+ (0, vitest_1.it)('agrees with DocumentsLocator for an asset that exists', async () => {
29
+ const assetUri = `${ROOT}/app/assets/app.js`;
30
+ const locator = new platformos_common_1.DocumentsLocator({
31
+ stat: async (uri) => {
32
+ if (uri !== assetUri)
33
+ throw new Error(`ENOENT: ${uri}`);
34
+ return { type: platformos_common_1.FileType.File, size: 0 };
35
+ },
36
+ readFile: async () => '',
37
+ // Resolution reads the candidate directory's listing, not a stat per spelling.
38
+ readDirectory: async (uri) => {
39
+ if (uri !== `${ROOT}/app/assets`)
40
+ throw new Error(`ENOENT: ${uri}`);
41
+ return [[assetUri, platformos_common_1.FileType.File]];
42
+ },
43
+ });
44
+ (0, vitest_1.expect)((0, module_1.getAssetModule)(emptyGraph(), 'app.js').uri).toBe(await locator.locate(vscode_uri_1.URI.parse(ROOT), 'asset', 'app.js'));
45
+ });
46
+ (0, vitest_1.it)('classifies an asset URI as an asset module without reconstructing its path', () => {
47
+ const nested = `${ROOT}/app/assets/styles/theme.css`;
48
+ const moduleAsset = `${ROOT}/modules/admin/private/assets/app.css`;
49
+ (0, vitest_1.expect)((0, module_1.getModule)(emptyGraph(), nested)).toMatchObject({
50
+ type: "Asset" /* ModuleType.Asset */,
51
+ uri: nested,
52
+ });
53
+ // A module ORIGINAL keeps its own path — resolving by name would have moved it to
54
+ // the app-overwrite slot.
55
+ (0, vitest_1.expect)((0, module_1.getModule)(emptyGraph(), moduleAsset)).toMatchObject({
56
+ type: "Asset" /* ModuleType.Asset */,
57
+ uri: moduleAsset,
58
+ });
59
+ });
60
+ (0, vitest_1.it)('does not treat a root-level assets/ path as part of the app', () => {
61
+ (0, vitest_1.expect)((0, module_1.getModule)(emptyGraph(), `${ROOT}/assets/app.js`)).toBe(undefined);
62
+ });
63
+ });
64
+ //# sourceMappingURL=asset-resolution.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-resolution.spec.js","sourceRoot":"","sources":["../../src/graph/asset-resolution.spec.ts"],"names":[],"mappings":"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"}
@@ -7,13 +7,15 @@ const utils_1 = require("../utils");
7
7
  function augmentDependencies(rootUri, ideps) {
8
8
  return {
9
9
  fs: ideps.fs,
10
+ // Passed through as given. There is nothing to default: an absent app means the
11
+ // caller has none, and `DocumentsLocator` already owns what to do then.
12
+ app: ideps.app,
10
13
  // parse at most once
11
14
  getSourceCode: (0, platformos_check_common_1.memoize)(ideps.getSourceCode ??
12
15
  async function defaultGetSourceCode(uri) {
13
16
  const contents = await ideps.fs.readFile(uri);
14
17
  return (0, toSourceCode_1.toSourceCode)(uri, contents);
15
18
  }, utils_1.identity),
16
- getWebComponentDefinitionReference: ideps.getWebComponentDefinitionReference,
17
19
  };
18
20
  }
19
21
  //# sourceMappingURL=augment.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"augment.js","sourceRoot":"","sources":["../../src/graph/augment.ts"],"names":[],"mappings":";;AAKA,kDAgBC;AArBD,iFAAoE;AACpE,kDAA+C;AAE/C,oCAAoC;AAEpC,SAAgB,mBAAmB,CAAC,OAAe,EAAE,KAAoB;IACvE,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QAEZ,qBAAqB;QACrB,aAAa,EAAE,IAAA,iCAAO,EACpB,KAAK,CAAC,aAAa;YACjB,KAAK,UAAU,oBAAoB,CAAC,GAAG;gBACrC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC9C,OAAO,IAAA,2BAAY,EAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YACrC,CAAC,EACH,gBAAQ,CACT;QAED,kCAAkC,EAAE,KAAK,CAAC,kCAAkC;KAC7E,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"augment.js","sourceRoot":"","sources":["../../src/graph/augment.ts"],"names":[],"mappings":";;AAKA,kDAkBC;AAvBD,iFAAoE;AACpE,kDAA+C;AAE/C,oCAAoC;AAEpC,SAAgB,mBAAmB,CAAC,OAAe,EAAE,KAAoB;IACvE,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QAEZ,gFAAgF;QAChF,wEAAwE;QACxE,GAAG,EAAE,KAAK,CAAC,GAAG;QAEd,qBAAqB;QACrB,aAAa,EAAE,IAAA,iCAAO,EACpB,KAAK,CAAC,aAAa;YACjB,KAAK,UAAU,oBAAoB,CAAC,GAAG;gBACrC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC9C,OAAO,IAAA,2BAAY,EAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YACrC,CAAC,EACH,gBAAQ,CACT;KACF,CAAC;AACJ,CAAC"}
@@ -1,3 +1,16 @@
1
1
  import { UriString } from '@platformos/platformos-check-common';
2
- import { IDependencies, AppGraph } from '../types';
3
- export declare function buildAppGraph(rootUri: UriString, ideps: IDependencies, entryPoints?: UriString[]): Promise<AppGraph>;
2
+ import { IDependencies, AppGraph, GraphBuildOptions } from '../types';
3
+ /**
4
+ * Build the project dependency graph.
5
+ *
6
+ * - `entryPoints` omitted → FULL build: a single directory sweep discovers pages
7
+ * + layouts (the render entry points) and standalone custom-model-type/schema
8
+ * nodes, and every reachable module is materialized.
9
+ * - `entryPoints` provided → SCOPED build (e.g. an LSP rebuild for changed
10
+ * files): built verbatim from those roots. Schema nodes are NOT auto-discovered
11
+ * in this mode — schema discovery is a full-build concern.
12
+ *
13
+ * `options.includeStructural` (default off) additionally populates each
14
+ * `LiquidModule.structural`; see {@link GraphBuildOptions}.
15
+ */
16
+ export declare function buildAppGraph(rootUri: UriString, ideps: IDependencies, entryPoints?: UriString[], options?: GraphBuildOptions): Promise<AppGraph>;
@@ -1,21 +1,60 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildAppGraph = buildAppGraph;
4
- const platformos_check_common_1 = require("@platformos/platformos-check-common");
4
+ const platformos_common_1 = require("@platformos/platformos-common");
5
5
  const augment_1 = require("./augment");
6
6
  const module_1 = require("./module");
7
7
  const traverse_1 = require("./traverse");
8
- async function buildAppGraph(rootUri, ideps, entryPoints) {
8
+ /**
9
+ * Build the project dependency graph.
10
+ *
11
+ * - `entryPoints` omitted → FULL build: a single directory sweep discovers pages
12
+ * + layouts (the render entry points) and standalone custom-model-type/schema
13
+ * nodes, and every reachable module is materialized.
14
+ * - `entryPoints` provided → SCOPED build (e.g. an LSP rebuild for changed
15
+ * files): built verbatim from those roots. Schema nodes are NOT auto-discovered
16
+ * in this mode — schema discovery is a full-build concern.
17
+ *
18
+ * `options.includeStructural` (default off) additionally populates each
19
+ * `LiquidModule.structural`; see {@link GraphBuildOptions}.
20
+ */
21
+ async function buildAppGraph(rootUri, ideps, entryPoints, options = {}) {
9
22
  const deps = (0, augment_1.augmentDependencies)(rootUri, ideps);
10
- entryPoints =
11
- entryPoints ??
12
- (await (0, platformos_check_common_1.recursiveReadDirectory)(deps.fs, rootUri, ([uri]) => {
13
- if (!uri.endsWith('.liquid'))
14
- return false;
15
- // Layouts are entry points — they wrap all page content.
16
- // Pages are also entry points — they are directly requested.
17
- return (0, platformos_check_common_1.isLayout)(uri) || (0, platformos_check_common_1.isPage)(uri);
18
- }));
23
+ // Table (schema / custom-model-type) files are platform nodes but are NOT
24
+ // render-reachable — nothing renders them — so they never appear via edge traversal. On
25
+ // a full build they are discovered as standalone leaf nodes, never entry points, so
26
+ // reachability/orphan semantics for the render graph are unaffected.
27
+ let schemaUris = [];
28
+ // An explicit entryPoints scope is built verbatim (e.g. a scoped LSP rebuild); the
29
+ // default full build (`entryPoints === undefined`) also discovers standalone Table
30
+ // nodes. Branching on the parameter directly lets the compiler narrow it below.
31
+ if (entryPoints === undefined) {
32
+ // ONE sweep yields both populations, partitioned by SourceCodeType below, so the
33
+ // tree is walked once. `walkAppSourceFiles` is anchored on APP_SOURCE_SUBTREES: the
34
+ // walk it replaces started at the root and skipped directories by NAME, which both
35
+ // dropped `app/views/pages/vendor/**` (a live site section — 137 files on one real
36
+ // project) and admitted `tmp/app/views/partials/x.liquid`.
37
+ const discovered = await (0, platformos_common_1.walkAppSourceFiles)(deps.fs, rootUri, ([uri]) => {
38
+ // Root-ANCHORED classification. The unanchored `getFileType(uri)` this used to call
39
+ // matched a known directory anywhere in the path, so
40
+ // `seed/post_import/app/migrations/x.liquid` classified as a Migration while being
41
+ // correctly absent from the lint's app.
42
+ const fileType = (0, platformos_common_1.getFileType)(uri, rootUri);
43
+ // A GRAPH-domain restriction, not a second answer to "what is a source file":
44
+ // Liquid is the only source that can reference another file, so a non-Liquid entry
45
+ // point would have no edges to traverse. Which extensions ARE Liquid still comes
46
+ // from platformos-common, never spelled here — which is also why the `.yml`/`.yaml`
47
+ // tests that used to partition this sweep are gone: `.yaml` is not a platformOS
48
+ // extension at all, so spelling it here promised coverage the platform never had.
49
+ if ((0, platformos_common_1.sourceCodeTypeOf)(uri) === platformos_common_1.SourceCodeType.LiquidHtml) {
50
+ // Layouts wrap all page content; pages are directly requested — both are entry points.
51
+ return fileType === platformos_common_1.PlatformOSFileType.Layout || fileType === platformos_common_1.PlatformOSFileType.Page;
52
+ }
53
+ return fileType === platformos_common_1.PlatformOSFileType.Table;
54
+ });
55
+ entryPoints = discovered.filter((uri) => (0, platformos_common_1.sourceCodeTypeOf)(uri) === platformos_common_1.SourceCodeType.LiquidHtml);
56
+ schemaUris = discovered.filter((uri) => (0, platformos_common_1.sourceCodeTypeOf)(uri) !== platformos_common_1.SourceCodeType.LiquidHtml);
57
+ }
19
58
  const graph = {
20
59
  entryPoints: [],
21
60
  modules: {},
@@ -24,7 +63,10 @@ async function buildAppGraph(rootUri, ideps, entryPoints) {
24
63
  graph.entryPoints = entryPoints
25
64
  .map((uri) => (0, module_1.getModule)(graph, uri))
26
65
  .filter((x) => x !== undefined);
27
- await Promise.all(graph.entryPoints.map((entry) => (0, traverse_1.traverseModule)(entry, graph, deps)));
66
+ await Promise.all(graph.entryPoints.map((entry) => (0, traverse_1.traverseModule)(entry, graph, deps, options)));
67
+ if (schemaUris.length > 0) {
68
+ await Promise.all(schemaUris.map((uri) => (0, traverse_1.traverseModule)((0, module_1.getSchemaModule)(graph, uri), graph, deps, options)));
69
+ }
28
70
  return graph;
29
71
  }
30
72
  //# sourceMappingURL=build.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/graph/build.ts"],"names":[],"mappings":";;AAYA,sCA6BC;AAzCD,iFAM6C;AAE7C,uCAAgD;AAChD,qCAAqC;AACrC,yCAA4C;AAErC,KAAK,UAAU,aAAa,CACjC,OAAkB,EAClB,KAAoB,EACpB,WAAyB;IAEzB,MAAM,IAAI,GAAG,IAAA,6BAAmB,EAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAEjD,WAAW;QACT,WAAW;YACX,CAAC,MAAM,IAAA,gDAAY,EAAC,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE;gBAC9C,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;oBAAE,OAAO,KAAK,CAAC;gBAC3C,yDAAyD;gBACzD,6DAA6D;gBAC7D,OAAO,IAAA,kCAAQ,EAAC,GAAG,CAAC,IAAI,IAAA,gCAAM,EAAC,GAAG,CAAC,CAAC;YACtC,CAAC,CAAC,CAAC,CAAC;IAEN,MAAM,KAAK,GAAa;QACtB,WAAW,EAAE,EAAE;QACf,OAAO,EAAE,EAAE;QACX,OAAO;KACR,CAAC;IAEF,KAAK,CAAC,WAAW,GAAG,WAAW;SAC5B,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAA,kBAAS,EAAC,KAAK,EAAE,GAAG,CAAC,CAAC;SACnC,MAAM,CAAC,CAAC,CAAC,EAAkB,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IAElD,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,yBAAc,EAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAExF,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/graph/build.ts"],"names":[],"mappings":";;AA0BA,sCAkEC;AA3FD,qEAMuC;AAEvC,uCAAgD;AAChD,qCAAsD;AACtD,yCAA4C;AAE5C;;;;;;;;;;;;GAYG;AACI,KAAK,UAAU,aAAa,CACjC,OAAkB,EAClB,KAAoB,EACpB,WAAyB,EACzB,UAA6B,EAAE;IAE/B,MAAM,IAAI,GAAG,IAAA,6BAAmB,EAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAEjD,0EAA0E;IAC1E,wFAAwF;IACxF,oFAAoF;IACpF,qEAAqE;IACrE,IAAI,UAAU,GAAgB,EAAE,CAAC;IAEjC,mFAAmF;IACnF,mFAAmF;IACnF,gFAAgF;IAChF,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,iFAAiF;QACjF,oFAAoF;QACpF,mFAAmF;QACnF,mFAAmF;QACnF,2DAA2D;QAC3D,MAAM,UAAU,GAAG,MAAM,IAAA,sCAAkB,EAAC,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE;YACtE,oFAAoF;YACpF,qDAAqD;YACrD,mFAAmF;YACnF,wCAAwC;YACxC,MAAM,QAAQ,GAAG,IAAA,+BAAW,EAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAE3C,8EAA8E;YAC9E,mFAAmF;YACnF,iFAAiF;YACjF,oFAAoF;YACpF,gFAAgF;YAChF,kFAAkF;YAClF,IAAI,IAAA,oCAAgB,EAAC,GAAG,CAAC,KAAK,kCAAc,CAAC,UAAU,EAAE,CAAC;gBACxD,uFAAuF;gBACvF,OAAO,QAAQ,KAAK,sCAAkB,CAAC,MAAM,IAAI,QAAQ,KAAK,sCAAkB,CAAC,IAAI,CAAC;YACxF,CAAC;YACD,OAAO,QAAQ,KAAK,sCAAkB,CAAC,KAAK,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAA,oCAAgB,EAAC,GAAG,CAAC,KAAK,kCAAc,CAAC,UAAU,CAAC,CAAC;QAC9F,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAA,oCAAgB,EAAC,GAAG,CAAC,KAAK,kCAAc,CAAC,UAAU,CAAC,CAAC;IAC/F,CAAC;IAED,MAAM,KAAK,GAAa;QACtB,WAAW,EAAE,EAAE;QACf,OAAO,EAAE,EAAE;QACX,OAAO;KACR,CAAC;IAEF,KAAK,CAAC,WAAW,GAAG,WAAW;SAC5B,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAA,kBAAS,EAAC,KAAK,EAAE,GAAG,CAAC,CAAC;SACnC,MAAM,CAAC,CAAC,CAAC,EAAkB,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IAElD,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,yBAAc,EAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAEjG,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,OAAO,CAAC,GAAG,CACf,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAA,yBAAc,EAAC,IAAA,wBAAe,EAAC,KAAK,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAC3F,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const platformos_check_common_1 = require("@platformos/platformos-check-common");
4
+ const test_1 = require("@platformos/platformos-check-common/src/test");
5
+ const vitest_1 = require("vitest");
6
+ const index_1 = require("../index");
7
+ const toSourceCode_1 = require("../toSourceCode");
8
+ const test_helpers_1 = require("./test-helpers");
9
+ (0, vitest_1.describe)('Module: index', () => {
10
+ const rootUri = test_helpers_1.skeleton;
11
+ const p = (part) => platformos_check_common_1.path.join(rootUri, ...part.split('/'));
12
+ const loc = (part) => vitest_1.expect.objectContaining({ uri: p(part) });
13
+ let dependencies;
14
+ (0, vitest_1.beforeAll)(async () => {
15
+ dependencies = (0, test_helpers_1.getDependencies)();
16
+ }, 15000);
17
+ (0, vitest_1.describe)('Unit: buildAppGraph', { timeout: 10000 }, () => {
18
+ (0, vitest_1.it)('builds a graph of the app', { timeout: 10000 }, async () => {
19
+ const graph = await (0, index_1.buildAppGraph)(rootUri, dependencies);
20
+ (0, vitest_1.expect)(graph).toBeDefined();
21
+ });
22
+ (0, vitest_1.describe)('with a valid app graph', () => {
23
+ let graph;
24
+ (0, vitest_1.beforeEach)(async () => {
25
+ graph = await (0, index_1.buildAppGraph)(rootUri, dependencies);
26
+ });
27
+ (0, vitest_1.it)('has a root URI', () => {
28
+ (0, vitest_1.expect)(graph.rootUri).toBeDefined();
29
+ (0, vitest_1.expect)(graph.rootUri).toBe(rootUri);
30
+ });
31
+ (0, vitest_1.it)('infers entry points from layouts and pages', () => {
32
+ (0, vitest_1.expect)(graph.entryPoints).toHaveLength(2);
33
+ (0, vitest_1.expect)(graph.entryPoints.map((x) => x.uri)).toEqual(vitest_1.expect.arrayContaining([
34
+ p('app/views/layouts/application.liquid'),
35
+ p('app/views/pages/index.liquid'),
36
+ ]));
37
+ });
38
+ (0, vitest_1.it)("finds app/views/layouts/application.liquid's dependencies", () => {
39
+ const layout = graph.modules[p('app/views/layouts/application.liquid')];
40
+ (0, vitest_1.assert)(layout);
41
+ (0, vitest_1.assert)(layout.type === "Liquid" /* ModuleType.Liquid */);
42
+ (0, vitest_1.assert)(layout.kind === "layout" /* LiquidModuleKind.Layout */);
43
+ const deps = layout.dependencies;
44
+ (0, vitest_1.expect)(deps.map((x) => x.target.uri)).toEqual(vitest_1.expect.arrayContaining([
45
+ p('app/assets/app.js'),
46
+ p('app/assets/app.css'),
47
+ p('app/views/partials/header.liquid'),
48
+ ]));
49
+ });
50
+ (0, vitest_1.it)("finds app/views/partials/parent's dependencies and references", async () => {
51
+ const parentPartial = graph.modules[p('app/views/partials/parent.liquid')];
52
+ (0, vitest_1.assert)(parentPartial);
53
+ (0, vitest_1.assert)(parentPartial.type === "Liquid" /* ModuleType.Liquid */);
54
+ (0, vitest_1.assert)(parentPartial.kind === "partial" /* LiquidModuleKind.Partial */);
55
+ // outgoing links — parent renders exactly one partial (child)
56
+ const deps = parentPartial.dependencies;
57
+ (0, vitest_1.assert)(deps.map((x) => x.source.uri).every((x) => x === parentPartial.uri));
58
+ (0, vitest_1.expect)(deps.map((x) => x.target.uri)).toEqual([p('app/views/partials/child.liquid')]);
59
+ // {% render 'child' %} dependency
60
+ const parentSource = await dependencies.getSourceCode(p('app/views/partials/parent.liquid'));
61
+ (0, vitest_1.assert)(parentSource);
62
+ (0, vitest_1.assert)(parentSource.type === platformos_check_common_1.SourceCodeType.LiquidHtml);
63
+ (0, vitest_1.expect)(parentPartial.dependencies.map((x) => x.source)).toContainEqual(vitest_1.expect.objectContaining({
64
+ uri: p('app/views/partials/parent.liquid'),
65
+ range: [
66
+ parentSource.source.indexOf('{% render "child"'),
67
+ parentSource.source.indexOf('{% render "child"') +
68
+ '{% render "child", children: children %}'.length,
69
+ ],
70
+ }));
71
+ });
72
+ (0, vitest_1.it)("finds app/views/partials/child's references", () => {
73
+ const childPartial = graph.modules[p('app/views/partials/child.liquid')];
74
+ (0, vitest_1.assert)(childPartial);
75
+ (0, vitest_1.assert)(childPartial.type === "Liquid" /* ModuleType.Liquid */);
76
+ (0, vitest_1.assert)(childPartial.kind === "partial" /* LiquidModuleKind.Partial */);
77
+ const refs = childPartial.references;
78
+ (0, vitest_1.expect)(refs.map((x) => x.source.uri)).toEqual(vitest_1.expect.arrayContaining([
79
+ p('app/views/partials/parent.liquid'),
80
+ p('app/views/partials/header.liquid'),
81
+ ]));
82
+ });
83
+ (0, vitest_1.it)('tags every layout edge with its kind (asset, asset, render)', () => {
84
+ const layout = graph.modules[p('app/views/layouts/application.liquid')];
85
+ (0, vitest_1.assert)(layout);
86
+ // The complete, ordered edge set — not a membership probe — so an extra,
87
+ // missing, or mis-kinded edge fails. (Source ranges are pinned by the
88
+ // dedicated render-dependency test above.)
89
+ (0, vitest_1.expect)(layout.dependencies.map((d) => ({ target: d.target.uri, type: d.type, kind: d.kind }))).toEqual([
90
+ { target: p('app/assets/app.js'), type: 'direct', kind: 'asset' },
91
+ { target: p('app/assets/app.css'), type: 'direct', kind: 'asset' },
92
+ { target: p('app/views/partials/header.liquid'), type: 'direct', kind: 'render' },
93
+ ]);
94
+ });
95
+ });
96
+ /**
97
+ * Entry points come from an ANCHORED walk of the app subtrees, so what a
98
+ * directory is CALLED never decides whether the graph can see it. The walk this
99
+ * replaced skipped any directory ending in `vendor`, `build`, `tmp` or `dist`,
100
+ * which lost every page under `app/views/pages/vendor/**` — a real section of a
101
+ * real site — while still descending into `tmp/app/views/pages/`, which the
102
+ * platform does not deploy at all.
103
+ */
104
+ (0, vitest_1.describe)('entry points on a project with app directories named like build output', () => {
105
+ const projectRoot = 'file:///project';
106
+ const u = (part) => `${projectRoot}/${part}`;
107
+ let graph;
108
+ (0, vitest_1.beforeEach)(async () => {
109
+ const fs = new test_1.MockFileSystem({
110
+ 'app/views/pages/vendor/index.liquid': `{% render 'vendor/card' %}`,
111
+ 'app/views/pages/build/status.liquid': `ok`,
112
+ 'app/views/partials/vendor/card.liquid': `a card`,
113
+ 'tmp/app/views/pages/scratch.liquid': `not deployed`,
114
+ 'node_modules/some-pkg/app/views/pages/decoy.liquid': `not ours`,
115
+ 'dist/app/views/pages/bundled.liquid': `build output`,
116
+ }, projectRoot);
117
+ graph = await (0, index_1.buildAppGraph)(projectRoot, {
118
+ fs,
119
+ getSourceCode: async (uri) => (0, toSourceCode_1.toSourceCode)(uri, await fs.readFile(uri)),
120
+ });
121
+ });
122
+ (0, vitest_1.it)('finds the pages under vendor/ and build/, and nothing outside the app subtrees', () => {
123
+ (0, vitest_1.expect)(graph.entryPoints.map((entry) => entry.uri).sort()).toEqual([
124
+ u('app/views/pages/build/status.liquid'),
125
+ u('app/views/pages/vendor/index.liquid'),
126
+ ]);
127
+ });
128
+ (0, vitest_1.it)('traverses them, so a partial under vendor/ is a graph node with a reference', () => {
129
+ const card = graph.modules[u('app/views/partials/vendor/card.liquid')];
130
+ (0, vitest_1.assert)(card);
131
+ (0, vitest_1.expect)(card.references.map((reference) => reference.source.uri)).toEqual([
132
+ u('app/views/pages/vendor/index.liquid'),
133
+ ]);
134
+ });
135
+ });
136
+ });
137
+ });
138
+ //# sourceMappingURL=build.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.spec.js","sourceRoot":"","sources":["../../src/graph/build.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { type UriString } from '@platformos/platformos-check-common';
2
+ import { type AbstractFileSystem } from '@platformos/platformos-common';
3
+ /**
4
+ * The canonical definition of an EDGE SOURCE: a liquid file whose own content can declare
5
+ * outgoing edges (a Page, Layout, or Partial). Only these files' add/remove/modify can change
6
+ * any file's set of dependents — `.graphql`/`.yml`/asset files are leaves.
7
+ *
8
+ * "Which files" derives entirely from the file-type classifier, so this predicate never
9
+ * re-encodes the classification. It is ANCHORED on `rootUri`, because a file's type IS its
10
+ * position relative to the project root: unanchored, `tmp/app/lib/x.liquid` is a Partial.
11
+ */
12
+ export declare function isEdgeSource(uri: UriString, rootUri: UriString): boolean;
13
+ /**
14
+ * Enumerate every edge-source liquid file under a project root — the single canonical primitive
15
+ * for "which files are the graph's edge sources". Consumers never re-derive the walk or the
16
+ * {@link isEdgeSource} predicate.
17
+ *
18
+ * The walk is `walkAppSourceFiles`, platformos-common's anchored expansion of
19
+ * `APP_SOURCE_SUBTREES`, so this file names no directory at all and a bundled `react-app/` is
20
+ * never walked. `edge-sources.spec` pins the scoped result against a whole-tree walk filtered
21
+ * by {@link isEdgeSource}.
22
+ *
23
+ * NOT shared with `buildAppGraph`'s full-build discovery: the two gather DIFFERENT domains —
24
+ * that one takes render entry points (pages + layouts, partials being edge-reached) plus
25
+ * standalone schema nodes, this one takes page + layout + partial. They share the walk
26
+ * primitive and the classifier, which are the parts that must not drift.
27
+ */
28
+ export declare function enumerateEdgeSources(fs: AbstractFileSystem, rootUri: UriString): Promise<UriString[]>;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isEdgeSource = isEdgeSource;
4
+ exports.enumerateEdgeSources = enumerateEdgeSources;
5
+ const platformos_common_1 = require("@platformos/platformos-common");
6
+ /**
7
+ * The canonical definition of an EDGE SOURCE: a liquid file whose own content can declare
8
+ * outgoing edges (a Page, Layout, or Partial). Only these files' add/remove/modify can change
9
+ * any file's set of dependents — `.graphql`/`.yml`/asset files are leaves.
10
+ *
11
+ * "Which files" derives entirely from the file-type classifier, so this predicate never
12
+ * re-encodes the classification. It is ANCHORED on `rootUri`, because a file's type IS its
13
+ * position relative to the project root: unanchored, `tmp/app/lib/x.liquid` is a Partial.
14
+ */
15
+ function isEdgeSource(uri, rootUri) {
16
+ switch ((0, platformos_common_1.getFileType)(uri, rootUri)) {
17
+ case platformos_common_1.PlatformOSFileType.Layout:
18
+ case platformos_common_1.PlatformOSFileType.Page:
19
+ case platformos_common_1.PlatformOSFileType.Partial:
20
+ return true;
21
+ default:
22
+ return false;
23
+ }
24
+ }
25
+ /**
26
+ * Enumerate every edge-source liquid file under a project root — the single canonical primitive
27
+ * for "which files are the graph's edge sources". Consumers never re-derive the walk or the
28
+ * {@link isEdgeSource} predicate.
29
+ *
30
+ * The walk is `walkAppSourceFiles`, platformos-common's anchored expansion of
31
+ * `APP_SOURCE_SUBTREES`, so this file names no directory at all and a bundled `react-app/` is
32
+ * never walked. `edge-sources.spec` pins the scoped result against a whole-tree walk filtered
33
+ * by {@link isEdgeSource}.
34
+ *
35
+ * NOT shared with `buildAppGraph`'s full-build discovery: the two gather DIFFERENT domains —
36
+ * that one takes render entry points (pages + layouts, partials being edge-reached) plus
37
+ * standalone schema nodes, this one takes page + layout + partial. They share the walk
38
+ * primitive and the classifier, which are the parts that must not drift.
39
+ */
40
+ async function enumerateEdgeSources(fs, rootUri) {
41
+ return (0, platformos_common_1.walkAppSourceFiles)(fs, rootUri, ([uri]) => isEdgeSource(uri, rootUri));
42
+ }
43
+ //# sourceMappingURL=edge-sources.js.map