openxiangda 1.0.134 → 1.0.136
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 +6 -0
- package/lib/cli.js +947 -16
- package/lib/design-gates.js +40 -10
- package/lib/sdd.js +777 -0
- package/lib/workspace-init.js +3 -0
- package/openxiangda-skills/SKILL.md +11 -1
- package/openxiangda-skills/references/best-practices.md +32 -5
- package/openxiangda-skills/references/openxiangda-api.md +32 -6
- package/openxiangda-skills/references/pages/page-sdk.md +3 -0
- package/openxiangda-skills/references/pages/publish-flow.md +16 -0
- package/openxiangda-skills/references/permission-design-patterns.md +216 -0
- package/openxiangda-skills/references/permissions-settings.md +58 -0
- package/openxiangda-skills/references/platform-data-model.md +19 -4
- package/openxiangda-skills/references/resource-manifest-cheatsheet.md +32 -1
- package/openxiangda-skills/skills/openxiangda-architecture-design/SKILL.md +8 -0
- package/openxiangda-skills/skills/openxiangda-core/SKILL.md +2 -0
- package/openxiangda-skills/skills/openxiangda-permission-settings/SKILL.md +38 -1
- package/package.json +2 -1
- package/packages/sdk/dist/{ProcessPreview-Dfc4-wIq.d.mts → ProcessPreview-Ci8_UsbN.d.mts} +4 -0
- package/packages/sdk/dist/{ProcessPreview-Dfc4-wIq.d.ts → ProcessPreview-Ci8_UsbN.d.ts} +4 -0
- package/packages/sdk/dist/build/index.cjs.map +1 -1
- package/packages/sdk/dist/build/index.d.mts +7 -0
- package/packages/sdk/dist/build/index.d.ts +7 -0
- package/packages/sdk/dist/build/index.mjs.map +1 -1
- package/packages/sdk/dist/components/index.cjs +32 -4
- package/packages/sdk/dist/components/index.cjs.map +1 -1
- package/packages/sdk/dist/components/index.d.mts +8 -2
- package/packages/sdk/dist/components/index.d.ts +8 -2
- package/packages/sdk/dist/components/index.mjs +32 -4
- package/packages/sdk/dist/components/index.mjs.map +1 -1
- package/packages/sdk/dist/runtime/index.cjs +181 -28
- package/packages/sdk/dist/runtime/index.cjs.map +1 -1
- package/packages/sdk/dist/runtime/index.d.mts +2 -2
- package/packages/sdk/dist/runtime/index.d.ts +2 -2
- package/packages/sdk/dist/runtime/index.mjs +181 -28
- package/packages/sdk/dist/runtime/index.mjs.map +1 -1
- package/packages/sdk/dist/runtime/react.cjs +152 -25
- package/packages/sdk/dist/runtime/react.cjs.map +1 -1
- package/packages/sdk/dist/runtime/react.d.mts +57 -4
- package/packages/sdk/dist/runtime/react.d.ts +57 -4
- package/packages/sdk/dist/runtime/react.mjs +152 -25
- package/packages/sdk/dist/runtime/react.mjs.map +1 -1
- package/templates/openxiangda-react-spa/.cursor/rules/openxiangda.mdc +8 -1
- package/templates/openxiangda-react-spa/.qoder/rules/openxiangda.md +8 -1
- package/templates/openxiangda-react-spa/AGENTS.md +9 -1
- package/templates/openxiangda-react-spa/app-workspace.config.ts +14 -0
- package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda-resources.mdc +5 -1
- package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda.mdc +7 -1
- package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda-resources.md +6 -0
- package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda.md +7 -1
- package/templates/sy-lowcode-app-workspace/AGENTS.md +10 -1
- package/templates/sy-lowcode-app-workspace/app-workspace.config.ts +14 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/README.md +3 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/access-governance.md +239 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/catalog.json +6 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/decision-guide.md +25 -1
- package/templates/sy-lowcode-app-workspace/src/types/app-workspace.types.ts +12 -0
|
@@ -101,6 +101,7 @@ var usePageSdkStore = () => {
|
|
|
101
101
|
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
102
102
|
var isSearchRuleLike = (value) => isRecord(value) && typeof value.key === "string" && (value.componentName === void 0 || typeof value.componentName === "string");
|
|
103
103
|
var isBlobLike = (value) => typeof Blob !== "undefined" && value instanceof Blob;
|
|
104
|
+
var nowMs = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
104
105
|
var normalizeMethod = (value) => {
|
|
105
106
|
const method = String(value || "get").toLowerCase();
|
|
106
107
|
if (method === "get" || method === "post" || method === "put" || method === "delete" || method === "patch") {
|
|
@@ -359,6 +360,26 @@ var normalizeJsonResponse = (rawResponse) => {
|
|
|
359
360
|
raw: rawResponse
|
|
360
361
|
};
|
|
361
362
|
};
|
|
363
|
+
var createMissingFormInstanceIdError = (response) => {
|
|
364
|
+
const error = new Error(
|
|
365
|
+
"\u4FDD\u5B58\u63A5\u53E3\u672A\u8FD4\u56DE formInstId/formInstanceId\u3002\u4FDD\u5B58\u63A5\u53E3\u53EA\u627F\u8BFA\u8FD4\u56DE\u5B9E\u4F8B\u6807\u8BC6\u548C\u5DF2\u751F\u6210\u7684\u6D41\u6C34\u53F7\uFF1B\u5982\u9700\u5B8C\u6574\u884C\u6570\u636E\u3001\u516C\u5F0F\u56DE\u586B\u6216\u5176\u4ED6\u670D\u52A1\u7AEF\u5B57\u6BB5\uFF0C\u8BF7\u5728\u4FDD\u5B58\u6210\u529F\u540E\u663E\u5F0F\u8C03\u7528 sdk.form.getDetail\u3002"
|
|
366
|
+
);
|
|
367
|
+
error.response = response;
|
|
368
|
+
error.raw = response.raw;
|
|
369
|
+
return error;
|
|
370
|
+
};
|
|
371
|
+
var isRequestTracingEnabled = (context, options) => {
|
|
372
|
+
if (options.trace) return true;
|
|
373
|
+
const env = context.env || {};
|
|
374
|
+
const value = env.OPENXIANGDA_REQUEST_TRACE ?? env.openxiangdaRequestTrace ?? env.requestTrace;
|
|
375
|
+
return value === true || value === "true" || value === "1";
|
|
376
|
+
};
|
|
377
|
+
var buildRequestDedupeKey = (payload) => JSON.stringify({
|
|
378
|
+
path: payload.path,
|
|
379
|
+
method: payload.method,
|
|
380
|
+
query: payload.query || "",
|
|
381
|
+
headers: payload.headers || {}
|
|
382
|
+
});
|
|
362
383
|
var normalizeBinaryResponse = (rawResponse) => {
|
|
363
384
|
if (isRecord(rawResponse) && isBlobLike(rawResponse.blob)) {
|
|
364
385
|
return rawResponse;
|
|
@@ -430,12 +451,90 @@ var pickCreatedFormInstanceId = (value) => {
|
|
|
430
451
|
return text || void 0;
|
|
431
452
|
}
|
|
432
453
|
if (!isRecord(value)) return void 0;
|
|
433
|
-
const direct = value.formInstId || value.formInstanceId || value.instanceId || value.id
|
|
434
|
-
if (direct !== value) {
|
|
435
|
-
|
|
454
|
+
const direct = value.formInstId || value.formInstanceId || value.instanceId || value.id;
|
|
455
|
+
if (direct !== value && direct !== void 0 && direct !== null) {
|
|
456
|
+
const picked = pickCreatedFormInstanceId(direct);
|
|
457
|
+
if (picked) return picked;
|
|
458
|
+
}
|
|
459
|
+
for (const candidate of [value.result, value.data, value.raw]) {
|
|
460
|
+
const picked = pickCreatedFormInstanceId(candidate);
|
|
461
|
+
if (picked) return picked;
|
|
462
|
+
}
|
|
463
|
+
return void 0;
|
|
464
|
+
};
|
|
465
|
+
var pickCreatedProcessInstanceId = (value) => {
|
|
466
|
+
if (!value || typeof value === "string") return void 0;
|
|
467
|
+
if (!isRecord(value)) return void 0;
|
|
468
|
+
const direct = value.processInstanceId || value.processInstId;
|
|
469
|
+
if (typeof direct === "string" && direct.trim()) return direct.trim();
|
|
470
|
+
for (const candidate of [value.result, value.data, value.raw]) {
|
|
471
|
+
const picked = pickCreatedProcessInstanceId(candidate);
|
|
472
|
+
if (picked) return picked;
|
|
473
|
+
}
|
|
474
|
+
return void 0;
|
|
475
|
+
};
|
|
476
|
+
var pickSerialNumbers = (value) => {
|
|
477
|
+
if (!value || typeof value === "string" || !isRecord(value)) return void 0;
|
|
478
|
+
const direct = value.serialNumbers;
|
|
479
|
+
if (isRecord(direct)) {
|
|
480
|
+
const entries = Object.entries(direct).map(([key, item]) => [key, String(item ?? "").trim()]).filter(([, item]) => Boolean(item));
|
|
481
|
+
if (entries.length > 0) return Object.fromEntries(entries);
|
|
482
|
+
}
|
|
483
|
+
for (const candidate of [value.result, value.data, value.raw]) {
|
|
484
|
+
const picked = pickSerialNumbers(candidate);
|
|
485
|
+
if (picked) return picked;
|
|
486
|
+
}
|
|
487
|
+
return void 0;
|
|
488
|
+
};
|
|
489
|
+
var pickSerialNumber = (value) => {
|
|
490
|
+
if (!value || typeof value === "string") return void 0;
|
|
491
|
+
if (!isRecord(value)) return void 0;
|
|
492
|
+
const direct = value.serialNumber || value.serialNo || value.sequenceNo;
|
|
493
|
+
if (typeof direct === "string" && direct.trim()) return direct.trim();
|
|
494
|
+
const serialNumbers = pickSerialNumbers(value);
|
|
495
|
+
if (serialNumbers) {
|
|
496
|
+
const first = Object.values(serialNumbers)[0];
|
|
497
|
+
if (first) return first;
|
|
498
|
+
}
|
|
499
|
+
for (const candidate of [value.result, value.data, value.raw]) {
|
|
500
|
+
const picked = pickSerialNumber(candidate);
|
|
501
|
+
if (picked) return picked;
|
|
436
502
|
}
|
|
437
503
|
return void 0;
|
|
438
504
|
};
|
|
505
|
+
var normalizeFormCreateResponse = (response, formInstanceId) => {
|
|
506
|
+
const processInstanceId = pickCreatedProcessInstanceId(response);
|
|
507
|
+
const serialNumbers = pickSerialNumbers(response);
|
|
508
|
+
const serialNumber = pickSerialNumber(response);
|
|
509
|
+
const sourceResult = isRecord(response.result) ? response.result : {};
|
|
510
|
+
const normalizedResult = {
|
|
511
|
+
...sourceResult,
|
|
512
|
+
formInstId: formInstanceId,
|
|
513
|
+
formInstanceId,
|
|
514
|
+
result: typeof response.result === "string" && response.result.trim() ? response.result.trim() : sourceResult.result || formInstanceId,
|
|
515
|
+
...processInstanceId ? { processInstanceId } : {},
|
|
516
|
+
...serialNumber ? { serialNumber } : {},
|
|
517
|
+
...serialNumbers ? { serialNumbers } : {}
|
|
518
|
+
};
|
|
519
|
+
const normalizedData = isRecord(response.data) ? {
|
|
520
|
+
...response.data,
|
|
521
|
+
formInstId: response.data.formInstId || formInstanceId,
|
|
522
|
+
formInstanceId: response.data.formInstanceId || formInstanceId,
|
|
523
|
+
...processInstanceId ? { processInstanceId } : {},
|
|
524
|
+
...serialNumber ? { serialNumber } : {},
|
|
525
|
+
...serialNumbers ? { serialNumbers } : {}
|
|
526
|
+
} : response.data;
|
|
527
|
+
return {
|
|
528
|
+
...response,
|
|
529
|
+
formInstId: formInstanceId,
|
|
530
|
+
formInstanceId,
|
|
531
|
+
...processInstanceId ? { processInstanceId } : {},
|
|
532
|
+
...serialNumber ? { serialNumber } : {},
|
|
533
|
+
...serialNumbers ? { serialNumbers } : {},
|
|
534
|
+
result: normalizedResult,
|
|
535
|
+
data: normalizedData
|
|
536
|
+
};
|
|
537
|
+
};
|
|
439
538
|
var isStableCreateLookupValue = (value) => {
|
|
440
539
|
if (value === void 0 || value === null || value === "") return false;
|
|
441
540
|
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
@@ -470,20 +569,6 @@ var firstListItem = (value) => {
|
|
|
470
569
|
}
|
|
471
570
|
return void 0;
|
|
472
571
|
};
|
|
473
|
-
var attachFormInstanceId = (response, formInstanceId) => {
|
|
474
|
-
const withIds = (value) => isRecord(value) ? {
|
|
475
|
-
...value,
|
|
476
|
-
formInstId: value.formInstId || formInstanceId,
|
|
477
|
-
formInstanceId: value.formInstanceId || formInstanceId
|
|
478
|
-
} : value;
|
|
479
|
-
return {
|
|
480
|
-
...response,
|
|
481
|
-
formInstId: formInstanceId,
|
|
482
|
-
formInstanceId,
|
|
483
|
-
result: response.result === null || response.result === void 0 ? formInstanceId : withIds(response.result),
|
|
484
|
-
data: response.data === void 0 ? response.data : withIds(response.data)
|
|
485
|
-
};
|
|
486
|
-
};
|
|
487
572
|
var withDefaultAppType = (context, params) => {
|
|
488
573
|
if (!params) {
|
|
489
574
|
return params;
|
|
@@ -603,6 +688,8 @@ var redirectAfterLogout = (context, options) => {
|
|
|
603
688
|
);
|
|
604
689
|
};
|
|
605
690
|
var createPageSdk = (context) => {
|
|
691
|
+
const inFlightGetRequests = /* @__PURE__ */ new Map();
|
|
692
|
+
const recentRequestStats = /* @__PURE__ */ new Map();
|
|
606
693
|
const request = async (options) => {
|
|
607
694
|
const payload = {
|
|
608
695
|
path: options.path,
|
|
@@ -611,17 +698,54 @@ var createPageSdk = (context) => {
|
|
|
611
698
|
body: options.body,
|
|
612
699
|
headers: options.headers
|
|
613
700
|
};
|
|
614
|
-
|
|
701
|
+
const traceEnabled = isRequestTracingEnabled(context, options);
|
|
702
|
+
const traceLabel = options.traceLabel || `${payload.method.toUpperCase()} ${payload.path}`;
|
|
703
|
+
const dedupeKey = options.dedupe !== false && payload.method === "get" ? buildRequestDedupeKey(payload) : void 0;
|
|
704
|
+
if (traceEnabled && dedupeKey) {
|
|
705
|
+
const currentAt = nowMs();
|
|
706
|
+
const previous = recentRequestStats.get(dedupeKey);
|
|
707
|
+
const nextCount = previous && currentAt - previous.lastAt < 500 ? previous.count + 1 : 1;
|
|
708
|
+
recentRequestStats.set(dedupeKey, { count: nextCount, lastAt: currentAt });
|
|
709
|
+
if (nextCount > 1) {
|
|
710
|
+
console.warn(
|
|
711
|
+
`[OpenXiangda SDK] repeated request within 500ms (${nextCount}): ${traceLabel}`
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
if (dedupeKey && inFlightGetRequests.has(dedupeKey)) {
|
|
716
|
+
if (traceEnabled) {
|
|
717
|
+
console.debug(`[OpenXiangda SDK] deduped in-flight request: ${traceLabel}`);
|
|
718
|
+
}
|
|
719
|
+
return inFlightGetRequests.get(dedupeKey);
|
|
720
|
+
}
|
|
721
|
+
const task = (async () => {
|
|
722
|
+
const startedAt = nowMs();
|
|
615
723
|
const rawResponse = await context.bridge.invoke(
|
|
616
724
|
"transport.request",
|
|
617
725
|
payload
|
|
618
726
|
);
|
|
619
|
-
|
|
727
|
+
const normalized = ensureSuccess(
|
|
620
728
|
normalizeJsonResponse(rawResponse),
|
|
621
729
|
payload
|
|
622
730
|
);
|
|
731
|
+
if (traceEnabled) {
|
|
732
|
+
console.debug(
|
|
733
|
+
`[OpenXiangda SDK] ${traceLabel} ${Math.round(nowMs() - startedAt)}ms`
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
return normalized;
|
|
737
|
+
})();
|
|
738
|
+
if (dedupeKey) {
|
|
739
|
+
inFlightGetRequests.set(dedupeKey, task);
|
|
740
|
+
}
|
|
741
|
+
try {
|
|
742
|
+
return await task;
|
|
623
743
|
} catch (error) {
|
|
624
744
|
throw toSdkError(error, payload);
|
|
745
|
+
} finally {
|
|
746
|
+
if (dedupeKey && inFlightGetRequests.get(dedupeKey) === task) {
|
|
747
|
+
inFlightGetRequests.delete(dedupeKey);
|
|
748
|
+
}
|
|
625
749
|
}
|
|
626
750
|
};
|
|
627
751
|
const download = async (options) => {
|
|
@@ -739,16 +863,17 @@ var createPageSdk = (context) => {
|
|
|
739
863
|
processStartMode: params.processStartMode
|
|
740
864
|
}
|
|
741
865
|
});
|
|
742
|
-
if (params.lookupAfterCreate === false) {
|
|
743
|
-
return response;
|
|
744
|
-
}
|
|
745
866
|
const directId = pickCreatedFormInstanceId(response);
|
|
746
867
|
if (directId) {
|
|
747
|
-
return
|
|
868
|
+
return normalizeFormCreateResponse(response, directId);
|
|
869
|
+
}
|
|
870
|
+
if (!params.lookupAfterCreate) {
|
|
871
|
+
throw createMissingFormInstanceIdError(response);
|
|
748
872
|
}
|
|
749
873
|
const filters = buildCreateLookupFilters(params.data || {}, params.lookupFields);
|
|
750
874
|
if (!filters) {
|
|
751
|
-
return response;
|
|
875
|
+
if (params.lookupAfterCreate === "legacy") return response;
|
|
876
|
+
throw createMissingFormInstanceIdError(response);
|
|
752
877
|
}
|
|
753
878
|
const lookupResponse = await request({
|
|
754
879
|
path: buildAppPath(
|
|
@@ -766,7 +891,9 @@ var createPageSdk = (context) => {
|
|
|
766
891
|
}
|
|
767
892
|
});
|
|
768
893
|
const lookupId = pickCreatedFormInstanceId(firstListItem(lookupResponse));
|
|
769
|
-
|
|
894
|
+
if (lookupId) return normalizeFormCreateResponse(response, lookupId);
|
|
895
|
+
if (params.lookupAfterCreate === "legacy") return response;
|
|
896
|
+
throw createMissingFormInstanceIdError(response);
|
|
770
897
|
},
|
|
771
898
|
update: (params) => request({
|
|
772
899
|
path: buildAppPath(
|