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
package/lib/core/yida-client.js
CHANGED
|
@@ -43,7 +43,9 @@ function isUsableAuthData(authData) {
|
|
|
43
43
|
if (authData.auth_mode === 'token' || authData.authMode === 'token') {
|
|
44
44
|
return true;
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
const cookies = Array.isArray(authData.cookies) ? authData.cookies : [];
|
|
47
|
+
const csrfToken = authData.csrf_token || authData.csrfToken || authData._csrf_token;
|
|
48
|
+
return cookies.length > 0 && typeof csrfToken === 'string' && csrfToken.length > 0;
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
function createAuthRef(authData) {
|
|
@@ -53,7 +55,7 @@ function createAuthRef(authData) {
|
|
|
53
55
|
: triggerLogin();
|
|
54
56
|
const safeAuthData = loadedAuthData || {};
|
|
55
57
|
|
|
56
|
-
|
|
58
|
+
const authRef = {
|
|
57
59
|
baseUrl: resolveBaseUrl(safeAuthData),
|
|
58
60
|
authData: safeAuthData,
|
|
59
61
|
authMode: safeAuthData.auth_mode || safeAuthData.authMode || '',
|
|
@@ -61,6 +63,12 @@ function createAuthRef(authData) {
|
|
|
61
63
|
corpId: safeAuthData.corp_id || '',
|
|
62
64
|
userId: safeAuthData.user_id || '',
|
|
63
65
|
};
|
|
66
|
+
if (Array.isArray(safeAuthData.cookies)) {
|
|
67
|
+
authRef.cookieData = safeAuthData;
|
|
68
|
+
authRef.cookies = safeAuthData.cookies;
|
|
69
|
+
authRef.csrfToken = safeAuthData.csrf_token || safeAuthData.csrfToken || safeAuthData._csrf_token || '';
|
|
70
|
+
}
|
|
71
|
+
return authRef;
|
|
64
72
|
}
|
|
65
73
|
|
|
66
74
|
function isTokenAuthRef(authRef) {
|
|
@@ -80,6 +88,22 @@ function isTokenAuthRef(authRef) {
|
|
|
80
88
|
return authMode === 'token' || authSource === 'token';
|
|
81
89
|
}
|
|
82
90
|
|
|
91
|
+
function isCookieAuthRef(authRef) {
|
|
92
|
+
if (!authRef) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
const authData = authRef.authData || authRef.cookieData || {};
|
|
96
|
+
const authMode = authRef.authMode || authRef.auth_mode || authData.auth_mode || authData.authMode;
|
|
97
|
+
const authSource = authRef.authSource || authRef.auth_source || authData.auth_source || authData.authSource;
|
|
98
|
+
return (
|
|
99
|
+
authMode === 'env' ||
|
|
100
|
+
authMode === 'cookie' ||
|
|
101
|
+
authSource === 'env' ||
|
|
102
|
+
authSource === 'cookie' ||
|
|
103
|
+
Array.isArray(authRef.cookies)
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
83
107
|
function isAuthRefReady(authRef) {
|
|
84
108
|
if (!authRef) {
|
|
85
109
|
return false;
|
|
@@ -87,7 +111,14 @@ function isAuthRefReady(authRef) {
|
|
|
87
111
|
if (isTokenAuthRef(authRef)) {
|
|
88
112
|
return true;
|
|
89
113
|
}
|
|
90
|
-
return
|
|
114
|
+
return (
|
|
115
|
+
isCookieAuthRef(authRef) &&
|
|
116
|
+
typeof authRef.baseUrl === 'string' &&
|
|
117
|
+
authRef.baseUrl.length > 0 &&
|
|
118
|
+
typeof authRef.csrfToken === 'string' &&
|
|
119
|
+
authRef.csrfToken.length > 0 &&
|
|
120
|
+
Array.isArray(authRef.cookies)
|
|
121
|
+
);
|
|
91
122
|
}
|
|
92
123
|
|
|
93
124
|
class YidaClient {
|
|
@@ -117,6 +148,20 @@ class YidaClient {
|
|
|
117
148
|
);
|
|
118
149
|
}
|
|
119
150
|
|
|
151
|
+
async getOnce(requestPath, queryParams, options) {
|
|
152
|
+
const ref = requireReadAuth(this.authRef);
|
|
153
|
+
const resolvedRequestPath = typeof requestPath === 'function'
|
|
154
|
+
? requestPath(ref)
|
|
155
|
+
: requestPath;
|
|
156
|
+
const resolvedQueryParams = typeof queryParams === 'function'
|
|
157
|
+
? queryParams(ref)
|
|
158
|
+
: queryParams;
|
|
159
|
+
if (options === undefined) {
|
|
160
|
+
return httpGet(ref.baseUrl, resolvedRequestPath, resolvedQueryParams || null, ref.cookies);
|
|
161
|
+
}
|
|
162
|
+
return httpGet(ref.baseUrl, resolvedRequestPath, resolvedQueryParams || null, ref.cookies, options);
|
|
163
|
+
}
|
|
164
|
+
|
|
120
165
|
async postForm(requestPath, bodyParams, options) {
|
|
121
166
|
return requestWithAutoLogin(
|
|
122
167
|
(ref) => {
|
|
@@ -138,6 +183,23 @@ class YidaClient {
|
|
|
138
183
|
);
|
|
139
184
|
}
|
|
140
185
|
|
|
186
|
+
async postFormOnce(requestPath, bodyParams, options) {
|
|
187
|
+
const ref = requireOneShotAuth(this.authRef);
|
|
188
|
+
const resolvedRequestPath = typeof requestPath === 'function'
|
|
189
|
+
? requestPath(ref)
|
|
190
|
+
: requestPath;
|
|
191
|
+
const resolvedBodyParams = typeof bodyParams === 'function'
|
|
192
|
+
? bodyParams(ref)
|
|
193
|
+
: bodyParams;
|
|
194
|
+
const postData = typeof resolvedBodyParams === 'string'
|
|
195
|
+
? resolvedBodyParams
|
|
196
|
+
: querystring.stringify(resolvedBodyParams || {});
|
|
197
|
+
if (options === undefined) {
|
|
198
|
+
return httpPost(ref.baseUrl, resolvedRequestPath, postData, ref.cookies);
|
|
199
|
+
}
|
|
200
|
+
return httpPost(ref.baseUrl, resolvedRequestPath, postData, ref.cookies, options);
|
|
201
|
+
}
|
|
202
|
+
|
|
141
203
|
async postJson(requestPath, bodyParams, options) {
|
|
142
204
|
return requestWithAutoLogin(
|
|
143
205
|
(ref) => {
|
|
@@ -178,6 +240,44 @@ class YidaClient {
|
|
|
178
240
|
}
|
|
179
241
|
}
|
|
180
242
|
|
|
243
|
+
function requireOneShotAuth(authRef) {
|
|
244
|
+
if (!authRef || typeof authRef.baseUrl !== 'string' || authRef.baseUrl.length === 0) {
|
|
245
|
+
const error = new Error('Schema write authentication is not ready.');
|
|
246
|
+
error.code = 'YIDA_WRITE_AUTH_NOT_READY';
|
|
247
|
+
throw error;
|
|
248
|
+
}
|
|
249
|
+
if (isTokenAuthRef(authRef)) {
|
|
250
|
+
return authRef;
|
|
251
|
+
}
|
|
252
|
+
if (
|
|
253
|
+
typeof authRef.csrfToken !== 'string' ||
|
|
254
|
+
authRef.csrfToken.length === 0 ||
|
|
255
|
+
!Array.isArray(authRef.cookies)
|
|
256
|
+
) {
|
|
257
|
+
const error = new Error('Schema write authentication is not ready.');
|
|
258
|
+
error.code = 'YIDA_WRITE_AUTH_NOT_READY';
|
|
259
|
+
throw error;
|
|
260
|
+
}
|
|
261
|
+
return authRef;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function requireReadAuth(authRef) {
|
|
265
|
+
if (!authRef || typeof authRef.baseUrl !== 'string' || authRef.baseUrl.length === 0) {
|
|
266
|
+
const error = new Error('Yida read authentication is not ready.');
|
|
267
|
+
error.code = 'YIDA_READ_AUTH_NOT_READY';
|
|
268
|
+
throw error;
|
|
269
|
+
}
|
|
270
|
+
if (isTokenAuthRef(authRef)) {
|
|
271
|
+
return authRef;
|
|
272
|
+
}
|
|
273
|
+
if (!Array.isArray(authRef.cookies)) {
|
|
274
|
+
const error = new Error('Yida read authentication is not ready.');
|
|
275
|
+
error.code = 'YIDA_READ_AUTH_NOT_READY';
|
|
276
|
+
throw error;
|
|
277
|
+
}
|
|
278
|
+
return authRef;
|
|
279
|
+
}
|
|
280
|
+
|
|
181
281
|
function createYidaClient(options = {}) {
|
|
182
282
|
return new YidaClient(options);
|
|
183
283
|
}
|
|
@@ -188,6 +288,7 @@ module.exports = {
|
|
|
188
288
|
createAuthRef,
|
|
189
289
|
createYidaClient,
|
|
190
290
|
isAuthRefReady,
|
|
291
|
+
isCookieAuthRef,
|
|
191
292
|
isTokenAuthRef,
|
|
192
293
|
unwrapYidaResponse,
|
|
193
294
|
};
|
package/lib/formula/evaluate.js
CHANGED
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const { throwCommandError, throwUsage } = require('../core/command-errors');
|
|
5
5
|
const path = require('path');
|
|
6
|
+
const {
|
|
7
|
+
normalizeFormulaFieldRefs,
|
|
8
|
+
normalizeSubtableFieldId,
|
|
9
|
+
stripSubtableFieldPrefix,
|
|
10
|
+
} = require('./field-refs');
|
|
6
11
|
|
|
7
12
|
const KNOWN_FUNCTIONS = new Set([
|
|
8
13
|
'ABS',
|
|
@@ -49,12 +54,6 @@ const KNOWN_FUNCTIONS = new Set([
|
|
|
49
54
|
'YEAR',
|
|
50
55
|
]);
|
|
51
56
|
|
|
52
|
-
// Subtable child fields are stored flat in the schema (get-schema / save never
|
|
53
|
-
// emit a "tableField_xxx.xxx" form), and Yida formulas reference them by their
|
|
54
|
-
// plain fieldId. A "tableField_xxx." prefix inside #{...} is therefore always
|
|
55
|
-
// an invalid reference that the web platform cannot resolve.
|
|
56
|
-
const SUBTABLE_FIELD_PREFIX_PATTERN = /^tableField_[A-Za-z0-9]+\./;
|
|
57
|
-
|
|
58
57
|
const CHINESE_PUNCTUATION = {
|
|
59
58
|
',': ',',
|
|
60
59
|
';': ',',
|
|
@@ -164,64 +163,6 @@ function collectSchemaFieldIds(value) {
|
|
|
164
163
|
return fieldIds;
|
|
165
164
|
}
|
|
166
165
|
|
|
167
|
-
// Rewrite every `#{tableField_xxx.field}` reference inside a string to the
|
|
168
|
-
// canonical `#{field}` form. Returns the corrected string plus how many refs
|
|
169
|
-
// were fixed. Only the exact `#{tableField_<alnum>.<rest>}` shape is touched,
|
|
170
|
-
// so unrelated text (e.g. a JS regex like `#{1,3}`) is left untouched.
|
|
171
|
-
function stripSubtableFieldPrefix(str) {
|
|
172
|
-
if (typeof str !== 'string' || str.indexOf('#{') === -1) {
|
|
173
|
-
return { value: str, count: 0 };
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
let count = 0;
|
|
177
|
-
const value = str.replace(/#\{([^}]*)\}/g, (whole, inner) => {
|
|
178
|
-
const trimmed = inner.trim();
|
|
179
|
-
if (SUBTABLE_FIELD_PREFIX_PATTERN.test(trimmed)) {
|
|
180
|
-
count += 1;
|
|
181
|
-
return `#{${trimmed.replace(SUBTABLE_FIELD_PREFIX_PATTERN, '')}}`;
|
|
182
|
-
}
|
|
183
|
-
return whole;
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
return { value, count };
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Recursively walk any schema node (object/array) and normalize subtable
|
|
190
|
-
// prefixes in every string value in place. Returns the total number of refs
|
|
191
|
-
// fixed. Covers formula, complexValue.formula, expression, linkage, and any
|
|
192
|
-
// other string-valued property uniformly.
|
|
193
|
-
function normalizeFormulaFieldRefs(node) {
|
|
194
|
-
let total = 0;
|
|
195
|
-
|
|
196
|
-
function visit(parent, key) {
|
|
197
|
-
const current = parent[key];
|
|
198
|
-
if (typeof current === 'string') {
|
|
199
|
-
const { value, count } = stripSubtableFieldPrefix(current);
|
|
200
|
-
if (count > 0) {
|
|
201
|
-
parent[key] = value;
|
|
202
|
-
total += count;
|
|
203
|
-
}
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
if (Array.isArray(current)) {
|
|
207
|
-
for (let i = 0; i < current.length; i++) {
|
|
208
|
-
visit(current, i);
|
|
209
|
-
}
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
if (current && typeof current === 'object') {
|
|
213
|
-
for (const childKey of Object.keys(current)) {
|
|
214
|
-
visit(current, childKey);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (node && typeof node === 'object') {
|
|
220
|
-
visit({ root: node }, 'root');
|
|
221
|
-
}
|
|
222
|
-
return total;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
166
|
function scanOutsideStrings(formula, callback) {
|
|
226
167
|
let quote = '';
|
|
227
168
|
let escaped = false;
|
|
@@ -355,8 +296,9 @@ function collectFieldRefs(formula, diagnostics) {
|
|
|
355
296
|
{ fieldId, index }
|
|
356
297
|
));
|
|
357
298
|
}
|
|
358
|
-
|
|
359
|
-
|
|
299
|
+
const normalizedFieldId = normalizeSubtableFieldId(fieldId);
|
|
300
|
+
if (normalizedFieldId.changed) {
|
|
301
|
+
const suggestion = normalizedFieldId.value;
|
|
360
302
|
diagnostics.push(createDiagnostic(
|
|
361
303
|
'error',
|
|
362
304
|
'field_ref_subtable_prefix',
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Subtable child fields are stored flat in the schema (get-schema / save never
|
|
4
|
+
// emit a "tableField_xxx.xxx" form), and Yida formulas reference them by their
|
|
5
|
+
// plain fieldId. A "tableField_xxx." prefix inside #{...} is therefore always
|
|
6
|
+
// an invalid reference that the web platform cannot resolve.
|
|
7
|
+
const SUBTABLE_FIELD_PREFIX_PATTERN = /^tableField_[A-Za-z0-9]+\./;
|
|
8
|
+
|
|
9
|
+
function normalizeSubtableFieldId(fieldId) {
|
|
10
|
+
const value = String(fieldId || '');
|
|
11
|
+
if (!SUBTABLE_FIELD_PREFIX_PATTERN.test(value)) {
|
|
12
|
+
return { value, changed: false };
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
value: value.replace(SUBTABLE_FIELD_PREFIX_PATTERN, ''),
|
|
16
|
+
changed: true,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Rewrite every `#{tableField_xxx.field}` reference inside a string to the
|
|
21
|
+
// canonical `#{field}` form. Returns the corrected string plus how many refs
|
|
22
|
+
// were fixed. Only the exact `#{tableField_<alnum>.<rest>}` shape is touched,
|
|
23
|
+
// so unrelated text (e.g. a JS regex like `#{1,3}`) is left untouched.
|
|
24
|
+
function stripSubtableFieldPrefix(str) {
|
|
25
|
+
if (typeof str !== 'string' || str.indexOf('#{') === -1) {
|
|
26
|
+
return { value: str, count: 0 };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let count = 0;
|
|
30
|
+
const value = str.replace(/#\{([^}]*)\}/g, (whole, inner) => {
|
|
31
|
+
const trimmed = inner.trim();
|
|
32
|
+
const normalized = normalizeSubtableFieldId(trimmed);
|
|
33
|
+
if (normalized.changed) {
|
|
34
|
+
count += 1;
|
|
35
|
+
return `#{${normalized.value}}`;
|
|
36
|
+
}
|
|
37
|
+
return whole;
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return { value, count };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Recursively walk any schema node (object/array) and normalize subtable
|
|
44
|
+
// prefixes in every string value in place. Returns the total number of refs
|
|
45
|
+
// fixed. Covers formula, complexValue.formula, expression, linkage, and any
|
|
46
|
+
// other string-valued property uniformly.
|
|
47
|
+
function normalizeFormulaFieldRefs(node) {
|
|
48
|
+
let total = 0;
|
|
49
|
+
|
|
50
|
+
function visit(parent, key) {
|
|
51
|
+
const current = parent[key];
|
|
52
|
+
if (typeof current === 'string') {
|
|
53
|
+
const { value, count } = stripSubtableFieldPrefix(current);
|
|
54
|
+
if (count > 0) {
|
|
55
|
+
parent[key] = value;
|
|
56
|
+
total += count;
|
|
57
|
+
}
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (Array.isArray(current)) {
|
|
61
|
+
for (let i = 0; i < current.length; i++) {
|
|
62
|
+
visit(current, i);
|
|
63
|
+
}
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (current && typeof current === 'object') {
|
|
67
|
+
for (const childKey of Object.keys(current)) {
|
|
68
|
+
visit(current, childKey);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (node && typeof node === 'object') {
|
|
74
|
+
visit({ root: node }, 'root');
|
|
75
|
+
}
|
|
76
|
+
return total;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
module.exports = {
|
|
80
|
+
normalizeFormulaFieldRefs,
|
|
81
|
+
normalizeSubtableFieldId,
|
|
82
|
+
stripSubtableFieldPrefix,
|
|
83
|
+
};
|