@objectstack/core 12.5.0 → 13.0.0
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/index.cjs +103 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +80 -3
- package/dist/index.d.ts +80 -3
- package/dist/index.js +100 -15
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -54,6 +54,7 @@ __export(index_exports, {
|
|
|
54
54
|
SemanticVersionManager: () => SemanticVersionManager,
|
|
55
55
|
ServiceLifecycle: () => ServiceLifecycle,
|
|
56
56
|
buildPermissionsFromGrants: () => buildPermissionsFromGrants,
|
|
57
|
+
bulkWrite: () => bulkWrite,
|
|
57
58
|
calendarPartsInTz: () => calendarPartsInTz,
|
|
58
59
|
calendarPartsInTzOrUtc: () => calendarPartsInTzOrUtc,
|
|
59
60
|
counterSignPayload: () => counterSignPayload,
|
|
@@ -67,6 +68,7 @@ __export(index_exports, {
|
|
|
67
68
|
createPluginConfigValidator: () => createPluginConfigValidator,
|
|
68
69
|
createPluginPermissionEnforcer: () => createPluginPermissionEnforcer,
|
|
69
70
|
deepMerge: () => deepMerge,
|
|
71
|
+
defaultIsTransientError: () => defaultIsTransientError,
|
|
70
72
|
evaluateAuthGate: () => evaluateAuthGate,
|
|
71
73
|
extractApiKey: () => extractApiKey,
|
|
72
74
|
generateApiKey: () => generateApiKey,
|
|
@@ -90,7 +92,8 @@ __export(index_exports, {
|
|
|
90
92
|
verifyPlatformSignature: () => verifyPlatformSignature,
|
|
91
93
|
verifyPluginArtifact: () => verifyPluginArtifact,
|
|
92
94
|
verifyPublisherSignature: () => verifyPublisherSignature,
|
|
93
|
-
wireAuthoredTranslationSync: () => wireAuthoredTranslationSync
|
|
95
|
+
wireAuthoredTranslationSync: () => wireAuthoredTranslationSync,
|
|
96
|
+
withTransientRetry: () => withTransientRetry
|
|
94
97
|
});
|
|
95
98
|
module.exports = __toCommonJS(index_exports);
|
|
96
99
|
|
|
@@ -4232,7 +4235,7 @@ async function tryFind(ql, object, where, limit = 100) {
|
|
|
4232
4235
|
async function resolveAuthzContext(input) {
|
|
4233
4236
|
const { ql, headers } = input;
|
|
4234
4237
|
const ctx = {
|
|
4235
|
-
|
|
4238
|
+
positions: [],
|
|
4236
4239
|
permissions: [],
|
|
4237
4240
|
systemPermissions: [],
|
|
4238
4241
|
org_user_ids: []
|
|
@@ -4281,16 +4284,16 @@ async function resolveAuthzContext(input) {
|
|
|
4281
4284
|
if (m.role && typeof m.role === "string") {
|
|
4282
4285
|
for (const raw of m.role.split(",").map((s) => s.trim()).filter(Boolean)) {
|
|
4283
4286
|
const r = (0, import_spec.mapMembershipRole)(raw);
|
|
4284
|
-
if (!ctx.
|
|
4287
|
+
if (!ctx.positions.includes(r)) ctx.positions.push(r);
|
|
4285
4288
|
}
|
|
4286
4289
|
}
|
|
4287
4290
|
}
|
|
4288
|
-
const
|
|
4289
|
-
for (const ur of
|
|
4291
|
+
const userPositionRows = await tryFind(ql, "sys_user_position", { user_id: userId }, 200);
|
|
4292
|
+
for (const ur of userPositionRows) {
|
|
4290
4293
|
const org = ur.organization_id ?? null;
|
|
4291
4294
|
if (org && tenantId && org !== tenantId) continue;
|
|
4292
|
-
const r = ur.
|
|
4293
|
-
if (typeof r === "string" && r && !ctx.
|
|
4295
|
+
const r = ur.position;
|
|
4296
|
+
if (typeof r === "string" && r && !ctx.positions.includes(r)) ctx.positions.push(r);
|
|
4294
4297
|
}
|
|
4295
4298
|
if (tenantId) {
|
|
4296
4299
|
const orgMembers = await tryFind(ql, "sys_member", { organization_id: tenantId }, 1e3);
|
|
@@ -4313,11 +4316,12 @@ async function resolveAuthzContext(input) {
|
|
|
4313
4316
|
upsRows.filter((r) => (r.organization_id ?? r.organizationId ?? null) === null).map((r) => r.permission_set_id ?? r.permissionSetId).filter(Boolean)
|
|
4314
4317
|
);
|
|
4315
4318
|
let hasPlatformAdminGrant = false;
|
|
4316
|
-
if (ctx.
|
|
4317
|
-
|
|
4318
|
-
const
|
|
4319
|
-
|
|
4320
|
-
|
|
4319
|
+
if (!ctx.positions.includes("everyone")) ctx.positions.push("everyone");
|
|
4320
|
+
if (ctx.positions.length > 0) {
|
|
4321
|
+
const positionRows = await tryFind(ql, "sys_position", { name: { $in: ctx.positions } }, 100);
|
|
4322
|
+
const positionIds = positionRows.map((r) => r.id).filter(Boolean);
|
|
4323
|
+
if (positionIds.length > 0) {
|
|
4324
|
+
const rpsRows = await tryFind(ql, "sys_position_permission_set", { position_id: { $in: positionIds } }, 500);
|
|
4321
4325
|
for (const r of rpsRows) {
|
|
4322
4326
|
const id = r.permission_set_id ?? r.permissionSetId;
|
|
4323
4327
|
if (id) psIds.add(id);
|
|
@@ -4350,8 +4354,8 @@ async function resolveAuthzContext(input) {
|
|
|
4350
4354
|
}
|
|
4351
4355
|
if (Object.keys(mergedTabs).length > 0) ctx.tabPermissions = mergedTabs;
|
|
4352
4356
|
}
|
|
4353
|
-
if (hasPlatformAdminGrant && !ctx.
|
|
4354
|
-
ctx.
|
|
4357
|
+
if (hasPlatformAdminGrant && !ctx.positions.includes(import_spec.BUILTIN_IDENTITY_PLATFORM_ADMIN)) {
|
|
4358
|
+
ctx.positions.unshift(import_spec.BUILTIN_IDENTITY_PLATFORM_ADMIN);
|
|
4355
4359
|
}
|
|
4356
4360
|
if (!ctx.permissions.includes("ai_seat")) {
|
|
4357
4361
|
const aiAccess = (await getUserRow())?.ai_access;
|
|
@@ -4463,6 +4467,87 @@ function calendarPartsInTzOrUtc(d, tz) {
|
|
|
4463
4467
|
};
|
|
4464
4468
|
}
|
|
4465
4469
|
|
|
4470
|
+
// src/utils/bulk-write.ts
|
|
4471
|
+
var DEFAULT_BATCH_SIZE = 200;
|
|
4472
|
+
var DEFAULT_MAX_RETRIES = 3;
|
|
4473
|
+
var DEFAULT_BACKOFF_BASE_MS = 200;
|
|
4474
|
+
var TRANSIENT_PATTERNS = [
|
|
4475
|
+
/fetch failed/i,
|
|
4476
|
+
/network/i,
|
|
4477
|
+
/timed?\s*out/i,
|
|
4478
|
+
/timeout/i,
|
|
4479
|
+
/socket hang ?up/i,
|
|
4480
|
+
/connection.*(closed|reset|refused|terminated|aborted)/i,
|
|
4481
|
+
/\b(502|503|504)\b/,
|
|
4482
|
+
/server.*unavailable/i,
|
|
4483
|
+
/too many connections/i
|
|
4484
|
+
];
|
|
4485
|
+
var TRANSIENT_CODES = /^(ECONNRESET|ECONNREFUSED|ECONNABORTED|EPIPE|EAI_AGAIN|ETIMEDOUT|EHOSTUNREACH|ENETUNREACH|ENOTFOUND)$/i;
|
|
4486
|
+
function defaultIsTransientError(err) {
|
|
4487
|
+
const code = err?.code;
|
|
4488
|
+
if (typeof code === "string" && TRANSIENT_CODES.test(code)) return true;
|
|
4489
|
+
const message = err?.message;
|
|
4490
|
+
const text = typeof message === "string" ? message : String(err ?? "");
|
|
4491
|
+
return TRANSIENT_PATTERNS.some((re) => re.test(text));
|
|
4492
|
+
}
|
|
4493
|
+
var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
4494
|
+
async function withRetry(fn, opts) {
|
|
4495
|
+
let lastError;
|
|
4496
|
+
for (let attempt = 1; attempt <= opts.maxRetries; attempt++) {
|
|
4497
|
+
try {
|
|
4498
|
+
return await fn();
|
|
4499
|
+
} catch (err) {
|
|
4500
|
+
lastError = err;
|
|
4501
|
+
if (attempt >= opts.maxRetries || !opts.isTransientError(err)) throw err;
|
|
4502
|
+
const jitter = Math.floor(Math.random() * 50);
|
|
4503
|
+
await opts.sleep(opts.backoffBaseMs * 2 ** (attempt - 1) + jitter);
|
|
4504
|
+
}
|
|
4505
|
+
}
|
|
4506
|
+
throw lastError;
|
|
4507
|
+
}
|
|
4508
|
+
async function withTransientRetry(fn, opts = {}) {
|
|
4509
|
+
return withRetry(fn, {
|
|
4510
|
+
maxRetries: Math.max(1, opts.maxRetries ?? DEFAULT_MAX_RETRIES),
|
|
4511
|
+
backoffBaseMs: opts.backoffBaseMs ?? DEFAULT_BACKOFF_BASE_MS,
|
|
4512
|
+
isTransientError: opts.isTransientError ?? defaultIsTransientError,
|
|
4513
|
+
sleep: opts.sleep ?? defaultSleep
|
|
4514
|
+
});
|
|
4515
|
+
}
|
|
4516
|
+
async function bulkWrite(rows, opts) {
|
|
4517
|
+
const batchSize = Math.max(1, opts.batchSize ?? DEFAULT_BATCH_SIZE);
|
|
4518
|
+
const retryOpts = {
|
|
4519
|
+
maxRetries: Math.max(1, opts.maxRetries ?? DEFAULT_MAX_RETRIES),
|
|
4520
|
+
backoffBaseMs: opts.backoffBaseMs ?? DEFAULT_BACKOFF_BASE_MS,
|
|
4521
|
+
isTransientError: opts.isTransientError ?? defaultIsTransientError,
|
|
4522
|
+
sleep: opts.sleep ?? defaultSleep
|
|
4523
|
+
};
|
|
4524
|
+
const results = new Array(rows.length);
|
|
4525
|
+
for (let start = 0; start < rows.length; start += batchSize) {
|
|
4526
|
+
const batch = rows.slice(start, start + batchSize);
|
|
4527
|
+
try {
|
|
4528
|
+
const records = await withRetry(() => opts.writeBatch(batch), retryOpts);
|
|
4529
|
+
for (let i = 0; i < batch.length; i++) {
|
|
4530
|
+
results[start + i] = { index: start + i, ok: true, record: records[i] };
|
|
4531
|
+
}
|
|
4532
|
+
} catch (batchErr) {
|
|
4533
|
+
if (batch.length === 1) {
|
|
4534
|
+
results[start] = { index: start, ok: false, error: batchErr };
|
|
4535
|
+
continue;
|
|
4536
|
+
}
|
|
4537
|
+
for (let i = 0; i < batch.length; i++) {
|
|
4538
|
+
const idx = start + i;
|
|
4539
|
+
try {
|
|
4540
|
+
const record = await withRetry(() => opts.writeOne(batch[i]), retryOpts);
|
|
4541
|
+
results[idx] = { index: idx, ok: true, record };
|
|
4542
|
+
} catch (err) {
|
|
4543
|
+
results[idx] = { index: idx, ok: false, error: err };
|
|
4544
|
+
}
|
|
4545
|
+
}
|
|
4546
|
+
}
|
|
4547
|
+
}
|
|
4548
|
+
return results;
|
|
4549
|
+
}
|
|
4550
|
+
|
|
4466
4551
|
// src/health-monitor.ts
|
|
4467
4552
|
var PluginHealthMonitor = class {
|
|
4468
4553
|
constructor(logger) {
|
|
@@ -5402,6 +5487,7 @@ var NamespaceResolver = class {
|
|
|
5402
5487
|
SemanticVersionManager,
|
|
5403
5488
|
ServiceLifecycle,
|
|
5404
5489
|
buildPermissionsFromGrants,
|
|
5490
|
+
bulkWrite,
|
|
5405
5491
|
calendarPartsInTz,
|
|
5406
5492
|
calendarPartsInTzOrUtc,
|
|
5407
5493
|
counterSignPayload,
|
|
@@ -5415,6 +5501,7 @@ var NamespaceResolver = class {
|
|
|
5415
5501
|
createPluginConfigValidator,
|
|
5416
5502
|
createPluginPermissionEnforcer,
|
|
5417
5503
|
deepMerge,
|
|
5504
|
+
defaultIsTransientError,
|
|
5418
5505
|
evaluateAuthGate,
|
|
5419
5506
|
extractApiKey,
|
|
5420
5507
|
generateApiKey,
|
|
@@ -5438,6 +5525,7 @@ var NamespaceResolver = class {
|
|
|
5438
5525
|
verifyPlatformSignature,
|
|
5439
5526
|
verifyPluginArtifact,
|
|
5440
5527
|
verifyPublisherSignature,
|
|
5441
|
-
wireAuthoredTranslationSync
|
|
5528
|
+
wireAuthoredTranslationSync,
|
|
5529
|
+
withTransientRetry
|
|
5442
5530
|
});
|
|
5443
5531
|
//# sourceMappingURL=index.cjs.map
|