90 lines
2.7 KiB
JavaScript
90 lines
2.7 KiB
JavaScript
|
|
/**
|
|||
|
|
* 从 MindSpace 公开 HTML 中解析 Page Data API 引用的 dataset 与读写意图。
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
export function detectPageDataDatasetUsageFromHtml(html) {
|
|||
|
|
const text = String(html ?? '');
|
|||
|
|
const datasets = new Map();
|
|||
|
|
|
|||
|
|
for (const match of text.matchAll(/\.insertRow\(\s*['"]([^'"]+)['"]/g)) {
|
|||
|
|
const name = match[1];
|
|||
|
|
const prev = datasets.get(name) ?? {};
|
|||
|
|
datasets.set(name, { ...prev, insert: true });
|
|||
|
|
}
|
|||
|
|
for (const match of text.matchAll(/\.listRows\(\s*['"]([^'"]+)['"]/g)) {
|
|||
|
|
const name = match[1];
|
|||
|
|
const prev = datasets.get(name) ?? {};
|
|||
|
|
datasets.set(name, { ...prev, read: true });
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return datasets;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function assertPolicyMatchesHtmlDatasets(html, policyDatasets) {
|
|||
|
|
const usage = detectPageDataDatasetUsageFromHtml(html);
|
|||
|
|
const htmlNames = [...usage.keys()].sort();
|
|||
|
|
const policyNames = Object.keys(policyDatasets ?? {}).sort();
|
|||
|
|
if (!htmlNames.length) return usage;
|
|||
|
|
if (htmlNames.join(',') !== policyNames.join(',')) {
|
|||
|
|
throw Object.assign(
|
|||
|
|
new Error(
|
|||
|
|
`Page Data 策略 dataset(${policyNames.join(', ') || '无'})与 HTML 中 insertRow/listRows 引用的 dataset(${htmlNames.join(', ')})不一致。请使用与页面脚本相同的 dataset 名称。`,
|
|||
|
|
),
|
|||
|
|
{
|
|||
|
|
code: 'dataset_policy_html_mismatch',
|
|||
|
|
htmlDatasets: htmlNames,
|
|||
|
|
policyDatasets: policyNames,
|
|||
|
|
},
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
return usage;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function buildPageDataPolicyDatasetsFromRegistry({ html, registryDatasets, usage }) {
|
|||
|
|
const detected = usage ?? detectPageDataDatasetUsageFromHtml(html);
|
|||
|
|
if (!detected.size) return null;
|
|||
|
|
|
|||
|
|
const registryMap = new Map(registryDatasets.map((dataset) => [dataset.name, dataset]));
|
|||
|
|
const datasets = {};
|
|||
|
|
|
|||
|
|
for (const [name, perms] of detected) {
|
|||
|
|
const registered = registryMap.get(name);
|
|||
|
|
if (!registered) {
|
|||
|
|
throw Object.assign(
|
|||
|
|
new Error(`HTML 引用的 dataset「${name}」尚未注册,请先执行 private_data_register_dataset`),
|
|||
|
|
{ code: 'dataset_not_registered', datasetName: name },
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const entry = {
|
|||
|
|
insert: false,
|
|||
|
|
read: false,
|
|||
|
|
update: false,
|
|||
|
|
softDelete: false,
|
|||
|
|
hardDelete: false,
|
|||
|
|
columns: {},
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (perms.insert && !perms.read) {
|
|||
|
|
entry.insert = true;
|
|||
|
|
entry.columns.insert = registered.columns?.insert ?? [];
|
|||
|
|
} else if (perms.read && !perms.insert) {
|
|||
|
|
entry.read = true;
|
|||
|
|
entry.columns.read = registered.columns?.read ?? [];
|
|||
|
|
} else {
|
|||
|
|
if (perms.insert) {
|
|||
|
|
entry.insert = true;
|
|||
|
|
entry.columns.insert = registered.columns?.insert ?? [];
|
|||
|
|
}
|
|||
|
|
if (perms.read) {
|
|||
|
|
entry.read = true;
|
|||
|
|
entry.columns.read = registered.columns?.read ?? [];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
datasets[name] = entry;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return datasets;
|
|||
|
|
}
|