@axium/core 0.18.2 → 0.19.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/README.md CHANGED
@@ -1 +1,3 @@
1
1
  # Axium Core
2
+
3
+ Axium Core is the shared library of types, schemas, and utilities for the Axium ecosystem.
package/dist/access.d.ts CHANGED
@@ -4,30 +4,38 @@ export declare const AccessControl: z.ZodObject<{
4
4
  itemId: z.ZodUUID;
5
5
  userId: z.ZodOptional<z.ZodNullable<z.ZodUUID>>;
6
6
  role: z.ZodOptional<z.ZodNullable<z.ZodString>>;
7
- user: z.ZodOptional<z.ZodObject<{
7
+ tag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8
+ user: z.ZodOptional<z.ZodNullable<z.ZodObject<{
8
9
  id: z.ZodUUID;
9
10
  name: z.ZodString;
10
- email: z.ZodEmail;
11
- emailVerified: z.ZodOptional<z.ZodNullable<z.ZodCoercedDate<unknown>>>;
11
+ email: z.ZodOptional<z.ZodEmail>;
12
+ emailVerified: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodCoercedDate<unknown>>>>;
12
13
  image: z.ZodOptional<z.ZodNullable<z.ZodURL>>;
13
- preferences: z.ZodLazy<z.ZodObject<{
14
+ preferences: z.ZodOptional<z.ZodLazy<z.ZodObject<{
14
15
  debug: z.ZodDefault<z.ZodBoolean>;
15
- }, z.core.$strip>>;
16
+ }, z.core.$strip>>>;
16
17
  roles: z.ZodArray<z.ZodString>;
17
- tags: z.ZodArray<z.ZodString>;
18
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
18
19
  registeredAt: z.ZodCoercedDate<unknown>;
19
- isAdmin: z.ZodBoolean;
20
- isSuspended: z.ZodBoolean;
21
- }, z.core.$strip>>;
20
+ isAdmin: z.ZodOptional<z.ZodBoolean>;
21
+ isSuspended: z.ZodOptional<z.ZodBoolean>;
22
+ }, z.core.$strip>>>;
22
23
  createdAt: z.ZodCoercedDate<unknown>;
23
- }, z.core.$strip>;
24
+ }, z.core.$loose>;
24
25
  export interface AccessControl extends z.infer<typeof AccessControl> {
25
26
  }
26
- export declare function pickPermissions<T extends AccessControl & object>(ac: T): Omit<T, 'itemId' | 'userId' | 'role' | 'user' | 'createdAt'>;
27
+ export declare function getTarget(ac: AccessControl): AccessTarget;
28
+ export declare function fromTarget(target: AccessTarget): Partial<Pick<AccessControl, 'userId' | 'role' | 'tag'>>;
29
+ export declare function pickPermissions<T extends AccessControl & object>(ac: T): Omit<T, 'itemId' | 'userId' | 'role' | 'tag' | 'user' | 'createdAt'>;
27
30
  export interface AccessControllable {
28
31
  userId: string;
29
32
  acl?: AccessControl[];
30
33
  }
31
- export declare const AccessMap: z.ZodRecord<z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<"public">]>, z.ZodAny>;
32
- export interface AccessMap extends z.infer<typeof AccessMap> {
34
+ export declare const AccessTarget: z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<"public">]>;
35
+ export type AccessTarget = z.infer<typeof AccessTarget>;
36
+ export declare const AccessControlUpdate: z.ZodObject<{
37
+ target: z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<"public">]>;
38
+ permissions: z.ZodRecord<z.ZodString, z.ZodAny>;
39
+ }, z.core.$strip>;
40
+ export interface AccessControlUpdate extends z.infer<typeof AccessControlUpdate> {
33
41
  }
package/dist/access.js CHANGED
@@ -1,14 +1,42 @@
1
1
  import * as z from 'zod';
2
- import { User } from './user.js';
2
+ import { UserPublic } from './user.js';
3
3
  import { omit } from 'utilium';
4
- export const AccessControl = z.object({
4
+ export const AccessControl = z.looseObject({
5
5
  itemId: z.uuid(),
6
6
  userId: z.uuid().nullish(),
7
7
  role: z.string().nullish(),
8
- user: User.optional(),
8
+ tag: z.string().nullish(),
9
+ user: UserPublic.nullish(),
9
10
  createdAt: z.coerce.date(),
10
11
  });
12
+ export function getTarget(ac) {
13
+ if (ac.userId)
14
+ return ac.userId;
15
+ if (ac.role)
16
+ return '@' + ac.role;
17
+ if (ac.tag)
18
+ return '#' + ac.tag;
19
+ return 'public';
20
+ }
21
+ export function fromTarget(target) {
22
+ if (target == 'public')
23
+ return { userId: null, role: null, tag: null };
24
+ if (target[0] == '@')
25
+ return { userId: null, role: target.slice(1), tag: null };
26
+ if (target[0] == '#')
27
+ return { userId: null, role: null, tag: target.slice(1) };
28
+ return { userId: target, role: null, tag: null };
29
+ }
11
30
  export function pickPermissions(ac) {
12
- return omit(ac, ['itemId', 'userId', 'role', 'user', 'createdAt']);
31
+ return omit(ac, 'itemId', 'userId', 'role', 'tag', 'user', 'createdAt');
13
32
  }
14
- export const AccessMap = z.record(z.union([z.uuid(), z.templateLiteral(['@', z.string()]), z.templateLiteral(['#', z.string()]), z.literal('public')]), z.any());
33
+ export const AccessTarget = z.union([
34
+ z.uuid(),
35
+ z.templateLiteral(['@', z.string()]),
36
+ z.templateLiteral(['#', z.string()]),
37
+ z.literal('public'),
38
+ ]);
39
+ export const AccessControlUpdate = z.object({
40
+ target: AccessTarget,
41
+ permissions: z.record(z.string(), z.any()),
42
+ });
package/dist/api.d.ts CHANGED
@@ -185,6 +185,23 @@ declare const _API: {
185
185
  isSuspended: z.ZodBoolean;
186
186
  }, z.core.$strip>;
187
187
  };
188
+ readonly 'users/discover': {
189
+ readonly POST: [z.ZodString, z.ZodArray<z.ZodObject<{
190
+ id: z.ZodUUID;
191
+ name: z.ZodString;
192
+ email: z.ZodOptional<z.ZodEmail>;
193
+ emailVerified: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodCoercedDate<unknown>>>>;
194
+ image: z.ZodOptional<z.ZodNullable<z.ZodURL>>;
195
+ preferences: z.ZodOptional<z.ZodLazy<z.ZodObject<{
196
+ debug: z.ZodDefault<z.ZodBoolean>;
197
+ }, z.core.$strip>>>;
198
+ roles: z.ZodArray<z.ZodString>;
199
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
200
+ registeredAt: z.ZodCoercedDate<unknown>;
201
+ isAdmin: z.ZodOptional<z.ZodBoolean>;
202
+ isSuspended: z.ZodOptional<z.ZodBoolean>;
203
+ }, z.core.$strip>>];
204
+ };
188
205
  readonly 'users/:id/full': {
189
206
  readonly GET: z.ZodObject<{
190
207
  sessions: z.ZodArray<z.ZodObject<{
@@ -392,44 +409,93 @@ declare const _API: {
392
409
  itemId: z.ZodUUID;
393
410
  userId: z.ZodOptional<z.ZodNullable<z.ZodUUID>>;
394
411
  role: z.ZodOptional<z.ZodNullable<z.ZodString>>;
395
- user: z.ZodOptional<z.ZodObject<{
412
+ tag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
413
+ user: z.ZodOptional<z.ZodNullable<z.ZodObject<{
396
414
  id: z.ZodUUID;
397
415
  name: z.ZodString;
398
- email: z.ZodEmail;
399
- emailVerified: z.ZodOptional<z.ZodNullable<z.ZodCoercedDate<unknown>>>;
416
+ email: z.ZodOptional<z.ZodEmail>;
417
+ emailVerified: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodCoercedDate<unknown>>>>;
400
418
  image: z.ZodOptional<z.ZodNullable<z.ZodURL>>;
401
- preferences: z.ZodLazy<z.ZodObject<{
419
+ preferences: z.ZodOptional<z.ZodLazy<z.ZodObject<{
402
420
  debug: z.ZodDefault<z.ZodBoolean>;
403
- }, z.core.$strip>>;
421
+ }, z.core.$strip>>>;
404
422
  roles: z.ZodArray<z.ZodString>;
405
- tags: z.ZodArray<z.ZodString>;
423
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
406
424
  registeredAt: z.ZodCoercedDate<unknown>;
407
- isAdmin: z.ZodBoolean;
408
- isSuspended: z.ZodBoolean;
409
- }, z.core.$strip>>;
425
+ isAdmin: z.ZodOptional<z.ZodBoolean>;
426
+ isSuspended: z.ZodOptional<z.ZodBoolean>;
427
+ }, z.core.$strip>>>;
410
428
  createdAt: z.ZodCoercedDate<unknown>;
411
- }, z.core.$strip>>;
412
- readonly POST: [z.ZodRecord<z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<"public">]>, z.ZodAny>, z.ZodArray<z.ZodObject<{
429
+ }, z.core.$loose>>;
430
+ readonly PATCH: [z.ZodObject<{
431
+ target: z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<"public">]>;
432
+ permissions: z.ZodRecord<z.ZodString, z.ZodAny>;
433
+ }, z.core.$strip>, z.ZodObject<{
413
434
  itemId: z.ZodUUID;
414
435
  userId: z.ZodOptional<z.ZodNullable<z.ZodUUID>>;
415
436
  role: z.ZodOptional<z.ZodNullable<z.ZodString>>;
416
- user: z.ZodOptional<z.ZodObject<{
437
+ tag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
438
+ user: z.ZodOptional<z.ZodNullable<z.ZodObject<{
417
439
  id: z.ZodUUID;
418
440
  name: z.ZodString;
419
- email: z.ZodEmail;
420
- emailVerified: z.ZodOptional<z.ZodNullable<z.ZodCoercedDate<unknown>>>;
441
+ email: z.ZodOptional<z.ZodEmail>;
442
+ emailVerified: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodCoercedDate<unknown>>>>;
421
443
  image: z.ZodOptional<z.ZodNullable<z.ZodURL>>;
422
- preferences: z.ZodLazy<z.ZodObject<{
444
+ preferences: z.ZodOptional<z.ZodLazy<z.ZodObject<{
423
445
  debug: z.ZodDefault<z.ZodBoolean>;
424
- }, z.core.$strip>>;
446
+ }, z.core.$strip>>>;
425
447
  roles: z.ZodArray<z.ZodString>;
426
- tags: z.ZodArray<z.ZodString>;
448
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
427
449
  registeredAt: z.ZodCoercedDate<unknown>;
428
- isAdmin: z.ZodBoolean;
429
- isSuspended: z.ZodBoolean;
430
- }, z.core.$strip>>;
450
+ isAdmin: z.ZodOptional<z.ZodBoolean>;
451
+ isSuspended: z.ZodOptional<z.ZodBoolean>;
452
+ }, z.core.$strip>>>;
431
453
  createdAt: z.ZodCoercedDate<unknown>;
432
- }, z.core.$strip>>];
454
+ }, z.core.$loose>];
455
+ readonly PUT: [z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<"public">]>, z.ZodObject<{
456
+ itemId: z.ZodUUID;
457
+ userId: z.ZodOptional<z.ZodNullable<z.ZodUUID>>;
458
+ role: z.ZodOptional<z.ZodNullable<z.ZodString>>;
459
+ tag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
460
+ user: z.ZodOptional<z.ZodNullable<z.ZodObject<{
461
+ id: z.ZodUUID;
462
+ name: z.ZodString;
463
+ email: z.ZodOptional<z.ZodEmail>;
464
+ emailVerified: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodCoercedDate<unknown>>>>;
465
+ image: z.ZodOptional<z.ZodNullable<z.ZodURL>>;
466
+ preferences: z.ZodOptional<z.ZodLazy<z.ZodObject<{
467
+ debug: z.ZodDefault<z.ZodBoolean>;
468
+ }, z.core.$strip>>>;
469
+ roles: z.ZodArray<z.ZodString>;
470
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
471
+ registeredAt: z.ZodCoercedDate<unknown>;
472
+ isAdmin: z.ZodOptional<z.ZodBoolean>;
473
+ isSuspended: z.ZodOptional<z.ZodBoolean>;
474
+ }, z.core.$strip>>>;
475
+ createdAt: z.ZodCoercedDate<unknown>;
476
+ }, z.core.$loose>];
477
+ readonly DELETE: [z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<"public">]>, z.ZodObject<{
478
+ itemId: z.ZodUUID;
479
+ userId: z.ZodOptional<z.ZodNullable<z.ZodUUID>>;
480
+ role: z.ZodOptional<z.ZodNullable<z.ZodString>>;
481
+ tag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
482
+ user: z.ZodOptional<z.ZodNullable<z.ZodObject<{
483
+ id: z.ZodUUID;
484
+ name: z.ZodString;
485
+ email: z.ZodOptional<z.ZodEmail>;
486
+ emailVerified: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodCoercedDate<unknown>>>>;
487
+ image: z.ZodOptional<z.ZodNullable<z.ZodURL>>;
488
+ preferences: z.ZodOptional<z.ZodLazy<z.ZodObject<{
489
+ debug: z.ZodDefault<z.ZodBoolean>;
490
+ }, z.core.$strip>>>;
491
+ roles: z.ZodArray<z.ZodString>;
492
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
493
+ registeredAt: z.ZodCoercedDate<unknown>;
494
+ isAdmin: z.ZodOptional<z.ZodBoolean>;
495
+ isSuspended: z.ZodOptional<z.ZodBoolean>;
496
+ }, z.core.$strip>>>;
497
+ createdAt: z.ZodCoercedDate<unknown>;
498
+ }, z.core.$loose>];
433
499
  };
434
500
  readonly 'admin/summary': {
435
501
  readonly GET: z.ZodObject<{
package/dist/api.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as z from 'zod';
2
- import { AccessControl, AccessMap } from './access.js';
2
+ import { AccessControl, AccessControlUpdate, AccessTarget } from './access.js';
3
3
  import { App } from './apps.js';
4
4
  import { AuditEvent, AuditFilter, Severity } from './audit.js';
5
5
  import { NewSessionResponse, Session, Verification, VerificationInternal } from './auth.js';
@@ -43,6 +43,9 @@ const _API = {
43
43
  PATCH: [UserChangeable, User],
44
44
  DELETE: User,
45
45
  },
46
+ 'users/discover': {
47
+ POST: [z.string(), UserPublic.array()],
48
+ },
46
49
  'users/:id/full': {
47
50
  GET: z.object({ ...User.shape, sessions: Session.array() }),
48
51
  },
@@ -77,7 +80,9 @@ const _API = {
77
80
  },
78
81
  'acl/:itemType/:itemId': {
79
82
  GET: AccessControl.array(),
80
- POST: [AccessMap, AccessControl.array()],
83
+ PATCH: [AccessControlUpdate, AccessControl],
84
+ PUT: [AccessTarget, AccessControl],
85
+ DELETE: [AccessTarget, AccessControl],
81
86
  },
82
87
  'admin/summary': {
83
88
  GET: AdminSummary,
@@ -1,5 +1,4 @@
1
1
  import type { PackageVersionInfo } from '../packages.js';
2
- export declare function locatePackage(specifier: string, loadedBy: string): string;
3
2
  export declare function setPackageCacheTTL(seconds: number): void;
4
3
  /**
5
4
  * @param name Package name
@@ -1,26 +1,10 @@
1
1
  import * as fs from 'node:fs';
2
- import { dirname, join, resolve } from 'node:path/posix';
3
- import { fileURLToPath } from 'node:url';
2
+ import { findPackageJSON } from 'node:module';
4
3
  import { lt as ltVersion } from 'semver';
5
4
  import { warn } from '../io.js';
6
5
  function isRelative(specifier) {
7
6
  return specifier[0] == '/' || ['.', '..'].includes(specifier.split('/')[0]);
8
7
  }
9
- export function locatePackage(specifier, loadedBy) {
10
- if (isRelative(specifier)) {
11
- const path = resolve(dirname(loadedBy), specifier);
12
- const stats = fs.statSync(path);
13
- if (stats.isFile())
14
- return path;
15
- if (!stats.isDirectory())
16
- throw new Error('Can not resolve package path: ' + path);
17
- return join(path, 'package.json');
18
- }
19
- let packageDir = dirname(fileURLToPath(import.meta.resolve(specifier)));
20
- for (; !fs.existsSync(join(packageDir, 'package.json')); packageDir = dirname(packageDir))
21
- ;
22
- return join(packageDir, 'package.json');
23
- }
24
8
  let cacheTTL = 1000 * 60 * 60;
25
9
  export function setPackageCacheTTL(seconds) {
26
10
  cacheTTL = seconds * 1000;
@@ -31,7 +15,9 @@ const cache = new Map();
31
15
  * @param version The current/installed version
32
16
  */
33
17
  export async function getVersionInfo(specifier, from = import.meta.filename) {
34
- const path = locatePackage(specifier, from);
18
+ const path = findPackageJSON(specifier, from);
19
+ if (!path)
20
+ throw new Error(`Cannot find package.json for package ${specifier} (from ${from})`);
35
21
  const { version, name } = JSON.parse(fs.readFileSync(path, 'utf8'));
36
22
  const info = { name, version, latest: null };
37
23
  if (isRelative(specifier))
@@ -1,11 +1,11 @@
1
1
  import * as io from '@axium/core/node/io';
2
2
  import { Plugin, plugins } from '@axium/core/plugins';
3
3
  import * as fs from 'node:fs';
4
+ import { findPackageJSON } from 'node:module';
4
5
  import { dirname, resolve } from 'node:path/posix';
5
6
  import { styleText } from 'node:util';
6
7
  import { _throw } from 'utilium';
7
8
  import { apps } from '../apps.js';
8
- import { locatePackage } from './packages.js';
9
9
  export function* pluginText(plugin) {
10
10
  yield styleText('whiteBright', plugin.name);
11
11
  yield `Version: ${plugin.version}`;
@@ -21,7 +21,9 @@ export function* pluginText(plugin) {
21
21
  }
22
22
  export async function loadPlugin(mode, specifier, loadedBy, safeMode = false) {
23
23
  try {
24
- const path = locatePackage(specifier, loadedBy);
24
+ const path = findPackageJSON(specifier, loadedBy);
25
+ if (!path)
26
+ throw new Error(`Cannot find package.json for package ${specifier} (from ${loadedBy})`);
25
27
  io.debug(`Loading plugin at ${path} (from ${loadedBy})`);
26
28
  let imported;
27
29
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axium/core",
3
- "version": "0.18.2",
3
+ "version": "0.19.1",
4
4
  "author": "James Prevett <axium@jamespre.dev>",
5
5
  "funding": {
6
6
  "type": "individual",