openyida 2026.7.19 → 2026.7.21
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/README.md +14 -0
- package/bin/yida.js +107 -18
- package/lib/app/create-app.js +12 -1
- package/lib/app/create-form/args.js +13 -0
- package/lib/app/create-form.js +154 -67
- package/lib/app/create-page.js +45 -9
- package/lib/app/get-schema.js +65 -14
- package/lib/app/import-app.js +92 -41
- package/lib/app/publish.js +289 -556
- package/lib/app/schema-field-resolution.js +370 -0
- package/lib/app/services/app-reader.js +85 -0
- package/lib/app/services/app-service.js +235 -0
- package/lib/app/services/canvas-page-compiler.js +91 -0
- package/lib/app/services/canvas-page-schema-builder.js +149 -0
- package/lib/app/services/field-bindings.js +68 -0
- package/lib/app/services/form-compiler.js +1922 -0
- package/lib/app/services/form-mode-service.js +182 -0
- package/lib/app/services/form-schema-patcher.js +333 -0
- package/lib/app/services/form-schema-reader.js +59 -0
- package/lib/app/services/form-service.js +379 -0
- package/lib/app/services/form-validation.js +562 -0
- package/lib/app/services/native-page-compiler.js +92 -0
- package/lib/app/services/native-page-schema-builder.js +428 -0
- package/lib/app/services/page-resource-service.js +185 -0
- package/lib/app/update-app.js +18 -6
- package/lib/auth/token-auth.js +34 -3
- package/lib/auth/token-store.js +22 -4
- package/lib/bridge/bridge.js +37 -5
- package/lib/core/agent-capabilities.js +5 -3
- package/lib/core/command-manifest.js +40 -0
- package/lib/core/doctor.js +15 -4
- package/lib/core/env-cmd.js +1 -1
- package/lib/core/env.js +7 -6
- package/lib/core/legacy-schema-guard.js +408 -0
- package/lib/core/locales/en.js +8 -46
- package/lib/core/locales/zh.js +8 -46
- package/lib/core/sample.js +1 -1
- package/lib/core/utils.js +334 -66
- package/lib/core/yida-client.js +104 -3
- package/lib/formula/evaluate.js +8 -66
- package/lib/formula/field-refs.js +83 -0
- package/lib/process/configure-process.js +44 -1992
- package/lib/process/create-process.js +54 -87
- package/lib/process/services/process-compiler.js +2056 -0
- package/lib/process/services/process-reader.js +232 -0
- package/lib/process/services/process-resource-service.js +571 -0
- package/lib/process/services/process-service.js +122 -0
- package/lib/process/services/process-stage-checkpoint.js +246 -0
- package/lib/report/append.js +7 -26
- package/lib/report/http.js +31 -5
- package/lib/report/index.js +10 -2
- package/lib/samples/yida-canvas-custom-page/business-list.canvas.jsx +63 -14
- package/lib/samples/yida-canvas-custom-page/dashboard-overview.canvas.jsx +176 -32
- package/lib/samples/yida-canvas-custom-page/data-management.canvas.jsx +228 -14
- package/lib/samples/yida-canvas-custom-page/split-pane-detail.canvas.jsx +204 -8
- package/lib/schema/adapters/app-adapter.js +210 -0
- package/lib/schema/adapters/form-adapter.js +1362 -0
- package/lib/schema/adapters/keys.js +19 -0
- package/lib/schema/adapters/page-adapter.js +566 -0
- package/lib/schema/adapters/process-adapter.js +519 -0
- package/lib/schema/applier.js +1878 -0
- package/lib/schema/apply-store.js +1083 -0
- package/lib/schema/command.js +645 -0
- package/lib/schema/dependency-graph.js +83 -0
- package/lib/schema/errors.js +481 -0
- package/lib/schema/hash.js +9 -0
- package/lib/schema/manifest-limits.js +177 -0
- package/lib/schema/manifest-loader.js +309 -0
- package/lib/schema/manifest-schema-v1.json +193 -0
- package/lib/schema/normalize-manifest.js +281 -0
- package/lib/schema/page-canvas-foundation.js +447 -0
- package/lib/schema/page-data-source-builder.js +561 -0
- package/lib/schema/page-foundation.js +556 -0
- package/lib/schema/page-source-loader.js +314 -0
- package/lib/schema/planner.js +691 -0
- package/lib/schema/remote-dispatch-boundary.js +39 -0
- package/lib/schema/remote-missing.js +21 -0
- package/lib/schema/remote-reader.js +189 -0
- package/lib/schema/resource-registry.js +157 -0
- package/lib/schema/server-revision.js +71 -0
- package/lib/schema/sort.js +28 -0
- package/lib/schema/state-store.js +589 -0
- package/package.json +2 -2
- package/scripts/postinstall.js +8 -12
- package/scripts/validate-package-size.js +1 -1
- package/yida-skills/SKILL.md +114 -29
- package/yida-skills/references/schema-as-code-phase1.md +99 -0
- package/yida-skills/references/setup-and-env.md +59 -59
- package/yida-skills/references/task-retrospective.md +6 -6
- package/yida-skills/skills/yida-app/SKILL.md +60 -14
- package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +18 -7
- package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +3 -3
- package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +7 -1
- package/yida-skills/skills/yida-create-app/SKILL.md +21 -3
- package/yida-skills/skills/yida-create-form-page/SKILL.md +19 -1
- package/yida-skills/skills/yida-create-page/SKILL.md +16 -3
- package/yida-skills/skills/yida-create-process/SKILL.md +100 -4
- package/yida-skills/skills/yida-custom-page/SKILL.md +19 -4
- package/yida-skills/skills/yida-dashboard/SKILL.md +1 -1
- package/yida-skills/skills/yida-dashboard/references/pitfalls.md +1 -1
- package/yida-skills/skills/yida-get-schema/SKILL.md +49 -5
- package/yida-skills/skills/yida-i18n/SKILL.md +1 -1
- package/yida-skills/skills/yida-integration/SKILL.md +7 -1
- package/yida-skills/skills/yida-login/SKILL.md +50 -99
- package/yida-skills/skills/yida-page-config/SKILL.md +7 -1
- package/yida-skills/skills/yida-page-uiux/references/app/blueprint.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/app/navigation-patterns.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/app/role-journey.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/dashboard/app-blueprint.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/dashboard/chart-contracts.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/dashboard/component-contracts.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/dashboard/layout-patterns.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/dashboard/theme-recipes.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/detail/object-narrative.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/detail/section-patterns.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/detail/timeline-and-related.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/landing/assets-workflow.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/landing/industry-playbooks.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/landing/research-levels.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/landing/section-patterns.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/list/drawer-detail.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/list/empty-loading-error.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/list/filter-patterns.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/list/table-patterns.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/scenes/screen.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/workbench/entry-patterns.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/workbench/portal-layouts.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/workbench/task-feed.md +0 -1
- package/yida-skills/skills/yida-page-uiux/workflow/output-decision-block.md +1 -1
- package/yida-skills/skills/yida-process-rule/SKILL.md +35 -1
- package/yida-skills/skills/yida-publish-page/SKILL.md +46 -4
- package/yida-skills/skills/yida-report/SKILL.md +7 -1
- package/yida-skills/skills-index.json +14 -46
- package/yida-skills/skills/large-file-write/SKILL.md +0 -93
- package/yida-skills/skills/large-file-write/references/write-patterns.md +0 -147
- package/yida-skills/skills/large-file-write/scripts/write.js +0 -157
- package/yida-skills/skills/sls-log-workbench/SKILL.md +0 -134
- package/yida-skills/skills/sls-log-workbench/references/workbench-reference.md +0 -130
- package/yida-skills/skills/sls-log-workbench/sls-query.js +0 -295
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const crypto = require('crypto');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { TextDecoder } = require('util');
|
|
7
|
+
const { schemaError } = require('./errors');
|
|
8
|
+
|
|
9
|
+
const PAGE_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
|
|
10
|
+
const TRUSTED_SOURCES = new WeakSet();
|
|
11
|
+
const NATIVE_SOURCE_PATTERN = /\.(?:oyd|openyida)\.jsx$|\.jsx?$|\.js$/i;
|
|
12
|
+
const CANVAS_SOURCE_PATTERN = /\.canvas\.(?:jsx?|tsx?)$/i;
|
|
13
|
+
const NATIVE_PAGE_PROFILE = 'native/default';
|
|
14
|
+
const CANVAS_PAGE_PROFILE = 'canvas/default';
|
|
15
|
+
|
|
16
|
+
function loadPageSource(sourcePath, options = {}) {
|
|
17
|
+
const fsImpl = options.fsImpl || fs;
|
|
18
|
+
const maxBytes = options.maxBytes === undefined ? PAGE_SOURCE_MAX_BYTES : options.maxBytes;
|
|
19
|
+
assertLoadInput(sourcePath, maxBytes);
|
|
20
|
+
|
|
21
|
+
const rootPath = path.resolve(options.workspaceRoot || process.cwd());
|
|
22
|
+
const rootRealPath = resolveRealPath(fsImpl, rootPath, 'SCHEMA_PAGE_SOURCE_PATH_UNSAFE');
|
|
23
|
+
const absolutePath = path.resolve(rootRealPath, sourcePath);
|
|
24
|
+
if (!isPathInside(rootRealPath, absolutePath)) {
|
|
25
|
+
sourceError('SCHEMA_PAGE_SOURCE_PATH_UNSAFE', 'Page source must stay inside the workspace trust root.');
|
|
26
|
+
}
|
|
27
|
+
assertNoSymlinkSegments(fsImpl, rootRealPath, absolutePath);
|
|
28
|
+
|
|
29
|
+
const initialRealPath = resolveRealPath(fsImpl, absolutePath, 'SCHEMA_PAGE_SOURCE_READ_FAILED');
|
|
30
|
+
if (!isPathInside(rootRealPath, initialRealPath)) {
|
|
31
|
+
sourceError('SCHEMA_PAGE_SOURCE_PATH_UNSAFE', 'Page source must stay inside the workspace trust root.');
|
|
32
|
+
}
|
|
33
|
+
const relativePath = normalizeRelativePath(path.relative(rootRealPath, initialRealPath));
|
|
34
|
+
const profile = resolvePageSourceProfile(relativePath);
|
|
35
|
+
|
|
36
|
+
let initialPathStat;
|
|
37
|
+
try {
|
|
38
|
+
initialPathStat = fsImpl.lstatSync(absolutePath);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
sourceError('SCHEMA_PAGE_SOURCE_READ_FAILED', 'Page source could not be read.');
|
|
41
|
+
}
|
|
42
|
+
if (initialPathStat.isSymbolicLink()) {
|
|
43
|
+
sourceError('SCHEMA_PAGE_SOURCE_PATH_UNSAFE', 'Page source must not be a symbolic link.');
|
|
44
|
+
}
|
|
45
|
+
if (!initialPathStat.isFile()) {
|
|
46
|
+
sourceError('SCHEMA_PAGE_SOURCE_INVALID', 'Page source must be a regular file.');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let fd;
|
|
50
|
+
try {
|
|
51
|
+
fd = fsImpl.openSync(absolutePath, resolveOpenFlags(fsImpl));
|
|
52
|
+
const before = fsImpl.fstatSync(fd);
|
|
53
|
+
if (!before || typeof before.isFile !== 'function' || !before.isFile()) {
|
|
54
|
+
sourceError('SCHEMA_PAGE_SOURCE_INVALID', 'Page source must be a regular file.');
|
|
55
|
+
}
|
|
56
|
+
if (!sameFileIdentityOrDefaultWindowsStatMatch(initialPathStat, before, fsImpl)) {
|
|
57
|
+
sourceError('SCHEMA_PAGE_SOURCE_READ_FAILED', 'Page source changed while it was being opened.');
|
|
58
|
+
}
|
|
59
|
+
assertPageSourceSize(before.size, maxBytes);
|
|
60
|
+
|
|
61
|
+
const buffer = readBounded(fsImpl, fd, maxBytes);
|
|
62
|
+
const after = fsImpl.fstatSync(fd);
|
|
63
|
+
if (
|
|
64
|
+
!sameFileIdentityOrDefaultWindowsStatMatch(before, after, fsImpl) ||
|
|
65
|
+
after.size !== before.size ||
|
|
66
|
+
buffer.length !== after.size
|
|
67
|
+
) {
|
|
68
|
+
sourceError('SCHEMA_PAGE_SOURCE_READ_FAILED', 'Page source changed while it was being read.');
|
|
69
|
+
}
|
|
70
|
+
assertPageSourceSize(after.size, maxBytes);
|
|
71
|
+
verifyPathAfterRead(fsImpl, rootRealPath, absolutePath, initialRealPath, after);
|
|
72
|
+
|
|
73
|
+
const source = decodeUtf8(buffer);
|
|
74
|
+
assertSafeText(source);
|
|
75
|
+
const record = Object.freeze({
|
|
76
|
+
byteLength: buffer.length,
|
|
77
|
+
profile,
|
|
78
|
+
relativePath,
|
|
79
|
+
source,
|
|
80
|
+
sourceHash: createSha256(source),
|
|
81
|
+
});
|
|
82
|
+
TRUSTED_SOURCES.add(record);
|
|
83
|
+
return record;
|
|
84
|
+
} catch (error) {
|
|
85
|
+
if (error && error.code && String(error.code).startsWith('SCHEMA_')) {
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
sourceError('SCHEMA_PAGE_SOURCE_READ_FAILED', 'Page source could not be read.');
|
|
89
|
+
} finally {
|
|
90
|
+
if (fd !== undefined) {
|
|
91
|
+
try {
|
|
92
|
+
fsImpl.closeSync(fd);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
// Preserve the original result or stable read error.
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function assertLoadInput(sourcePath, maxBytes) {
|
|
101
|
+
if (
|
|
102
|
+
typeof sourcePath !== 'string' ||
|
|
103
|
+
!sourcePath ||
|
|
104
|
+
sourcePath.includes('\0') ||
|
|
105
|
+
path.isAbsolute(sourcePath) ||
|
|
106
|
+
path.win32.isAbsolute(sourcePath) ||
|
|
107
|
+
sourcePath.split(/[\\/]+/).includes('..')
|
|
108
|
+
) {
|
|
109
|
+
sourceError('SCHEMA_PAGE_SOURCE_PATH_UNSAFE', 'Page source path must be workspace-relative.');
|
|
110
|
+
}
|
|
111
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > PAGE_SOURCE_MAX_BYTES) {
|
|
112
|
+
sourceError('SCHEMA_PAGE_SOURCE_INVALID', 'Page source size limit is invalid.');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function resolvePageSourceProfile(relativePath) {
|
|
117
|
+
if (CANVAS_SOURCE_PATTERN.test(relativePath)) {
|
|
118
|
+
return CANVAS_PAGE_PROFILE;
|
|
119
|
+
}
|
|
120
|
+
if (NATIVE_SOURCE_PATTERN.test(relativePath)) {
|
|
121
|
+
return NATIVE_PAGE_PROFILE;
|
|
122
|
+
}
|
|
123
|
+
sourceError('SCHEMA_PAGE_SOURCE_PROFILE_UNSUPPORTED', 'Page source must use a supported page source profile.');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function assertNoSymlinkSegments(fsImpl, rootRealPath, absolutePath) {
|
|
127
|
+
const relative = path.relative(rootRealPath, absolutePath);
|
|
128
|
+
if (!relative || relative.startsWith('..') || path.isAbsolute(relative)) {
|
|
129
|
+
sourceError('SCHEMA_PAGE_SOURCE_PATH_UNSAFE', 'Page source must stay inside the workspace trust root.');
|
|
130
|
+
}
|
|
131
|
+
let current = rootRealPath;
|
|
132
|
+
for (const segment of relative.split(path.sep)) {
|
|
133
|
+
current = path.join(current, segment);
|
|
134
|
+
let stat;
|
|
135
|
+
try {
|
|
136
|
+
stat = fsImpl.lstatSync(current);
|
|
137
|
+
} catch (error) {
|
|
138
|
+
sourceError('SCHEMA_PAGE_SOURCE_READ_FAILED', 'Page source could not be read.');
|
|
139
|
+
}
|
|
140
|
+
if (stat.isSymbolicLink()) {
|
|
141
|
+
sourceError('SCHEMA_PAGE_SOURCE_PATH_UNSAFE', 'Page source path must not traverse symbolic links.');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function verifyPathAfterRead(fsImpl, rootRealPath, absolutePath, initialRealPath, fdStat) {
|
|
147
|
+
assertNoSymlinkSegments(fsImpl, rootRealPath, absolutePath);
|
|
148
|
+
const currentRealPath = resolveRealPath(fsImpl, absolutePath, 'SCHEMA_PAGE_SOURCE_READ_FAILED');
|
|
149
|
+
if (
|
|
150
|
+
currentRealPath !== initialRealPath ||
|
|
151
|
+
!isPathInside(rootRealPath, currentRealPath)
|
|
152
|
+
) {
|
|
153
|
+
sourceError('SCHEMA_PAGE_SOURCE_READ_FAILED', 'Page source changed while it was being read.');
|
|
154
|
+
}
|
|
155
|
+
let currentPathStat;
|
|
156
|
+
try {
|
|
157
|
+
currentPathStat = fsImpl.lstatSync(absolutePath);
|
|
158
|
+
} catch (error) {
|
|
159
|
+
sourceError('SCHEMA_PAGE_SOURCE_READ_FAILED', 'Page source changed while it was being read.');
|
|
160
|
+
}
|
|
161
|
+
if (
|
|
162
|
+
currentPathStat.isSymbolicLink() ||
|
|
163
|
+
!sameFileIdentityOrDefaultWindowsStatMatch(currentPathStat, fdStat, fsImpl)
|
|
164
|
+
) {
|
|
165
|
+
sourceError('SCHEMA_PAGE_SOURCE_READ_FAILED', 'Page source changed while it was being read.');
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function readBounded(fsImpl, fd, maxBytes) {
|
|
170
|
+
const buffer = Buffer.alloc(maxBytes + 1);
|
|
171
|
+
let totalRead = 0;
|
|
172
|
+
while (totalRead < buffer.length) {
|
|
173
|
+
const bytesRead = fsImpl.readSync(fd, buffer, totalRead, buffer.length - totalRead, null);
|
|
174
|
+
if (bytesRead === 0) {
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
totalRead += bytesRead;
|
|
178
|
+
if (totalRead > maxBytes) {
|
|
179
|
+
sourceError('SCHEMA_PAGE_SOURCE_TOO_LARGE', 'Page source exceeds the maximum supported size.', {
|
|
180
|
+
limit: maxBytes,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return buffer.subarray(0, totalRead);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function assertPageSourceSize(size, maxBytes) {
|
|
188
|
+
if (!Number.isSafeInteger(size) || size < 0) {
|
|
189
|
+
sourceError('SCHEMA_PAGE_SOURCE_READ_FAILED', 'Page source size is invalid.');
|
|
190
|
+
}
|
|
191
|
+
if (size > maxBytes) {
|
|
192
|
+
sourceError('SCHEMA_PAGE_SOURCE_TOO_LARGE', 'Page source exceeds the maximum supported size.', {
|
|
193
|
+
limit: maxBytes,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function decodeUtf8(buffer) {
|
|
199
|
+
try {
|
|
200
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(buffer);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
sourceError('SCHEMA_PAGE_SOURCE_INVALID', 'Page source must be valid UTF-8 text.');
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function assertSafeText(source) {
|
|
207
|
+
for (let index = 0; index < source.length; index++) {
|
|
208
|
+
const code = source.charCodeAt(index);
|
|
209
|
+
if ((code < 32 && code !== 9 && code !== 10 && code !== 13) || code === 127) {
|
|
210
|
+
sourceError('SCHEMA_PAGE_SOURCE_INVALID', 'Page source contains unsafe control text.');
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function resolveOpenFlags(fsImpl) {
|
|
216
|
+
const constants = fsImpl.constants || fs.constants;
|
|
217
|
+
let flags = constants.O_RDONLY;
|
|
218
|
+
if (typeof constants.O_NOFOLLOW === 'number') {
|
|
219
|
+
flags |= constants.O_NOFOLLOW;
|
|
220
|
+
}
|
|
221
|
+
return flags;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function resolveRealPath(fsImpl, targetPath, errorCode) {
|
|
225
|
+
try {
|
|
226
|
+
return fsImpl.realpathSync(targetPath);
|
|
227
|
+
} catch (error) {
|
|
228
|
+
sourceError(errorCode, 'Page source path could not be verified.');
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function sameFileIdentity(left, right) {
|
|
233
|
+
return !!(
|
|
234
|
+
left && right &&
|
|
235
|
+
isReliableFileIdentityValue(left.dev) &&
|
|
236
|
+
isReliableFileIdentityValue(left.ino) &&
|
|
237
|
+
isReliableFileIdentityValue(right.dev) &&
|
|
238
|
+
isReliableFileIdentityValue(right.ino) &&
|
|
239
|
+
left.dev === right.dev &&
|
|
240
|
+
left.ino === right.ino
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function sameFileIdentityOrDefaultWindowsStatMatch(left, right, fsImpl) {
|
|
245
|
+
if (sameFileIdentity(left, right)) {
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
if (process.platform !== 'win32' || fsImpl !== fs) {
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
return sameRegularFileStatFingerprint(left, right);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function sameRegularFileStatFingerprint(left, right) {
|
|
255
|
+
return !!(
|
|
256
|
+
left && right &&
|
|
257
|
+
statLooksLikeRegularFile(left) &&
|
|
258
|
+
statLooksLikeRegularFile(right) &&
|
|
259
|
+
left.size === right.size &&
|
|
260
|
+
sameStatTime(left.mtimeMs, right.mtimeMs) &&
|
|
261
|
+
sameStatTime(left.ctimeMs, right.ctimeMs) &&
|
|
262
|
+
sameStatTime(left.birthtimeMs, right.birthtimeMs)
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function statLooksLikeRegularFile(stat) {
|
|
267
|
+
return typeof stat.isFile !== 'function' || stat.isFile();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function sameStatTime(left, right) {
|
|
271
|
+
if (typeof left !== 'number' || typeof right !== 'number') {
|
|
272
|
+
return left === right;
|
|
273
|
+
}
|
|
274
|
+
return Math.abs(left - right) <= 1;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function isReliableFileIdentityValue(value) {
|
|
278
|
+
return (
|
|
279
|
+
(Number.isSafeInteger(value) && value >= 0) ||
|
|
280
|
+
(typeof value === 'bigint' && value >= 0n)
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function isPathInside(rootPath, targetPath) {
|
|
285
|
+
const relative = path.relative(rootPath, targetPath);
|
|
286
|
+
return relative === '' || (!!relative && !relative.startsWith('..') && !path.isAbsolute(relative));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function normalizeRelativePath(value) {
|
|
290
|
+
return value.split(path.sep).join('/');
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function createSha256(value) {
|
|
294
|
+
return 'sha256:' + crypto.createHash('sha256').update(value).digest('hex');
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function isLoadedPageSource(value) {
|
|
298
|
+
return !!(value && typeof value === 'object' && TRUSTED_SOURCES.has(value));
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function sourceError(code, message, details) {
|
|
302
|
+
throw schemaError(code, message, details ? { details } : undefined);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
module.exports = {
|
|
306
|
+
CANVAS_PAGE_PROFILE,
|
|
307
|
+
CANVAS_SOURCE_PATTERN,
|
|
308
|
+
NATIVE_PAGE_PROFILE,
|
|
309
|
+
NATIVE_SOURCE_PATTERN,
|
|
310
|
+
PAGE_SOURCE_MAX_BYTES,
|
|
311
|
+
isLoadedPageSource,
|
|
312
|
+
loadPageSource,
|
|
313
|
+
resolvePageSourceProfile,
|
|
314
|
+
};
|