@axium/core 0.22.2 → 0.24.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/access.d.ts +24 -5
- package/dist/access.js +38 -4
- package/dist/api.d.ts +4 -4
- package/dist/node/index.d.ts +0 -1
- package/dist/node/index.js +0 -1
- package/dist/node/plugins.js +1 -1
- package/dist/packages.js +1 -1
- package/dist/plugins.js +1 -1
- package/package.json +2 -1
- package/dist/io.d.ts +0 -42
- package/dist/io.js +0 -65
- package/dist/node/io.d.ts +0 -16
- package/dist/node/io.js +0 -243
package/dist/access.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import * as z from 'zod';
|
|
2
1
|
import { type Omit } from 'utilium';
|
|
2
|
+
import * as z from 'zod';
|
|
3
|
+
import { UserPublic } from './user.js';
|
|
3
4
|
export declare const AccessControl: z.ZodObject<{
|
|
4
5
|
itemId: z.ZodUUID;
|
|
5
6
|
userId: z.ZodOptional<z.ZodNullable<z.ZodUUID>>;
|
|
@@ -25,19 +26,37 @@ export declare const AccessControl: z.ZodObject<{
|
|
|
25
26
|
export interface AccessControl extends z.infer<typeof AccessControl> {
|
|
26
27
|
}
|
|
27
28
|
export declare function getTarget(ac: AccessControl): AccessTarget;
|
|
28
|
-
export declare function fromTarget(target: AccessTarget):
|
|
29
|
-
export declare function
|
|
29
|
+
export declare function fromTarget(target: AccessTarget): Pick<AccessControl, 'userId' | 'role' | 'tag'>;
|
|
30
|
+
export declare function controlMatchesUser(control: AccessControl, user?: Pick<UserPublic, 'id' | 'roles' | 'tags'>): boolean;
|
|
31
|
+
type NonPermKeys = keyof (typeof AccessControl)['shape'];
|
|
32
|
+
export type PickPermissions<T extends AccessControl> = Omit<T, NonPermKeys>;
|
|
33
|
+
export declare function pickPermissions<T extends AccessControl>(ac: T): PickPermissions<T>;
|
|
34
|
+
/**
|
|
35
|
+
* Check an ACL against a set of permissions.
|
|
36
|
+
* Returns the set of permissions that are missing.
|
|
37
|
+
*/
|
|
38
|
+
export declare function checkACL<const AC extends AccessControl>(acl: AC[], permissions: Partial<PickPermissions<AC>>): Set<keyof PickPermissions<AC>>;
|
|
39
|
+
/**
|
|
40
|
+
* Check an ACL against a set of permissions and a user.
|
|
41
|
+
* Returns the set of permissions that are missing for the user.
|
|
42
|
+
*/
|
|
43
|
+
export declare function checkAndMatchACL<const AC extends AccessControl>(acl: AC[], user: Pick<UserPublic, 'id' | 'roles' | 'tags'>, permissions: Partial<PickPermissions<AC>>): Set<keyof PickPermissions<AC>>;
|
|
30
44
|
export interface AccessControllable {
|
|
31
45
|
id: string;
|
|
32
46
|
userId: string;
|
|
33
47
|
parentId?: string | null;
|
|
34
48
|
acl?: AccessControl[];
|
|
35
49
|
}
|
|
36
|
-
export declare const AccessTarget: z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<
|
|
50
|
+
export declare const AccessTarget: z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<null>]>;
|
|
51
|
+
/**
|
|
52
|
+
* A primitive representation for the target of an access control.
|
|
53
|
+
*
|
|
54
|
+
*/
|
|
37
55
|
export type AccessTarget = z.infer<typeof AccessTarget>;
|
|
38
56
|
export declare const AccessControlUpdate: z.ZodObject<{
|
|
39
|
-
target: z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<
|
|
57
|
+
target: z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<null>]>;
|
|
40
58
|
permissions: z.ZodRecord<z.ZodString, z.ZodAny>;
|
|
41
59
|
}, z.core.$strip>;
|
|
42
60
|
export interface AccessControlUpdate extends z.infer<typeof AccessControlUpdate> {
|
|
43
61
|
}
|
|
62
|
+
export {};
|
package/dist/access.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { omit } from 'utilium';
|
|
1
2
|
import * as z from 'zod';
|
|
2
3
|
import { UserPublic } from './user.js';
|
|
3
|
-
import { omit } from 'utilium';
|
|
4
4
|
export const AccessControl = z
|
|
5
5
|
.object({
|
|
6
6
|
itemId: z.uuid(),
|
|
@@ -18,10 +18,10 @@ export function getTarget(ac) {
|
|
|
18
18
|
return '@' + ac.role;
|
|
19
19
|
if (ac.tag)
|
|
20
20
|
return '#' + ac.tag;
|
|
21
|
-
return
|
|
21
|
+
return null;
|
|
22
22
|
}
|
|
23
23
|
export function fromTarget(target) {
|
|
24
|
-
if (target ==
|
|
24
|
+
if (target == null)
|
|
25
25
|
return { userId: null, role: null, tag: null };
|
|
26
26
|
if (target[0] == '@')
|
|
27
27
|
return { userId: null, role: target.slice(1), tag: null };
|
|
@@ -29,14 +29,48 @@ export function fromTarget(target) {
|
|
|
29
29
|
return { userId: null, role: null, tag: target.slice(1) };
|
|
30
30
|
return { userId: target, role: null, tag: null };
|
|
31
31
|
}
|
|
32
|
+
export function controlMatchesUser(control, user) {
|
|
33
|
+
if (!control.role && !control.tag && !control.userId)
|
|
34
|
+
return true;
|
|
35
|
+
if (!user)
|
|
36
|
+
return false;
|
|
37
|
+
return !!(control.userId === user.id ||
|
|
38
|
+
(control.role && user.roles.includes(control.role)) ||
|
|
39
|
+
(control.tag && user.tags?.includes(control.tag)));
|
|
40
|
+
}
|
|
32
41
|
export function pickPermissions(ac) {
|
|
33
42
|
return omit(ac, 'itemId', 'userId', 'role', 'tag', 'user', 'createdAt');
|
|
34
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Check an ACL against a set of permissions.
|
|
46
|
+
* Returns the set of permissions that are missing.
|
|
47
|
+
*/
|
|
48
|
+
export function checkACL(acl, permissions) {
|
|
49
|
+
const allowed = new Set();
|
|
50
|
+
const all = new Set(Object.keys(permissions));
|
|
51
|
+
const entries = Object.entries(permissions);
|
|
52
|
+
for (const control of acl) {
|
|
53
|
+
for (const [key, needed] of entries) {
|
|
54
|
+
const value = control[key];
|
|
55
|
+
if (value === needed)
|
|
56
|
+
allowed.add(key);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return all.difference(allowed);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check an ACL against a set of permissions and a user.
|
|
63
|
+
* Returns the set of permissions that are missing for the user.
|
|
64
|
+
*/
|
|
65
|
+
export function checkAndMatchACL(acl, user, permissions) {
|
|
66
|
+
const filtered = acl.filter(c => controlMatchesUser(c, user));
|
|
67
|
+
return checkACL(filtered, permissions);
|
|
68
|
+
}
|
|
35
69
|
export const AccessTarget = z.union([
|
|
36
70
|
z.uuid(),
|
|
37
71
|
z.templateLiteral(['@', z.string()]),
|
|
38
72
|
z.templateLiteral(['#', z.string()]),
|
|
39
|
-
z.literal(
|
|
73
|
+
z.literal(null),
|
|
40
74
|
]);
|
|
41
75
|
export const AccessControlUpdate = z.object({
|
|
42
76
|
target: AccessTarget,
|
package/dist/api.d.ts
CHANGED
|
@@ -434,7 +434,7 @@ declare const _API: {
|
|
|
434
434
|
createdAt: z.ZodCoercedDate<unknown>;
|
|
435
435
|
}, z.core.$catchall<z.ZodBoolean>>>;
|
|
436
436
|
readonly PATCH: [z.ZodObject<{
|
|
437
|
-
target: z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<
|
|
437
|
+
target: z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<null>]>;
|
|
438
438
|
permissions: z.ZodRecord<z.ZodString, z.ZodAny>;
|
|
439
439
|
}, z.core.$strip>, z.ZodObject<{
|
|
440
440
|
itemId: z.ZodUUID;
|
|
@@ -458,7 +458,7 @@ declare const _API: {
|
|
|
458
458
|
}, z.core.$strip>>>;
|
|
459
459
|
createdAt: z.ZodCoercedDate<unknown>;
|
|
460
460
|
}, z.core.$catchall<z.ZodBoolean>>];
|
|
461
|
-
readonly PUT: [z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<
|
|
461
|
+
readonly PUT: [z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<null>]>, z.ZodObject<{
|
|
462
462
|
itemId: z.ZodUUID;
|
|
463
463
|
userId: z.ZodOptional<z.ZodNullable<z.ZodUUID>>;
|
|
464
464
|
role: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -480,7 +480,7 @@ declare const _API: {
|
|
|
480
480
|
}, z.core.$strip>>>;
|
|
481
481
|
createdAt: z.ZodCoercedDate<unknown>;
|
|
482
482
|
}, z.core.$catchall<z.ZodBoolean>>];
|
|
483
|
-
readonly DELETE: [z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<
|
|
483
|
+
readonly DELETE: [z.ZodUnion<readonly [z.ZodUUID, z.ZodTemplateLiteral<`@${string}`>, z.ZodTemplateLiteral<`#${string}`>, z.ZodLiteral<null>]>, z.ZodObject<{
|
|
484
484
|
itemId: z.ZodUUID;
|
|
485
485
|
userId: z.ZodOptional<z.ZodNullable<z.ZodUUID>>;
|
|
486
486
|
role: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -601,9 +601,9 @@ declare const _API: {
|
|
|
601
601
|
hooks: z.ZodOptional<z.ZodString>;
|
|
602
602
|
integrations: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
603
603
|
}, z.core.$strip>>;
|
|
604
|
+
description: z.ZodOptional<z.ZodString>;
|
|
604
605
|
version: z.ZodString;
|
|
605
606
|
cli: z.ZodOptional<z.ZodString>;
|
|
606
|
-
description: z.ZodOptional<z.ZodString>;
|
|
607
607
|
apps: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
608
608
|
id: z.ZodString;
|
|
609
609
|
name: z.ZodOptional<z.ZodString>;
|
package/dist/node/index.d.ts
CHANGED
package/dist/node/index.js
CHANGED
package/dist/node/plugins.js
CHANGED
package/dist/packages.js
CHANGED
package/dist/plugins.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as z from 'zod';
|
|
2
2
|
import { App } from './apps.js';
|
|
3
|
-
import { debug, warn } from '
|
|
3
|
+
import { debug, warn } from 'ioium';
|
|
4
4
|
import { zAsyncFunction } from './schemas.js';
|
|
5
5
|
const fn = z.custom(data => typeof data === 'function');
|
|
6
6
|
export const PluginServerHooks = z.object({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axium/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"author": "James Prevett <axium@jamespre.dev>",
|
|
5
5
|
"funding": {
|
|
6
6
|
"type": "individual",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@types/semver": "^7.7.1",
|
|
39
|
+
"ioium": "^0.1.0",
|
|
39
40
|
"mime": "^4.0.7",
|
|
40
41
|
"semver": "^7.7.3"
|
|
41
42
|
}
|
package/dist/io.d.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Get a human-readable string for a date that also fits into CLIs well (fixed-width)
|
|
3
|
-
*/
|
|
4
|
-
export declare function prettyDate(date: Date): string;
|
|
5
|
-
export declare let _debugOutput: boolean;
|
|
6
|
-
/**
|
|
7
|
-
* Enable or disable debug output.
|
|
8
|
-
*/
|
|
9
|
-
export declare function _setDebugOutput(enabled: boolean): void;
|
|
10
|
-
export declare let start: (message: string) => void;
|
|
11
|
-
export declare let progress: (value: number, max: number, message?: any) => void;
|
|
12
|
-
export declare let done: () => void;
|
|
13
|
-
export interface ProgressIO {
|
|
14
|
-
start(message: string): void;
|
|
15
|
-
progress(value: number, max: number, message?: any): void;
|
|
16
|
-
done(): void;
|
|
17
|
-
}
|
|
18
|
-
export declare function useProgress(io: ProgressIO): void;
|
|
19
|
-
export declare let debug: (...args: any[]) => void;
|
|
20
|
-
export declare let log: (...args: any[]) => void;
|
|
21
|
-
export declare let info: (...args: any[]) => void;
|
|
22
|
-
export declare let warn: (...args: any[]) => void;
|
|
23
|
-
export declare let error: (...args: any[]) => void;
|
|
24
|
-
export interface ConsoleLike {
|
|
25
|
-
debug(...args: any[]): void;
|
|
26
|
-
log(...args: any[]): void;
|
|
27
|
-
info(...args: any[]): void;
|
|
28
|
-
warn(...args: any[]): void;
|
|
29
|
-
error(...args: any[]): void;
|
|
30
|
-
}
|
|
31
|
-
export declare function useOutput(output: ConsoleLike): void;
|
|
32
|
-
/**
|
|
33
|
-
* This is a factory for handling errors when performing operations.
|
|
34
|
-
* The handler will allow the parent scope to continue if certain errors occur,
|
|
35
|
-
* rather than fatally exiting.
|
|
36
|
-
*/
|
|
37
|
-
export declare function someWarnings(...allowList: [RegExp, string?][]): (error: string | Error) => void;
|
|
38
|
-
export declare function errorText(error: unknown): string;
|
|
39
|
-
/** @hidden @internal for Logzen */
|
|
40
|
-
export declare const constructor: {
|
|
41
|
-
name: string;
|
|
42
|
-
};
|
package/dist/io.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { $ZodError, prettifyError } from 'zod/v4/core';
|
|
2
|
-
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
3
|
-
// Shortcut to convert to 2-digit. Mostly used to make the line shorter.
|
|
4
|
-
const _2 = (v) => v.toString().padStart(2, '0');
|
|
5
|
-
/**
|
|
6
|
-
* Get a human-readable string for a date that also fits into CLIs well (fixed-width)
|
|
7
|
-
*/
|
|
8
|
-
export function prettyDate(date) {
|
|
9
|
-
return `${date.getFullYear()} ${months[date.getMonth()]} ${_2(date.getDate())} ${_2(date.getHours())}:${_2(date.getMinutes())}:${_2(date.getSeconds())}.${date.getMilliseconds().toString().padStart(3, '0')}`;
|
|
10
|
-
}
|
|
11
|
-
export let _debugOutput = false;
|
|
12
|
-
/**
|
|
13
|
-
* Enable or disable debug output.
|
|
14
|
-
*/
|
|
15
|
-
export function _setDebugOutput(enabled) {
|
|
16
|
-
_debugOutput = enabled;
|
|
17
|
-
}
|
|
18
|
-
// I/O for "progressive" actions
|
|
19
|
-
export let start;
|
|
20
|
-
export let progress;
|
|
21
|
-
export let done;
|
|
22
|
-
export function useProgress(io) {
|
|
23
|
-
start = io.start.bind(io);
|
|
24
|
-
progress = io.progress.bind(io);
|
|
25
|
-
done = io.done.bind(io);
|
|
26
|
-
}
|
|
27
|
-
// User-facing messaging
|
|
28
|
-
export let debug = console.debug;
|
|
29
|
-
export let log = console.log;
|
|
30
|
-
export let info = console.info;
|
|
31
|
-
export let warn = console.warn;
|
|
32
|
-
export let error = console.error;
|
|
33
|
-
export function useOutput(output) {
|
|
34
|
-
debug = output.debug.bind(output);
|
|
35
|
-
log = output.log.bind(output);
|
|
36
|
-
info = output.info.bind(output);
|
|
37
|
-
warn = output.warn.bind(output);
|
|
38
|
-
error = output.error.bind(output);
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* This is a factory for handling errors when performing operations.
|
|
42
|
-
* The handler will allow the parent scope to continue if certain errors occur,
|
|
43
|
-
* rather than fatally exiting.
|
|
44
|
-
*/
|
|
45
|
-
export function someWarnings(...allowList) {
|
|
46
|
-
return (error) => {
|
|
47
|
-
error = typeof error == 'object' && 'message' in error ? error.message : error;
|
|
48
|
-
for (const [pattern, message = error] of allowList) {
|
|
49
|
-
if (!pattern.test(error))
|
|
50
|
-
continue;
|
|
51
|
-
warn(message);
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
throw error;
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
export function errorText(error) {
|
|
58
|
-
if (error instanceof $ZodError)
|
|
59
|
-
return prettifyError(error);
|
|
60
|
-
if (error instanceof Error)
|
|
61
|
-
return error.message;
|
|
62
|
-
return String(error);
|
|
63
|
-
}
|
|
64
|
-
/** @hidden @internal for Logzen */
|
|
65
|
-
export const constructor = { name: 'Console' };
|
package/dist/node/io.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type * as z from 'zod';
|
|
2
|
-
export * from '../io.js';
|
|
3
|
-
export declare function setCommandTimeout(value: number): void;
|
|
4
|
-
/**
|
|
5
|
-
* Run a system command with the fancy "Example... done."
|
|
6
|
-
* @internal
|
|
7
|
-
*/
|
|
8
|
-
export declare function run(message: string, command: string): Promise<string>;
|
|
9
|
-
/** Yet another convenience function */
|
|
10
|
-
export declare function exit(message: unknown, code?: number): never;
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
* @param defaultValue Returned when the file can't be loaded. If omitted, loading errors will be thrown.
|
|
14
|
-
*/
|
|
15
|
-
export declare function readJSON<S extends z.ZodType>(path: string, schema: S): z.infer<S>;
|
|
16
|
-
export declare function writeJSON(path: string, data: any): void;
|
package/dist/node/io.js
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
-
if (value !== null && value !== void 0) {
|
|
3
|
-
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
-
var dispose, inner;
|
|
5
|
-
if (async) {
|
|
6
|
-
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
-
dispose = value[Symbol.asyncDispose];
|
|
8
|
-
}
|
|
9
|
-
if (dispose === void 0) {
|
|
10
|
-
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
-
dispose = value[Symbol.dispose];
|
|
12
|
-
if (async) inner = dispose;
|
|
13
|
-
}
|
|
14
|
-
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
-
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
-
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
-
}
|
|
18
|
-
else if (async) {
|
|
19
|
-
env.stack.push({ async: true });
|
|
20
|
-
}
|
|
21
|
-
return value;
|
|
22
|
-
};
|
|
23
|
-
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
-
return function (env) {
|
|
25
|
-
function fail(e) {
|
|
26
|
-
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
-
env.hasError = true;
|
|
28
|
-
}
|
|
29
|
-
var r, s = 0;
|
|
30
|
-
function next() {
|
|
31
|
-
while (r = env.stack.pop()) {
|
|
32
|
-
try {
|
|
33
|
-
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
34
|
-
if (r.dispose) {
|
|
35
|
-
var result = r.dispose.call(r.value);
|
|
36
|
-
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
37
|
-
}
|
|
38
|
-
else s |= 1;
|
|
39
|
-
}
|
|
40
|
-
catch (e) {
|
|
41
|
-
fail(e);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
45
|
-
if (env.hasError) throw env.error;
|
|
46
|
-
}
|
|
47
|
-
return next();
|
|
48
|
-
};
|
|
49
|
-
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
50
|
-
var e = new Error(message);
|
|
51
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
|
-
});
|
|
53
|
-
import { exec } from 'node:child_process';
|
|
54
|
-
import { readFileSync, writeFileSync } from 'node:fs';
|
|
55
|
-
import { styleText } from 'node:util';
|
|
56
|
-
import * as io from '../io.js';
|
|
57
|
-
export * from '../io.js';
|
|
58
|
-
let _currentOperation = null, _progress = null;
|
|
59
|
-
function handleProgress() {
|
|
60
|
-
if (!_currentOperation || !_progress)
|
|
61
|
-
return {
|
|
62
|
-
[Symbol.dispose]() {
|
|
63
|
-
if (!_progress)
|
|
64
|
-
_currentOperation = null;
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
process.stdout.clearLine(0);
|
|
68
|
-
process.stdout.cursorTo(0);
|
|
69
|
-
return {
|
|
70
|
-
[Symbol.dispose]() {
|
|
71
|
-
process.stdout.write(_currentOperation + '... ');
|
|
72
|
-
if (_progress)
|
|
73
|
-
io.progress(..._progress);
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
io.useProgress({
|
|
78
|
-
start(message) {
|
|
79
|
-
_currentOperation = message;
|
|
80
|
-
process.stdout.write(message + '... ');
|
|
81
|
-
},
|
|
82
|
-
/** @todo implement additional messaging */
|
|
83
|
-
progress(value, max, message) {
|
|
84
|
-
_progress = [value, max];
|
|
85
|
-
value++;
|
|
86
|
-
process.stdout.clearLine(0);
|
|
87
|
-
process.stdout.cursorTo(0);
|
|
88
|
-
process.stdout.write(`${_currentOperation}... ${value.toString().padStart(max.toString().length)}/${max} ${message && value < max ? `(${message})` : ''}`);
|
|
89
|
-
if (value >= max) {
|
|
90
|
-
_currentOperation = null;
|
|
91
|
-
_progress = null;
|
|
92
|
-
console.log();
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
done() {
|
|
96
|
-
_currentOperation = null;
|
|
97
|
-
_progress = null;
|
|
98
|
-
console.log('done.');
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
function* maybeStyle(style, parts) {
|
|
102
|
-
for (const part of parts) {
|
|
103
|
-
if (typeof part != 'string')
|
|
104
|
-
yield part;
|
|
105
|
-
else if (part.startsWith('\x1b'))
|
|
106
|
-
yield part;
|
|
107
|
-
else
|
|
108
|
-
yield styleText(style, part);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
io.useOutput({
|
|
112
|
-
error(...message) {
|
|
113
|
-
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
114
|
-
try {
|
|
115
|
-
const _ = __addDisposableResource(env_1, handleProgress(), false);
|
|
116
|
-
console.error(...maybeStyle('red', message));
|
|
117
|
-
}
|
|
118
|
-
catch (e_1) {
|
|
119
|
-
env_1.error = e_1;
|
|
120
|
-
env_1.hasError = true;
|
|
121
|
-
}
|
|
122
|
-
finally {
|
|
123
|
-
__disposeResources(env_1);
|
|
124
|
-
}
|
|
125
|
-
},
|
|
126
|
-
warn(...message) {
|
|
127
|
-
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
128
|
-
try {
|
|
129
|
-
const _ = __addDisposableResource(env_2, handleProgress(), false);
|
|
130
|
-
console.warn(...maybeStyle('yellow', message));
|
|
131
|
-
}
|
|
132
|
-
catch (e_2) {
|
|
133
|
-
env_2.error = e_2;
|
|
134
|
-
env_2.hasError = true;
|
|
135
|
-
}
|
|
136
|
-
finally {
|
|
137
|
-
__disposeResources(env_2);
|
|
138
|
-
}
|
|
139
|
-
},
|
|
140
|
-
info(...message) {
|
|
141
|
-
const env_3 = { stack: [], error: void 0, hasError: false };
|
|
142
|
-
try {
|
|
143
|
-
const _ = __addDisposableResource(env_3, handleProgress(), false);
|
|
144
|
-
console.info(...maybeStyle('blue', message));
|
|
145
|
-
}
|
|
146
|
-
catch (e_3) {
|
|
147
|
-
env_3.error = e_3;
|
|
148
|
-
env_3.hasError = true;
|
|
149
|
-
}
|
|
150
|
-
finally {
|
|
151
|
-
__disposeResources(env_3);
|
|
152
|
-
}
|
|
153
|
-
},
|
|
154
|
-
log(...message) {
|
|
155
|
-
const env_4 = { stack: [], error: void 0, hasError: false };
|
|
156
|
-
try {
|
|
157
|
-
const _ = __addDisposableResource(env_4, handleProgress(), false);
|
|
158
|
-
console.log(...message);
|
|
159
|
-
}
|
|
160
|
-
catch (e_4) {
|
|
161
|
-
env_4.error = e_4;
|
|
162
|
-
env_4.hasError = true;
|
|
163
|
-
}
|
|
164
|
-
finally {
|
|
165
|
-
__disposeResources(env_4);
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
debug(...message) {
|
|
169
|
-
const env_5 = { stack: [], error: void 0, hasError: false };
|
|
170
|
-
try {
|
|
171
|
-
if (!io._debugOutput)
|
|
172
|
-
return;
|
|
173
|
-
const _ = __addDisposableResource(env_5, handleProgress(), false);
|
|
174
|
-
console.debug(...maybeStyle('gray', message));
|
|
175
|
-
}
|
|
176
|
-
catch (e_5) {
|
|
177
|
-
env_5.error = e_5;
|
|
178
|
-
env_5.hasError = true;
|
|
179
|
-
}
|
|
180
|
-
finally {
|
|
181
|
-
__disposeResources(env_5);
|
|
182
|
-
}
|
|
183
|
-
},
|
|
184
|
-
});
|
|
185
|
-
let timeout = 1000;
|
|
186
|
-
export function setCommandTimeout(value) {
|
|
187
|
-
timeout = value;
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Run a system command with the fancy "Example... done."
|
|
191
|
-
* @internal
|
|
192
|
-
*/
|
|
193
|
-
export async function run(message, command) {
|
|
194
|
-
let stderr;
|
|
195
|
-
try {
|
|
196
|
-
io.start(message);
|
|
197
|
-
const { promise, resolve, reject } = Promise.withResolvers();
|
|
198
|
-
exec(command, { timeout }, (err, stdout, _stderr) => {
|
|
199
|
-
stderr = _stderr.startsWith('ERROR:') ? _stderr.slice(6).trim() : _stderr;
|
|
200
|
-
if (err)
|
|
201
|
-
reject('[command]');
|
|
202
|
-
else
|
|
203
|
-
resolve(stdout);
|
|
204
|
-
});
|
|
205
|
-
const value = await promise;
|
|
206
|
-
io.done();
|
|
207
|
-
return value;
|
|
208
|
-
}
|
|
209
|
-
catch (error) {
|
|
210
|
-
throw error == '[command]'
|
|
211
|
-
? stderr?.slice(0, 100) || 'failed.'
|
|
212
|
-
: typeof error == 'object' && 'message' in error
|
|
213
|
-
? error.message
|
|
214
|
-
: error;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
/** Yet another convenience function */
|
|
218
|
-
export function exit(message, code = 1) {
|
|
219
|
-
if (typeof message == 'number') {
|
|
220
|
-
code = message;
|
|
221
|
-
message = 'Unknown error!';
|
|
222
|
-
}
|
|
223
|
-
if (message instanceof Error)
|
|
224
|
-
message = message.message;
|
|
225
|
-
io.error(message);
|
|
226
|
-
process.exit(code);
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
*
|
|
230
|
-
* @param defaultValue Returned when the file can't be loaded. If omitted, loading errors will be thrown.
|
|
231
|
-
*/
|
|
232
|
-
export function readJSON(path, schema) {
|
|
233
|
-
try {
|
|
234
|
-
const data = JSON.parse(readFileSync(path, 'utf-8'));
|
|
235
|
-
return schema.parse(data);
|
|
236
|
-
}
|
|
237
|
-
catch (e) {
|
|
238
|
-
throw io.errorText(e);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
export function writeJSON(path, data) {
|
|
242
|
-
writeFileSync(path, JSON.stringify(data, null, 4).replaceAll(/^( {4})+/g, match => '\t'.repeat(match.length / 4)), 'utf-8');
|
|
243
|
-
}
|