@awesomeness-js/server 1.1.10 → 1.1.13
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/build/build.js +4 -1
- package/build/postBuild.js +4 -1
- package/index.js +6 -4
- package/package.json +1 -1
- package/src/componentAndPageMemory.js +297 -0
- package/src/componentDependencies.js +7 -19
- package/src/extractUiComponentRefs.js +55 -0
- package/src/fetchPage.js +79 -4
- package/src/resolveRealCasePath.js +0 -4
- package/tests/componentAndPageMemory.test.js +172 -0
- package/tests/fetchPage.test.js +259 -0
- package/tests/fixtures/site-and-components/components/app/cleanMain/index.js +26 -0
- package/tests/fixtures/site-and-components/components/app/cleanMain.js +14 -0
- package/tests/fixtures/site-and-components/components/app/index.css +4 -0
- package/tests/fixtures/site-and-components/components/app/index.js +42 -0
- package/tests/fixtures/site-and-components/components/app/insertIntoList.jquery.js +150 -0
- package/tests/fixtures/site-and-components/components/app/keyUpWithTimeout.jQuery.js +26 -0
- package/tests/fixtures/site-and-components/components/app/onEnter.jQuery.js +39 -0
- package/tests/fixtures/site-and-components/components/app/onResize.jQuery.js +64 -0
- package/tests/fixtures/site-and-components/components/app/pwa/_.css +305 -0
- package/tests/fixtures/site-and-components/components/app/pwa/index.js +235 -0
- package/tests/fixtures/site-and-components/components/app/pwa/updateProfileImage.js +7 -0
- package/tests/fixtures/site-and-components/components/app/shapes.css +3 -0
- package/tests/fixtures/site-and-components/components/app/simple/_.css +151 -0
- package/tests/fixtures/site-and-components/components/app/simple/index.js +170 -0
- package/tests/fixtures/site-and-components/components/app/start.js +165 -0
- package/tests/fixtures/site-and-components/components/app/vanilla/_.css +1 -0
- package/tests/fixtures/site-and-components/components/app/vanilla/index.js +27 -0
- package/tests/fixtures/site-and-components/components/card/index.js +88 -0
- package/tests/fixtures/site-and-components/components/cardMain/index.js +86 -0
- package/tests/fixtures/site-and-components/components/cardMount/index.js +86 -0
- package/tests/fixtures/site-and-components/components/pageInit/index.js +86 -0
- package/tests/fixtures/site-and-components/components/pageScript/index.js +86 -0
- package/tests/fixtures/site-and-components/components/pageWidget/index.js +86 -0
- package/tests/fixtures/site-and-components/components/scrollSpy/elm.js +172 -0
- package/tests/fixtures/site-and-components/components/scrollSpy/index.js +63 -0
- package/tests/fixtures/site-and-components/components/scrollSpy/observerPoolGet.js +91 -0
- package/tests/fixtures/site-and-components/components/scrollSpy/observerPoolRegistry.js +18 -0
- package/tests/fixtures/site-and-components/components/scrollSpy/observerPoolSubscribe.js +37 -0
- package/tests/fixtures/site-and-components/components/scrollSpy/observerPoolUnsubscribe.js +44 -0
- package/tests/fixtures/site-and-components/components/scrollSpy/top.js +86 -0
- package/tests/fixtures/site-and-components/sites/site-a/pages/home/init.js +78 -0
- package/tests/fixtures/site-and-components/sites/site-a/pages/home/js/index.js +93 -0
- package/tests/setup.js +1 -0
- package/tsconfig.json +18 -0
- package/types/errors.d.ts +0 -0
- package/types/index.d.ts +109 -0
- package/types/src/applicationMap.d.ts +1 -0
- package/types/src/awesomenessNormalizeRequest.d.ts +27 -0
- package/types/src/brotliJsonResponse.d.ts +10 -0
- package/types/src/checkAccess.d.ts +5 -0
- package/types/src/componentAndPageMemory.d.ts +75 -0
- package/types/src/componentDependencies.d.ts +6 -0
- package/types/src/config.d.ts +7 -0
- package/types/src/extractUiComponentRefs.d.ts +5 -0
- package/types/src/fetchPage.d.ts +4 -0
- package/types/src/getConfig.d.ts +2 -0
- package/types/src/getMD.d.ts +1 -0
- package/types/src/init.d.ts +2 -0
- package/types/src/koa/attachAwesomenessRequest.d.ts +1 -0
- package/types/src/koa/cors.d.ts +1 -0
- package/types/src/koa/errorHandler.d.ts +1 -0
- package/types/src/koa/finalFormat.d.ts +1 -0
- package/types/src/koa/jsonBodyParser.d.ts +1 -0
- package/types/src/koa/routeRequest.d.ts +1 -0
- package/types/src/koa/serverUp.d.ts +1 -0
- package/types/src/koa/staticFiles.d.ts +1 -0
- package/types/src/koa/timeout.d.ts +1 -0
- package/types/src/pageInfo.d.ts +8 -0
- package/types/src/reRoute.d.ts +7 -0
- package/types/src/resolveRealCasePath.d.ts +1 -0
- package/types/src/specialPaths.d.ts +3 -0
- package/types/src/start.d.ts +1 -0
- package/types/src/validateRequest.d.ts +2 -0
- package/types/src/ws/handlers.d.ts +4 -0
- package/types/src/ws/index.d.ts +1 -0
package/build/build.js
CHANGED
package/build/postBuild.js
CHANGED
package/index.js
CHANGED
|
@@ -7,8 +7,10 @@ import _applicationMap from './src/applicationMap.js';
|
|
|
7
7
|
import _awesomenessNormalizeRequest from './src/awesomenessNormalizeRequest.js';
|
|
8
8
|
import _brotliJsonResponse from './src/brotliJsonResponse.js';
|
|
9
9
|
import _checkAccess from './src/checkAccess.js';
|
|
10
|
+
import _componentAndPageMemory from './src/componentAndPageMemory.js';
|
|
10
11
|
import _componentDependencies from './src/componentDependencies.js';
|
|
11
12
|
import _config from './src/config.js';
|
|
13
|
+
import _extractUiComponentRefs from './src/extractUiComponentRefs.js';
|
|
12
14
|
import _fetchPage from './src/fetchPage.js';
|
|
13
15
|
import _getConfig from './src/getConfig.js';
|
|
14
16
|
import _getMD from './src/getMD.js';
|
|
@@ -35,8 +37,10 @@ export { _applicationMap as applicationMap };
|
|
|
35
37
|
export { _awesomenessNormalizeRequest as awesomenessNormalizeRequest };
|
|
36
38
|
export { _brotliJsonResponse as brotliJsonResponse };
|
|
37
39
|
export { _checkAccess as checkAccess };
|
|
40
|
+
export { _componentAndPageMemory as componentAndPageMemory };
|
|
38
41
|
export { _componentDependencies as componentDependencies };
|
|
39
42
|
export { _config as config };
|
|
43
|
+
export { _extractUiComponentRefs as extractUiComponentRefs };
|
|
40
44
|
export { _fetchPage as fetchPage };
|
|
41
45
|
export { _getConfig as getConfig };
|
|
42
46
|
export { _getMD as getMD };
|
|
@@ -71,18 +75,16 @@ export default {
|
|
|
71
75
|
awesomenessNormalizeRequest: _awesomenessNormalizeRequest,
|
|
72
76
|
brotliJsonResponse: _brotliJsonResponse,
|
|
73
77
|
checkAccess: _checkAccess,
|
|
78
|
+
componentAndPageMemory: _componentAndPageMemory,
|
|
74
79
|
componentDependencies: _componentDependencies,
|
|
75
80
|
config: _config,
|
|
81
|
+
extractUiComponentRefs: _extractUiComponentRefs,
|
|
76
82
|
fetchPage: _fetchPage,
|
|
77
83
|
getConfig: _getConfig,
|
|
78
84
|
getMD: _getMD,
|
|
79
85
|
init: _init,
|
|
80
86
|
pageInfo: _pageInfo,
|
|
81
87
|
reRoute: _reRoute,
|
|
82
|
-
/**
|
|
83
|
-
* Case-insensitive real path resolver.
|
|
84
|
-
* Works correctly on Windows, macOS, and Linux/Docker.
|
|
85
|
-
*/
|
|
86
88
|
resolveRealCasePath: _resolveRealCasePath,
|
|
87
89
|
specialPaths: _specialPaths,
|
|
88
90
|
start: _start,
|
package/package.json
CHANGED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { createHash } from "crypto";
|
|
2
|
+
import { readFileSync, statSync } from "fs";
|
|
3
|
+
import extractUiComponentRefs from "./extractUiComponentRefs.js";
|
|
4
|
+
|
|
5
|
+
const FILE_CACHE_LIMIT = 2000;
|
|
6
|
+
const REFS_CACHE_LIMIT = 5000;
|
|
7
|
+
|
|
8
|
+
const fileCache = new Map();
|
|
9
|
+
const refsCache = new Map();
|
|
10
|
+
|
|
11
|
+
const DEFAULT_EXTRACT_OPTIONS = Object.freeze({
|
|
12
|
+
namespace: "ui",
|
|
13
|
+
includeCall: true,
|
|
14
|
+
includeDotAccess: false,
|
|
15
|
+
cacheContext: "",
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
function toMB(bytes) {
|
|
19
|
+
|
|
20
|
+
return Number((bytes / (1024 * 1024)).toFixed(6));
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function toGB(bytes) {
|
|
25
|
+
|
|
26
|
+
return Number((bytes / (1024 * 1024 * 1024)).toFixed(6));
|
|
27
|
+
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function withMBGB(bytes) {
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
bytes,
|
|
34
|
+
mb: toMB(bytes),
|
|
35
|
+
gb: toGB(bytes),
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function pruneCache(cache, limit) {
|
|
41
|
+
|
|
42
|
+
if (cache.size <= limit) {
|
|
43
|
+
|
|
44
|
+
return;
|
|
45
|
+
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const deleteCount = cache.size - limit;
|
|
49
|
+
let i = 0;
|
|
50
|
+
|
|
51
|
+
for (const key of cache.keys()) {
|
|
52
|
+
|
|
53
|
+
cache.delete(key);
|
|
54
|
+
i += 1;
|
|
55
|
+
|
|
56
|
+
if (i >= deleteCount) {
|
|
57
|
+
|
|
58
|
+
break;
|
|
59
|
+
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function hashContent(content) {
|
|
67
|
+
|
|
68
|
+
return createHash("sha1").update(content).digest("hex");
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function normalizeExtractOptions(
|
|
73
|
+
{
|
|
74
|
+
namespace = DEFAULT_EXTRACT_OPTIONS.namespace,
|
|
75
|
+
includeCall = DEFAULT_EXTRACT_OPTIONS.includeCall,
|
|
76
|
+
includeDotAccess = DEFAULT_EXTRACT_OPTIONS.includeDotAccess,
|
|
77
|
+
cacheContext,
|
|
78
|
+
} = {},
|
|
79
|
+
{
|
|
80
|
+
defaultCacheContext = DEFAULT_EXTRACT_OPTIONS.cacheContext,
|
|
81
|
+
} = {}
|
|
82
|
+
) {
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
namespace,
|
|
86
|
+
includeCall,
|
|
87
|
+
includeDotAccess,
|
|
88
|
+
cacheContext: cacheContext ?? defaultCacheContext,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function refsCacheKey(content, options = {}) {
|
|
94
|
+
|
|
95
|
+
const {
|
|
96
|
+
namespace,
|
|
97
|
+
includeCall,
|
|
98
|
+
includeDotAccess,
|
|
99
|
+
cacheContext,
|
|
100
|
+
} = normalizeExtractOptions(options);
|
|
101
|
+
const contentHash = hashContent(content);
|
|
102
|
+
const contextPart = cacheContext ? `${cacheContext}|` : "";
|
|
103
|
+
|
|
104
|
+
return `${contextPart}${namespace}|${includeCall}|${includeDotAccess}|${contentHash}`;
|
|
105
|
+
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function refsCacheKeyFromFile(filePath, fileMeta, options = {}) {
|
|
109
|
+
|
|
110
|
+
const {
|
|
111
|
+
namespace,
|
|
112
|
+
includeCall,
|
|
113
|
+
includeDotAccess,
|
|
114
|
+
cacheContext,
|
|
115
|
+
} = normalizeExtractOptions(options, {
|
|
116
|
+
defaultCacheContext: `file:${filePath}`,
|
|
117
|
+
});
|
|
118
|
+
const contextPart = cacheContext ? `${cacheContext}|` : "";
|
|
119
|
+
|
|
120
|
+
return `${contextPart}${namespace}|${includeCall}|${includeDotAccess}|mtime:${fileMeta.mtimeMs}|size:${fileMeta.size}`;
|
|
121
|
+
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function getFileCacheEntry(filePath) {
|
|
125
|
+
|
|
126
|
+
const stat = statSync(filePath);
|
|
127
|
+
const cacheEntry = fileCache.get(filePath);
|
|
128
|
+
|
|
129
|
+
if (
|
|
130
|
+
cacheEntry &&
|
|
131
|
+
cacheEntry.mtimeMs === stat.mtimeMs &&
|
|
132
|
+
cacheEntry.size === stat.size
|
|
133
|
+
) {
|
|
134
|
+
|
|
135
|
+
return cacheEntry;
|
|
136
|
+
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const content = readFileSync(filePath, "utf-8");
|
|
140
|
+
const nextEntry = {
|
|
141
|
+
mtimeMs: stat.mtimeMs,
|
|
142
|
+
size: stat.size,
|
|
143
|
+
content,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
fileCache.set(filePath, nextEntry);
|
|
147
|
+
pruneCache(fileCache, FILE_CACHE_LIMIT);
|
|
148
|
+
|
|
149
|
+
return nextEntry;
|
|
150
|
+
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function readFileMemoized(filePath) {
|
|
154
|
+
|
|
155
|
+
return getFileCacheEntry(filePath).content;
|
|
156
|
+
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function extractUiRefsMemoized(content, options = {}) {
|
|
160
|
+
|
|
161
|
+
if (typeof content !== "string" || !content.length) {
|
|
162
|
+
|
|
163
|
+
return [];
|
|
164
|
+
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const extractionOptions = normalizeExtractOptions(options);
|
|
168
|
+
const key = refsCacheKey(content, extractionOptions);
|
|
169
|
+
const existing = refsCache.get(key);
|
|
170
|
+
|
|
171
|
+
if (existing) {
|
|
172
|
+
|
|
173
|
+
return existing;
|
|
174
|
+
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const refs = extractUiComponentRefs(content, extractionOptions);
|
|
178
|
+
|
|
179
|
+
refsCache.set(key, refs);
|
|
180
|
+
pruneCache(refsCache, REFS_CACHE_LIMIT);
|
|
181
|
+
|
|
182
|
+
return refs;
|
|
183
|
+
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function extractUiRefsFromFileMemoized(filePath, options = {}) {
|
|
187
|
+
|
|
188
|
+
const fileEntry = getFileCacheEntry(filePath);
|
|
189
|
+
const extractionOptions = normalizeExtractOptions(options, {
|
|
190
|
+
defaultCacheContext: `file:${filePath}`,
|
|
191
|
+
});
|
|
192
|
+
const key = refsCacheKeyFromFile(filePath, fileEntry, extractionOptions);
|
|
193
|
+
const existing = refsCache.get(key);
|
|
194
|
+
|
|
195
|
+
if (existing) {
|
|
196
|
+
|
|
197
|
+
return existing;
|
|
198
|
+
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const refs = extractUiComponentRefs(fileEntry.content, extractionOptions);
|
|
202
|
+
|
|
203
|
+
refsCache.set(key, refs);
|
|
204
|
+
pruneCache(refsCache, REFS_CACHE_LIMIT);
|
|
205
|
+
|
|
206
|
+
return refs;
|
|
207
|
+
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function clearComponentAndPageMemory() {
|
|
211
|
+
|
|
212
|
+
fileCache.clear();
|
|
213
|
+
refsCache.clear();
|
|
214
|
+
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export function getComponentAndPageMemoryStatus({
|
|
218
|
+
includeKeys = true,
|
|
219
|
+
sampleSize = 25,
|
|
220
|
+
} = {}) {
|
|
221
|
+
|
|
222
|
+
let fileCacheBytes = 0;
|
|
223
|
+
|
|
224
|
+
for (const value of fileCache.values()) {
|
|
225
|
+
|
|
226
|
+
fileCacheBytes += Buffer.byteLength(value.content || "", "utf-8");
|
|
227
|
+
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
let refsCacheBytes = 0;
|
|
231
|
+
|
|
232
|
+
for (const [ key, value ] of refsCache.entries()) {
|
|
233
|
+
|
|
234
|
+
refsCacheBytes += Buffer.byteLength(key, "utf-8");
|
|
235
|
+
refsCacheBytes += Buffer.byteLength(JSON.stringify(value || []), "utf-8");
|
|
236
|
+
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const processMemoryUsage = typeof process?.memoryUsage === "function"
|
|
240
|
+
? process.memoryUsage()
|
|
241
|
+
: null;
|
|
242
|
+
const totalCacheBytes = fileCacheBytes + refsCacheBytes;
|
|
243
|
+
const processMemoryUsageWithUnits = processMemoryUsage
|
|
244
|
+
? {
|
|
245
|
+
rss: withMBGB(processMemoryUsage.rss || 0),
|
|
246
|
+
heapTotal: withMBGB(processMemoryUsage.heapTotal || 0),
|
|
247
|
+
heapUsed: withMBGB(processMemoryUsage.heapUsed || 0),
|
|
248
|
+
external: withMBGB(processMemoryUsage.external || 0),
|
|
249
|
+
arrayBuffers: withMBGB(processMemoryUsage.arrayBuffers || 0),
|
|
250
|
+
}
|
|
251
|
+
: null;
|
|
252
|
+
|
|
253
|
+
const out = {
|
|
254
|
+
limits: {
|
|
255
|
+
fileCacheLimit: FILE_CACHE_LIMIT,
|
|
256
|
+
refsCacheLimit: REFS_CACHE_LIMIT,
|
|
257
|
+
},
|
|
258
|
+
counts: {
|
|
259
|
+
fileCacheEntries: fileCache.size,
|
|
260
|
+
refsCacheEntries: refsCache.size,
|
|
261
|
+
},
|
|
262
|
+
approximateBytes: {
|
|
263
|
+
fileCacheBytes,
|
|
264
|
+
refsCacheBytes,
|
|
265
|
+
totalCacheBytes,
|
|
266
|
+
},
|
|
267
|
+
approximateMemory: {
|
|
268
|
+
fileCache: withMBGB(fileCacheBytes),
|
|
269
|
+
refsCache: withMBGB(refsCacheBytes),
|
|
270
|
+
totalCache: withMBGB(totalCacheBytes),
|
|
271
|
+
},
|
|
272
|
+
processMemoryUsage,
|
|
273
|
+
processMemoryUsageWithUnits,
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
if (includeKeys) {
|
|
277
|
+
|
|
278
|
+
out.keys = {
|
|
279
|
+
fileCacheKeys: [ ...fileCache.keys() ].slice(0, sampleSize),
|
|
280
|
+
refsCacheKeys: [ ...refsCache.keys() ].slice(0, sampleSize),
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return out;
|
|
286
|
+
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const componentAndPageMemory = {
|
|
290
|
+
readFileMemoized,
|
|
291
|
+
extractUiRefsMemoized,
|
|
292
|
+
extractUiRefsFromFileMemoized,
|
|
293
|
+
clearComponentAndPageMemory,
|
|
294
|
+
getComponentAndPageMemoryStatus,
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
export default componentAndPageMemory;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import { fileURLToPath } from "url";
|
|
3
3
|
import { each, getAllFiles } from "@awesomeness-js/utils";
|
|
4
|
-
import { readFileSync } from "fs";
|
|
5
4
|
import getConfig from "./getConfig.js";
|
|
5
|
+
import { extractUiRefsFromFileMemoized, readFileMemoized } from "./componentAndPageMemory.js";
|
|
6
6
|
|
|
7
7
|
function urlToFsPath(u) {
|
|
8
8
|
|
|
@@ -34,22 +34,6 @@ function urlToFsPath(u) {
|
|
|
34
34
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
function extractUiFirstParts(str) {
|
|
38
|
-
|
|
39
|
-
const regex = /ui\.([a-zA-Z0-9_]+)(?:\.[a-zA-Z0-9_.]*)?\(/g;
|
|
40
|
-
const matches = new Set();
|
|
41
|
-
let match;
|
|
42
|
-
|
|
43
|
-
while ((match = regex.exec(str)) !== null) {
|
|
44
|
-
|
|
45
|
-
matches.add(match[1]);
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return [ ...matches ];
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
37
|
export default function componentDependencies(
|
|
54
38
|
allComponents,
|
|
55
39
|
{
|
|
@@ -186,14 +170,18 @@ export default function componentDependencies(
|
|
|
186
170
|
|
|
187
171
|
// readFileSync must use chosenRoot + relative file path
|
|
188
172
|
const filePath = path.isAbsolute(file) ? file : path.join(chosenRoot, file);
|
|
189
|
-
const fileContent =
|
|
173
|
+
const fileContent = readFileMemoized(filePath);
|
|
190
174
|
|
|
191
175
|
const lines = fileContent.split("\n");
|
|
192
176
|
let fileWithImportsStripped = "";
|
|
193
177
|
|
|
194
178
|
try {
|
|
195
179
|
|
|
196
|
-
const newTest =
|
|
180
|
+
const newTest = extractUiRefsFromFileMemoized(filePath, {
|
|
181
|
+
namespace,
|
|
182
|
+
includeDotAccess: true,
|
|
183
|
+
cacheContext: `component:${component}|file:${filePath}`,
|
|
184
|
+
});
|
|
197
185
|
|
|
198
186
|
if (newTest.length > 0) {
|
|
199
187
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
function escapeRegex(input) {
|
|
2
|
+
|
|
3
|
+
return String(input).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4
|
+
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export default function extractUiComponentRefs(
|
|
8
|
+
str,
|
|
9
|
+
{
|
|
10
|
+
namespace = "ui",
|
|
11
|
+
includeCall = true,
|
|
12
|
+
includeDotAccess = false,
|
|
13
|
+
} = {}
|
|
14
|
+
) {
|
|
15
|
+
|
|
16
|
+
if (typeof str !== "string" || !str.length) {
|
|
17
|
+
|
|
18
|
+
return [];
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const ns = escapeRegex(namespace);
|
|
23
|
+
const lookaheads = [];
|
|
24
|
+
|
|
25
|
+
if (includeDotAccess) {
|
|
26
|
+
|
|
27
|
+
lookaheads.push("\\.");
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (includeCall) {
|
|
32
|
+
|
|
33
|
+
lookaheads.push("\\(");
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!lookaheads.length) {
|
|
38
|
+
|
|
39
|
+
return [];
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const regex = new RegExp(`${ns}\\.([a-zA-Z0-9_]+)(?=${lookaheads.join("|")})`, "g");
|
|
44
|
+
const matches = new Set();
|
|
45
|
+
let match;
|
|
46
|
+
|
|
47
|
+
while ((match = regex.exec(str)) !== null) {
|
|
48
|
+
|
|
49
|
+
matches.add(match[1]);
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return [ ...matches ];
|
|
54
|
+
|
|
55
|
+
}
|
package/src/fetchPage.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import { fileURLToPath } from "url";
|
|
3
|
+
import { existsSync } from "fs";
|
|
3
4
|
|
|
4
5
|
import componentDependencies from "./componentDependencies.js";
|
|
5
6
|
import pageInfo from "./pageInfo.js";
|
|
6
7
|
import { each, md5, combineFiles } from "@awesomeness-js/utils";
|
|
7
8
|
import getConfig from "./getConfig.js";
|
|
9
|
+
import { extractUiRefsFromFileMemoized, extractUiRefsMemoized } from "./componentAndPageMemory.js";
|
|
8
10
|
|
|
9
11
|
const componentNamespace = "ui";
|
|
10
12
|
const pageNamespaceBase = `app.pages`;
|
|
@@ -68,6 +70,63 @@ export default async function fetchPage(
|
|
|
68
70
|
return inits.join("\n");
|
|
69
71
|
|
|
70
72
|
}
|
|
73
|
+
|
|
74
|
+
function collectComponentsFromPageFiles() {
|
|
75
|
+
|
|
76
|
+
const found = new Set();
|
|
77
|
+
const initPath = path.join(path.dirname(jsPath), "init.js");
|
|
78
|
+
const cacheScope = `site:${awesomenessRequest.site}|page:${page}`;
|
|
79
|
+
|
|
80
|
+
if (existsSync(initPath)) {
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
extractUiRefsFromFileMemoized(initPath, {
|
|
86
|
+
namespace: componentNamespace,
|
|
87
|
+
includeDotAccess: true,
|
|
88
|
+
}).forEach((name) => found.add(name));
|
|
89
|
+
|
|
90
|
+
} catch (err) {
|
|
91
|
+
|
|
92
|
+
console.log("failed to infer components from page init.js", {
|
|
93
|
+
page,
|
|
94
|
+
initPath,
|
|
95
|
+
err,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
|
|
104
|
+
combineFiles(jsPath, "js", {
|
|
105
|
+
processContent: ({ content }) => {
|
|
106
|
+
|
|
107
|
+
extractUiRefsMemoized(content, {
|
|
108
|
+
namespace: componentNamespace,
|
|
109
|
+
includeDotAccess: true,
|
|
110
|
+
cacheContext: `${cacheScope}|js-content`,
|
|
111
|
+
}).forEach((name) => found.add(name));
|
|
112
|
+
|
|
113
|
+
return content;
|
|
114
|
+
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
} catch (err) {
|
|
119
|
+
|
|
120
|
+
console.log("failed to infer components from page js", {
|
|
121
|
+
page,
|
|
122
|
+
err,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return [ ...found ];
|
|
128
|
+
|
|
129
|
+
}
|
|
71
130
|
|
|
72
131
|
|
|
73
132
|
// initialize if not already available
|
|
@@ -189,7 +248,8 @@ export default async function fetchPage(
|
|
|
189
248
|
|
|
190
249
|
}
|
|
191
250
|
|
|
192
|
-
return content;
|
|
251
|
+
return content;
|
|
252
|
+
|
|
193
253
|
|
|
194
254
|
},
|
|
195
255
|
});
|
|
@@ -218,9 +278,24 @@ export default async function fetchPage(
|
|
|
218
278
|
|
|
219
279
|
}
|
|
220
280
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
281
|
+
const explicitComponents = Array.isArray(about?.components) ? about.components : [];
|
|
282
|
+
const inferredComponents = [
|
|
283
|
+
...new Set([
|
|
284
|
+
...collectComponentsFromPageFiles(),
|
|
285
|
+
...(meta.pages[page]?.js
|
|
286
|
+
? extractUiRefsMemoized(meta.pages[page].js, {
|
|
287
|
+
namespace: componentNamespace,
|
|
288
|
+
includeDotAccess: true,
|
|
289
|
+
cacheContext: `site:${awesomenessRequest.site}|page:${page}|bundled-js`,
|
|
290
|
+
})
|
|
291
|
+
: []),
|
|
292
|
+
]),
|
|
293
|
+
];
|
|
294
|
+
const pageComponents = [ ...new Set([ ...explicitComponents, ...inferredComponents ]) ];
|
|
295
|
+
|
|
296
|
+
if (pageComponents.length) {
|
|
297
|
+
|
|
298
|
+
const allDependencies = componentDependencies(pageComponents, {
|
|
224
299
|
componentLocations: awesomenessConfig.componentLocations(awesomenessRequest),
|
|
225
300
|
namespace: componentNamespace,
|
|
226
301
|
showDetails,
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { readdirSync } from "fs";
|
|
2
2
|
import path from "path";
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* Case-insensitive real path resolver.
|
|
6
|
-
* Works correctly on Windows, macOS, and Linux/Docker.
|
|
7
|
-
*/
|
|
8
4
|
export default function resolveRealCasePath(inputPath, returnAbsolute = false) {
|
|
9
5
|
|
|
10
6
|
if (!inputPath) return null;
|