weaver-work-cli 0.1.29 → 0.1.32
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/dist/chunks/archive-UMGX72K6.js +2537 -0
- package/dist/chunks/archive-oa-N2IYBLF3.js +1317 -0
- package/dist/chunks/asset-GLEGKFG5.js +2109 -0
- package/dist/chunks/attachment-content-AQNX5N3S.js +23 -0
- package/dist/chunks/blog-E44OTVDA.js +2157 -0
- package/dist/chunks/caizhilian-DQUFZXZL.js +10087 -0
- package/dist/chunks/calendar-JKPIRKFD.js +1195 -0
- package/dist/chunks/chunk-2GA5ZIQL.js +1615 -0
- package/dist/chunks/chunk-4YC43QQ4.js +403 -0
- package/dist/chunks/chunk-6EFWDL7Y.js +161 -0
- package/dist/chunks/chunk-6RKD4DRZ.js +5556 -0
- package/dist/chunks/chunk-AJ62BGAW.js +29 -0
- package/dist/chunks/chunk-BUSC6UAE.js +43 -0
- package/dist/chunks/chunk-C6R3B2ML.js +358 -0
- package/dist/chunks/chunk-CVZ2JOSW.js +62 -0
- package/dist/chunks/chunk-DW6AUUKS.js +508 -0
- package/dist/chunks/chunk-E4Z23GHM.js +6962 -0
- package/dist/chunks/chunk-EG6ZU444.js +654 -0
- package/dist/chunks/chunk-EZALDOQH.js +383 -0
- package/dist/chunks/chunk-FMPJJYYI.js +106 -0
- package/dist/chunks/chunk-G2JSIUWF.js +769 -0
- package/dist/chunks/chunk-G3QJULO2.js +387 -0
- package/dist/chunks/chunk-GCG2NMWR.js +703 -0
- package/dist/chunks/chunk-GPMFD4RD.js +75 -0
- package/dist/chunks/chunk-H6XSTSLM.js +2357 -0
- package/dist/chunks/chunk-H7J4DC5R.js +464 -0
- package/dist/chunks/chunk-IURUFGZK.js +477 -0
- package/dist/chunks/chunk-LUSPKZKY.js +53 -0
- package/dist/chunks/chunk-NIAJ5ZCG.js +73 -0
- package/dist/chunks/chunk-NOODWMCL.js +584 -0
- package/dist/chunks/chunk-OOUTBLZ4.js +51 -0
- package/dist/chunks/chunk-P26ZWSKU.js +73 -0
- package/dist/chunks/chunk-QWY6PGL6.js +3472 -0
- package/dist/chunks/chunk-WKI2FBIQ.js +15606 -0
- package/dist/chunks/chunk-WSKBSQ2U.js +231 -0
- package/dist/chunks/chunk-YLCYX7LE.js +371 -0
- package/dist/chunks/chunk-YRVDW4WN.js +205 -0
- package/dist/chunks/chunk-ZEDWSH32.js +68 -0
- package/dist/chunks/continuation-2CKSBLA6.js +11 -0
- package/dist/chunks/continuation-HZIZRZBX.js +13 -0
- package/dist/chunks/continuation-NLECEJPX.js +11 -0
- package/dist/chunks/ebuilder-form-V5FG2EHC.js +2276 -0
- package/dist/chunks/ehr-HMFY6VIL.js +5241 -0
- package/dist/chunks/employee-SAK2QYXX.js +11 -0
- package/dist/chunks/esb-ZYSVB7SG.js +141 -0
- package/dist/chunks/fna-B7RKPAZD.js +1444 -0
- package/dist/chunks/host-45WED2KK.js +21 -0
- package/dist/chunks/host-I4Z6BFYX.js +23 -0
- package/dist/chunks/host-KNZ52LJZ.js +17 -0
- package/dist/chunks/host-OCH2BCCV.js +19 -0
- package/dist/chunks/hrm-2KAZGUHI.js +244 -0
- package/dist/chunks/im-ACJJWH4U.js +252 -0
- package/dist/chunks/invoice-ZK3WCX2U.js +5179 -0
- package/dist/chunks/jiuchuanhui-5PQD3IL2.js +1940 -0
- package/dist/chunks/lazy-dispatch-JQXBW3GM.js +28 -0
- package/dist/chunks/mail-S2HDDXO2.js +2695 -0
- package/dist/chunks/meeting-QVN3I37L.js +504 -0
- package/dist/chunks/msg-parse-4GSQ2WTO.js +41 -0
- package/dist/chunks/okr-QNG4VC2Q.js +2482 -0
- package/dist/chunks/plan-A25EMW6U.js +2025 -0
- package/dist/chunks/project-G6XV66DZ.js +1361 -0
- package/dist/chunks/registry-2VLUAESA.js +14 -0
- package/dist/chunks/registry-7C5UMIPL.js +19 -0
- package/dist/chunks/registry-DC6KR3NH.js +18 -0
- package/dist/chunks/registry-NYPYMZXG.js +16 -0
- package/dist/chunks/registry-TI3CIUXF.js +19 -0
- package/dist/chunks/room-recommend-WRTHO6Y2.js +20 -0
- package/dist/chunks/schedule-KFIITGSK.js +24 -0
- package/dist/chunks/state-Y2XBP6YE.js +15 -0
- package/dist/chunks/workflow-DJ7SYWAF.js +245 -0
- package/dist/cmd/argv.js +45 -0
- package/dist/cmd/docs/index.js +3 -3
- package/dist/cmd/lazy-dispatch.js +20 -0
- package/dist/cmd/root.js +2 -4
- package/dist/cmd/setup/index.js +2 -2
- package/dist/cmd/skills/index.js +2 -2
- package/dist/core/package-paths.js +61 -0
- package/dist/index.js +163 -7
- package/dist/internal/e10/auth/xiaoe.js +3 -3
- package/dist/internal/e10/request-runtime.js +18 -62
- package/dist/internal/skills/detector.js +2 -2
- package/dist/shortcuts/contract/data/performance-catalog.js +1306 -0
- package/dist/shortcuts/contract/host.js +91 -35
- package/dist/shortcuts/contract/index.js +213 -0
- package/dist/shortcuts/contract/manifest.js +928 -0
- package/dist/shortcuts/contract/ooxml/docx.js +295 -0
- package/dist/shortcuts/contract/ooxml/xlsx.js +221 -0
- package/dist/shortcuts/contract/ooxml/zip.js +158 -0
- package/dist/shortcuts/contract/operations/assistant.js +1156 -0
- package/dist/shortcuts/contract/operations/clause-library.js +522 -0
- package/dist/shortcuts/contract/operations/compare.js +193 -0
- package/dist/shortcuts/contract/operations/credit-page.js +34 -0
- package/dist/shortcuts/contract/operations/flow.js +98 -0
- package/dist/shortcuts/contract/operations/page.js +66 -0
- package/dist/shortcuts/contract/operations/performance.js +733 -0
- package/dist/shortcuts/contract/operations/quote.js +557 -0
- package/dist/shortcuts/contract/operations/recommend.js +78 -0
- package/dist/shortcuts/contract/operations/registry.js +18 -0
- package/dist/shortcuts/contract/operations/review.js +83 -0
- package/dist/shortcuts/contract/operations/shared.js +37 -0
- package/dist/shortcuts/contract/operations/upload.js +108 -0
- package/dist/shortcuts/contract/operations/write.js +3 -2
- package/dist/shortcuts/index.js +140 -40
- package/dist/shortcuts/invoice/manifest.js +34 -11
- package/dist/shortcuts/invoice/operations/reim-auto.js +9 -0
- package/dist/shortcuts/invoice/operations/reim.js +81 -5
- package/dist/shortcuts/invoice/operations/shared.js +12 -5
- package/dist/shortcuts/meeting/host.js +45 -3
- package/dist/shortcuts/meeting/invitation/docx.js +442 -0
- package/dist/shortcuts/meeting/operations/attachment-content.js +418 -0
- package/dist/shortcuts/meeting/operations/attachment.js +442 -0
- package/dist/shortcuts/meeting/operations/eb/cache.js +57 -0
- package/dist/shortcuts/meeting/operations/eb/catalog.js +343 -28
- package/dist/shortcuts/meeting/operations/eb/conflict.js +372 -11
- package/dist/shortcuts/meeting/operations/eb/create-flow.js +710 -0
- package/dist/shortcuts/meeting/operations/eb/decision.js +47 -1
- package/dist/shortcuts/meeting/operations/eb/factory.js +129 -11
- package/dist/shortcuts/meeting/operations/eb/index.js +122 -2
- package/dist/shortcuts/meeting/operations/eb/room-recommend.js +378 -0
- package/dist/shortcuts/meeting/operations/eb/room-summary.js +84 -0
- package/dist/shortcuts/meeting/operations/eb/schedule.js +450 -0
- package/dist/shortcuts/meeting/operations/from-group-chat.js +576 -0
- package/dist/shortcuts/meeting/operations/invitation.js +458 -0
- package/dist/shortcuts/meeting/operations/minute-content.js +266 -0
- package/dist/shortcuts/meeting/operations/pipeline.js +489 -0
- package/dist/shortcuts/meeting/operations/qrcode.js +131 -0
- package/dist/shortcuts/meeting/operations/receipts.js +1 -1
- package/dist/shortcuts/meeting/operations/registry.js +18 -0
- package/dist/shortcuts/meeting/operations/summary.js +276 -0
- package/dist/shortcuts/meeting/operations/task-notify.js +325 -0
- package/dist/shortcuts/meeting/operations.js +42 -1
- package/dist/shortcuts/meeting/qr/encoder.js +427 -0
- package/dist/shortcuts/meeting/qr/render.js +103 -0
- package/dist/shortcuts/workflow/operations/form.js +17 -5
- package/docs/contract.md +39 -4
- package/docs/invoice.md +5 -5
- package/package.json +3 -2
- package/scripts/bundle.mjs +63 -0
- package/skill-template/business-info.json +25 -4
- package/skill-template/domains/jinchengda.md +16 -3
- package/skill-template/domains/yepiaotong.md +1 -1
- package/skills/weaver-e10-jinchengda/SKILL.md +111 -31
- package/skills/weaver-e10-jinchengda/references/contract-agent-entry.md +7 -13
- package/skills/weaver-e10-jinchengda/references/contract-ai-assistant.md +150 -0
- package/skills/weaver-e10-jinchengda/references/contract-ai-review.md +87 -0
- package/skills/weaver-e10-jinchengda/references/contract-clause-library-crud.md +111 -0
- package/skills/weaver-e10-jinchengda/references/contract-clause-recommender.md +0 -15
- package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +0 -13
- package/skills/weaver-e10-jinchengda/references/contract-credit-page.md +50 -0
- package/skills/weaver-e10-jinchengda/references/contract-disabled-capabilities.md +4 -2
- package/skills/weaver-e10-jinchengda/references/contract-doc-compare.md +74 -0
- package/skills/weaver-e10-jinchengda/references/contract-flow-launch.md +84 -0
- package/skills/weaver-e10-jinchengda/references/contract-performance-query.md +29 -0
- package/skills/weaver-e10-jinchengda/references/contract-quote-to-contract.md +28 -0
- package/skills/weaver-e10-jinchengda/references/contract-request-status.md +2 -21
- package/skills/weaver-e10-jinchengda/references/contract-request-write.md +0 -24
- package/skills/weaver-e10-jinchengda/references/contract-signing-subjects.md +0 -15
- package/skills/weaver-e10-jinchengda/references/contract-subject-create.md +0 -17
- package/skills/weaver-e10-jinchengda/references/contract-template-recommend.md +70 -0
- package/skills/weaver-e10-jinchengda/references/contract-template-selector.md +0 -15
- package/skills/weaver-e10-jinchengda/references/contract-workflow-discovery.md +0 -15
- package/skills/weaver-e10-jinchengda/references/source-manifest.json +1168 -152
- package/skills/weaver-e10-meeting/SKILL.md +493 -17
- package/skills/weaver-e10-meeting/references/meeting-change.md +4 -4
- package/skills/weaver-e10-meeting/references/meeting-create.md +6 -6
- package/skills/weaver-e10-meeting/references/meeting-eb.md +503 -27
- package/skills/weaver-e10-meeting/references/meeting-invitation.md +113 -0
- package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +6 -6
- package/skills/weaver-e10-meeting/references/meeting-minute-file.md +425 -0
- package/skills/weaver-e10-meeting/references/meeting-queries.md +4 -4
- package/skills/weaver-e10-meeting/references/meeting-receipts-signs.md +15 -15
- package/skills/weaver-e10-meeting/references/meeting-verification.md +19 -11
- package/skills/weaver-e10-meeting.zip +0 -0
- package/skills/weaver-e10-yepiaotong/SKILL.md +9 -5
- package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +1 -1
- package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +6 -5
- package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +14 -11
- package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +97 -56
- package/skills/weaver-e10-yepiaotong/references/reim-examples.md +84 -60
- package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +142 -105
- package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +53 -194
- package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +7 -7
- package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +164 -72
- package/skills/weaver-e10-yepiaotong/references/source-manifest.json +6 -0
- package/templates/meeting/invitation.docx +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createRequire as __esbuildCreateRequire } from 'node:module';
|
|
2
|
+
const require = __esbuildCreateRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// src/core/state.ts
|
|
5
|
+
import { homedir } from "node:os";
|
|
6
|
+
import { dirname, join, resolve } from "node:path";
|
|
7
|
+
function stateRoot(ctx) {
|
|
8
|
+
const home = process.env.WEAVER_WORK_CLI_HOME || process.env.WORK_CLI_HOME || resolve(homedir(), ".weaver-work-cli");
|
|
9
|
+
if (ctx?.getGlobalOptions?.().config) return resolve(home);
|
|
10
|
+
const configured = ctx?.config?.path?.();
|
|
11
|
+
if (configured) return dirname(resolve(configured));
|
|
12
|
+
return resolve(home);
|
|
13
|
+
}
|
|
14
|
+
function stateDir(ctx) {
|
|
15
|
+
return join(stateRoot(ctx), "state");
|
|
16
|
+
}
|
|
17
|
+
function refsDir(ctx) {
|
|
18
|
+
return join(stateDir(ctx), "refs");
|
|
19
|
+
}
|
|
20
|
+
function refsIndexPath(ctx) {
|
|
21
|
+
return join(refsDir(ctx), "index.jsonl");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
stateRoot,
|
|
26
|
+
stateDir,
|
|
27
|
+
refsDir,
|
|
28
|
+
refsIndexPath
|
|
29
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { createRequire as __esbuildCreateRequire } from 'node:module';
|
|
2
|
+
const require = __esbuildCreateRequire(import.meta.url);
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
10
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
11
|
+
}) : x)(function(x) {
|
|
12
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
13
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
14
|
+
});
|
|
15
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
16
|
+
try {
|
|
17
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
18
|
+
} catch (e) {
|
|
19
|
+
throw mod = 0, e;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var __copyProps = (to, from, except, desc) => {
|
|
23
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
24
|
+
for (let key of __getOwnPropNames(from))
|
|
25
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
26
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
27
|
+
}
|
|
28
|
+
return to;
|
|
29
|
+
};
|
|
30
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
31
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
32
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
33
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
34
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
35
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
36
|
+
mod
|
|
37
|
+
));
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
__require,
|
|
41
|
+
__commonJS,
|
|
42
|
+
__toESM
|
|
43
|
+
};
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import { createRequire as __esbuildCreateRequire } from 'node:module';
|
|
2
|
+
const require = __esbuildCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
cacheScopeSuffix,
|
|
5
|
+
readCache,
|
|
6
|
+
writeCache
|
|
7
|
+
} from "./chunk-CVZ2JOSW.js";
|
|
8
|
+
import {
|
|
9
|
+
EB_BASE,
|
|
10
|
+
SCHEMA_DATETIME_MINUTE,
|
|
11
|
+
ebBusinessSuccess,
|
|
12
|
+
extractEbRows,
|
|
13
|
+
meetingSuccess,
|
|
14
|
+
queryBody,
|
|
15
|
+
schemaOf
|
|
16
|
+
} from "./chunk-H6XSTSLM.js";
|
|
17
|
+
|
|
18
|
+
// src/shortcuts/meeting/operations/eb/room-recommend.ts
|
|
19
|
+
var ROOMS_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
20
|
+
var FREQUENT_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
21
|
+
var FREQUENT_WINDOW_DAYS = 180;
|
|
22
|
+
var PAGE_SIZE = 100;
|
|
23
|
+
var MAX_PAGES = 20;
|
|
24
|
+
var STATUS_TEXT = { "0": "\u6B63\u5E38", "1": "\u5C01\u5B58" };
|
|
25
|
+
var ATTR_TEXT = { "0": "\u5B9E\u4F53", "1": "\u865A\u62DF", "2": "\u7EC4\u5408" };
|
|
26
|
+
function toText(value) {
|
|
27
|
+
if (value === void 0 || value === null) return "";
|
|
28
|
+
if (Array.isArray(value)) {
|
|
29
|
+
return value.map((item) => item && typeof item === "object" ? String(item.name ?? item.id ?? "") : String(item ?? "")).filter((item) => item !== "").join(",");
|
|
30
|
+
}
|
|
31
|
+
if (typeof value === "object") {
|
|
32
|
+
const item = value;
|
|
33
|
+
return String(item.name ?? item.id ?? "");
|
|
34
|
+
}
|
|
35
|
+
return String(value);
|
|
36
|
+
}
|
|
37
|
+
function toNumber(value) {
|
|
38
|
+
const text = toText(value).trim();
|
|
39
|
+
if (text === "") return 0;
|
|
40
|
+
const parsed = Number(text);
|
|
41
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
42
|
+
}
|
|
43
|
+
async function fetchRoomsPage(env, pageNo) {
|
|
44
|
+
const session = await env.host.getSession();
|
|
45
|
+
const response = await env.host.request({
|
|
46
|
+
method: "POST",
|
|
47
|
+
path: `${EB_BASE}/getFormDataList/query_meeting_room_list`,
|
|
48
|
+
operation: "meeting.eb.room.recommend",
|
|
49
|
+
body: queryBody(session.userId, { pageNo, pageSize: PAGE_SIZE }),
|
|
50
|
+
acceptBusiness: ebBusinessSuccess
|
|
51
|
+
});
|
|
52
|
+
const { rows } = extractEbRows(response);
|
|
53
|
+
return { rows, requests: 1 };
|
|
54
|
+
}
|
|
55
|
+
function normalizeRoom(row) {
|
|
56
|
+
const main = row?.mainTable ?? row ?? {};
|
|
57
|
+
const status = toText(main.status).trim();
|
|
58
|
+
const roomAttr = toText(main.room_attr).trim();
|
|
59
|
+
return {
|
|
60
|
+
id: toText(main.id).trim(),
|
|
61
|
+
name: toText(main.room_name).trim(),
|
|
62
|
+
status,
|
|
63
|
+
statusText: STATUS_TEXT[status] ?? (status === "" ? "\u672A\u8BBE\u7F6E" : status),
|
|
64
|
+
roomAttr,
|
|
65
|
+
roomAttrText: ATTR_TEXT[roomAttr] ?? roomAttr,
|
|
66
|
+
minNum: toNumber(main.allow_minnum),
|
|
67
|
+
maxNum: toNumber(main.allow_maxnum),
|
|
68
|
+
place: toText(main.place).trim(),
|
|
69
|
+
equipments: toText(main.equipments).trim(),
|
|
70
|
+
mrType: toText(main.mr_type).trim()
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async function loadRooms(env, options = {}) {
|
|
74
|
+
const key = `rooms-${await cacheScopeSuffix(env)}`;
|
|
75
|
+
const warnings = [];
|
|
76
|
+
if (!options.refresh) {
|
|
77
|
+
const cached = await readCache(env, key, { ttlMs: ROOMS_TTL_MS });
|
|
78
|
+
if (cached?.data?.length) {
|
|
79
|
+
return {
|
|
80
|
+
rooms: cached.data,
|
|
81
|
+
fromCache: true,
|
|
82
|
+
ageSeconds: Math.floor(cached.ageMs / 1e3),
|
|
83
|
+
requests: 0,
|
|
84
|
+
warnings
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const rooms = [];
|
|
89
|
+
let requests = 0;
|
|
90
|
+
for (let pageNo = 1; pageNo <= MAX_PAGES; pageNo += 1) {
|
|
91
|
+
const page = await fetchRoomsPage(env, pageNo);
|
|
92
|
+
requests += page.requests;
|
|
93
|
+
rooms.push(...page.rows.map(normalizeRoom).filter((room) => room.id !== ""));
|
|
94
|
+
if (page.rows.length < PAGE_SIZE) break;
|
|
95
|
+
}
|
|
96
|
+
if (rooms.length === 0) {
|
|
97
|
+
warnings.push("\u4F1A\u8BAE\u5BA4\u5217\u8868\u4E3A\u7A7A\uFF08\u6216\u5F53\u524D\u8D26\u53F7\u65E0\u4F1A\u8BAE\u5BA4\u8BFB\u53D6\u6743\u9650\uFF09\u2014\u2014\u65E0\u6CD5\u63A8\u8350\uFF0C\u8BF7\u6539\u4E3A\u624B\u5DE5\u6307\u5B9A\u4F1A\u8BAE\u5BA4");
|
|
98
|
+
} else {
|
|
99
|
+
await writeCache(env, key, rooms);
|
|
100
|
+
}
|
|
101
|
+
return { rooms, fromCache: false, ageSeconds: 0, requests, warnings };
|
|
102
|
+
}
|
|
103
|
+
async function loadFrequentRooms(env, options = {}) {
|
|
104
|
+
const session = await env.host.getSession();
|
|
105
|
+
const userId = String(session?.userId ?? "").trim();
|
|
106
|
+
const key = `frequent-rooms-${await cacheScopeSuffix(env)}-${userId}`;
|
|
107
|
+
const warnings = [];
|
|
108
|
+
if (!options.refresh) {
|
|
109
|
+
const cached = await readCache(env, key, { ttlMs: FREQUENT_TTL_MS });
|
|
110
|
+
if (cached?.data) {
|
|
111
|
+
return { order: cached.data, fromCache: true, requests: 0, warnings };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (!userId) {
|
|
115
|
+
return { order: [], fromCache: false, requests: 0, warnings: ["\u53D6\u4E0D\u5230\u5F53\u524D\u7528\u6237 id\uFF0C\u8DF3\u8FC7\u300C\u5E38\u7528\u4F1A\u8BAE\u5BA4\u300D\u7EDF\u8BA1"] };
|
|
116
|
+
}
|
|
117
|
+
const since = new Date(Date.now() - FREQUENT_WINDOW_DAYS * 24 * 60 * 60 * 1e3);
|
|
118
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
119
|
+
const sinceText = `${since.getFullYear()}-${pad(since.getMonth() + 1)}-${pad(since.getDate())} 00:00`;
|
|
120
|
+
const counts = /* @__PURE__ */ new Map();
|
|
121
|
+
let requests = 0;
|
|
122
|
+
try {
|
|
123
|
+
const { getMeetingOperation } = await import("./registry-TI3CIUXF.js");
|
|
124
|
+
const listOp = getMeetingOperation("meeting.eb.meeting.list");
|
|
125
|
+
for (let pageNo = 1; pageNo <= 5; pageNo += 1) {
|
|
126
|
+
const page = await listOp.handler(
|
|
127
|
+
{ creator: userId, begindatetime: sinceText, pageNo, pageSize: PAGE_SIZE },
|
|
128
|
+
env
|
|
129
|
+
);
|
|
130
|
+
requests += 1;
|
|
131
|
+
const rows = page?.data?.rows ?? [];
|
|
132
|
+
for (const row of rows) {
|
|
133
|
+
const main = row?.mainTable ?? row ?? {};
|
|
134
|
+
const name = toText(main.address).trim();
|
|
135
|
+
if (!name) continue;
|
|
136
|
+
counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
137
|
+
}
|
|
138
|
+
if (rows.length < PAGE_SIZE) break;
|
|
139
|
+
}
|
|
140
|
+
} catch (error) {
|
|
141
|
+
warnings.push(`\u5E38\u7528\u4F1A\u8BAE\u5BA4\u7EDF\u8BA1\u5931\u8D25\uFF08${String(error?.message ?? error).slice(0, 80)}\uFF09\uFF1A\u672C\u6B21\u6309\u5168\u91CF\u4F1A\u8BAE\u5BA4\u6392\u5E8F\u63A8\u8350`);
|
|
142
|
+
}
|
|
143
|
+
const order = [...counts.entries()].map(([name, count]) => ({ name, count })).sort((left, right) => right.count - left.count).slice(0, 10);
|
|
144
|
+
if (order.length > 0) await writeCache(env, key, order);
|
|
145
|
+
return { order, fromCache: false, requests, warnings };
|
|
146
|
+
}
|
|
147
|
+
async function fetchBusyRoomIds(env, begin, end) {
|
|
148
|
+
const session = await env.host.getSession();
|
|
149
|
+
const ids = /* @__PURE__ */ new Set();
|
|
150
|
+
let requests = 0;
|
|
151
|
+
const usageQuery = { enddatetime: end, begindatetime: begin };
|
|
152
|
+
for (let pageNo = 1; pageNo <= MAX_PAGES; pageNo += 1) {
|
|
153
|
+
const response = await env.host.request({
|
|
154
|
+
method: "POST",
|
|
155
|
+
path: `${EB_BASE}/getFormDataList/query_roomusage_list`,
|
|
156
|
+
operation: "meeting.eb.room.recommend",
|
|
157
|
+
query: usageQuery,
|
|
158
|
+
body: queryBody(session.userId, { pageNo, pageSize: PAGE_SIZE }),
|
|
159
|
+
acceptBusiness: ebBusinessSuccess
|
|
160
|
+
});
|
|
161
|
+
requests += 1;
|
|
162
|
+
const { rows } = extractEbRows(response);
|
|
163
|
+
for (const row of rows) {
|
|
164
|
+
const main = row?.mainTable ?? row ?? {};
|
|
165
|
+
const roomId = toText(main.address ?? main.room_id).trim();
|
|
166
|
+
if (roomId) ids.add(roomId);
|
|
167
|
+
}
|
|
168
|
+
if (rows.length < PAGE_SIZE) break;
|
|
169
|
+
}
|
|
170
|
+
return { ids, requests };
|
|
171
|
+
}
|
|
172
|
+
async function recommendRooms(env, input) {
|
|
173
|
+
const warnings = [];
|
|
174
|
+
const topN = Math.max(1, Math.min(10, input.topN ?? 3));
|
|
175
|
+
const roomData = await loadRooms(env, { refresh: input.refreshRooms === true });
|
|
176
|
+
warnings.push(...roomData.warnings);
|
|
177
|
+
const frequent = await loadFrequentRooms(env, { refresh: input.refreshFrequent === true });
|
|
178
|
+
warnings.push(...frequent.warnings);
|
|
179
|
+
const busy = await fetchBusyRoomIds(env, input.beginDatetime, input.endDatetime);
|
|
180
|
+
const frequentRank = /* @__PURE__ */ new Map();
|
|
181
|
+
frequent.order.forEach((item, index) => {
|
|
182
|
+
frequentRank.set(item.name, { rank: index, count: item.count });
|
|
183
|
+
});
|
|
184
|
+
const memberCount = input.memberCount && input.memberCount > 0 ? input.memberCount : null;
|
|
185
|
+
const requirement = input.requirement ?? {};
|
|
186
|
+
const usable = roomData.rooms.filter((room) => room.status === "0");
|
|
187
|
+
let busyCount = 0;
|
|
188
|
+
const candidates = [];
|
|
189
|
+
for (const room of usable) {
|
|
190
|
+
const isBusy = busy.ids.has(room.id);
|
|
191
|
+
if (isBusy) {
|
|
192
|
+
busyCount += 1;
|
|
193
|
+
if (!input.includeBusy) continue;
|
|
194
|
+
}
|
|
195
|
+
if (memberCount !== null) {
|
|
196
|
+
if (room.maxNum > 0 && room.maxNum < memberCount) continue;
|
|
197
|
+
if (room.minNum > 0 && room.minNum > memberCount) continue;
|
|
198
|
+
}
|
|
199
|
+
if (requirement.roomAttr && room.roomAttr !== requirement.roomAttr) continue;
|
|
200
|
+
if (requirement.mrType && room.mrType !== requirement.mrType) continue;
|
|
201
|
+
if (requirement.placeKeyword && !room.place.includes(requirement.placeKeyword)) continue;
|
|
202
|
+
if (requirement.nameKeyword && !room.name.includes(requirement.nameKeyword)) continue;
|
|
203
|
+
if (requirement.equipmentsKeyword && !room.equipments.includes(requirement.equipmentsKeyword)) continue;
|
|
204
|
+
const reasons = [];
|
|
205
|
+
let score = 0;
|
|
206
|
+
const freq = frequentRank.get(room.name);
|
|
207
|
+
if (freq) {
|
|
208
|
+
reasons.push(`\u4F60\u8FD1 ${FREQUENT_WINDOW_DAYS} \u5929\u7528\u8FC7 ${freq.count} \u6B21`);
|
|
209
|
+
score += 40 - Math.min(30, freq.rank * 5);
|
|
210
|
+
}
|
|
211
|
+
if (memberCount !== null && room.maxNum > 0) {
|
|
212
|
+
const waste = room.maxNum - memberCount;
|
|
213
|
+
reasons.push(`\u5BB9\u91CF ${room.maxNum} \u4EBA\uFF0C\u5BB9\u7EB3 ${memberCount} \u4EBA`);
|
|
214
|
+
score += Math.max(0, 20 - Math.min(20, waste));
|
|
215
|
+
} else if (room.maxNum > 0) {
|
|
216
|
+
reasons.push(`\u5BB9\u91CF ${room.maxNum} \u4EBA`);
|
|
217
|
+
score += 5;
|
|
218
|
+
}
|
|
219
|
+
if (requirement.placeKeyword) {
|
|
220
|
+
reasons.push(`\u5730\u70B9\u5339\u914D\u300C${requirement.placeKeyword}\u300D`);
|
|
221
|
+
score += 10;
|
|
222
|
+
}
|
|
223
|
+
if (requirement.equipmentsKeyword) {
|
|
224
|
+
reasons.push(`\u8BBE\u5907\u542B\u300C${requirement.equipmentsKeyword}\u300D`);
|
|
225
|
+
score += 10;
|
|
226
|
+
}
|
|
227
|
+
if (isBusy) {
|
|
228
|
+
reasons.push("\u8BE5\u65F6\u6BB5\u5DF2\u88AB\u5360\u7528\uFF08\u6309 includeBusy \u4E00\u5E76\u8FD4\u56DE\uFF09");
|
|
229
|
+
score -= 100;
|
|
230
|
+
} else {
|
|
231
|
+
reasons.push("\u8BE5\u65F6\u6BB5\u7A7A\u95F2");
|
|
232
|
+
}
|
|
233
|
+
candidates.push({
|
|
234
|
+
id: room.id,
|
|
235
|
+
name: room.name,
|
|
236
|
+
capacity: { min: room.minNum, max: room.maxNum },
|
|
237
|
+
place: room.place,
|
|
238
|
+
equipments: room.equipments,
|
|
239
|
+
roomAttrText: room.roomAttrText,
|
|
240
|
+
frequentCount: freq?.count ?? 0,
|
|
241
|
+
score,
|
|
242
|
+
reasons
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
candidates.sort((left, right) => {
|
|
246
|
+
if (right.score !== left.score) return right.score - left.score;
|
|
247
|
+
const leftCap = left.capacity.max > 0 ? left.capacity.max : Number.MAX_SAFE_INTEGER;
|
|
248
|
+
const rightCap = right.capacity.max > 0 ? right.capacity.max : Number.MAX_SAFE_INTEGER;
|
|
249
|
+
if (leftCap !== rightCap) return leftCap - rightCap;
|
|
250
|
+
return left.name.localeCompare(right.name, "zh-Hans-CN");
|
|
251
|
+
});
|
|
252
|
+
if (candidates.length === 0) {
|
|
253
|
+
warnings.push(
|
|
254
|
+
`\u6CA1\u6709\u6EE1\u8DB3\u6761\u4EF6\u7684\u7A7A\u95F2\u4F1A\u8BAE\u5BA4\uFF08\u5171 ${roomData.rooms.length} \u95F4\uFF0C\u53EF\u7528 ${usable.length} \u95F4\uFF0C\u8BE5\u65F6\u6BB5\u88AB\u5360\u7528 ${busyCount} \u95F4${memberCount ? `\uFF0C\u4EBA\u6570 ${memberCount}` : ""}\uFF09\u2014\u2014\u8BF7\u653E\u5BBD\u4EBA\u6570/\u5730\u70B9/\u8BBE\u5907\u8981\u6C42\uFF0C\u6216\u6539\u4E3A\u7EBF\u4E0A\u4F1A\u8BAE\u3002`
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
best: candidates[0] ?? null,
|
|
259
|
+
candidates: candidates.slice(0, topN),
|
|
260
|
+
meta: {
|
|
261
|
+
roomsTotal: roomData.rooms.length,
|
|
262
|
+
roomsUsable: usable.length,
|
|
263
|
+
roomsMatched: candidates.length,
|
|
264
|
+
roomsBusy: busyCount,
|
|
265
|
+
memberCount,
|
|
266
|
+
roomsFromCache: roomData.fromCache,
|
|
267
|
+
roomsCacheAgeSeconds: roomData.ageSeconds,
|
|
268
|
+
frequentFromCache: frequent.fromCache,
|
|
269
|
+
requests: roomData.requests + frequent.requests + busy.requests
|
|
270
|
+
},
|
|
271
|
+
warnings
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
var ebRoomRecommendOperation = {
|
|
275
|
+
name: "meeting.eb.room.recommend",
|
|
276
|
+
resource: "eb",
|
|
277
|
+
method: "meeting.eb.room.recommend",
|
|
278
|
+
action: "meeting.eb.room.recommend",
|
|
279
|
+
summary: "\u4F1A\u8BAE\u5BA4\u63A8\u8350\uFF1A\u6309\u4EBA\u6570 + \u5730\u70B9/\u8BBE\u5907/\u7C7B\u578B\u8981\u6C42 + \u4E2A\u4EBA\u5E38\u7528\uFF08\u8FD1 180 \u5929\uFF09+ \u65F6\u6BB5\u5360\u7528\uFF0C\u7ED9\u51FA\u6392\u5E8F\u5019\u9009\uFF1B\u4F1A\u8BAE\u5BA4\u4E0E\u5E38\u7528\u8BB0\u5F55\u8D70\u672C\u5730\u7F13\u5B58\uFF08\u5206\u522B 24h / 7d\uFF09\uFF0C\u5360\u7528\u5B9E\u65F6\u67E5 1 \u6B21",
|
|
280
|
+
capability: "eb.room",
|
|
281
|
+
risk: "read",
|
|
282
|
+
inputSchema: schemaOf(
|
|
283
|
+
{
|
|
284
|
+
beginDatetime: { ...SCHEMA_DATETIME_MINUTE, description: "\u5F00\u59CB\u65F6\u95F4\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd HH:mm\uFF09" },
|
|
285
|
+
endDatetime: { ...SCHEMA_DATETIME_MINUTE, description: "\u7ED3\u675F\u65F6\u95F4\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd HH:mm\uFF09" },
|
|
286
|
+
memberCount: { type: "number", description: "\u53C2\u4F1A\u4EBA\u6570\uFF08\u53EF\u9009\uFF1B\u7528\u4E8E\u5BB9\u91CF\u8FC7\u6EE4\uFF0C0 \u6216\u4E0D\u4F20 = \u4E0D\u6309\u4EBA\u6570\u8FC7\u6EE4\uFF09" },
|
|
287
|
+
hrmMembers: {
|
|
288
|
+
type: "string",
|
|
289
|
+
description: "\u53C2\u4F1A\u4EBA id \u9017\u53F7\u5206\u9694\uFF08\u53EF\u9009\uFF09\uFF1A\u4E0D\u4F20 memberCount \u65F6\u6309\u5B83\u7684\u4EBA\u6570\u63A8\u7B97"
|
|
290
|
+
},
|
|
291
|
+
placeKeyword: { type: "string", description: "\u5730\u70B9/\u697C\u5C42\u5173\u952E\u8BCD\uFF08\u6A21\u7CCA\u5339\u914D\u4F1A\u8BAE\u5BA4 place\uFF09" },
|
|
292
|
+
nameKeyword: { type: "string", description: "\u4F1A\u8BAE\u5BA4\u540D\u79F0\u5173\u952E\u8BCD" },
|
|
293
|
+
mrType: { type: "string", description: "\u4F1A\u8BAE\u5BA4\u7C7B\u578B id\uFF08mr_type\uFF09" },
|
|
294
|
+
roomAttr: { type: "string", enum: ["0", "1", "2"], description: "\u4F1A\u8BAE\u5BA4\u5C5E\u6027\uFF1A0 \u5B9E\u4F53 / 1 \u865A\u62DF / 2 \u7EC4\u5408" },
|
|
295
|
+
equipmentsKeyword: { type: "string", description: "\u8BBE\u5907\u5173\u952E\u8BCD\uFF08\u6A21\u7CCA\u5339\u914D equipments\uFF0C\u5982 \u6295\u5F71/\u89C6\u9891\uFF09" },
|
|
296
|
+
topN: { type: "number", description: "\u8FD4\u56DE\u5019\u9009\u6570\u91CF\uFF08\u9ED8\u8BA4 3\uFF0C\u6700\u591A 10\uFF09" },
|
|
297
|
+
refresh: { type: "boolean", description: "true=\u5237\u65B0\u4F1A\u8BAE\u5BA4\u5168\u91CF\u4E0E\u5E38\u7528\u8BB0\u5F55\u7F13\u5B58" },
|
|
298
|
+
includeBusy: { type: "boolean", description: "true=\u628A\u8BE5\u65F6\u6BB5\u5DF2\u88AB\u5360\u7528\u7684\u4F1A\u8BAE\u5BA4\u4E5F\u8FD4\u56DE\uFF08\u6392\u5728\u6700\u540E\uFF0C\u5E26\u8BF4\u660E\uFF09" }
|
|
299
|
+
},
|
|
300
|
+
{ required: ["beginDatetime", "endDatetime"] }
|
|
301
|
+
),
|
|
302
|
+
handler: async (args, env) => {
|
|
303
|
+
const hrmCount = String(args.hrmMembers ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "").length;
|
|
304
|
+
const memberCount = args.memberCount !== void 0 ? Number(args.memberCount) : hrmCount;
|
|
305
|
+
const result = await recommendRooms(env, {
|
|
306
|
+
beginDatetime: String(args.beginDatetime),
|
|
307
|
+
endDatetime: String(args.endDatetime),
|
|
308
|
+
...Number.isFinite(memberCount) && memberCount > 0 ? { memberCount } : {},
|
|
309
|
+
requirement: {
|
|
310
|
+
...args.placeKeyword ? { placeKeyword: String(args.placeKeyword) } : {},
|
|
311
|
+
...args.nameKeyword ? { nameKeyword: String(args.nameKeyword) } : {},
|
|
312
|
+
...args.mrType ? { mrType: String(args.mrType) } : {},
|
|
313
|
+
...args.roomAttr ? { roomAttr: String(args.roomAttr) } : {},
|
|
314
|
+
...args.equipmentsKeyword ? { equipmentsKeyword: String(args.equipmentsKeyword) } : {}
|
|
315
|
+
},
|
|
316
|
+
...args.topN !== void 0 ? { topN: Number(args.topN) } : {},
|
|
317
|
+
...args.refresh === true ? { refreshRooms: true, refreshFrequent: true } : {},
|
|
318
|
+
...args.includeBusy === true ? { includeBusy: true } : {}
|
|
319
|
+
});
|
|
320
|
+
return meetingSuccess(
|
|
321
|
+
"meeting.eb.room.recommend",
|
|
322
|
+
{
|
|
323
|
+
best: result.best,
|
|
324
|
+
candidates: result.candidates,
|
|
325
|
+
meta: result.meta
|
|
326
|
+
},
|
|
327
|
+
result.warnings.length > 0 ? { warnings: result.warnings } : {}
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
async function rememberFrequentRoom(env, roomId) {
|
|
332
|
+
const id = String(roomId ?? "").trim();
|
|
333
|
+
if (!id) return false;
|
|
334
|
+
const scope = await cacheScopeSuffix(env);
|
|
335
|
+
const roomsCached = await readCache(env, `rooms-${scope}`, { ttlMs: ROOMS_TTL_MS });
|
|
336
|
+
const name = roomsCached?.data?.find((room) => room.id === id)?.name ?? "";
|
|
337
|
+
if (!name) return false;
|
|
338
|
+
const session = await env.host.getSession().catch(() => null);
|
|
339
|
+
const userId = String(session?.userId ?? "").trim();
|
|
340
|
+
if (!userId) return false;
|
|
341
|
+
const key = `frequent-rooms-${scope}-${userId}`;
|
|
342
|
+
const cached = await readCache(env, key, { ttlMs: FREQUENT_TTL_MS });
|
|
343
|
+
const order = cached?.data ?? [];
|
|
344
|
+
const existing = order.find((item) => item.name === name);
|
|
345
|
+
if (existing) existing.count += 1;
|
|
346
|
+
else order.push({ name, count: 1 });
|
|
347
|
+
order.sort((left, right) => right.count - left.count);
|
|
348
|
+
await writeCache(env, key, order.slice(0, 10));
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export {
|
|
353
|
+
loadRooms,
|
|
354
|
+
loadFrequentRooms,
|
|
355
|
+
recommendRooms,
|
|
356
|
+
ebRoomRecommendOperation,
|
|
357
|
+
rememberFrequentRoom
|
|
358
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { createRequire as __esbuildCreateRequire } from 'node:module';
|
|
2
|
+
const require = __esbuildCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
meetingStateDir
|
|
5
|
+
} from "./chunk-H6XSTSLM.js";
|
|
6
|
+
|
|
7
|
+
// src/shortcuts/meeting/operations/eb/cache.ts
|
|
8
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
9
|
+
import { dirname, join } from "node:path";
|
|
10
|
+
var DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
11
|
+
function cacheDir(env) {
|
|
12
|
+
return join(meetingStateDir(env.ctx), "cache");
|
|
13
|
+
}
|
|
14
|
+
function cacheFile(env, key) {
|
|
15
|
+
return join(cacheDir(env), `${key}.json`);
|
|
16
|
+
}
|
|
17
|
+
async function identity(env) {
|
|
18
|
+
try {
|
|
19
|
+
const session = await env.host.getSession();
|
|
20
|
+
return {
|
|
21
|
+
baseUrl: String(session?.baseUrl ?? ""),
|
|
22
|
+
tenantKey: String(session?.tenantKey ?? "")
|
|
23
|
+
};
|
|
24
|
+
} catch {
|
|
25
|
+
return { baseUrl: "", tenantKey: "" };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async function readCache(env, key, options = {}) {
|
|
29
|
+
try {
|
|
30
|
+
const raw = await readFile(cacheFile(env, key), "utf8");
|
|
31
|
+
const parsed = JSON.parse(raw);
|
|
32
|
+
const current = await identity(env);
|
|
33
|
+
if (parsed.baseUrl !== current.baseUrl || parsed.tenantKey !== current.tenantKey) return null;
|
|
34
|
+
const ageMs = Date.now() - Number(parsed.savedAt || 0);
|
|
35
|
+
const ttl = options.ttlMs ?? DEFAULT_TTL_MS;
|
|
36
|
+
if (!Number.isFinite(ageMs) || ageMs < 0 || ageMs > ttl) return null;
|
|
37
|
+
return { data: parsed.data, savedAt: parsed.savedAt, ageMs };
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function writeCache(env, key, data) {
|
|
43
|
+
try {
|
|
44
|
+
const current = await identity(env);
|
|
45
|
+
const payload = { savedAt: Date.now(), baseUrl: current.baseUrl, tenantKey: current.tenantKey, data };
|
|
46
|
+
const file = cacheFile(env, key);
|
|
47
|
+
await mkdir(dirname(file), { recursive: true });
|
|
48
|
+
await writeFile(file, JSON.stringify(payload), "utf8");
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function cacheScopeSuffix(env) {
|
|
53
|
+
const { baseUrl, tenantKey } = await identity(env);
|
|
54
|
+
const host = baseUrl.replace(/^https?:\/\//, "").replace(/[^0-9a-zA-Z]+/g, "-");
|
|
55
|
+
return `${host || "local"}-${tenantKey || "unknown"}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export {
|
|
59
|
+
readCache,
|
|
60
|
+
writeCache,
|
|
61
|
+
cacheScopeSuffix
|
|
62
|
+
};
|