@travetto/runtime 7.0.0-rc.1 → 7.0.0-rc.3

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
@@ -19,6 +19,7 @@ Runtime is the foundation of all [Travetto](https://travetto.dev) applications.
19
19
  * Standard Error Support
20
20
  * Console Management
21
21
  * Resource Access
22
+ * JSON Utilities
22
23
  * Common Utilities
23
24
  * Time Utilities
24
25
  * Process Execution
@@ -38,8 +39,6 @@ class $Runtime {
38
39
  get env(): string | undefined;
39
40
  /** Are we in development mode */
40
41
  get production(): boolean;
41
- /** Is the app in dynamic mode? */
42
- get dynamic(): boolean;
43
42
  /** Get debug value */
44
43
  get debug(): false | string;
45
44
  /** Manifest main */
@@ -51,11 +50,11 @@ class $Runtime {
51
50
  /** Main source path */
52
51
  get mainSourcePath(): string;
53
52
  /** Produce a workspace relative path */
54
- workspaceRelative(...rel: string[]): string;
53
+ workspaceRelative(...parts: string[]): string;
55
54
  /** Strip off the workspace path from a file */
56
55
  stripWorkspacePath(full: string): string;
57
56
  /** Produce a workspace path for tooling, with '@' being replaced by node_module/name folder */
58
- toolPath(...rel: string[]): string;
57
+ toolPath(...parts: string[]): string;
59
58
  /** Resolve single module path */
60
59
  modulePath(modulePath: string, overrides?: Record<string, string>): string;
61
60
  /** Resolve resource paths */
@@ -95,10 +94,6 @@ interface EnvData {
95
94
  * Special role to run as, used to access additional files from the manifest during runtime.
96
95
  */
97
96
  TRV_ROLE: Role;
98
- /**
99
- * Whether or not to run the program in dynamic mode, allowing for real-time updates
100
- */
101
- TRV_DYNAMIC: boolean;
102
97
  /**
103
98
  * The folders to use for resource lookup
104
99
  */
@@ -145,9 +140,9 @@ export class EnvProp<T> {
145
140
  /** Remove value */
146
141
  clear(): void;
147
142
  /** Export value */
148
- export(val?: T | undefined | null): Record<string, string>;
143
+ export(value?: T | undefined | null): Record<string, string>;
149
144
  /** Read value as string */
150
- get val(): string | undefined;
145
+ get value(): string | undefined;
151
146
  /** Read value as list */
152
147
  get list(): string[] | undefined;
153
148
  /** Read value as object */
@@ -204,8 +199,8 @@ export function work() {
204
199
 
205
200
  try {
206
201
  1 / 0;
207
- } catch (err) {
208
- console.error('Divide by zero', { error: err });
202
+ } catch (error) {
203
+ console.error('Divide by zero', { error });
209
204
  }
210
205
  console.debug('End Work');
211
206
  }
@@ -225,12 +220,12 @@ function work() {
225
220
  try {
226
221
  1 / 0;
227
222
  }
228
- catch (err) {
229
- Δconsole.log({ level: "error", import: mod_1, line: 7, scope: "work", args: ['Divide by zero', { error: err }] });
223
+ catch (error) {
224
+ Δconsole.log({ level: "error", import: mod_1, line: 7, scope: "work", args: ['Divide by zero', { error }] });
230
225
  }
231
226
  Δconsole.log({ level: "debug", import: mod_1, line: 9, scope: "work", args: ['End Work'] });
232
227
  }
233
- Δfunction.registerFunction(work, mod_1, { hash: 1030247697, lines: [1, 10, 2] });
228
+ Δfunction.registerFunction(work, mod_1, { hash: 159357293, lines: [1, 10, 2] });
234
229
  ```
235
230
 
236
231
  #### Filtering Debug
@@ -258,9 +253,18 @@ $ DEBUG=express:*,@travetto/web npx trv run web
258
253
  ## Resource Access
259
254
  The primary access patterns for resources, is to directly request a file, and to resolve that file either via file-system look up or leveraging the [Manifest](https://github.com/travetto/travetto/tree/main/module/manifest#readme "Support for project indexing, manifesting, along with file watching")'s data for what resources were found at manifesting time.
260
255
 
261
- The [FileLoader](https://github.com/travetto/travetto/tree/main/module/runtime/src/file-loader.ts#L11) allows for accessing information about the resources, and subsequently reading the file as text/binary or to access the resource as a `Readable` stream. If a file is not found, it will throw an [AppError](https://github.com/travetto/travetto/tree/main/module/runtime/src/error.ts#L26) with a category of 'notfound'.
256
+ The [FileLoader](https://github.com/travetto/travetto/tree/main/module/runtime/src/file-loader.ts#L12) allows for accessing information about the resources, and subsequently reading the file as text/binary or to access the resource as a `Readable` stream. If a file is not found, it will throw an [AppError](https://github.com/travetto/travetto/tree/main/module/runtime/src/error.ts#L26) with a category of 'notfound'.
257
+
258
+ The [FileLoader](https://github.com/travetto/travetto/tree/main/module/runtime/src/file-loader.ts#L12) also supports tying itself to [Env](https://github.com/travetto/travetto/tree/main/module/runtime/src/env.ts#L114)'s `TRV_RESOURCES` information on where to attempt to find a requested resource.
259
+
260
+ ## JSON Utilities
261
+ The framework provides utilities for working with JSON data. This module provides methods for reading and writing JSON files, as well as serializing and deserializing JSON data. It also provides support for working with Base64 encoded data for web safe transfer. The primary goal is ease of use, but also a centralized location for performance and security improvements over time.
262
262
 
263
- The [FileLoader](https://github.com/travetto/travetto/tree/main/module/runtime/src/file-loader.ts#L11) also supports tying itself to [Env](https://github.com/travetto/travetto/tree/main/module/runtime/src/env.ts#L114)'s `TRV_RESOURCES` information on where to attempt to find a requested resource.
263
+ * `parseSafe(input: string | Buffer)` parses JSON safely from a string or Buffer.
264
+ * `stringifyBase64(value: any)` encodes a JSON value as a base64 encoded string.
265
+ * `parseBase64(input: string)` decodes a JSON value from a base64 encoded string.
266
+ * `readFile(file: string)` reads a JSON file asynchronously.
267
+ * `readFileSync(file: string, onMissing?: any)` reads a JSON file synchronously.
264
268
 
265
269
  ## Common Utilities
266
270
  Common utilities used throughout the framework. Currently [Util](https://github.com/travetto/travetto/tree/main/module/runtime/src/util.ts#L12) includes:
@@ -271,7 +275,7 @@ Common utilities used throughout the framework. Currently [Util](https://github.
271
275
 
272
276
  **Code: Sample makeTemplate Usage**
273
277
  ```typescript
274
- const tpl = makeTemplate((name: 'age'|'name', val) => `**${name}: ${val}**`);
278
+ const tpl = makeTemplate((name: 'age'|'name', value) => `**${name}: ${value}**`);
275
279
  tpl`{{age:20}} {{name: 'bob'}}</>;
276
280
  // produces
277
281
  '**age: 20** **name: bob**'
@@ -287,7 +291,7 @@ export class TimeUtil {
287
291
  * Test to see if a string is valid for relative time
288
292
  * @param val
289
293
  */
290
- static isTimeSpan(val: string): val is TimeSpan;
294
+ static isTimeSpan(value: string): value is TimeSpan;
291
295
  /**
292
296
  * Returns time units convert to ms
293
297
  * @param amount Number of units to extend
@@ -323,7 +327,7 @@ export class TimeUtil {
323
327
  ```
324
328
 
325
329
  ## Process Execution
326
- [ExecUtil](https://github.com/travetto/travetto/tree/main/module/runtime/src/exec.ts#L43) exposes `getResult` as a means to wrap [child_process](https://nodejs.org/api/child_process.html)'s process object. This wrapper allows for a promise-based resolution of the subprocess with the ability to capture the stderr/stdout.
330
+ [ExecUtil](https://github.com/travetto/travetto/tree/main/module/runtime/src/exec.ts#L40) exposes `getResult` as a means to wrap [child_process](https://nodejs.org/api/child_process.html)'s process object. This wrapper allows for a promise-based resolution of the subprocess with the ability to capture the stderr/stdout.
327
331
 
328
332
  A simple example would be:
329
333
 
package/__index__.ts CHANGED
@@ -9,6 +9,7 @@ export * from './src/exec.ts';
9
9
  export * from './src/env.ts';
10
10
  export * from './src/file-loader.ts';
11
11
  export * from './src/function.ts';
12
+ export * from './src/json.ts';
12
13
  export * from './src/manifest-index.ts';
13
14
  export * from './src/queue.ts';
14
15
  export * from './src/resources.ts';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/runtime",
3
- "version": "7.0.0-rc.1",
3
+ "version": "7.0.0-rc.3",
4
4
  "description": "Runtime for travetto applications.",
5
5
  "keywords": [
6
6
  "console-manager",
@@ -25,12 +25,12 @@
25
25
  "directory": "module/runtime"
26
26
  },
27
27
  "dependencies": {
28
- "@travetto/manifest": "^7.0.0-rc.0",
28
+ "@travetto/manifest": "^7.0.0-rc.2",
29
29
  "@types/debug": "^4.1.12",
30
30
  "debug": "^4.4.3"
31
31
  },
32
32
  "peerDependencies": {
33
- "@travetto/transformer": "^7.0.0-rc.1"
33
+ "@travetto/transformer": "^7.0.0-rc.3"
34
34
  },
35
35
  "peerDependenciesMeta": {
36
36
  "@travetto/transformer": {
package/src/binary.ts CHANGED
@@ -24,27 +24,27 @@ export class BinaryUtil {
24
24
  /** Is ReadableStream */
25
25
  static isReadableStream = hasFunction<ReadableStream>('pipeTo');
26
26
  /** Is Async Iterable */
27
- static isAsyncIterable = (v: unknown): v is AsyncIterable<unknown> =>
28
- !!v && (typeof v === 'object' || typeof v === 'function') && Symbol.asyncIterator in v;
27
+ static isAsyncIterable = (value: unknown): value is AsyncIterable<unknown> =>
28
+ !!value && (typeof value === 'object' || typeof value === 'function') && Symbol.asyncIterator in value;
29
29
 
30
30
  /**
31
- * Is src a binary type
31
+ * Is value a binary type
32
32
  */
33
- static isBinaryType(src: unknown): boolean {
34
- return src instanceof Blob || Buffer.isBuffer(src) || this.isReadable(src) ||
35
- this.isArrayBuffer(src) || this.isReadableStream(src) || this.isAsyncIterable(src);
33
+ static isBinaryType(value: unknown): boolean {
34
+ return value instanceof Blob || Buffer.isBuffer(value) || this.isReadable(value) ||
35
+ this.isArrayBuffer(value) || this.isReadableStream(value) || this.isAsyncIterable(value);
36
36
  }
37
37
 
38
38
  /**
39
- * Generate a proper sha512 hash from a src value
40
- * @param src The seed value to build the hash from
41
- * @param len The optional length of the hash to generate
39
+ * Generate a proper sha512 hash from an input value
40
+ * @param input The seed value to build the hash from
41
+ * @param length The optional length of the hash to generate
42
42
  */
43
- static hash(src: string, len: number = -1): string {
43
+ static hash(input: string, length: number = -1): string {
44
44
  const hash = crypto.createHash('sha512');
45
- hash.update(src);
45
+ hash.update(input);
46
46
  const digest = hash.digest('hex');
47
- return len > 0 ? digest.substring(0, len) : digest;
47
+ return length > 0 ? digest.substring(0, length) : digest;
48
48
  }
49
49
 
50
50
  /**
@@ -88,7 +88,7 @@ export class BinaryUtil {
88
88
  static readableBlob(input: () => (Readable | Promise<Readable>), metadata: BlobMeta = {}): Blob | File {
89
89
  const go = (): Readable => {
90
90
  const stream = new PassThrough();
91
- Promise.resolve(input()).then(v => v.pipe(stream), (err) => stream.destroy(err));
91
+ Promise.resolve(input()).then(readable => readable.pipe(stream), (error) => stream.destroy(error));
92
92
  return stream;
93
93
  };
94
94
 
@@ -102,7 +102,7 @@ export class BinaryUtil {
102
102
  stream: { value: () => ReadableStream.from(go()) },
103
103
  arrayBuffer: { value: () => toArrayBuffer(go()) },
104
104
  text: { value: () => toText(go()) },
105
- bytes: { value: () => toArrayBuffer(go()).then(v => new Uint8Array(v)) },
105
+ bytes: { value: () => toArrayBuffer(go()).then(buffer => new Uint8Array(buffer)) },
106
106
  [BlobMetaSymbol]: { value: metadata }
107
107
  });
108
108
  }
package/src/console.ts CHANGED
@@ -27,10 +27,10 @@ export interface ConsoleEvent {
27
27
  * @concrete
28
28
  */
29
29
  export interface ConsoleListener {
30
- log(ev: ConsoleEvent): void;
30
+ log(event: ConsoleEvent): void;
31
31
  }
32
32
 
33
- const DEBUG_OG = { formatArgs: debug.formatArgs, log: debug.log };
33
+ const DEBUG_HANDLE = { formatArgs: debug.formatArgs, log: debug.log };
34
34
 
35
35
  /**
36
36
  * Provides a general abstraction against the console.* methods to allow for easier capture and redirection.
@@ -50,7 +50,7 @@ class $ConsoleManager implements ConsoleListener {
50
50
  /**
51
51
  * List of logging filters
52
52
  */
53
- #filters: Partial<Record<ConsoleEvent['level'], (x: ConsoleEvent) => boolean>> = {};
53
+ #filters: Partial<Record<ConsoleEvent['level'], (event: ConsoleEvent) => boolean>> = {};
54
54
 
55
55
  constructor(listener: ConsoleListener) {
56
56
  this.set(listener);
@@ -66,8 +66,8 @@ class $ConsoleManager implements ConsoleListener {
66
66
  filter(level: ConsoleEvent['level'], filter?: boolean | ((ctx: ConsoleEvent) => boolean)): void {
67
67
  if (filter !== undefined) {
68
68
  if (typeof filter === 'boolean') {
69
- const v = filter;
70
- filter = (): boolean => v;
69
+ const filterValue = filter;
70
+ filter = (): boolean => filterValue;
71
71
  }
72
72
  this.#filters[level] = filter;
73
73
  } else {
@@ -90,8 +90,8 @@ class $ConsoleManager implements ConsoleListener {
90
90
  args: [util.format(...args)], line: 0, timestamp: new Date()
91
91
  });
92
92
  } else {
93
- debug.formatArgs = DEBUG_OG.formatArgs;
94
- debug.log = DEBUG_OG.log;
93
+ debug.formatArgs = DEBUG_HANDLE.formatArgs;
94
+ debug.log = DEBUG_HANDLE.log;
95
95
  }
96
96
  }
97
97
 
@@ -111,18 +111,18 @@ class $ConsoleManager implements ConsoleListener {
111
111
  /**
112
112
  * Handle direct call in lieu of the console.* commands
113
113
  */
114
- log(ev: ConsoleEvent & { import?: [string, string] }): void {
115
- const outEv = {
116
- ...ev,
114
+ log(event: ConsoleEvent & { import?: [string, string] }): void {
115
+ const result = {
116
+ ...event,
117
117
  timestamp: new Date(),
118
- module: ev.module ?? ev.import?.[0],
119
- modulePath: ev.modulePath ?? ev.import?.[1]
118
+ module: event.module ?? event.import?.[0],
119
+ modulePath: event.modulePath ?? event.import?.[1]
120
120
  };
121
121
 
122
- if (this.#filters[outEv.level] && !this.#filters[outEv.level]!(outEv)) {
122
+ if (this.#filters[result.level] && !this.#filters[result.level]!(result)) {
123
123
  return; // Do nothing
124
124
  } else {
125
- return this.#listener.log(outEv);
125
+ return this.#listener.log(result);
126
126
  }
127
127
  }
128
128
 
@@ -141,5 +141,5 @@ class $ConsoleManager implements ConsoleListener {
141
141
  }
142
142
  }
143
143
 
144
- export const ConsoleManager = new $ConsoleManager({ log(ev): void { console![ev.level](...ev.args); } });
144
+ export const ConsoleManager = new $ConsoleManager({ log(event): void { console![event.level](...event.args); } });
145
145
  export const log = ConsoleManager.log.bind(ConsoleManager);
package/src/context.ts CHANGED
@@ -7,6 +7,7 @@ import { Env } from './env.ts';
7
7
  import { RuntimeIndex } from './manifest-index.ts';
8
8
  import { describeFunction } from './function.ts';
9
9
  import { castTo } from './types.ts';
10
+ import { JSONUtil } from './json.ts';
10
11
 
11
12
  /** Constrained version of {@type ManifestContext} */
12
13
  class $Runtime {
@@ -28,7 +29,7 @@ class $Runtime {
28
29
 
29
30
  /** Get env name, with support for the default env */
30
31
  get env(): string | undefined {
31
- return Env.TRV_ENV.val || (!this.production ? this.#idx.manifest.workspace.defaultEnv : undefined);
32
+ return Env.TRV_ENV.value || (!this.production ? this.#idx.manifest.workspace.defaultEnv : undefined);
32
33
  }
33
34
 
34
35
  /** Are we in development mode */
@@ -36,15 +37,10 @@ class $Runtime {
36
37
  return process.env.NODE_ENV === 'production';
37
38
  }
38
39
 
39
- /** Is the app in dynamic mode? */
40
- get dynamic(): boolean {
41
- return Env.TRV_DYNAMIC.isTrue;
42
- }
43
-
44
40
  /** Get debug value */
45
41
  get debug(): false | string {
46
- const val = Env.DEBUG.val ?? '';
47
- return (!val && this.production) || Env.DEBUG.isFalse ? false : val;
42
+ const value = Env.DEBUG.value ?? '';
43
+ return (!value && this.production) || Env.DEBUG.isFalse ? false : value;
48
44
  }
49
45
 
50
46
  /** Manifest main */
@@ -68,8 +64,8 @@ class $Runtime {
68
64
  }
69
65
 
70
66
  /** Produce a workspace relative path */
71
- workspaceRelative(...rel: string[]): string {
72
- return path.resolve(this.workspace.path, ...rel);
67
+ workspaceRelative(...parts: string[]): string {
68
+ return path.resolve(this.workspace.path, ...parts);
73
69
  }
74
70
 
75
71
  /** Strip off the workspace path from a file */
@@ -78,23 +74,23 @@ class $Runtime {
78
74
  }
79
75
 
80
76
  /** Produce a workspace path for tooling, with '@' being replaced by node_module/name folder */
81
- toolPath(...rel: string[]): string {
82
- rel = rel.flatMap(x => x === '@' ? ['node_modules', this.#idx.manifest.main.name] : [x]);
83
- return path.resolve(this.workspace.path, this.#idx.manifest.build.toolFolder, ...rel);
77
+ toolPath(...parts: string[]): string {
78
+ parts = parts.flatMap(part => part === '@' ? ['node_modules', this.#idx.manifest.main.name] : [part]);
79
+ return path.resolve(this.workspace.path, this.#idx.manifest.build.toolFolder, ...parts);
84
80
  }
85
81
 
86
82
  /** Resolve single module path */
87
83
  modulePath(modulePath: string, overrides?: Record<string, string>): string {
88
84
  const combined = { ...this.#resourceOverrides, ...overrides };
89
85
  const [base, sub] = (combined[modulePath] ?? modulePath)
90
- .replace(/^([^#]*)(#|$)/g, (_, v, r) => `${this.#moduleAliases[v] ?? v}${r}`)
86
+ .replace(/^([^#]*)(#|$)/g, (_, module, relativePath) => `${this.#moduleAliases[module] ?? module}${relativePath}`)
91
87
  .split('#');
92
88
  return path.resolve(this.#idx.getModule(base)?.sourcePath ?? base, sub ?? '.');
93
89
  }
94
90
 
95
91
  /** Resolve resource paths */
96
92
  resourcePaths(paths: string[] = []): string[] {
97
- return [...new Set([...paths, ...Env.TRV_RESOURCES.list ?? [], '@#resources', '@@#resources'].map(v => this.modulePath(v)))];
93
+ return [...new Set([...paths, ...Env.TRV_RESOURCES.list ?? [], '@#resources', '@@#resources'].map(module => this.modulePath(module)))];
98
94
  }
99
95
 
100
96
  /** Get source for function */
@@ -118,10 +114,10 @@ class $Runtime {
118
114
  throw new Error(`Unable to find ${imp}, not in the manifest`);
119
115
  } else if (imp.endsWith('.json')) {
120
116
  imp = this.#idx.getFromImport(imp)?.sourceFile ?? imp;
121
- return fs.readFile(imp, 'utf8').then(JSON.parse);
117
+ return fs.readFile(imp, 'utf8').then(JSONUtil.parseSafe<T>);
122
118
  }
123
119
 
124
- if (!ManifestModuleUtil.SOURCE_EXT_RE.test(imp)) {
120
+ if (!ManifestModuleUtil.SOURCE_EXT_REGEX.test(imp)) {
125
121
  if (imp.startsWith('@')) {
126
122
  if (/[/].*?[/]/.test(imp)) {
127
123
  imp = `${imp}.ts`;
@@ -132,16 +128,16 @@ class $Runtime {
132
128
  }
133
129
 
134
130
  imp = ManifestModuleUtil.withOutputExtension(imp);
135
- const res = await import(imp);
136
- if (res?.default?.default) {
131
+ const imported = await import(imp);
132
+ if (imported?.default?.default) {
137
133
  // Unpack default.default, typescript does this in a way that requires recreating the whole object
138
- const def = res?.default?.default;
134
+ const def = imported?.default?.default;
139
135
  return Object.defineProperties(castTo({}), {
140
- ...Object.getOwnPropertyDescriptors(res),
136
+ ...Object.getOwnPropertyDescriptors(imported),
141
137
  default: { get: () => def, configurable: false }
142
138
  });
143
139
  }
144
- return res;
140
+ return imported;
145
141
  }
146
142
  }
147
143
 
package/src/env.ts CHANGED
@@ -9,12 +9,12 @@ export class EnvProp<T> {
9
9
  readonly key: string;
10
10
  constructor(key: string) { this.key = key; }
11
11
 
12
- /** Set value according to prop type */
13
- set(val: T | undefined | null): void {
14
- if (val === undefined || val === null) {
12
+ /** Set value according to type */
13
+ set(value: T | undefined | null): void {
14
+ if (value === undefined || value === null) {
15
15
  delete process.env[this.key];
16
16
  } else {
17
- process.env[this.key] = Array.isArray(val) ? `${val.join(',')}` : `${val}`;
17
+ process.env[this.key] = Array.isArray(value) ? `${value.join(',')}` : `${value}`;
18
18
  }
19
19
  }
20
20
 
@@ -24,36 +24,36 @@ export class EnvProp<T> {
24
24
  }
25
25
 
26
26
  /** Export value */
27
- export(val?: T | undefined | null): Record<string, string> {
27
+ export(value?: T | undefined | null): Record<string, string> {
28
28
  let out: string;
29
29
  if (arguments.length === 0) { // If nothing passed in
30
- out = `${this.val}`;
31
- } else if (val === undefined || val === null) {
30
+ out = `${this.value}`;
31
+ } else if (value === undefined || value === null) {
32
32
  out = '';
33
- } else if (Array.isArray(val)) {
34
- out = val.join(',');
35
- } else if (typeof val === 'object') {
36
- out = Object.entries(val).map(([k, v]) => `${k}=${v}`).join(',');
33
+ } else if (Array.isArray(value)) {
34
+ out = value.join(',');
35
+ } else if (typeof value === 'object') {
36
+ out = Object.entries(value).map(([key, keyValue]) => `${key}=${keyValue}`).join(',');
37
37
  } else {
38
- out = `${val}`;
38
+ out = `${value}`;
39
39
  }
40
40
  return { [this.key]: out };
41
41
  }
42
42
 
43
43
  /** Read value as string */
44
- get val(): string | undefined { return process.env[this.key] || undefined; }
44
+ get value(): string | undefined { return process.env[this.key] || undefined; }
45
45
 
46
46
  /** Read value as list */
47
47
  get list(): string[] | undefined {
48
- const val = this.val;
49
- return (val === undefined || val === '') ?
50
- undefined : val.split(/[, ]+/g).map(x => x.trim()).filter(x => !!x);
48
+ const value = this.value;
49
+ return (value === undefined || value === '') ?
50
+ undefined : value.split(/[, ]+/g).map(item => item.trim()).filter(item => !!item);
51
51
  }
52
52
 
53
53
  /** Read value as object */
54
54
  get object(): Record<string, string> | undefined {
55
55
  const items = this.list;
56
- return items ? Object.fromEntries(items.map(x => x.split(/[:=]/g))) : undefined;
56
+ return items ? Object.fromEntries(items.map(item => item.split(/[:=]/g))) : undefined;
57
57
  }
58
58
 
59
59
  /** Add values to list */
@@ -63,35 +63,35 @@ export class EnvProp<T> {
63
63
 
64
64
  /** Read value as int */
65
65
  get int(): number | undefined {
66
- const vi = parseInt(this.val ?? '', 10);
67
- return Number.isNaN(vi) ? undefined : vi;
66
+ const parsed = parseInt(this.value ?? '', 10);
67
+ return Number.isNaN(parsed) ? undefined : parsed;
68
68
  }
69
69
 
70
70
  /** Read value as boolean */
71
71
  get bool(): boolean | undefined {
72
- const val = this.val;
73
- return (val === undefined || val === '') ? undefined : IS_TRUE.test(val);
72
+ const value = this.value;
73
+ return (value === undefined || value === '') ? undefined : IS_TRUE.test(value);
74
74
  }
75
75
 
76
76
  /** Determine if the underlying value is truthy */
77
77
  get isTrue(): boolean {
78
- return IS_TRUE.test(this.val ?? '');
78
+ return IS_TRUE.test(this.value ?? '');
79
79
  }
80
80
 
81
81
  /** Determine if the underlying value is falsy */
82
82
  get isFalse(): boolean {
83
- return IS_FALSE.test(this.val ?? '');
83
+ return IS_FALSE.test(this.value ?? '');
84
84
  }
85
85
 
86
86
  /** Determine if the underlying value is set */
87
87
  get isSet(): boolean {
88
- const val = this.val;
89
- return val !== undefined && val !== '';
88
+ const value = this.value;
89
+ return value !== undefined && value !== '';
90
90
  }
91
91
  }
92
92
 
93
93
  type AllType = {
94
- [K in keyof EnvData]: Pick<EnvProp<EnvData[K]>, 'key' | 'export' | 'val' | 'set' | 'clear' | 'isSet' |
94
+ [K in keyof EnvData]: Pick<EnvProp<EnvData[K]>, 'key' | 'export' | 'value' | 'set' | 'clear' | 'isSet' |
95
95
  (EnvData[K] extends unknown[] ? 'list' | 'add' : never) |
96
96
  (Extract<EnvData[K], object> extends never ? never : 'object') |
97
97
  (Extract<EnvData[K], number> extends never ? never : 'int') |
@@ -101,10 +101,10 @@ type AllType = {
101
101
 
102
102
  function delegate<T extends object>(base: T): AllType & T {
103
103
  return new Proxy(castTo(base), {
104
- get(target, prop): unknown {
105
- return typeof prop !== 'string' ? undefined :
106
- (prop in base ? base[castKey(prop)] :
107
- target[castKey<typeof target>(prop)] ??= castTo(new EnvProp(prop))
104
+ get(target, property): unknown {
105
+ return typeof property !== 'string' ? undefined :
106
+ (property in base ? base[castKey(property)] :
107
+ target[castKey<typeof target>(property)] ??= castTo(new EnvProp(property))
108
108
  );
109
109
  }
110
110
  });
package/src/error.ts CHANGED
@@ -28,14 +28,14 @@ export class AppError<T = Record<string, unknown> | undefined> extends Error {
28
28
  static defaultCategory?: ErrorCategory;
29
29
 
30
30
  /** Convert from JSON object */
31
- static fromJSON(e: unknown): AppError | undefined {
32
- if (!!e && typeof e === 'object' &&
33
- ('message' in e && typeof e.message === 'string') &&
34
- ('category' in e && typeof e.category === 'string') &&
35
- ('type' in e && typeof e.type === 'string') &&
36
- ('at' in e && typeof e.at === 'string')
31
+ static fromJSON(error: unknown): AppError | undefined {
32
+ if (!!error && typeof error === 'object' &&
33
+ ('message' in error && typeof error.message === 'string') &&
34
+ ('category' in error && typeof error.category === 'string') &&
35
+ ('type' in error && typeof error.type === 'string') &&
36
+ ('at' in error && typeof error.at === 'string')
37
37
  ) {
38
- return new AppError(e.message, castTo<AppErrorOptions<Record<string, unknown>>>(e));
38
+ return new AppError(error.message, castTo<AppErrorOptions<Record<string, unknown>>>(error));
39
39
  }
40
40
  }
41
41
 
@@ -50,21 +50,21 @@ export class AppError<T = Record<string, unknown> | undefined> extends Error {
50
50
  * @param message The error message
51
51
  */
52
52
  constructor(
53
- ...[message, opts]:
53
+ ...[message, options]:
54
54
  T extends undefined ? ([string] | [string, AppErrorOptions<T>]) : [string, AppErrorOptions<T>]
55
55
  ) {
56
- super(message, opts?.cause ? { cause: opts.cause } : undefined);
57
- this.type = opts?.type ?? this.constructor.name;
58
- this.details = opts?.details!;
59
- this.category = opts?.category ?? castTo<typeof AppError>(this.constructor).defaultCategory ?? 'general';
60
- this.at = new Date(opts?.at ?? Date.now()).toISOString();
56
+ super(message, options?.cause ? { cause: options.cause } : undefined);
57
+ this.type = options?.type ?? this.constructor.name;
58
+ this.details = options?.details!;
59
+ this.category = options?.category ?? castTo<typeof AppError>(this.constructor).defaultCategory ?? 'general';
60
+ this.at = new Date(options?.at ?? Date.now()).toISOString();
61
61
  }
62
62
 
63
63
  /**
64
64
  * Serializes an error to a basic object
65
65
  */
66
66
  toJSON(): AppErrorOptions<T> & { message: string } {
67
- const res: AppErrorOptions<unknown> = {
67
+ const options: AppErrorOptions<unknown> = {
68
68
  category: this.category,
69
69
  ...(this.cause ? { cause: `${this.cause}` } : undefined),
70
70
  type: this.type,
@@ -73,6 +73,6 @@ export class AppError<T = Record<string, unknown> | undefined> extends Error {
73
73
  };
74
74
 
75
75
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
76
- return { message: this.message, ...res as AppErrorOptions<T> };
76
+ return { message: this.message, ...options as AppErrorOptions<T> };
77
77
  }
78
78
  }