@bonginkan/maria-lite 6.3.1 → 6.3.2
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 +16 -2
- package/dist/cli.cjs +311 -459
- package/dist/ext.cjs +1 -1
- package/origin/index.meta.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
MARIA-LITE (v6.3.
|
|
1
|
+
MARIA-LITE (v6.3.2)
|
|
2
2
|
===================
|
|
3
3
|
|
|
4
4
|
MARIA-LITE is a lightweight, standalone CLI build of MARIA OS focused on a smaller runtime surface while preserving API compatibility with `@bonginkan/maria`.
|
|
@@ -43,7 +43,7 @@ Notes:
|
|
|
43
43
|
- Clone commands write under `artifacts/<role>-clone/` when `--apply` (or implicit apply is enabled).
|
|
44
44
|
|
|
45
45
|
## Version
|
|
46
|
-
This package is published as `6.3.
|
|
46
|
+
This package is published as `6.3.2`.
|
|
47
47
|
|
|
48
48
|
## Extensions (Enterprise)
|
|
49
49
|
|
|
@@ -126,6 +126,20 @@ Append creator-provided knowledge to common context:
|
|
|
126
126
|
|
|
127
127
|
## Release Notes
|
|
128
128
|
|
|
129
|
+
### v6.3.2 (2026/03)
|
|
130
|
+
|
|
131
|
+
#### Features
|
|
132
|
+
|
|
133
|
+
- Improved /gcal Admin resource management (buildings & rooms) output and handling.
|
|
134
|
+
- Enhanced /resource-manager with clearer tables and create flows for buildings/resources.
|
|
135
|
+
|
|
136
|
+
#### Bug fixes
|
|
137
|
+
|
|
138
|
+
- More consistent Google Admin API error reporting across /gcal and /resource-manager.
|
|
139
|
+
- Improved floor parsing for building creation (numeric counts or comma-separated).
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
129
143
|
### v6.3.1 (2026/03)
|
|
130
144
|
|
|
131
145
|
#### Features
|
package/dist/cli.cjs
CHANGED
|
@@ -97578,7 +97578,7 @@ function resolvePackageJsonNearEntrypoint() {
|
|
|
97578
97578
|
}
|
|
97579
97579
|
function resolveMariaLiteVersionInfo() {
|
|
97580
97580
|
const fallbackName = EXPECTED_PKG_NAME;
|
|
97581
|
-
const fallbackVersion = String(process.env.MARIA_LITE_VERSION || "").trim() || "6.3.
|
|
97581
|
+
const fallbackVersion = String(process.env.MARIA_LITE_VERSION || "").trim() || "6.3.2";
|
|
97582
97582
|
const near = resolvePackageJsonNearEntrypoint();
|
|
97583
97583
|
if (near) {
|
|
97584
97584
|
const name = fallbackName;
|
|
@@ -256284,6 +256284,161 @@ var init_phone_routes = __esm({
|
|
|
256284
256284
|
}
|
|
256285
256285
|
});
|
|
256286
256286
|
|
|
256287
|
+
// services/google/admin-resources.ts
|
|
256288
|
+
async function adminFetch(token, url, init) {
|
|
256289
|
+
const headers = {
|
|
256290
|
+
Authorization: `Bearer ${token}`,
|
|
256291
|
+
...init?.headers || {}
|
|
256292
|
+
};
|
|
256293
|
+
return fetch(url, { ...init, headers });
|
|
256294
|
+
}
|
|
256295
|
+
function slugify2(name, prefix) {
|
|
256296
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40) || `${prefix}-${Date.now()}`;
|
|
256297
|
+
}
|
|
256298
|
+
function parseFloorNames(raw) {
|
|
256299
|
+
const trimmed = raw.trim();
|
|
256300
|
+
if (!trimmed) return [];
|
|
256301
|
+
const n = Number(trimmed);
|
|
256302
|
+
if (!isNaN(n) && n > 0 && Number.isInteger(n)) {
|
|
256303
|
+
return Array.from({ length: n }, (_, i2) => String(i2 + 1));
|
|
256304
|
+
}
|
|
256305
|
+
return trimmed.split(",").map((f3) => f3.trim()).filter(Boolean);
|
|
256306
|
+
}
|
|
256307
|
+
function toBuilding(raw) {
|
|
256308
|
+
return {
|
|
256309
|
+
buildingId: String(raw.buildingId || ""),
|
|
256310
|
+
buildingName: String(raw.buildingName || ""),
|
|
256311
|
+
description: String(raw.description || ""),
|
|
256312
|
+
floorNames: Array.isArray(raw.floorNames) ? raw.floorNames.map(String) : []
|
|
256313
|
+
};
|
|
256314
|
+
}
|
|
256315
|
+
function toResource(raw) {
|
|
256316
|
+
return {
|
|
256317
|
+
resourceId: String(raw.resourceId || ""),
|
|
256318
|
+
resourceEmail: String(raw.resourceEmail || ""),
|
|
256319
|
+
resourceName: String(raw.resourceName || ""),
|
|
256320
|
+
resourceType: String(raw.resourceType || ""),
|
|
256321
|
+
capacity: Number(raw.capacity || 0),
|
|
256322
|
+
buildingId: String(raw.buildingId || ""),
|
|
256323
|
+
floorName: String(raw.floorName || ""),
|
|
256324
|
+
userVisibleDescription: String(raw.userVisibleDescription || ""),
|
|
256325
|
+
resourceDescription: String(raw.resourceDescription || ""),
|
|
256326
|
+
generatedResourceName: String(raw.generatedResourceName || "")
|
|
256327
|
+
};
|
|
256328
|
+
}
|
|
256329
|
+
async function parseErrorText(res) {
|
|
256330
|
+
return res.text().catch(() => "");
|
|
256331
|
+
}
|
|
256332
|
+
function apiError(status, errText) {
|
|
256333
|
+
if (status === 403) return { ok: false, error: "permission_denied", status };
|
|
256334
|
+
if (status === 404) return { ok: false, error: "not_found", status };
|
|
256335
|
+
return { ok: false, error: `Admin SDK: ${status} ${errText.slice(0, 200)}`, status };
|
|
256336
|
+
}
|
|
256337
|
+
async function listBuildingsRaw(token, signal) {
|
|
256338
|
+
const res = await adminFetch(token, `${ADMIN_RESOURCES_BASE}/buildings?maxResults=500`, signal ? { signal } : void 0);
|
|
256339
|
+
if (!res.ok) return apiError(res.status, await parseErrorText(res));
|
|
256340
|
+
const data = await res.json();
|
|
256341
|
+
const items = Array.isArray(data.buildings) ? data.buildings : [];
|
|
256342
|
+
return { ok: true, data: items.map(toBuilding) };
|
|
256343
|
+
}
|
|
256344
|
+
async function createBuildingRaw(token, params, signal) {
|
|
256345
|
+
const buildingId = params.buildingId || slugify2(params.name, "bld");
|
|
256346
|
+
const body = { buildingId, buildingName: params.name };
|
|
256347
|
+
if (params.description) body.description = params.description;
|
|
256348
|
+
if (params.floorNames) {
|
|
256349
|
+
body.floorNames = params.floorNames;
|
|
256350
|
+
} else if (params.floors) {
|
|
256351
|
+
body.floorNames = parseFloorNames(params.floors);
|
|
256352
|
+
}
|
|
256353
|
+
const res = await adminFetch(token, `${ADMIN_RESOURCES_BASE}/buildings`, {
|
|
256354
|
+
method: "POST",
|
|
256355
|
+
headers: { "Content-Type": "application/json" },
|
|
256356
|
+
body: JSON.stringify(body),
|
|
256357
|
+
...signal ? { signal } : {}
|
|
256358
|
+
});
|
|
256359
|
+
if (!res.ok) return apiError(res.status, await parseErrorText(res));
|
|
256360
|
+
return { ok: true, data: toBuilding(await res.json()) };
|
|
256361
|
+
}
|
|
256362
|
+
async function updateBuildingRaw(token, buildingId, body, signal) {
|
|
256363
|
+
const res = await adminFetch(
|
|
256364
|
+
token,
|
|
256365
|
+
`${ADMIN_RESOURCES_BASE}/buildings/${encodeURIComponent(buildingId)}`,
|
|
256366
|
+
{ method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), ...signal ? { signal } : {} }
|
|
256367
|
+
);
|
|
256368
|
+
if (!res.ok) return apiError(res.status, await parseErrorText(res));
|
|
256369
|
+
return { ok: true, data: toBuilding(await res.json()) };
|
|
256370
|
+
}
|
|
256371
|
+
async function listResourcesRaw(token, opts, signal) {
|
|
256372
|
+
let url = `${ADMIN_RESOURCES_BASE}/calendars?maxResults=500`;
|
|
256373
|
+
if (opts?.buildingId) {
|
|
256374
|
+
url += `&query=buildingId="${encodeURIComponent(opts.buildingId)}"`;
|
|
256375
|
+
}
|
|
256376
|
+
const res = await adminFetch(token, url, signal ? { signal } : void 0);
|
|
256377
|
+
if (!res.ok) return apiError(res.status, await parseErrorText(res));
|
|
256378
|
+
const data = await res.json();
|
|
256379
|
+
let items = Array.isArray(data.items) ? data.items : [];
|
|
256380
|
+
if (opts?.capacity && opts.capacity > 0) {
|
|
256381
|
+
items = items.filter((r2) => Number(r2.capacity || 0) >= opts.capacity);
|
|
256382
|
+
}
|
|
256383
|
+
return { ok: true, data: items.map(toResource) };
|
|
256384
|
+
}
|
|
256385
|
+
async function getResourceRaw(token, resourceId, signal) {
|
|
256386
|
+
const res = await adminFetch(
|
|
256387
|
+
token,
|
|
256388
|
+
`${ADMIN_RESOURCES_BASE}/calendars/${encodeURIComponent(resourceId)}`,
|
|
256389
|
+
signal ? { signal } : void 0
|
|
256390
|
+
);
|
|
256391
|
+
if (!res.ok) return apiError(res.status, await parseErrorText(res));
|
|
256392
|
+
return { ok: true, data: toResource(await res.json()) };
|
|
256393
|
+
}
|
|
256394
|
+
async function createResourceRaw(token, params, signal) {
|
|
256395
|
+
const body = {
|
|
256396
|
+
resourceName: params.name,
|
|
256397
|
+
resourceType: params.resourceType || "CONFERENCE_ROOM"
|
|
256398
|
+
};
|
|
256399
|
+
if (params.resourceId) body.resourceId = params.resourceId;
|
|
256400
|
+
if (params.buildingId) body.buildingId = params.buildingId;
|
|
256401
|
+
if (params.capacity) body.capacity = params.capacity;
|
|
256402
|
+
if (params.floorName) body.floorName = params.floorName;
|
|
256403
|
+
if (params.description) body.resourceDescription = params.description;
|
|
256404
|
+
const res = await adminFetch(token, `${ADMIN_RESOURCES_BASE}/calendars`, {
|
|
256405
|
+
method: "POST",
|
|
256406
|
+
headers: { "Content-Type": "application/json" },
|
|
256407
|
+
body: JSON.stringify(body),
|
|
256408
|
+
...signal ? { signal } : {}
|
|
256409
|
+
});
|
|
256410
|
+
if (!res.ok) return apiError(res.status, await parseErrorText(res));
|
|
256411
|
+
return { ok: true, data: toResource(await res.json()) };
|
|
256412
|
+
}
|
|
256413
|
+
async function updateResourceRaw(token, resourceId, body, signal) {
|
|
256414
|
+
const res = await adminFetch(
|
|
256415
|
+
token,
|
|
256416
|
+
`${ADMIN_RESOURCES_BASE}/calendars/${encodeURIComponent(resourceId)}`,
|
|
256417
|
+
{ method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), ...signal ? { signal } : {} }
|
|
256418
|
+
);
|
|
256419
|
+
if (!res.ok) return apiError(res.status, await parseErrorText(res));
|
|
256420
|
+
return { ok: true, data: toResource(await res.json()) };
|
|
256421
|
+
}
|
|
256422
|
+
async function fetchExistingBuildingIds(token, signal) {
|
|
256423
|
+
const ids = /* @__PURE__ */ new Set();
|
|
256424
|
+
try {
|
|
256425
|
+
const result = await listBuildingsRaw(token, signal);
|
|
256426
|
+
if (result.ok && result.data) {
|
|
256427
|
+
for (const b of result.data) {
|
|
256428
|
+
if (b.buildingId) ids.add(b.buildingId);
|
|
256429
|
+
}
|
|
256430
|
+
}
|
|
256431
|
+
} catch {
|
|
256432
|
+
}
|
|
256433
|
+
return ids;
|
|
256434
|
+
}
|
|
256435
|
+
var ADMIN_RESOURCES_BASE;
|
|
256436
|
+
var init_admin_resources = __esm({
|
|
256437
|
+
"services/google/admin-resources.ts"() {
|
|
256438
|
+
ADMIN_RESOURCES_BASE = "https://admin.googleapis.com/admin/directory/v1/customer/my_customer/resources";
|
|
256439
|
+
}
|
|
256440
|
+
});
|
|
256441
|
+
|
|
256287
256442
|
// services/desktop/routes/calendar-api-routes.ts
|
|
256288
256443
|
async function getToken2() {
|
|
256289
256444
|
const mgr = new GoogleOAuthManager();
|
|
@@ -256293,13 +256448,6 @@ function notConnected2(res) {
|
|
|
256293
256448
|
respondJson2(res, 200, { ok: false, error: "not_connected" });
|
|
256294
256449
|
return true;
|
|
256295
256450
|
}
|
|
256296
|
-
async function gFetch2(token, url, init) {
|
|
256297
|
-
const headers = {
|
|
256298
|
-
Authorization: `Bearer ${token}`,
|
|
256299
|
-
...init?.headers || {}
|
|
256300
|
-
};
|
|
256301
|
-
return fetch(url, { ...init, headers });
|
|
256302
|
-
}
|
|
256303
256451
|
function resolveProjectId2() {
|
|
256304
256452
|
return process.env.GCLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT || process.env.FIREBASE_PROJECT_ID || process.env.GCP_PROJECT_ID || "";
|
|
256305
256453
|
}
|
|
@@ -256357,28 +256505,9 @@ function buildRrule(type2, count, until) {
|
|
|
256357
256505
|
return rule;
|
|
256358
256506
|
}
|
|
256359
256507
|
async function fetchResources(token, buildingId, minCapacity) {
|
|
256360
|
-
|
|
256361
|
-
if (
|
|
256362
|
-
|
|
256363
|
-
}
|
|
256364
|
-
const apiRes = await gFetch2(token, url);
|
|
256365
|
-
if (!apiRes.ok) return [];
|
|
256366
|
-
const data = await apiRes.json();
|
|
256367
|
-
const items = Array.isArray(data.items) ? data.items : [];
|
|
256368
|
-
const resources = items.map((item) => ({
|
|
256369
|
-
resourceId: String(item.resourceId || ""),
|
|
256370
|
-
resourceEmail: String(item.resourceEmail || ""),
|
|
256371
|
-
resourceName: String(item.resourceName || ""),
|
|
256372
|
-
resourceType: String(item.resourceType || ""),
|
|
256373
|
-
capacity: Number(item.capacity || 0),
|
|
256374
|
-
buildingId: String(item.buildingId || ""),
|
|
256375
|
-
floorName: String(item.floorName || ""),
|
|
256376
|
-
userVisibleDescription: String(item.userVisibleDescription || "")
|
|
256377
|
-
}));
|
|
256378
|
-
if (minCapacity != null && minCapacity > 0) {
|
|
256379
|
-
return resources.filter((r2) => r2.capacity >= minCapacity);
|
|
256380
|
-
}
|
|
256381
|
-
return resources;
|
|
256508
|
+
const result = await listResourcesRaw(token, { buildingId, capacity: minCapacity });
|
|
256509
|
+
if (!result.ok || !result.data) return [];
|
|
256510
|
+
return result.data;
|
|
256382
256511
|
}
|
|
256383
256512
|
function findSlots(params) {
|
|
256384
256513
|
const {
|
|
@@ -256538,19 +256667,9 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
256538
256667
|
if (method === "GET" && pathname === "/api/calendar/buildings") {
|
|
256539
256668
|
const token = await getToken2();
|
|
256540
256669
|
if (!token) return notConnected2(res);
|
|
256541
|
-
const
|
|
256542
|
-
if (!
|
|
256543
|
-
|
|
256544
|
-
}
|
|
256545
|
-
const data = await apiRes.json();
|
|
256546
|
-
const items = Array.isArray(data.buildings) ? data.buildings : [];
|
|
256547
|
-
const buildings = items.map((b) => ({
|
|
256548
|
-
buildingId: String(b.buildingId || ""),
|
|
256549
|
-
buildingName: String(b.buildingName || ""),
|
|
256550
|
-
description: String(b.description || ""),
|
|
256551
|
-
floorNames: Array.isArray(b.floorNames) ? b.floorNames : []
|
|
256552
|
-
}));
|
|
256553
|
-
return respondJson2(res, 200, { ok: true, buildings }), true;
|
|
256670
|
+
const result = await listBuildingsRaw(token);
|
|
256671
|
+
if (!result.ok) return respondJson2(res, 200, { ok: false, error: result.error }), true;
|
|
256672
|
+
return respondJson2(res, 200, { ok: true, buildings: result.data }), true;
|
|
256554
256673
|
}
|
|
256555
256674
|
if (method === "POST" && pathname === "/api/calendar/buildings") {
|
|
256556
256675
|
const token = await getToken2();
|
|
@@ -256559,44 +256678,21 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
256559
256678
|
if (!reqBody) return respondJson2(res, 400, { ok: false, error: "Request body is required" }), true;
|
|
256560
256679
|
const buildingName = String(reqBody.buildingName || "").trim();
|
|
256561
256680
|
if (!buildingName) return respondJson2(res, 400, { ok: false, error: "buildingName is required" }), true;
|
|
256562
|
-
const buildingId = String(reqBody.buildingId || "").trim() || buildingName
|
|
256563
|
-
const
|
|
256564
|
-
|
|
256565
|
-
|
|
256566
|
-
|
|
256567
|
-
|
|
256568
|
-
|
|
256569
|
-
|
|
256570
|
-
|
|
256571
|
-
if (!isNaN(n) && n > 0 && Number.isInteger(n)) {
|
|
256572
|
-
body.floorNames = Array.from({ length: n }, (_, i2) => String(i2 + 1));
|
|
256573
|
-
} else {
|
|
256574
|
-
body.floorNames = raw.split(",").map((f3) => f3.trim()).filter(Boolean);
|
|
256575
|
-
}
|
|
256576
|
-
}
|
|
256577
|
-
}
|
|
256578
|
-
const apiRes = await gFetch2(token, `${ADMIN_RESOURCES_BASE}/buildings`, {
|
|
256579
|
-
method: "POST",
|
|
256580
|
-
headers: { "Content-Type": "application/json" },
|
|
256581
|
-
body: JSON.stringify(body)
|
|
256681
|
+
const buildingId = String(reqBody.buildingId || "").trim() || slugify2(buildingName, "bld");
|
|
256682
|
+
const floorNames = reqBody.floorNames ? Array.isArray(reqBody.floorNames) ? reqBody.floorNames.map(String) : void 0 : void 0;
|
|
256683
|
+
const floors = !floorNames && reqBody.floorNames ? String(reqBody.floorNames).trim() : void 0;
|
|
256684
|
+
const result = await createBuildingRaw(token, {
|
|
256685
|
+
name: buildingName,
|
|
256686
|
+
buildingId,
|
|
256687
|
+
description: reqBody.description ? String(reqBody.description).trim() : void 0,
|
|
256688
|
+
floorNames: floorNames || void 0,
|
|
256689
|
+
floors: floors || void 0
|
|
256582
256690
|
});
|
|
256583
|
-
if (!
|
|
256584
|
-
|
|
256585
|
-
|
|
256586
|
-
return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
|
|
256587
|
-
}
|
|
256588
|
-
return respondJson2(res, 200, { ok: false, error: `Admin SDK: ${apiRes.status} ${errText}` }), true;
|
|
256691
|
+
if (!result.ok) {
|
|
256692
|
+
if (result.status === 403) return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
|
|
256693
|
+
return respondJson2(res, 200, { ok: false, error: result.error }), true;
|
|
256589
256694
|
}
|
|
256590
|
-
|
|
256591
|
-
return respondJson2(res, 200, {
|
|
256592
|
-
ok: true,
|
|
256593
|
-
building: {
|
|
256594
|
-
buildingId: String(created.buildingId || ""),
|
|
256595
|
-
buildingName: String(created.buildingName || ""),
|
|
256596
|
-
description: String(created.description || ""),
|
|
256597
|
-
floorNames: Array.isArray(created.floorNames) ? created.floorNames : []
|
|
256598
|
-
}
|
|
256599
|
-
}), true;
|
|
256695
|
+
return respondJson2(res, 200, { ok: true, building: result.data }), true;
|
|
256600
256696
|
}
|
|
256601
256697
|
if (method === "POST" && pathname === "/api/calendar/resources") {
|
|
256602
256698
|
const token = await getToken2();
|
|
@@ -256605,41 +256701,21 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
256605
256701
|
if (!reqBody) return respondJson2(res, 400, { ok: false, error: "Request body is required" }), true;
|
|
256606
256702
|
const resourceName = String(reqBody.resourceName || "").trim();
|
|
256607
256703
|
if (!resourceName) return respondJson2(res, 400, { ok: false, error: "resourceName is required" }), true;
|
|
256608
|
-
const resourceId = String(reqBody.resourceId || "").trim() || resourceName
|
|
256609
|
-
const
|
|
256704
|
+
const resourceId = String(reqBody.resourceId || "").trim() || slugify2(resourceName, "res");
|
|
256705
|
+
const result = await createResourceRaw(token, {
|
|
256706
|
+
name: resourceName,
|
|
256610
256707
|
resourceId,
|
|
256611
|
-
|
|
256612
|
-
|
|
256613
|
-
|
|
256614
|
-
|
|
256615
|
-
|
|
256616
|
-
if (reqBody.floorName) body.floorName = String(reqBody.floorName).trim();
|
|
256617
|
-
if (reqBody.resourceDescription) body.resourceDescription = String(reqBody.resourceDescription).trim();
|
|
256618
|
-
const apiRes = await gFetch2(token, `${ADMIN_RESOURCES_BASE}/calendars`, {
|
|
256619
|
-
method: "POST",
|
|
256620
|
-
headers: { "Content-Type": "application/json" },
|
|
256621
|
-
body: JSON.stringify(body)
|
|
256708
|
+
buildingId: reqBody.buildingId ? String(reqBody.buildingId).trim() : void 0,
|
|
256709
|
+
capacity: reqBody.capacity ? Math.max(0, Number(reqBody.capacity) || 0) : void 0,
|
|
256710
|
+
resourceType: String(reqBody.resourceType || "CONFERENCE_ROOM").trim(),
|
|
256711
|
+
floorName: reqBody.floorName ? String(reqBody.floorName).trim() : void 0,
|
|
256712
|
+
description: reqBody.resourceDescription ? String(reqBody.resourceDescription).trim() : void 0
|
|
256622
256713
|
});
|
|
256623
|
-
if (!
|
|
256624
|
-
|
|
256625
|
-
|
|
256626
|
-
return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
|
|
256627
|
-
}
|
|
256628
|
-
return respondJson2(res, 200, { ok: false, error: `Admin SDK: ${apiRes.status} ${errText}` }), true;
|
|
256714
|
+
if (!result.ok) {
|
|
256715
|
+
if (result.status === 403) return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
|
|
256716
|
+
return respondJson2(res, 200, { ok: false, error: result.error }), true;
|
|
256629
256717
|
}
|
|
256630
|
-
|
|
256631
|
-
return respondJson2(res, 200, {
|
|
256632
|
-
ok: true,
|
|
256633
|
-
resource: {
|
|
256634
|
-
resourceId: String(created.resourceId || ""),
|
|
256635
|
-
resourceEmail: String(created.resourceEmail || ""),
|
|
256636
|
-
resourceName: String(created.resourceName || ""),
|
|
256637
|
-
capacity: Number(created.capacity || 0),
|
|
256638
|
-
buildingId: String(created.buildingId || ""),
|
|
256639
|
-
resourceType: String(created.resourceType || ""),
|
|
256640
|
-
floorName: String(created.floorName || "")
|
|
256641
|
-
}
|
|
256642
|
-
}), true;
|
|
256718
|
+
return respondJson2(res, 200, { ok: true, resource: result.data }), true;
|
|
256643
256719
|
}
|
|
256644
256720
|
if (method === "PATCH" && pathname.startsWith("/api/calendar/buildings/")) {
|
|
256645
256721
|
const buildingId = decodeURIComponent(pathname.slice("/api/calendar/buildings/".length));
|
|
@@ -256667,31 +256743,13 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
256667
256743
|
if (Object.keys(body).length === 0) {
|
|
256668
256744
|
return respondJson2(res, 400, { ok: false, error: "No fields to update" }), true;
|
|
256669
256745
|
}
|
|
256670
|
-
const
|
|
256671
|
-
|
|
256672
|
-
|
|
256673
|
-
|
|
256674
|
-
|
|
256675
|
-
if (!apiRes.ok) {
|
|
256676
|
-
const errText = await apiRes.text().catch(() => "");
|
|
256677
|
-
if (apiRes.status === 403) {
|
|
256678
|
-
return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
|
|
256679
|
-
}
|
|
256680
|
-
if (apiRes.status === 404) {
|
|
256681
|
-
return respondJson2(res, 404, { ok: false, error: "Building not found" }), true;
|
|
256682
|
-
}
|
|
256683
|
-
return respondJson2(res, 200, { ok: false, error: `Admin SDK: ${apiRes.status} ${errText}` }), true;
|
|
256746
|
+
const result = await updateBuildingRaw(token, buildingId, body);
|
|
256747
|
+
if (!result.ok) {
|
|
256748
|
+
if (result.status === 403) return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
|
|
256749
|
+
if (result.status === 404) return respondJson2(res, 404, { ok: false, error: "Building not found" }), true;
|
|
256750
|
+
return respondJson2(res, 200, { ok: false, error: result.error }), true;
|
|
256684
256751
|
}
|
|
256685
|
-
|
|
256686
|
-
return respondJson2(res, 200, {
|
|
256687
|
-
ok: true,
|
|
256688
|
-
building: {
|
|
256689
|
-
buildingId: String(updated.buildingId || ""),
|
|
256690
|
-
buildingName: String(updated.buildingName || ""),
|
|
256691
|
-
description: String(updated.description || ""),
|
|
256692
|
-
floorNames: Array.isArray(updated.floorNames) ? updated.floorNames : []
|
|
256693
|
-
}
|
|
256694
|
-
}), true;
|
|
256752
|
+
return respondJson2(res, 200, { ok: true, building: result.data }), true;
|
|
256695
256753
|
}
|
|
256696
256754
|
if (method === "PATCH" && pathname.startsWith("/api/calendar/resources/")) {
|
|
256697
256755
|
const resourceId = decodeURIComponent(pathname.slice("/api/calendar/resources/".length));
|
|
@@ -256710,34 +256768,13 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
256710
256768
|
if (Object.keys(body).length === 0) {
|
|
256711
256769
|
return respondJson2(res, 400, { ok: false, error: "No fields to update" }), true;
|
|
256712
256770
|
}
|
|
256713
|
-
const
|
|
256714
|
-
|
|
256715
|
-
|
|
256716
|
-
|
|
256717
|
-
|
|
256718
|
-
if (!apiRes.ok) {
|
|
256719
|
-
const errText = await apiRes.text().catch(() => "");
|
|
256720
|
-
if (apiRes.status === 403) {
|
|
256721
|
-
return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
|
|
256722
|
-
}
|
|
256723
|
-
if (apiRes.status === 404) {
|
|
256724
|
-
return respondJson2(res, 404, { ok: false, error: "Resource not found" }), true;
|
|
256725
|
-
}
|
|
256726
|
-
return respondJson2(res, 200, { ok: false, error: `Admin SDK: ${apiRes.status} ${errText}` }), true;
|
|
256771
|
+
const result = await updateResourceRaw(token, resourceId, body);
|
|
256772
|
+
if (!result.ok) {
|
|
256773
|
+
if (result.status === 403) return respondJson2(res, 403, { ok: false, error: "permission_denied", message: "Google Workspace admin privileges required" }), true;
|
|
256774
|
+
if (result.status === 404) return respondJson2(res, 404, { ok: false, error: "Resource not found" }), true;
|
|
256775
|
+
return respondJson2(res, 200, { ok: false, error: result.error }), true;
|
|
256727
256776
|
}
|
|
256728
|
-
|
|
256729
|
-
return respondJson2(res, 200, {
|
|
256730
|
-
ok: true,
|
|
256731
|
-
resource: {
|
|
256732
|
-
resourceId: String(updated.resourceId || ""),
|
|
256733
|
-
resourceEmail: String(updated.resourceEmail || ""),
|
|
256734
|
-
resourceName: String(updated.resourceName || ""),
|
|
256735
|
-
capacity: Number(updated.capacity || 0),
|
|
256736
|
-
buildingId: String(updated.buildingId || ""),
|
|
256737
|
-
resourceType: String(updated.resourceType || ""),
|
|
256738
|
-
floorName: String(updated.floorName || "")
|
|
256739
|
-
}
|
|
256740
|
-
}), true;
|
|
256777
|
+
return respondJson2(res, 200, { ok: true, resource: result.data }), true;
|
|
256741
256778
|
}
|
|
256742
256779
|
if (method === "POST" && pathname === "/api/calendar/slots") {
|
|
256743
256780
|
const token = await getToken2();
|
|
@@ -256788,7 +256825,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
256788
256825
|
timeZone: tz,
|
|
256789
256826
|
items: allTargets.map((e2) => ({ id: e2 }))
|
|
256790
256827
|
};
|
|
256791
|
-
const fbRes = await
|
|
256828
|
+
const fbRes = await adminFetch(token, `${CALENDAR_API_BASE}/freeBusy`, {
|
|
256792
256829
|
method: "POST",
|
|
256793
256830
|
headers: { "Content-Type": "application/json" },
|
|
256794
256831
|
body: JSON.stringify(fbBody)
|
|
@@ -256864,7 +256901,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
256864
256901
|
timeZone: tz,
|
|
256865
256902
|
items: targets.map((e2) => ({ id: e2 }))
|
|
256866
256903
|
};
|
|
256867
|
-
const fbRes = await
|
|
256904
|
+
const fbRes = await adminFetch(token, `${CALENDAR_API_BASE}/freeBusy`, {
|
|
256868
256905
|
method: "POST",
|
|
256869
256906
|
headers: { "Content-Type": "application/json" },
|
|
256870
256907
|
body: JSON.stringify(fbBody)
|
|
@@ -256926,7 +256963,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
256926
256963
|
timeZone: DEFAULT_TIMEZONE,
|
|
256927
256964
|
items: [{ id: calendarId }]
|
|
256928
256965
|
};
|
|
256929
|
-
const fbRes = await
|
|
256966
|
+
const fbRes = await adminFetch(token, `${CALENDAR_API_BASE}/freeBusy`, {
|
|
256930
256967
|
method: "POST",
|
|
256931
256968
|
headers: { "Content-Type": "application/json" },
|
|
256932
256969
|
body: JSON.stringify(fbBody)
|
|
@@ -256968,7 +257005,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
256968
257005
|
if (rrule) {
|
|
256969
257006
|
eventBody.recurrence = [rrule];
|
|
256970
257007
|
}
|
|
256971
|
-
const createRes = await
|
|
257008
|
+
const createRes = await adminFetch(
|
|
256972
257009
|
token,
|
|
256973
257010
|
`${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events`,
|
|
256974
257011
|
{
|
|
@@ -257043,7 +257080,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
257043
257080
|
const msg = err instanceof Error ? err.message : String(err);
|
|
257044
257081
|
if (calendarEventId) {
|
|
257045
257082
|
try {
|
|
257046
|
-
await
|
|
257083
|
+
await adminFetch(
|
|
257047
257084
|
token,
|
|
257048
257085
|
`${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(calendarEventId)}`,
|
|
257049
257086
|
{ method: "DELETE" }
|
|
@@ -257100,7 +257137,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
257100
257137
|
if (!token) return notConnected2(res);
|
|
257101
257138
|
const calendarId = String(data.resourceCalendarId || "") || "primary";
|
|
257102
257139
|
const eventId = String(data.calendarEventId);
|
|
257103
|
-
const instancesRes = await
|
|
257140
|
+
const instancesRes = await adminFetch(
|
|
257104
257141
|
token,
|
|
257105
257142
|
`${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(eventId)}/instances?maxResults=50`
|
|
257106
257143
|
);
|
|
@@ -257150,7 +257187,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
257150
257187
|
}
|
|
257151
257188
|
const upsertToken = await getToken2();
|
|
257152
257189
|
if (!upsertToken) return notConnected2(res);
|
|
257153
|
-
const eventRes = await
|
|
257190
|
+
const eventRes = await adminFetch(
|
|
257154
257191
|
upsertToken,
|
|
257155
257192
|
`${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarIdForUpsert)}/events/${encodeURIComponent(gcalEventId)}`
|
|
257156
257193
|
);
|
|
@@ -257203,7 +257240,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
257203
257240
|
timeZone: DEFAULT_TIMEZONE,
|
|
257204
257241
|
items: [{ id: calendarId }]
|
|
257205
257242
|
};
|
|
257206
|
-
const fbRes = await
|
|
257243
|
+
const fbRes = await adminFetch(token, `${CALENDAR_API_BASE}/freeBusy`, {
|
|
257207
257244
|
method: "POST",
|
|
257208
257245
|
headers: { "Content-Type": "application/json" },
|
|
257209
257246
|
body: JSON.stringify(fbBody)
|
|
@@ -257250,7 +257287,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
257250
257287
|
if (resourceEmail && resourceEmail !== String(data.resourceCalendarId || "")) {
|
|
257251
257288
|
patchBody.attendees = [{ email: resourceEmail, resource: true }];
|
|
257252
257289
|
}
|
|
257253
|
-
const patchRes = await
|
|
257290
|
+
const patchRes = await adminFetch(
|
|
257254
257291
|
token,
|
|
257255
257292
|
`${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(calendarEventId)}`,
|
|
257256
257293
|
{ method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(patchBody) }
|
|
@@ -257303,7 +257340,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
257303
257340
|
}
|
|
257304
257341
|
const upsertToken = await getToken2();
|
|
257305
257342
|
if (!upsertToken) return notConnected2(res);
|
|
257306
|
-
const eventRes = await
|
|
257343
|
+
const eventRes = await adminFetch(
|
|
257307
257344
|
upsertToken,
|
|
257308
257345
|
`${CALENDAR_API_BASE}/calendars/${encodeURIComponent(gcalCalendarId)}/events/${encodeURIComponent(gcalEventId)}`
|
|
257309
257346
|
);
|
|
@@ -257355,7 +257392,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
257355
257392
|
}
|
|
257356
257393
|
if (token) {
|
|
257357
257394
|
try {
|
|
257358
|
-
await
|
|
257395
|
+
await adminFetch(
|
|
257359
257396
|
token,
|
|
257360
257397
|
`${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(instanceEventId)}`,
|
|
257361
257398
|
{ method: "DELETE" }
|
|
@@ -257379,7 +257416,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
257379
257416
|
}
|
|
257380
257417
|
if (token && calendarEventId) {
|
|
257381
257418
|
try {
|
|
257382
|
-
const instanceRes = await
|
|
257419
|
+
const instanceRes = await adminFetch(
|
|
257383
257420
|
token,
|
|
257384
257421
|
`${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(instanceEventId)}`
|
|
257385
257422
|
);
|
|
@@ -257390,7 +257427,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
257390
257427
|
const cutoffDate = new Date(instanceStart);
|
|
257391
257428
|
cutoffDate.setDate(cutoffDate.getDate() - 1);
|
|
257392
257429
|
const untilStr = cutoffDate.toISOString().replace(/[-:]/g, "").split(".")[0] + "Z";
|
|
257393
|
-
const parentRes = await
|
|
257430
|
+
const parentRes = await adminFetch(
|
|
257394
257431
|
token,
|
|
257395
257432
|
`${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(calendarEventId)}`
|
|
257396
257433
|
);
|
|
@@ -257404,7 +257441,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
257404
257441
|
);
|
|
257405
257442
|
return [...parts, `UNTIL=${untilStr}`].join(";");
|
|
257406
257443
|
});
|
|
257407
|
-
await
|
|
257444
|
+
await adminFetch(
|
|
257408
257445
|
token,
|
|
257409
257446
|
`${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(calendarEventId)}`,
|
|
257410
257447
|
{
|
|
@@ -257436,7 +257473,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
257436
257473
|
} else {
|
|
257437
257474
|
if (calendarEventId && token) {
|
|
257438
257475
|
try {
|
|
257439
|
-
await
|
|
257476
|
+
await adminFetch(
|
|
257440
257477
|
token,
|
|
257441
257478
|
`${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events/${encodeURIComponent(calendarEventId)}`,
|
|
257442
257479
|
{ method: "DELETE" }
|
|
@@ -257581,7 +257618,7 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
257581
257618
|
try {
|
|
257582
257619
|
const calendarFetches = Array.from(byCalendar.keys()).map(async (calendarId) => {
|
|
257583
257620
|
const eventsUrl = `${CALENDAR_API_BASE}/calendars/${encodeURIComponent(calendarId)}/events?timeMin=${encodeURIComponent(timeMin)}&timeMax=${encodeURIComponent(timeMax)}&singleEvents=true&orderBy=startTime&maxResults=250`;
|
|
257584
|
-
const eventsRes = await
|
|
257621
|
+
const eventsRes = await adminFetch(token, eventsUrl);
|
|
257585
257622
|
if (!eventsRes.ok) {
|
|
257586
257623
|
console.warn(
|
|
257587
257624
|
`GCal events.list failed for calendar ${calendarId}: ${eventsRes.status}`
|
|
@@ -257748,13 +257785,13 @@ async function handleCalendarApiRoute(method, pathname, req, res) {
|
|
|
257748
257785
|
}
|
|
257749
257786
|
return false;
|
|
257750
257787
|
}
|
|
257751
|
-
var
|
|
257788
|
+
var CALENDAR_API_BASE, DEFAULT_WORK_START_HOUR, DEFAULT_WORK_END_HOUR, DEFAULT_DURATION_MINUTES, DEFAULT_RESERVATION_LIMIT, SLOT_STEP_MS, DEFAULT_BUFFER_MINUTES, TOP_SLOT_COUNT, DEFAULT_TIMEZONE, _firestoreInstance2, _firestoreInitPromise2, VALID_RECURRENCE_TYPES;
|
|
257752
257789
|
var init_calendar_api_routes = __esm({
|
|
257753
257790
|
"services/desktop/routes/calendar-api-routes.ts"() {
|
|
257754
257791
|
init_desktop_server_helpers();
|
|
257755
257792
|
init_google_oauth();
|
|
257756
257793
|
init_date_tz();
|
|
257757
|
-
|
|
257794
|
+
init_admin_resources();
|
|
257758
257795
|
CALENDAR_API_BASE = "https://www.googleapis.com/calendar/v3";
|
|
257759
257796
|
DEFAULT_WORK_START_HOUR = 9;
|
|
257760
257797
|
DEFAULT_WORK_END_HOUR = 18;
|
|
@@ -263703,12 +263740,8 @@ async function findMeetingSlots(token, required, optional, durationMin, dateFrom
|
|
|
263703
263740
|
if (extra?.resourceId) {
|
|
263704
263741
|
resourceCalendarIds = [extra.resourceId];
|
|
263705
263742
|
try {
|
|
263706
|
-
const adminBaseUrl = "https://admin.googleapis.com/admin/directory/v1/customer/my_customer/resources/calendars";
|
|
263707
263743
|
const qParams = new URLSearchParams({ maxResults: "5", query: `resourceEmail="${extra.resourceId}"` });
|
|
263708
|
-
const rRes = await
|
|
263709
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
263710
|
-
...signal ? { signal } : {}
|
|
263711
|
-
});
|
|
263744
|
+
const rRes = await adminFetch(token, `${ADMIN_RESOURCES_BASE}/calendars?${qParams}`, signal ? { signal } : void 0);
|
|
263712
263745
|
if (rRes.ok) {
|
|
263713
263746
|
const rData = await rRes.json();
|
|
263714
263747
|
const items = Array.isArray(rData.items) ? rData.items : [];
|
|
@@ -263722,25 +263755,12 @@ async function findMeetingSlots(token, required, optional, durationMin, dateFrom
|
|
|
263722
263755
|
}
|
|
263723
263756
|
} else if (extra?.buildingId || extra?.capacity) {
|
|
263724
263757
|
try {
|
|
263725
|
-
const
|
|
263726
|
-
|
|
263727
|
-
|
|
263728
|
-
|
|
263729
|
-
|
|
263730
|
-
|
|
263731
|
-
});
|
|
263732
|
-
if (rRes.ok) {
|
|
263733
|
-
const rData = await rRes.json();
|
|
263734
|
-
const items = Array.isArray(rData.items) ? rData.items : [];
|
|
263735
|
-
const filtered = items.filter((r2) => {
|
|
263736
|
-
if (extra?.capacity && typeof r2.capacity === "number" && r2.capacity < extra.capacity) return false;
|
|
263737
|
-
return true;
|
|
263738
|
-
});
|
|
263739
|
-
resourceCalendarIds = filtered.map((r2) => String(r2.resourceEmail || "")).filter(Boolean);
|
|
263740
|
-
for (const r2 of items) {
|
|
263741
|
-
const email = String(r2.resourceEmail || "");
|
|
263742
|
-
const name = String(r2.resourceName || r2.generatedResourceName || "");
|
|
263743
|
-
if (email && name) resourceNameMap[email] = name;
|
|
263758
|
+
const result = await listResourcesRaw(token, { buildingId: extra?.buildingId, capacity: extra?.capacity }, signal);
|
|
263759
|
+
if (result.ok && result.data) {
|
|
263760
|
+
resourceCalendarIds = result.data.map((r2) => r2.resourceEmail).filter(Boolean);
|
|
263761
|
+
for (const r2 of result.data) {
|
|
263762
|
+
const name = r2.resourceName || r2.generatedResourceName || "";
|
|
263763
|
+
if (r2.resourceEmail && name) resourceNameMap[r2.resourceEmail] = name;
|
|
263744
263764
|
}
|
|
263745
263765
|
}
|
|
263746
263766
|
} catch {
|
|
@@ -264122,46 +264142,17 @@ function formatImportSummary(results, totalRecords, isDryRun) {
|
|
|
264122
264142
|
}
|
|
264123
264143
|
return lines;
|
|
264124
264144
|
}
|
|
264125
|
-
async function
|
|
264126
|
-
const
|
|
264127
|
-
|
|
264128
|
-
|
|
264129
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
264130
|
-
...signal ? { signal } : {}
|
|
264131
|
-
});
|
|
264132
|
-
if (res.ok) {
|
|
264133
|
-
const data = await res.json();
|
|
264134
|
-
const buildings = Array.isArray(data.buildings) ? data.buildings : [];
|
|
264135
|
-
for (const b of buildings) {
|
|
264136
|
-
if (typeof b.buildingId === "string" && b.buildingId) {
|
|
264137
|
-
ids.add(b.buildingId);
|
|
264138
|
-
}
|
|
264139
|
-
}
|
|
264140
|
-
}
|
|
264141
|
-
} catch {
|
|
264142
|
-
}
|
|
264143
|
-
return ids;
|
|
264144
|
-
}
|
|
264145
|
-
async function listResources(token, buildingId, signal) {
|
|
264146
|
-
const params = new URLSearchParams({ maxResults: "200" });
|
|
264147
|
-
if (buildingId) params.set("query", `buildingId="${buildingId}"`);
|
|
264148
|
-
const res = await fetch(`${ADMIN_RESOURCES_BASE2}/calendars?${params}`, {
|
|
264149
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
264150
|
-
...signal ? { signal } : {}
|
|
264151
|
-
});
|
|
264152
|
-
if (!res.ok) {
|
|
264153
|
-
const err = await res.text().catch(() => "");
|
|
264154
|
-
return { text: `Admin API error: ${res.status} ${err.slice(0, 200)}`, json: { ok: false, error: res.status } };
|
|
264155
|
-
}
|
|
264156
|
-
const data = await res.json();
|
|
264157
|
-
const items = Array.isArray(data.items) ? data.items : [];
|
|
264145
|
+
async function fmtListResources(token, buildingId, signal) {
|
|
264146
|
+
const result = await listResourcesRaw(token, { buildingId }, signal);
|
|
264147
|
+
if (!result.ok) return { text: `Admin API error: ${result.error}`, json: { ok: false, error: result.error } };
|
|
264148
|
+
const items = result.data;
|
|
264158
264149
|
if (items.length === 0) {
|
|
264159
264150
|
const filter = buildingId ? ` (building: ${buildingId})` : "";
|
|
264160
264151
|
return { text: `No resource calendars found${filter}.`, json: { ok: true, resources: [] } };
|
|
264161
264152
|
}
|
|
264162
264153
|
const lines = [`${items.length} resource calendar(s):`, ""];
|
|
264163
264154
|
for (const r2 of items) {
|
|
264164
|
-
const cap =
|
|
264155
|
+
const cap = r2.capacity ? ` (capacity: ${r2.capacity})` : "";
|
|
264165
264156
|
const bld = r2.buildingId ? ` [building: ${r2.buildingId}]` : "";
|
|
264166
264157
|
lines.push(` ${r2.resourceName || r2.generatedResourceName || "Unnamed"}${cap}${bld}`);
|
|
264167
264158
|
lines.push(` ID: ${r2.resourceId}`);
|
|
@@ -264172,22 +264163,16 @@ async function listResources(token, buildingId, signal) {
|
|
|
264172
264163
|
}
|
|
264173
264164
|
return { text: lines.join("\n"), json: { ok: true, resources: items } };
|
|
264174
264165
|
}
|
|
264175
|
-
async function
|
|
264176
|
-
const
|
|
264177
|
-
|
|
264178
|
-
|
|
264179
|
-
});
|
|
264180
|
-
if (!res.ok) {
|
|
264181
|
-
const err = await res.text().catch(() => "");
|
|
264182
|
-
return { text: `Admin API error: ${res.status} ${err.slice(0, 200)}`, json: { ok: false, error: res.status } };
|
|
264183
|
-
}
|
|
264184
|
-
const r2 = await res.json();
|
|
264166
|
+
async function fmtGetResource(token, resourceId, signal) {
|
|
264167
|
+
const result = await getResourceRaw(token, resourceId, signal);
|
|
264168
|
+
if (!result.ok) return { text: `Admin API error: ${result.error}`, json: { ok: false, error: result.error } };
|
|
264169
|
+
const r2 = result.data;
|
|
264185
264170
|
const lines = [
|
|
264186
264171
|
`Resource: ${r2.resourceName || r2.generatedResourceName || "Unnamed"}`,
|
|
264187
264172
|
` ID: ${r2.resourceId}`,
|
|
264188
264173
|
` Email: ${r2.resourceEmail || "N/A"}`,
|
|
264189
264174
|
` Type: ${r2.resourceType || "N/A"}`,
|
|
264190
|
-
|
|
264175
|
+
r2.capacity ? ` Capacity: ${r2.capacity}` : "",
|
|
264191
264176
|
r2.buildingId ? ` Building: ${r2.buildingId}` : "",
|
|
264192
264177
|
r2.floorName ? ` Floor: ${r2.floorName}` : "",
|
|
264193
264178
|
r2.resourceDescription ? ` Description: ${r2.resourceDescription}` : "",
|
|
@@ -264195,26 +264180,10 @@ async function getResource(token, resourceId, signal) {
|
|
|
264195
264180
|
].filter(Boolean);
|
|
264196
264181
|
return { text: lines.join("\n"), json: { ok: true, resource: r2 } };
|
|
264197
264182
|
}
|
|
264198
|
-
async function
|
|
264199
|
-
const
|
|
264200
|
-
|
|
264201
|
-
|
|
264202
|
-
};
|
|
264203
|
-
if (params.buildingId) body.buildingId = params.buildingId;
|
|
264204
|
-
if (params.capacity) body.capacity = params.capacity;
|
|
264205
|
-
if (params.floorName) body.floorName = params.floorName;
|
|
264206
|
-
if (params.description) body.resourceDescription = params.description;
|
|
264207
|
-
const res = await fetch(`${ADMIN_RESOURCES_BASE2}/calendars`, {
|
|
264208
|
-
method: "POST",
|
|
264209
|
-
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
264210
|
-
body: JSON.stringify(body),
|
|
264211
|
-
...signal ? { signal } : {}
|
|
264212
|
-
});
|
|
264213
|
-
if (!res.ok) {
|
|
264214
|
-
const err = await res.text().catch(() => "");
|
|
264215
|
-
return { text: `Admin API create error: ${res.status} ${err.slice(0, 200)}`, json: { ok: false, error: res.status } };
|
|
264216
|
-
}
|
|
264217
|
-
const r2 = await res.json();
|
|
264183
|
+
async function fmtCreateResource(token, params, signal) {
|
|
264184
|
+
const result = await createResourceRaw(token, params, signal);
|
|
264185
|
+
if (!result.ok) return { text: `Admin API create error: ${result.error}`, json: { ok: false, error: result.error } };
|
|
264186
|
+
const r2 = result.data;
|
|
264218
264187
|
return {
|
|
264219
264188
|
text: `Created resource: "${r2.resourceName}" (id=${r2.resourceId}, email=${r2.resourceEmail})`,
|
|
264220
264189
|
json: { ok: true, created: true, resource: r2 }
|
|
@@ -264295,9 +264264,9 @@ async function bulkImportResources(token, filePath4, signal, dryRun = false) {
|
|
|
264295
264264
|
if (rec.floor || rec.floorName) body.floorName = rec.floor || rec.floorName;
|
|
264296
264265
|
if (rec.description || rec.resourceDescription) body.resourceDescription = rec.description || rec.resourceDescription;
|
|
264297
264266
|
try {
|
|
264298
|
-
const createRes = await
|
|
264267
|
+
const createRes = await adminFetch(token, `${ADMIN_RESOURCES_BASE}/calendars`, {
|
|
264299
264268
|
method: "POST",
|
|
264300
|
-
headers: {
|
|
264269
|
+
headers: { "Content-Type": "application/json" },
|
|
264301
264270
|
body: JSON.stringify(body),
|
|
264302
264271
|
...signal ? { signal } : {}
|
|
264303
264272
|
});
|
|
@@ -264325,54 +264294,25 @@ async function bulkImportResources(token, filePath4, signal, dryRun = false) {
|
|
|
264325
264294
|
}
|
|
264326
264295
|
};
|
|
264327
264296
|
}
|
|
264328
|
-
async function
|
|
264329
|
-
const
|
|
264330
|
-
|
|
264331
|
-
|
|
264332
|
-
});
|
|
264333
|
-
if (!res.ok) {
|
|
264334
|
-
const err = await res.text().catch(() => "");
|
|
264335
|
-
return { text: `Admin API error: ${res.status} ${err.slice(0, 200)}`, json: { ok: false, error: res.status } };
|
|
264336
|
-
}
|
|
264337
|
-
const data = await res.json();
|
|
264338
|
-
const buildings = Array.isArray(data.buildings) ? data.buildings : [];
|
|
264297
|
+
async function fmtListBuildings(token, signal) {
|
|
264298
|
+
const result = await listBuildingsRaw(token, signal);
|
|
264299
|
+
if (!result.ok) return { text: `Admin API error: ${result.error}`, json: { ok: false, error: result.error } };
|
|
264300
|
+
const buildings = result.data;
|
|
264339
264301
|
if (buildings.length === 0) return { text: "No buildings found.", json: { ok: true, buildings: [] } };
|
|
264340
264302
|
const lines = [`${buildings.length} building(s):`, ""];
|
|
264341
264303
|
for (const b of buildings) {
|
|
264342
264304
|
lines.push(` ${b.buildingName || "Unnamed"}`);
|
|
264343
264305
|
lines.push(` ID: ${b.buildingId}`);
|
|
264344
264306
|
if (b.description) lines.push(` Description: ${b.description}`);
|
|
264345
|
-
if (
|
|
264307
|
+
if (b.floorNames.length) lines.push(` Floors: ${b.floorNames.join(", ")}`);
|
|
264346
264308
|
lines.push("");
|
|
264347
264309
|
}
|
|
264348
264310
|
return { text: lines.join("\n"), json: { ok: true, buildings } };
|
|
264349
264311
|
}
|
|
264350
|
-
async function
|
|
264351
|
-
const
|
|
264352
|
-
|
|
264353
|
-
|
|
264354
|
-
buildingName: params.name
|
|
264355
|
-
};
|
|
264356
|
-
if (params.description) body.description = params.description;
|
|
264357
|
-
if (params.floors) {
|
|
264358
|
-
const n = Number(params.floors);
|
|
264359
|
-
if (n > 0) {
|
|
264360
|
-
body.floorNames = Array.from({ length: n }, (_, i2) => String(i2 + 1));
|
|
264361
|
-
} else {
|
|
264362
|
-
body.floorNames = params.floors.split(",").map((f3) => f3.trim()).filter(Boolean);
|
|
264363
|
-
}
|
|
264364
|
-
}
|
|
264365
|
-
const res = await fetch(`${ADMIN_RESOURCES_BASE2}/buildings`, {
|
|
264366
|
-
method: "POST",
|
|
264367
|
-
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
264368
|
-
body: JSON.stringify(body),
|
|
264369
|
-
...signal ? { signal } : {}
|
|
264370
|
-
});
|
|
264371
|
-
if (!res.ok) {
|
|
264372
|
-
const err = await res.text().catch(() => "");
|
|
264373
|
-
return { text: `Admin API create error: ${res.status} ${err.slice(0, 200)}`, json: { ok: false, error: res.status } };
|
|
264374
|
-
}
|
|
264375
|
-
const b = await res.json();
|
|
264312
|
+
async function fmtCreateBuilding(token, params, signal) {
|
|
264313
|
+
const result = await createBuildingRaw(token, params, signal);
|
|
264314
|
+
if (!result.ok) return { text: `Admin API create error: ${result.error}`, json: { ok: false, error: result.error } };
|
|
264315
|
+
const b = result.data;
|
|
264376
264316
|
return {
|
|
264377
264317
|
text: `Created building: "${b.buildingName}" (id=${b.buildingId})`,
|
|
264378
264318
|
json: { ok: true, created: true, building: b }
|
|
@@ -264441,18 +264381,16 @@ async function bulkImportBuildings(token, filePath4, signal, dryRun = false) {
|
|
|
264441
264381
|
const rec = records[i2];
|
|
264442
264382
|
const row = i2 + 2;
|
|
264443
264383
|
const name = rec.name || rec.buildingName || "";
|
|
264444
|
-
const bldId = (rec.id || rec.buildingId || name
|
|
264384
|
+
const bldId = slugify2(rec.id || rec.buildingId || name, "bld");
|
|
264445
264385
|
const body = { buildingId: bldId, buildingName: name };
|
|
264446
264386
|
if (rec.description) body.description = rec.description;
|
|
264447
264387
|
if (rec.floors || rec.floorNames) {
|
|
264448
|
-
|
|
264449
|
-
const n = Number(f3);
|
|
264450
|
-
body.floorNames = n > 0 ? Array.from({ length: n }, (_, i22) => String(i22 + 1)) : f3.split(",").map((s2) => s2.trim()).filter(Boolean);
|
|
264388
|
+
body.floorNames = parseFloorNames(rec.floors || rec.floorNames);
|
|
264451
264389
|
}
|
|
264452
264390
|
try {
|
|
264453
|
-
const createRes = await
|
|
264391
|
+
const createRes = await adminFetch(token, `${ADMIN_RESOURCES_BASE}/buildings`, {
|
|
264454
264392
|
method: "POST",
|
|
264455
|
-
headers: {
|
|
264393
|
+
headers: { "Content-Type": "application/json" },
|
|
264456
264394
|
body: JSON.stringify(body),
|
|
264457
264395
|
...signal ? { signal } : {}
|
|
264458
264396
|
});
|
|
@@ -264529,12 +264467,13 @@ async function checkAvailability(token, targets, datetime, durationMinutes, sign
|
|
|
264529
264467
|
function createGcalField() {
|
|
264530
264468
|
return { commandId: "gcal", worker: new GcalWorker(), checker: new AlwaysPassChecker11() };
|
|
264531
264469
|
}
|
|
264532
|
-
var GcalWorker,
|
|
264470
|
+
var GcalWorker, EMAIL_REGEX, AlwaysPassChecker11;
|
|
264533
264471
|
var init_gcal_field = __esm({
|
|
264534
264472
|
"commands/google/gcal.field.ts"() {
|
|
264535
264473
|
init_base2();
|
|
264536
264474
|
init_google_oauth();
|
|
264537
264475
|
init_date_tz();
|
|
264476
|
+
init_admin_resources();
|
|
264538
264477
|
GcalWorker = class extends LiteWorkerAgent {
|
|
264539
264478
|
commandId = "gcal";
|
|
264540
264479
|
help = {
|
|
@@ -264642,17 +264581,17 @@ var init_gcal_field = __esm({
|
|
|
264642
264581
|
const resSub = (ctx.parsed.args?.[1] || "list").toLowerCase();
|
|
264643
264582
|
if (resSub === "list") {
|
|
264644
264583
|
const buildingId = String(ctx.parsed.options.building || "").trim() || void 0;
|
|
264645
|
-
return await
|
|
264584
|
+
return await fmtListResources(token, buildingId, ctx.abortSignal);
|
|
264646
264585
|
}
|
|
264647
264586
|
if (resSub === "get") {
|
|
264648
264587
|
const resourceId = String(ctx.parsed.args?.[2] || ctx.parsed.options.id || "").trim();
|
|
264649
264588
|
if (!resourceId) return { text: "gcal resources get: resourceId is required" };
|
|
264650
|
-
return await
|
|
264589
|
+
return await fmtGetResource(token, resourceId, ctx.abortSignal);
|
|
264651
264590
|
}
|
|
264652
264591
|
if (resSub === "create") {
|
|
264653
264592
|
const name = String(ctx.parsed.options.name || "").trim();
|
|
264654
264593
|
if (!name) return { text: "gcal resources create: --name is required" };
|
|
264655
|
-
return await
|
|
264594
|
+
return await fmtCreateResource(token, {
|
|
264656
264595
|
name,
|
|
264657
264596
|
buildingId: String(ctx.parsed.options.building || "").trim() || void 0,
|
|
264658
264597
|
capacity: Number(ctx.parsed.options.capacity || "0") || void 0,
|
|
@@ -264672,12 +264611,12 @@ var init_gcal_field = __esm({
|
|
|
264672
264611
|
if (sub === "buildings") {
|
|
264673
264612
|
const bldSub = (ctx.parsed.args?.[1] || "list").toLowerCase();
|
|
264674
264613
|
if (bldSub === "list") {
|
|
264675
|
-
return await
|
|
264614
|
+
return await fmtListBuildings(token, ctx.abortSignal);
|
|
264676
264615
|
}
|
|
264677
264616
|
if (bldSub === "create") {
|
|
264678
264617
|
const name = String(ctx.parsed.options.name || "").trim();
|
|
264679
264618
|
if (!name) return { text: "gcal buildings create: --name is required" };
|
|
264680
|
-
return await
|
|
264619
|
+
return await fmtCreateBuilding(token, {
|
|
264681
264620
|
name,
|
|
264682
264621
|
floors: String(ctx.parsed.options.floors || "").trim() || void 0,
|
|
264683
264622
|
description: String(ctx.parsed.options.description || "").trim() || void 0
|
|
@@ -264706,7 +264645,6 @@ var init_gcal_field = __esm({
|
|
|
264706
264645
|
}
|
|
264707
264646
|
];
|
|
264708
264647
|
};
|
|
264709
|
-
ADMIN_RESOURCES_BASE2 = "https://admin.googleapis.com/admin/directory/v1/customer/my_customer/resources";
|
|
264710
264648
|
EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
264711
264649
|
AlwaysPassChecker11 = class extends LiteCheckerAgent {
|
|
264712
264650
|
commandId = "gcal";
|
|
@@ -293291,152 +293229,38 @@ var init_phone_init_field = __esm({
|
|
|
293291
293229
|
});
|
|
293292
293230
|
|
|
293293
293231
|
// commands/resource-manager.field.ts
|
|
293294
|
-
|
|
293295
|
-
return fetch(url, {
|
|
293296
|
-
...opts,
|
|
293297
|
-
headers: { Authorization: `Bearer ${token}`, ...opts?.headers || {} }
|
|
293298
|
-
});
|
|
293299
|
-
}
|
|
293300
|
-
async function listBuildings2(token, _signal) {
|
|
293301
|
-
const res = await gFetch3(token, `${ADMIN_RESOURCES_BASE3}/buildings?maxResults=500`);
|
|
293302
|
-
if (!res.ok) {
|
|
293303
|
-
return { text: `Resource Manager: Admin SDK error ${res.status}`, json: { ok: false, error: `Admin SDK: ${res.status}` } };
|
|
293304
|
-
}
|
|
293305
|
-
const data = await res.json();
|
|
293306
|
-
const items = Array.isArray(data.buildings) ? data.buildings : [];
|
|
293307
|
-
if (items.length === 0) {
|
|
293308
|
-
return { text: "No buildings found.", json: { ok: true, buildings: [] } };
|
|
293309
|
-
}
|
|
293232
|
+
function formatBuildingsTable(items) {
|
|
293310
293233
|
const lines = ["## Buildings", ""];
|
|
293311
293234
|
lines.push("| ID | Name | Floors | Description |");
|
|
293312
293235
|
lines.push("|---|---|---|---|");
|
|
293313
293236
|
for (const b of items) {
|
|
293314
|
-
const floors =
|
|
293315
|
-
lines.push(`| ${b.buildingId
|
|
293237
|
+
const floors = b.floorNames.join(", ");
|
|
293238
|
+
lines.push(`| ${b.buildingId} | ${b.buildingName} | ${floors} | ${b.description} |`);
|
|
293316
293239
|
}
|
|
293317
293240
|
lines.push("", `Total: ${items.length} building(s)`);
|
|
293318
|
-
return
|
|
293241
|
+
return lines.join("\n");
|
|
293319
293242
|
}
|
|
293320
|
-
|
|
293321
|
-
let url = `${ADMIN_RESOURCES_BASE3}/calendars?maxResults=500`;
|
|
293322
|
-
const res = await gFetch3(token, url);
|
|
293323
|
-
if (!res.ok) {
|
|
293324
|
-
return { text: `Resource Manager: Admin SDK error ${res.status}`, json: { ok: false, error: `Admin SDK: ${res.status}` } };
|
|
293325
|
-
}
|
|
293326
|
-
const data = await res.json();
|
|
293327
|
-
let items = Array.isArray(data.items) ? data.items : [];
|
|
293328
|
-
if (buildingId) items = items.filter((r2) => String(r2.buildingId || "") === buildingId);
|
|
293329
|
-
if (capacity) items = items.filter((r2) => Number(r2.capacity || 0) >= capacity);
|
|
293330
|
-
if (items.length === 0) {
|
|
293331
|
-
return { text: "No resources found.", json: { ok: true, resources: [] } };
|
|
293332
|
-
}
|
|
293243
|
+
function formatResourcesTable(items) {
|
|
293333
293244
|
const lines = ["## Calendar Resources", ""];
|
|
293334
293245
|
lines.push("| Name | Building | Capacity | Type | Floor | Email |");
|
|
293335
293246
|
lines.push("|---|---|---|---|---|---|");
|
|
293336
293247
|
for (const r2 of items) {
|
|
293337
|
-
lines.push(`| ${r2.resourceName
|
|
293248
|
+
lines.push(`| ${r2.resourceName} | ${r2.buildingId} | ${r2.capacity || ""} | ${r2.resourceType} | ${r2.floorName} | ${r2.resourceEmail} |`);
|
|
293338
293249
|
}
|
|
293339
293250
|
lines.push("", `Total: ${items.length} resource(s)`);
|
|
293340
|
-
return
|
|
293341
|
-
}
|
|
293342
|
-
async function createBuilding2(token, name, floorsRaw, description, _signal) {
|
|
293343
|
-
const buildingId = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40) || `bld-${Date.now()}`;
|
|
293344
|
-
const body = { buildingId, buildingName: name };
|
|
293345
|
-
if (description) body.description = description;
|
|
293346
|
-
if (floorsRaw) {
|
|
293347
|
-
const n = Number(floorsRaw);
|
|
293348
|
-
if (!isNaN(n) && n > 0 && Number.isInteger(n)) {
|
|
293349
|
-
body.floorNames = Array.from({ length: n }, (_, i2) => String(i2 + 1));
|
|
293350
|
-
} else {
|
|
293351
|
-
body.floorNames = floorsRaw.split(",").map((f3) => f3.trim()).filter(Boolean);
|
|
293352
|
-
}
|
|
293353
|
-
}
|
|
293354
|
-
const res = await gFetch3(token, `${ADMIN_RESOURCES_BASE3}/buildings`, {
|
|
293355
|
-
method: "POST",
|
|
293356
|
-
headers: { "Content-Type": "application/json" },
|
|
293357
|
-
body: JSON.stringify(body)
|
|
293358
|
-
});
|
|
293359
|
-
if (!res.ok) {
|
|
293360
|
-
const errText = await res.text().catch(() => "");
|
|
293361
|
-
if (res.status === 403) return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
|
|
293362
|
-
return { text: `Failed to create building: ${res.status} ${errText}`, json: { ok: false, error: `Admin SDK: ${res.status}` } };
|
|
293363
|
-
}
|
|
293364
|
-
const created = await res.json();
|
|
293365
|
-
return {
|
|
293366
|
-
text: `Building created: ${created.buildingName} (${created.buildingId})`,
|
|
293367
|
-
json: { ok: true, building: created }
|
|
293368
|
-
};
|
|
293369
|
-
}
|
|
293370
|
-
async function createResource2(token, opts, _signal) {
|
|
293371
|
-
const resourceId = opts.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40) || `res-${Date.now()}`;
|
|
293372
|
-
const body = { resourceId, resourceName: opts.name, resourceType: opts.resourceType };
|
|
293373
|
-
if (opts.buildingId) body.buildingId = opts.buildingId;
|
|
293374
|
-
if (opts.capacity) body.capacity = opts.capacity;
|
|
293375
|
-
if (opts.floorName) body.floorName = opts.floorName;
|
|
293376
|
-
if (opts.description) body.resourceDescription = opts.description;
|
|
293377
|
-
const res = await gFetch3(token, `${ADMIN_RESOURCES_BASE3}/calendars`, {
|
|
293378
|
-
method: "POST",
|
|
293379
|
-
headers: { "Content-Type": "application/json" },
|
|
293380
|
-
body: JSON.stringify(body)
|
|
293381
|
-
});
|
|
293382
|
-
if (!res.ok) {
|
|
293383
|
-
const errText = await res.text().catch(() => "");
|
|
293384
|
-
if (res.status === 403) return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
|
|
293385
|
-
return { text: `Failed to create resource: ${res.status} ${errText}`, json: { ok: false, error: `Admin SDK: ${res.status}` } };
|
|
293386
|
-
}
|
|
293387
|
-
const created = await res.json();
|
|
293388
|
-
return {
|
|
293389
|
-
text: `Resource created: ${created.resourceName} (${created.resourceEmail})`,
|
|
293390
|
-
json: { ok: true, resource: created }
|
|
293391
|
-
};
|
|
293392
|
-
}
|
|
293393
|
-
async function updateBuilding(token, buildingId, body, _signal) {
|
|
293394
|
-
const res = await gFetch3(token, `${ADMIN_RESOURCES_BASE3}/buildings/${encodeURIComponent(buildingId)}`, {
|
|
293395
|
-
method: "PATCH",
|
|
293396
|
-
headers: { "Content-Type": "application/json" },
|
|
293397
|
-
body: JSON.stringify(body)
|
|
293398
|
-
});
|
|
293399
|
-
if (!res.ok) {
|
|
293400
|
-
const errText = await res.text().catch(() => "");
|
|
293401
|
-
if (res.status === 403) return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
|
|
293402
|
-
if (res.status === 404) return { text: `Building "${buildingId}" not found.`, json: { ok: false, error: "not_found" } };
|
|
293403
|
-
return { text: `Failed to update building: ${res.status} ${errText}`, json: { ok: false, error: `Admin SDK: ${res.status}` } };
|
|
293404
|
-
}
|
|
293405
|
-
const updated = await res.json();
|
|
293406
|
-
return {
|
|
293407
|
-
text: `Building updated: ${updated.buildingName} (${updated.buildingId})`,
|
|
293408
|
-
json: { ok: true, building: updated }
|
|
293409
|
-
};
|
|
293410
|
-
}
|
|
293411
|
-
async function updateResource(token, resourceId, body, _signal) {
|
|
293412
|
-
const res = await gFetch3(token, `${ADMIN_RESOURCES_BASE3}/calendars/${encodeURIComponent(resourceId)}`, {
|
|
293413
|
-
method: "PATCH",
|
|
293414
|
-
headers: { "Content-Type": "application/json" },
|
|
293415
|
-
body: JSON.stringify(body)
|
|
293416
|
-
});
|
|
293417
|
-
if (!res.ok) {
|
|
293418
|
-
const errText = await res.text().catch(() => "");
|
|
293419
|
-
if (res.status === 403) return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
|
|
293420
|
-
if (res.status === 404) return { text: `Resource "${resourceId}" not found.`, json: { ok: false, error: "not_found" } };
|
|
293421
|
-
return { text: `Failed to update resource: ${res.status} ${errText}`, json: { ok: false, error: `Admin SDK: ${res.status}` } };
|
|
293422
|
-
}
|
|
293423
|
-
const updated = await res.json();
|
|
293424
|
-
return {
|
|
293425
|
-
text: `Resource updated: ${updated.resourceName} (${updated.resourceEmail})`,
|
|
293426
|
-
json: { ok: true, resource: updated }
|
|
293427
|
-
};
|
|
293251
|
+
return lines.join("\n");
|
|
293428
293252
|
}
|
|
293429
293253
|
function createResourceManagerField() {
|
|
293430
293254
|
const worker = new ResourceManagerWorker();
|
|
293431
293255
|
const checker = new ResourceManagerChecker();
|
|
293432
293256
|
return { worker, checker };
|
|
293433
293257
|
}
|
|
293434
|
-
var
|
|
293258
|
+
var ResourceManagerWorker, ResourceManagerChecker;
|
|
293435
293259
|
var init_resource_manager_field = __esm({
|
|
293436
293260
|
"commands/resource-manager.field.ts"() {
|
|
293437
293261
|
init_base2();
|
|
293438
293262
|
init_google_oauth();
|
|
293439
|
-
|
|
293263
|
+
init_admin_resources();
|
|
293440
293264
|
ResourceManagerWorker = class extends LiteWorkerAgent {
|
|
293441
293265
|
commandId = "resource-manager";
|
|
293442
293266
|
help = {
|
|
@@ -293460,20 +293284,34 @@ var init_resource_manager_field = __esm({
|
|
|
293460
293284
|
}
|
|
293461
293285
|
const sub = (ctx.parsed.subcommand || ctx.parsed.args?.[0] || "buildings").toLowerCase();
|
|
293462
293286
|
if (sub === "buildings" || sub === "list-buildings") {
|
|
293463
|
-
|
|
293287
|
+
const result = await listBuildingsRaw(token, ctx.abortSignal);
|
|
293288
|
+
if (!result.ok) return { text: `Resource Manager: ${result.error}`, json: { ok: false, error: result.error } };
|
|
293289
|
+
const items = result.data;
|
|
293290
|
+
if (items.length === 0) return { text: "No buildings found.", json: { ok: true, buildings: [] } };
|
|
293291
|
+
return { text: formatBuildingsTable(items), json: { ok: true, buildings: items } };
|
|
293464
293292
|
}
|
|
293465
293293
|
if (sub === "resources" || sub === "list-resources") {
|
|
293466
293294
|
const buildingId = String(ctx.parsed.options.building || ctx.parsed.options.buildingId || "").trim() || void 0;
|
|
293467
293295
|
const capacityRaw = String(ctx.parsed.options.capacity || "").trim();
|
|
293468
293296
|
const capacity = capacityRaw ? Math.max(0, Number(capacityRaw) || 0) : void 0;
|
|
293469
|
-
|
|
293297
|
+
const result = await listResourcesRaw(token, { buildingId, capacity }, ctx.abortSignal);
|
|
293298
|
+
if (!result.ok) return { text: `Resource Manager: ${result.error}`, json: { ok: false, error: result.error } };
|
|
293299
|
+
const items = result.data;
|
|
293300
|
+
if (items.length === 0) return { text: "No resources found.", json: { ok: true, resources: [] } };
|
|
293301
|
+
return { text: formatResourcesTable(items), json: { ok: true, resources: items } };
|
|
293470
293302
|
}
|
|
293471
293303
|
if (sub === "create-building") {
|
|
293472
293304
|
const name = String(ctx.parsed.options.name || ctx.parsed.prompt || "").trim();
|
|
293473
293305
|
if (!name) return { text: "resource-manager create-building: --name is required" };
|
|
293474
293306
|
const floorsRaw = String(ctx.parsed.options.floors || "").trim();
|
|
293475
293307
|
const description = String(ctx.parsed.options.description || "").trim() || void 0;
|
|
293476
|
-
|
|
293308
|
+
const result = await createBuildingRaw(token, { name, floors: floorsRaw || void 0, description }, ctx.abortSignal);
|
|
293309
|
+
if (!result.ok) {
|
|
293310
|
+
if (result.error === "permission_denied") return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
|
|
293311
|
+
return { text: `Failed to create building: ${result.error}`, json: { ok: false, error: result.error } };
|
|
293312
|
+
}
|
|
293313
|
+
const b = result.data;
|
|
293314
|
+
return { text: `Building created: ${b.buildingName} (${b.buildingId})`, json: { ok: true, building: b } };
|
|
293477
293315
|
}
|
|
293478
293316
|
if (sub === "create-resource") {
|
|
293479
293317
|
const name = String(ctx.parsed.options.name || ctx.parsed.prompt || "").trim();
|
|
@@ -293483,7 +293321,14 @@ var init_resource_manager_field = __esm({
|
|
|
293483
293321
|
const resourceType = String(ctx.parsed.options.type || "CONFERENCE_ROOM").trim();
|
|
293484
293322
|
const floorName = String(ctx.parsed.options.floor || "").trim() || void 0;
|
|
293485
293323
|
const description = String(ctx.parsed.options.description || "").trim() || void 0;
|
|
293486
|
-
|
|
293324
|
+
const resourceId = slugify2(name, "res");
|
|
293325
|
+
const result = await createResourceRaw(token, { name, resourceId, buildingId, capacity, resourceType, floorName, description }, ctx.abortSignal);
|
|
293326
|
+
if (!result.ok) {
|
|
293327
|
+
if (result.error === "permission_denied") return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
|
|
293328
|
+
return { text: `Failed to create resource: ${result.error}`, json: { ok: false, error: result.error } };
|
|
293329
|
+
}
|
|
293330
|
+
const r2 = result.data;
|
|
293331
|
+
return { text: `Resource created: ${r2.resourceName} (${r2.resourceEmail})`, json: { ok: true, resource: r2 } };
|
|
293487
293332
|
}
|
|
293488
293333
|
if (sub === "update-building") {
|
|
293489
293334
|
const id = String(ctx.parsed.options.id || "").trim();
|
|
@@ -293492,18 +293337,18 @@ var init_resource_manager_field = __esm({
|
|
|
293492
293337
|
const name = String(ctx.parsed.options.name || "").trim();
|
|
293493
293338
|
if (name) body.buildingName = name;
|
|
293494
293339
|
const floorsRaw = String(ctx.parsed.options.floors || "").trim();
|
|
293495
|
-
if (floorsRaw)
|
|
293496
|
-
const n = Number(floorsRaw);
|
|
293497
|
-
if (!isNaN(n) && n > 0 && Number.isInteger(n)) {
|
|
293498
|
-
body.floorNames = Array.from({ length: n }, (_, i2) => String(i2 + 1));
|
|
293499
|
-
} else {
|
|
293500
|
-
body.floorNames = floorsRaw.split(",").map((f3) => f3.trim()).filter(Boolean);
|
|
293501
|
-
}
|
|
293502
|
-
}
|
|
293340
|
+
if (floorsRaw) body.floorNames = parseFloorNames(floorsRaw);
|
|
293503
293341
|
const description = String(ctx.parsed.options.description || "").trim();
|
|
293504
293342
|
if (description) body.description = description;
|
|
293505
293343
|
if (Object.keys(body).length === 0) return { text: "resource-manager update-building: at least one field to update is required (--name, --floors, --description)" };
|
|
293506
|
-
|
|
293344
|
+
const result = await updateBuildingRaw(token, id, body, ctx.abortSignal);
|
|
293345
|
+
if (!result.ok) {
|
|
293346
|
+
if (result.error === "permission_denied") return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
|
|
293347
|
+
if (result.error === "not_found") return { text: `Building "${id}" not found.`, json: { ok: false, error: "not_found" } };
|
|
293348
|
+
return { text: `Failed to update building: ${result.error}`, json: { ok: false, error: result.error } };
|
|
293349
|
+
}
|
|
293350
|
+
const b = result.data;
|
|
293351
|
+
return { text: `Building updated: ${b.buildingName} (${b.buildingId})`, json: { ok: true, building: b } };
|
|
293507
293352
|
}
|
|
293508
293353
|
if (sub === "update-resource") {
|
|
293509
293354
|
const id = String(ctx.parsed.options.id || "").trim();
|
|
@@ -293522,7 +293367,14 @@ var init_resource_manager_field = __esm({
|
|
|
293522
293367
|
const description = String(ctx.parsed.options.description || "").trim();
|
|
293523
293368
|
if (description) body.resourceDescription = description;
|
|
293524
293369
|
if (Object.keys(body).length === 0) return { text: "resource-manager update-resource: at least one field to update is required" };
|
|
293525
|
-
|
|
293370
|
+
const result = await updateResourceRaw(token, id, body, ctx.abortSignal);
|
|
293371
|
+
if (!result.ok) {
|
|
293372
|
+
if (result.error === "permission_denied") return { text: "Permission denied: Google Workspace admin privileges required.", json: { ok: false, error: "permission_denied" } };
|
|
293373
|
+
if (result.error === "not_found") return { text: `Resource "${id}" not found.`, json: { ok: false, error: "not_found" } };
|
|
293374
|
+
return { text: `Failed to update resource: ${result.error}`, json: { ok: false, error: result.error } };
|
|
293375
|
+
}
|
|
293376
|
+
const r2 = result.data;
|
|
293377
|
+
return { text: `Resource updated: ${r2.resourceName} (${r2.resourceEmail})`, json: { ok: true, resource: r2 } };
|
|
293526
293378
|
}
|
|
293527
293379
|
return { text: `resource-manager: unknown subcommand "${sub}". Use buildings, resources, create-building, create-resource, update-building, or update-resource.` };
|
|
293528
293380
|
}
|
package/dist/ext.cjs
CHANGED
|
@@ -98004,7 +98004,7 @@ function resolvePackageJsonNearEntrypoint() {
|
|
|
98004
98004
|
}
|
|
98005
98005
|
function resolveMariaLiteVersionInfo() {
|
|
98006
98006
|
const fallbackName = EXPECTED_PKG_NAME;
|
|
98007
|
-
const fallbackVersion = String(process.env.MARIA_LITE_VERSION || "").trim() || "6.3.
|
|
98007
|
+
const fallbackVersion = String(process.env.MARIA_LITE_VERSION || "").trim() || "6.3.2";
|
|
98008
98008
|
const near = resolvePackageJsonNearEntrypoint();
|
|
98009
98009
|
if (near) {
|
|
98010
98010
|
const name = fallbackName;
|
package/origin/index.meta.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"buildTimestamp":"2026-03-
|
|
1
|
+
{"buildTimestamp":"2026-03-03T20:12:12.348Z","fileCount":952,"indexJsonlRelPath":"src-lite/origin/index.jsonl","schemaVersion":"maria_lite_origin_index_meta_v1","sourceDir":"src-lite/origin","textExtractedCount":952}
|