@brika/permissions 0.3.1
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/package.json +23 -0
- package/src/__tests__/permissions.test.ts +56 -0
- package/src/index.ts +12 -0
- package/src/registry.ts +46 -0
- package/tsconfig.json +4 -0
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@brika/permissions",
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "Plugin permission definitions and validation for BRIKA",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/brikalabs/brika.git",
|
|
10
|
+
"directory": "packages/permissions"
|
|
11
|
+
},
|
|
12
|
+
"keywords": ["brika", "permissions", "validation"],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./src/index.ts"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"typecheck": "tsgo --noEmit",
|
|
18
|
+
"test": "bun test"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/bun": "^1.3.9"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import { filterValidPermissions, isValidPermission, PERMISSION_LIST, PERMISSIONS } from '..';
|
|
3
|
+
|
|
4
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
5
|
+
// isValidPermission
|
|
6
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
7
|
+
|
|
8
|
+
describe('isValidPermission', () => {
|
|
9
|
+
test('accepts known permissions', () => {
|
|
10
|
+
expect(isValidPermission('location')).toBe(true);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test('rejects unknown strings', () => {
|
|
14
|
+
expect(isValidPermission('network')).toBe(false);
|
|
15
|
+
expect(isValidPermission('')).toBe(false);
|
|
16
|
+
expect(isValidPermission('Location')).toBe(false);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
21
|
+
// filterValidPermissions
|
|
22
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
describe('filterValidPermissions', () => {
|
|
25
|
+
test('keeps valid permissions, drops invalid', () => {
|
|
26
|
+
expect(filterValidPermissions(['location', 'network', 'bogus'])).toEqual(['location']);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('returns empty for all invalid', () => {
|
|
30
|
+
expect(filterValidPermissions(['x', 'y'])).toEqual([]);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('returns empty for empty input', () => {
|
|
34
|
+
expect(filterValidPermissions([])).toEqual([]);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
39
|
+
// PERMISSIONS registry
|
|
40
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
describe('PERMISSIONS registry', () => {
|
|
43
|
+
test('has metadata for each permission', () => {
|
|
44
|
+
expect(PERMISSIONS.location).toEqual({
|
|
45
|
+
id: 'location',
|
|
46
|
+
icon: 'map-pin',
|
|
47
|
+
labelKey: 'plugins:permissions.location',
|
|
48
|
+
descriptionKey: 'plugins:permissions.locationDesc',
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('PERMISSION_LIST matches PERMISSIONS values', () => {
|
|
53
|
+
expect(PERMISSION_LIST).toEqual(Object.values(PERMISSIONS));
|
|
54
|
+
expect(PERMISSION_LIST.length).toBeGreaterThan(0);
|
|
55
|
+
});
|
|
56
|
+
});
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createRegistry } from './registry';
|
|
2
|
+
|
|
3
|
+
// Add new permissions here.
|
|
4
|
+
export const { PERMISSIONS, PERMISSION_LIST, isValidPermission, filterValidPermissions } =
|
|
5
|
+
createRegistry({
|
|
6
|
+
location: {
|
|
7
|
+
icon: 'map-pin',
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export type Permission = keyof typeof PERMISSIONS;
|
|
12
|
+
export type { PermissionDefinition } from './registry';
|
package/src/registry.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface PermissionDefinition {
|
|
2
|
+
readonly id: string;
|
|
3
|
+
readonly icon: string;
|
|
4
|
+
readonly labelKey: string;
|
|
5
|
+
readonly descriptionKey: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function createRegistry<
|
|
9
|
+
T extends Record<
|
|
10
|
+
string,
|
|
11
|
+
{
|
|
12
|
+
icon: string;
|
|
13
|
+
}
|
|
14
|
+
>,
|
|
15
|
+
>(map: T) {
|
|
16
|
+
type P = keyof T & string;
|
|
17
|
+
|
|
18
|
+
const PERMISSIONS = Object.fromEntries(
|
|
19
|
+
Object.entries(map).map(([id, meta]) => [
|
|
20
|
+
id,
|
|
21
|
+
{
|
|
22
|
+
id,
|
|
23
|
+
...meta,
|
|
24
|
+
labelKey: `plugins:permissions.${id}`,
|
|
25
|
+
descriptionKey: `plugins:permissions.${id}Desc`,
|
|
26
|
+
},
|
|
27
|
+
])
|
|
28
|
+
) as Readonly<Record<P, PermissionDefinition>>;
|
|
29
|
+
|
|
30
|
+
const PERMISSION_LIST: readonly PermissionDefinition[] = Object.values(PERMISSIONS);
|
|
31
|
+
|
|
32
|
+
function isValidPermission(value: string): value is P {
|
|
33
|
+
return Object.hasOwn(PERMISSIONS, value);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function filterValidPermissions(values: string[]): P[] {
|
|
37
|
+
return values.filter(isValidPermission);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
PERMISSIONS,
|
|
42
|
+
PERMISSION_LIST,
|
|
43
|
+
isValidPermission,
|
|
44
|
+
filterValidPermissions,
|
|
45
|
+
};
|
|
46
|
+
}
|
package/tsconfig.json
ADDED