@objectstack/plugin-sharing 9.2.0 → 9.3.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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +20 -0
- package/dist/index.d.mts +102 -3
- package/dist/index.d.ts +102 -3
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/src/share-link-routes.ts +1 -1
- package/src/sharing-rule-service.ts +1 -1
- package/src/sharing-service.test.ts +25 -1
- package/src/sharing-service.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/plugin-sharing",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.3.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Record-level sharing for ObjectStack — sys_record_share + middleware that enforces sharingModel + ISharingService.",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@objectstack/core": "9.
|
|
17
|
-
"@objectstack/objectql": "9.
|
|
18
|
-
"@objectstack/platform-objects": "9.
|
|
19
|
-
"@objectstack/spec": "9.
|
|
16
|
+
"@objectstack/core": "9.3.0",
|
|
17
|
+
"@objectstack/objectql": "9.3.0",
|
|
18
|
+
"@objectstack/platform-objects": "9.3.0",
|
|
19
|
+
"@objectstack/spec": "9.3.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^25.9.2",
|
package/src/share-link-routes.ts
CHANGED
|
@@ -249,7 +249,7 @@ export function registerShareLinkRoutes(
|
|
|
249
249
|
const SYSTEM_CTX = { isSystem: true, roles: [], permissions: [] } as const;
|
|
250
250
|
const rows = await engine.find('ai_messages', {
|
|
251
251
|
where: { conversation_id: resolved.link.record_id },
|
|
252
|
-
sort: [{ field: 'created_at',
|
|
252
|
+
sort: [{ field: 'created_at', order: 'asc' }],
|
|
253
253
|
limit: 500,
|
|
254
254
|
context: SYSTEM_CTX,
|
|
255
255
|
} as any);
|
|
@@ -149,7 +149,7 @@ export class SharingRuleService implements ISharingRuleService {
|
|
|
149
149
|
if (orgId) where.organization_id = orgId;
|
|
150
150
|
const rows = await this.engine.find('sys_sharing_rule', {
|
|
151
151
|
filter: where,
|
|
152
|
-
orderBy: [{ field: 'name',
|
|
152
|
+
orderBy: [{ field: 'name', order: 'asc' }],
|
|
153
153
|
limit: 1000,
|
|
154
154
|
context: SYSTEM_CTX,
|
|
155
155
|
});
|
|
@@ -42,7 +42,20 @@ function makeFakeEngine(schemas: Record<string, any>) {
|
|
|
42
42
|
async find(object: string, options?: any) {
|
|
43
43
|
const table = ensure(object);
|
|
44
44
|
const filter = options?.filter ?? options?.where;
|
|
45
|
-
|
|
45
|
+
let out = table.filter(r => matches(r, filter));
|
|
46
|
+
if (options?.orderBy?.[0]) {
|
|
47
|
+
// Canonical SortNode key only (spec/data/query.zod.ts): the real
|
|
48
|
+
// engine strips an unknown `direction:` key and defaults to asc, so
|
|
49
|
+
// the mock must too — honoring both keys masks wrong-key sorts.
|
|
50
|
+
const { field, order } = options.orderBy[0];
|
|
51
|
+
out = [...out].sort((a, b) => {
|
|
52
|
+
const av = a[field]; const bv = b[field];
|
|
53
|
+
if (av === bv) return 0;
|
|
54
|
+
const cmp = av > bv ? 1 : -1;
|
|
55
|
+
return order === 'desc' ? -cmp : cmp;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return out.slice(0, options?.limit ?? 1000);
|
|
46
59
|
},
|
|
47
60
|
async insert(object: string, data: any) {
|
|
48
61
|
const row = { ...data };
|
|
@@ -236,6 +249,17 @@ describe('SharingService.grant / listShares / revoke', () => {
|
|
|
236
249
|
expect(rows.length).toBe(2);
|
|
237
250
|
});
|
|
238
251
|
|
|
252
|
+
it('listShares returns the newest grant first', async () => {
|
|
253
|
+
// Regression: the query sorted with the non-canonical `direction: 'desc'`
|
|
254
|
+
// key, which SortNode strips — so it sorted ascending (oldest first).
|
|
255
|
+
engine._tables.sys_record_share = [
|
|
256
|
+
{ id: 'shr_old', object_name: 'account', record_id: 'a1', recipient_id: 'bob', created_at: '2026-01-01T00:00:00Z' },
|
|
257
|
+
{ id: 'shr_new', object_name: 'account', record_id: 'a1', recipient_id: 'carol', created_at: '2026-02-01T00:00:00Z' },
|
|
258
|
+
];
|
|
259
|
+
const rows = await svc.listShares('account', 'a1', { userId: 'admin' });
|
|
260
|
+
expect(rows.map(r => r.id)).toEqual(['shr_new', 'shr_old']);
|
|
261
|
+
});
|
|
262
|
+
|
|
239
263
|
it('revoke removes the row', async () => {
|
|
240
264
|
const r = await svc.grant({ object: 'account', recordId: 'a1', recipientId: 'bob' }, { userId: 'admin' });
|
|
241
265
|
await svc.revoke(r.id, { userId: 'admin' });
|
package/src/sharing-service.ts
CHANGED
|
@@ -266,7 +266,7 @@ export class SharingService implements ISharingService {
|
|
|
266
266
|
): Promise<RecordShare[]> {
|
|
267
267
|
const rows = await this.engine.find('sys_record_share', {
|
|
268
268
|
filter: { object_name: object, record_id: recordId },
|
|
269
|
-
orderBy: [{ field: 'created_at',
|
|
269
|
+
orderBy: [{ field: 'created_at', order: 'desc' }],
|
|
270
270
|
limit: 500,
|
|
271
271
|
context: SYSTEM_CTX,
|
|
272
272
|
});
|