@h3ravel/shared 1.29.0-alpha.15 → 2.0.0-alpha.16
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/index.d.ts +26 -4
- package/dist/index.js +111 -14
- package/package.json +4 -5
- package/dist/index.cjs +0 -976
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/// <reference path="./app.globals.d.ts" />
|
|
2
|
-
import { Options, Ora } from "ora";
|
|
3
|
-
import { Separator } from "@inquirer/prompts";
|
|
4
|
-
import { ChoiceOrSeparatorArray, ChoiceOrSeparatorArray as ChoiceOrSeparatorArray$1 } from "inquirer-autocomplete-standalone";
|
|
5
2
|
import { ChalkInstance } from "chalk";
|
|
3
|
+
import { JitiOptions, JitiResolveOptions } from "jiti";
|
|
4
|
+
import { ChoiceOrSeparatorArray, ChoiceOrSeparatorArray as ChoiceOrSeparatorArray$1 } from "inquirer-autocomplete-standalone";
|
|
5
|
+
import { Separator } from "@inquirer/prompts";
|
|
6
|
+
import { Options, Ora } from "ora";
|
|
6
7
|
import { ClassConstructor, IPathName } from "@h3ravel/contracts";
|
|
7
8
|
|
|
8
9
|
//#region src/Container.d.ts
|
|
@@ -398,6 +399,27 @@ declare class FileSystem {
|
|
|
398
399
|
static resolveModulePath(moduleId: string, pathName: string | string[], cwd?: string): string | undefined;
|
|
399
400
|
}
|
|
400
401
|
//#endregion
|
|
402
|
+
//#region src/Utils/Imports.d.ts
|
|
403
|
+
interface FileImporter {
|
|
404
|
+
<T = unknown>(filePath: string): Promise<T>;
|
|
405
|
+
<T = unknown>(filePath: string, userOptions?: JitiOptions): Promise<T>;
|
|
406
|
+
<T = unknown>(filePath: string, userOptions?: JitiOptions, resolveOptions?: JitiResolveOptions & {
|
|
407
|
+
default?: true;
|
|
408
|
+
}): Promise<T>;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
*
|
|
412
|
+
* Dynamically imports a file at the given path with full TypeScript support,
|
|
413
|
+
* including `tsconfig.json` path aliases.
|
|
414
|
+
*
|
|
415
|
+
* @param filePath - The path to the file to import.
|
|
416
|
+
* @returns The imported module typed as `T`.
|
|
417
|
+
*
|
|
418
|
+
* @example
|
|
419
|
+
* const config = await importFile<AppConfig>('./config/app.ts')
|
|
420
|
+
*/
|
|
421
|
+
declare const importFile: FileImporter;
|
|
422
|
+
//#endregion
|
|
401
423
|
//#region src/Utils/PathLoader.d.ts
|
|
402
424
|
declare class PathLoader {
|
|
403
425
|
private paths;
|
|
@@ -569,4 +591,4 @@ declare class TaskManager {
|
|
|
569
591
|
static advancedTaskRunner<R = any>(info: [[string, string], [string, string]] | [[string, string]], task: (() => Promise<R>) | (() => R)): Promise<R | undefined>;
|
|
570
592
|
}
|
|
571
593
|
//#endregion
|
|
572
|
-
export { Choice, type ChoiceOrSeparatorArray, Choices, Console, Derived, DotFlatten, DotNestedKeys, DotNestedValue, EnvParser, FileSystem, Finalizable, GenericWithNullableStringValues, INTERNAL_METHODS, ISeparator, Logger, LoggerChalk, LoggerLog, LoggerParseSignature, Magic, PathLoader, Prompts, Resolver, Spinner, TaskManager, Trait, UseMagic, baseTsconfig, crc32, internal, isInternal, mainTsconfig, makeMagic, makeStaticMagic, mix, packageJsonScript, trait, use, uses };
|
|
594
|
+
export { Choice, type ChoiceOrSeparatorArray, Choices, Console, Derived, DotFlatten, DotNestedKeys, DotNestedValue, EnvParser, FileImporter, FileSystem, Finalizable, GenericWithNullableStringValues, INTERNAL_METHODS, ISeparator, Logger, LoggerChalk, LoggerLog, LoggerParseSignature, Magic, PathLoader, Prompts, Resolver, Spinner, TaskManager, Trait, UseMagic, baseTsconfig, crc32, importFile, internal, isInternal, mainTsconfig, makeMagic, makeStaticMagic, mix, packageJsonScript, trait, use, uses };
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,10 @@ import { access } from "fs/promises";
|
|
|
3
3
|
import escalade from "escalade/sync";
|
|
4
4
|
import { existsSync } from "fs";
|
|
5
5
|
import path from "path";
|
|
6
|
+
import { createJiti } from "jiti";
|
|
7
|
+
import { existsSync as existsSync$1 } from "node:fs";
|
|
8
|
+
import { pathToFileURL } from "node:url";
|
|
9
|
+
import path$1, { resolve } from "node:path";
|
|
6
10
|
import autocomplete from "inquirer-autocomplete-standalone";
|
|
7
11
|
import { checkbox, confirm, editor, input, password, select } from "@inquirer/prompts";
|
|
8
12
|
import ora from "ora";
|
|
@@ -619,6 +623,98 @@ var FileSystem = class {
|
|
|
619
623
|
}
|
|
620
624
|
};
|
|
621
625
|
//#endregion
|
|
626
|
+
//#region src/Utils/Imports.ts
|
|
627
|
+
const findProjectRoot = (filePath) => {
|
|
628
|
+
let directory = path$1.dirname(filePath);
|
|
629
|
+
while (directory !== path$1.dirname(directory)) {
|
|
630
|
+
if (existsSync$1(path$1.join(directory, "package.json"))) return directory;
|
|
631
|
+
directory = path$1.dirname(directory);
|
|
632
|
+
}
|
|
633
|
+
return process.cwd();
|
|
634
|
+
};
|
|
635
|
+
const conventionalAliases = (root) => ({
|
|
636
|
+
src: path$1.join(root, "src"),
|
|
637
|
+
App: path$1.join(root, "src/app"),
|
|
638
|
+
root,
|
|
639
|
+
routes: path$1.join(root, "src/routes"),
|
|
640
|
+
config: path$1.join(root, "src/config"),
|
|
641
|
+
resources: path$1.join(root, "src/resources")
|
|
642
|
+
});
|
|
643
|
+
const frameworkModules = [
|
|
644
|
+
"@h3ravel/arquebus",
|
|
645
|
+
"@h3ravel/cache",
|
|
646
|
+
"@h3ravel/collect.js",
|
|
647
|
+
"@h3ravel/config",
|
|
648
|
+
"@h3ravel/console",
|
|
649
|
+
"@h3ravel/contracts",
|
|
650
|
+
"@h3ravel/core",
|
|
651
|
+
"@h3ravel/database",
|
|
652
|
+
"@h3ravel/events",
|
|
653
|
+
"@h3ravel/filesystem",
|
|
654
|
+
"@h3ravel/foundation",
|
|
655
|
+
"@h3ravel/hashing",
|
|
656
|
+
"@h3ravel/http",
|
|
657
|
+
"@h3ravel/mail",
|
|
658
|
+
"@h3ravel/musket",
|
|
659
|
+
"@h3ravel/queue",
|
|
660
|
+
"@h3ravel/router",
|
|
661
|
+
"@h3ravel/session",
|
|
662
|
+
"@h3ravel/shared",
|
|
663
|
+
"@h3ravel/support",
|
|
664
|
+
"@h3ravel/support/facades",
|
|
665
|
+
"@h3ravel/support/traits",
|
|
666
|
+
"@h3ravel/url",
|
|
667
|
+
"@h3ravel/validation",
|
|
668
|
+
"@h3ravel/view"
|
|
669
|
+
];
|
|
670
|
+
/**
|
|
671
|
+
*
|
|
672
|
+
* Dynamically imports a file at the given path with full TypeScript support,
|
|
673
|
+
* including `tsconfig.json` path aliases.
|
|
674
|
+
*
|
|
675
|
+
* @param filePath - The path to the file to import.
|
|
676
|
+
* @returns The imported module typed as `T`.
|
|
677
|
+
*
|
|
678
|
+
* @example
|
|
679
|
+
* const config = await importFile<AppConfig>('./config/app.ts')
|
|
680
|
+
*/
|
|
681
|
+
const importFile = async (filePath, userOptions, resolveOptions) => {
|
|
682
|
+
const resolvedPath = resolve(filePath);
|
|
683
|
+
const parentUrl = pathToFileURL(resolvedPath).href;
|
|
684
|
+
const extension = path$1.extname(resolvedPath).toLowerCase();
|
|
685
|
+
if ([
|
|
686
|
+
".js",
|
|
687
|
+
".mjs",
|
|
688
|
+
".cjs"
|
|
689
|
+
].includes(extension)) return await import(parentUrl);
|
|
690
|
+
let jiti;
|
|
691
|
+
try {
|
|
692
|
+
jiti = createJiti(parentUrl, {
|
|
693
|
+
...userOptions,
|
|
694
|
+
interopDefault: false,
|
|
695
|
+
tryNative: userOptions?.tryNative ?? true,
|
|
696
|
+
sourceMaps: userOptions?.sourceMaps ?? true,
|
|
697
|
+
nativeModules: [...frameworkModules, ...userOptions?.nativeModules ?? []],
|
|
698
|
+
tsconfigPaths: userOptions?.tsconfigPaths ?? true
|
|
699
|
+
});
|
|
700
|
+
} catch {
|
|
701
|
+
const projectRoot = findProjectRoot(resolvedPath);
|
|
702
|
+
jiti = createJiti(parentUrl, {
|
|
703
|
+
...userOptions,
|
|
704
|
+
alias: {
|
|
705
|
+
...conventionalAliases(projectRoot),
|
|
706
|
+
...userOptions?.alias
|
|
707
|
+
},
|
|
708
|
+
interopDefault: false,
|
|
709
|
+
tryNative: userOptions?.tryNative ?? true,
|
|
710
|
+
sourceMaps: userOptions?.sourceMaps ?? true,
|
|
711
|
+
nativeModules: [...frameworkModules, ...userOptions?.nativeModules ?? []],
|
|
712
|
+
tsconfigPaths: false
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
return await jiti.import(resolvedPath, resolveOptions);
|
|
716
|
+
};
|
|
717
|
+
//#endregion
|
|
622
718
|
//#region src/Utils/PathLoader.ts
|
|
623
719
|
var PathLoader = class {
|
|
624
720
|
paths = {
|
|
@@ -643,12 +739,12 @@ var PathLoader = class {
|
|
|
643
739
|
* @returns
|
|
644
740
|
*/
|
|
645
741
|
getPath(name, prefix) {
|
|
646
|
-
let path$
|
|
647
|
-
if (prefix && name !== "base") path$
|
|
648
|
-
else path$
|
|
649
|
-
if (name === "public") path$
|
|
650
|
-
else path$
|
|
651
|
-
return path.normalize(path$
|
|
742
|
+
let path$2;
|
|
743
|
+
if (prefix && name !== "base") path$2 = path.join(prefix, this.paths[name]);
|
|
744
|
+
else path$2 = this.paths[name];
|
|
745
|
+
if (process.env.NODE_ENV === "production") if (name === "public") path$2 = path$2.replace("/public", path.join("/", process.env.DIST_DIR ?? ".h3ravel/serve", "public"));
|
|
746
|
+
else path$2 = path$2.replace("/src/", `/${process.env.DIST_DIR ?? ".h3ravel/serve"}/`);
|
|
747
|
+
return path.normalize(path$2);
|
|
652
748
|
}
|
|
653
749
|
/**
|
|
654
750
|
* Programatically set the paths.
|
|
@@ -657,14 +753,15 @@ var PathLoader = class {
|
|
|
657
753
|
* @param path - The new path
|
|
658
754
|
* @param base - The base path to include to the path
|
|
659
755
|
*/
|
|
660
|
-
setPath(name, path$
|
|
661
|
-
if (base && name !== "base") this.paths[name] = path.join(base, path$
|
|
662
|
-
this.paths[name] = path$
|
|
756
|
+
setPath(name, path$3, base) {
|
|
757
|
+
if (base && name !== "base") this.paths[name] = path.join(base, path$3);
|
|
758
|
+
this.paths[name] = path$3;
|
|
663
759
|
}
|
|
664
|
-
distPath(path$
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
760
|
+
distPath(path$4, skipExt = false) {
|
|
761
|
+
if (process.env.NODE_ENV !== "production") return path.normalize(path$4);
|
|
762
|
+
path$4 = path$4.replace("/src/", `/${process.env.DIST_DIR ?? ".h3ravel/serve"}/`.replace(/([^:]\/)\/+/g, "$1"));
|
|
763
|
+
if (!skipExt) path$4 = path$4.replace(/\.(ts|tsx|mts|cts)$/, ".js");
|
|
764
|
+
return path.normalize(path$4);
|
|
668
765
|
}
|
|
669
766
|
};
|
|
670
767
|
//#endregion
|
|
@@ -920,4 +1017,4 @@ var TaskManager = class {
|
|
|
920
1017
|
}
|
|
921
1018
|
};
|
|
922
1019
|
//#endregion
|
|
923
|
-
export { Console, EnvParser, FileSystem, Finalizable, INTERNAL_METHODS, Logger, Magic, PathLoader, Prompts, Resolver, TaskManager, UseMagic, baseTsconfig, crc32, internal, isInternal, mainTsconfig, makeMagic, makeStaticMagic, mix, packageJsonScript, trait, use, uses };
|
|
1020
|
+
export { Console, EnvParser, FileSystem, Finalizable, INTERNAL_METHODS, Logger, Magic, PathLoader, Prompts, Resolver, TaskManager, UseMagic, baseTsconfig, crc32, importFile, internal, isInternal, mainTsconfig, makeMagic, makeStaticMagic, mix, packageJsonScript, trait, use, uses };
|
package/package.json
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@h3ravel/shared",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-alpha.16",
|
|
4
4
|
"description": "Shared Utilities.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./dist/index.cjs",
|
|
7
6
|
"types": "./dist/index.d.ts",
|
|
8
|
-
"module": "./dist/index.js",
|
|
9
7
|
"exports": {
|
|
10
8
|
".": {
|
|
11
9
|
"import": "./dist/index.js",
|
|
@@ -50,17 +48,18 @@
|
|
|
50
48
|
"escalade": "^3.2.0",
|
|
51
49
|
"h3": "2.0.1-rc.5",
|
|
52
50
|
"inquirer-autocomplete-standalone": "^0.8.1",
|
|
51
|
+
"jiti": "^2.7.0",
|
|
53
52
|
"ora": "^9.1.0",
|
|
54
53
|
"preferred-pm": "^4.1.1"
|
|
55
54
|
},
|
|
56
55
|
"devDependencies": {
|
|
57
|
-
"@h3ravel/contracts": "^
|
|
56
|
+
"@h3ravel/contracts": "^2.0.0-alpha.16",
|
|
58
57
|
"fetchdts": "^0.1.6",
|
|
59
58
|
"pnpm": "^10.14.0"
|
|
60
59
|
},
|
|
61
60
|
"scripts": {
|
|
62
61
|
"build": "tsdown --config-loader unrun",
|
|
63
|
-
"dev": "
|
|
62
|
+
"dev": "tsdown --watch --config-loader unrun",
|
|
64
63
|
"start": "node dist/index.js",
|
|
65
64
|
"lint": "eslint . --ext .ts",
|
|
66
65
|
"test": "jest --passWithNoTests",
|
package/dist/index.cjs
DELETED
|
@@ -1,976 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
//#region \0rolldown/runtime.js
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
-
key = keys[i];
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
-
get: ((k) => from[k]).bind(null, key),
|
|
14
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
-
value: mod,
|
|
21
|
-
enumerable: true
|
|
22
|
-
}) : target, mod));
|
|
23
|
-
//#endregion
|
|
24
|
-
let chalk = require("chalk");
|
|
25
|
-
chalk = __toESM(chalk, 1);
|
|
26
|
-
let fs_promises = require("fs/promises");
|
|
27
|
-
let escalade_sync = require("escalade/sync");
|
|
28
|
-
escalade_sync = __toESM(escalade_sync, 1);
|
|
29
|
-
let fs = require("fs");
|
|
30
|
-
let path = require("path");
|
|
31
|
-
path = __toESM(path, 1);
|
|
32
|
-
let inquirer_autocomplete_standalone = require("inquirer-autocomplete-standalone");
|
|
33
|
-
inquirer_autocomplete_standalone = __toESM(inquirer_autocomplete_standalone, 1);
|
|
34
|
-
let _inquirer_prompts = require("@inquirer/prompts");
|
|
35
|
-
let ora = require("ora");
|
|
36
|
-
ora = __toESM(ora, 1);
|
|
37
|
-
let crypto = require("crypto");
|
|
38
|
-
crypto = __toESM(crypto, 1);
|
|
39
|
-
let preferred_pm = require("preferred-pm");
|
|
40
|
-
preferred_pm = __toESM(preferred_pm, 1);
|
|
41
|
-
//#region src/Container.ts
|
|
42
|
-
const INTERNAL_METHODS = Symbol("internal_methods");
|
|
43
|
-
/**
|
|
44
|
-
* Decorator to mark class properties as internal
|
|
45
|
-
*
|
|
46
|
-
* @param target
|
|
47
|
-
* @param propertyKey
|
|
48
|
-
*/
|
|
49
|
-
const internal = (target, propertyKey) => {
|
|
50
|
-
if (!target[INTERNAL_METHODS]) target[INTERNAL_METHODS] = /* @__PURE__ */ new Set();
|
|
51
|
-
target[INTERNAL_METHODS].add(propertyKey);
|
|
52
|
-
};
|
|
53
|
-
/**
|
|
54
|
-
* Checks if a property is decorated with the @internal decorator
|
|
55
|
-
*
|
|
56
|
-
* @param instance
|
|
57
|
-
* @param prop
|
|
58
|
-
* @returns
|
|
59
|
-
*/
|
|
60
|
-
const isInternal = (instance, prop) => {
|
|
61
|
-
return Object.getPrototypeOf(instance)[INTERNAL_METHODS]?.has(prop) ?? false;
|
|
62
|
-
};
|
|
63
|
-
//#endregion
|
|
64
|
-
//#region src/Mixins/MixinSystem.ts
|
|
65
|
-
/**
|
|
66
|
-
* Helper to mix multiple classes into one, this allows extending multiple classes by any single class
|
|
67
|
-
*
|
|
68
|
-
* @param bases
|
|
69
|
-
* @returns
|
|
70
|
-
*/
|
|
71
|
-
const mix = (...bases) => {
|
|
72
|
-
class Base {
|
|
73
|
-
constructor(...args) {
|
|
74
|
-
let instance = this;
|
|
75
|
-
for (const constructor of bases) {
|
|
76
|
-
const result = Reflect.construct(constructor, args, new.target);
|
|
77
|
-
if (result && (typeof result === "object" || typeof result === "function")) {
|
|
78
|
-
if (result !== instance) {
|
|
79
|
-
Object.assign(result, instance);
|
|
80
|
-
instance = result;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return instance;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
for (let i = 0; i < bases.length; i++) {
|
|
88
|
-
const currentBase = bases[i];
|
|
89
|
-
const nextBase = bases[i + 1];
|
|
90
|
-
Object.getOwnPropertyNames(currentBase.prototype).forEach((prop) => {
|
|
91
|
-
if (prop !== "constructor") Object.defineProperty(Base.prototype, prop, Object.getOwnPropertyDescriptor(currentBase.prototype, prop));
|
|
92
|
-
});
|
|
93
|
-
Object.getOwnPropertyNames(currentBase).forEach((prop) => {
|
|
94
|
-
if (![
|
|
95
|
-
"prototype",
|
|
96
|
-
"name",
|
|
97
|
-
"length"
|
|
98
|
-
].includes(prop)) Object.defineProperty(Base, prop, Object.getOwnPropertyDescriptor(currentBase, prop));
|
|
99
|
-
});
|
|
100
|
-
if (nextBase) {
|
|
101
|
-
Object.setPrototypeOf(currentBase.prototype, nextBase.prototype);
|
|
102
|
-
Object.setPrototypeOf(currentBase, nextBase);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
Object.setPrototypeOf(Base.prototype, bases[0].prototype);
|
|
106
|
-
Object.setPrototypeOf(Base, bases[0]);
|
|
107
|
-
return Base;
|
|
108
|
-
};
|
|
109
|
-
//#endregion
|
|
110
|
-
//#region src/Mixins/TraitSystem.ts
|
|
111
|
-
const crcTable = [];
|
|
112
|
-
for (let n = 0; n < 256; n++) {
|
|
113
|
-
let c = n;
|
|
114
|
-
for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
115
|
-
crcTable[n] = c;
|
|
116
|
-
}
|
|
117
|
-
const crc32 = (str) => {
|
|
118
|
-
let crc = -1;
|
|
119
|
-
for (let i = 0; i < str.length; i++) crc = crc >>> 8 ^ crcTable[(crc ^ str.charCodeAt(i)) & 255];
|
|
120
|
-
return (crc ^ -1) >>> 0;
|
|
121
|
-
};
|
|
122
|
-
const isCons = (fn) => typeof fn === "function" && !!fn.prototype && !!fn.prototype.constructor;
|
|
123
|
-
const isTypeFactory = (fn) => typeof fn === "function" && !fn.prototype && fn.length === 0;
|
|
124
|
-
function trait(...args) {
|
|
125
|
-
const factory = args.length === 2 ? args[1] : args[0];
|
|
126
|
-
const superTraits = args.length === 2 ? args[0] : void 0;
|
|
127
|
-
return {
|
|
128
|
-
id: crc32(factory.toString()),
|
|
129
|
-
symbol: Symbol("trait"),
|
|
130
|
-
factory,
|
|
131
|
-
superTraits
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
const extendProperties = (cons, field, value) => Object.defineProperty(cons, field, {
|
|
135
|
-
value,
|
|
136
|
-
enumerable: false,
|
|
137
|
-
writable: false
|
|
138
|
-
});
|
|
139
|
-
const rawTrait = (x) => isTypeFactory(x) ? x() : x;
|
|
140
|
-
const deriveTrait = (trait$, baseClz, derived) => {
|
|
141
|
-
const trait = rawTrait(trait$);
|
|
142
|
-
let clz = baseClz;
|
|
143
|
-
if (!derived.has(trait.id)) {
|
|
144
|
-
derived.set(trait.id, true);
|
|
145
|
-
if (trait.superTraits !== void 0) for (const superTrait of reverseTraitList(trait.superTraits)) clz = deriveTrait(superTrait, clz, derived);
|
|
146
|
-
clz = trait.factory(clz);
|
|
147
|
-
extendProperties(clz, "id", crc32(trait.factory.toString()));
|
|
148
|
-
extendProperties(clz, trait.symbol, true);
|
|
149
|
-
}
|
|
150
|
-
return clz;
|
|
151
|
-
};
|
|
152
|
-
const reverseTraitList = (traits) => traits.slice().reverse();
|
|
153
|
-
function use(...traits) {
|
|
154
|
-
if (traits.length === 0) throw new Error("invalid number of parameters (expected one or more traits)");
|
|
155
|
-
let clz;
|
|
156
|
-
let lot;
|
|
157
|
-
const last = traits[traits.length - 1];
|
|
158
|
-
if (isCons(last) && !isTypeFactory(last)) {
|
|
159
|
-
clz = last;
|
|
160
|
-
lot = traits.slice(0, -1);
|
|
161
|
-
} else {
|
|
162
|
-
clz = class ROOT {};
|
|
163
|
-
lot = traits;
|
|
164
|
-
}
|
|
165
|
-
const derived = /* @__PURE__ */ new Map();
|
|
166
|
-
for (const trait of reverseTraitList(lot)) clz = deriveTrait(trait, clz, derived);
|
|
167
|
-
return clz;
|
|
168
|
-
}
|
|
169
|
-
function uses(instance, trait) {
|
|
170
|
-
if (typeof instance !== "object" || instance === null) return false;
|
|
171
|
-
let obj = instance;
|
|
172
|
-
if (isCons(trait) && !isTypeFactory(trait)) return instance instanceof trait;
|
|
173
|
-
const idTrait = (isTypeFactory(trait) ? trait() : trait)["id"];
|
|
174
|
-
while (obj) {
|
|
175
|
-
if (Object.hasOwn(obj, "constructor")) {
|
|
176
|
-
if ((obj.constructor["id"] ?? 0) === idTrait) return true;
|
|
177
|
-
}
|
|
178
|
-
obj = Object.getPrototypeOf(obj);
|
|
179
|
-
}
|
|
180
|
-
return false;
|
|
181
|
-
}
|
|
182
|
-
//#endregion
|
|
183
|
-
//#region src/Mixins/UseFinalizable.ts
|
|
184
|
-
/**
|
|
185
|
-
* the central class instance registry
|
|
186
|
-
*/
|
|
187
|
-
const registry = new FinalizationRegistry((fn) => {
|
|
188
|
-
if (typeof fn === "function" && !fn.finalized) {
|
|
189
|
-
fn.finalized = true;
|
|
190
|
-
fn();
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
/**
|
|
194
|
-
* the API trait "Finalizable<T>"
|
|
195
|
-
*/
|
|
196
|
-
const Finalizable = trait((base) => class Finalizable extends base {
|
|
197
|
-
constructor(...args) {
|
|
198
|
-
super(...args);
|
|
199
|
-
const fn1 = this.$finalize;
|
|
200
|
-
if (typeof fn1 !== "function") throw new Error("trait Finalizable requires a $finalize method to be defined");
|
|
201
|
-
const fn2 = () => {
|
|
202
|
-
fn1(this);
|
|
203
|
-
};
|
|
204
|
-
fn2.finalized = false;
|
|
205
|
-
registry.register(this, fn2, this);
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
//#endregion
|
|
209
|
-
//#region src/Mixins/UseMagic.ts
|
|
210
|
-
/**
|
|
211
|
-
* Wraps an object in a Proxy to emulate PHP magic methods.
|
|
212
|
-
*
|
|
213
|
-
* Supported:
|
|
214
|
-
* - __call(method, args)
|
|
215
|
-
* - __get(property)
|
|
216
|
-
* - __set(property, value)
|
|
217
|
-
* - __isset(property)
|
|
218
|
-
* - __unset(property)
|
|
219
|
-
*
|
|
220
|
-
* Called automatically by Magic's constructor.
|
|
221
|
-
*
|
|
222
|
-
* Return in any class constructor to use
|
|
223
|
-
*
|
|
224
|
-
* @param target
|
|
225
|
-
* @returns
|
|
226
|
-
*/
|
|
227
|
-
function makeMagic(target) {
|
|
228
|
-
return new Proxy(target, {
|
|
229
|
-
/**
|
|
230
|
-
* Intercepts property access and missing method calls.
|
|
231
|
-
*/
|
|
232
|
-
get(obj, prop, receiver) {
|
|
233
|
-
if (typeof prop === "string") {
|
|
234
|
-
if (prop in obj) return Reflect.get(obj, prop, receiver);
|
|
235
|
-
if (obj.__call) return (...args) => obj.__call(prop, args);
|
|
236
|
-
if (obj.__get) return obj.__get(prop);
|
|
237
|
-
}
|
|
238
|
-
},
|
|
239
|
-
/**
|
|
240
|
-
* Intercepts property assignment.
|
|
241
|
-
*/
|
|
242
|
-
set(obj, prop, value) {
|
|
243
|
-
if (typeof prop === "string" && obj.__set) {
|
|
244
|
-
obj.__set(prop, value);
|
|
245
|
-
return true;
|
|
246
|
-
}
|
|
247
|
-
return Reflect.set(obj, prop, value);
|
|
248
|
-
},
|
|
249
|
-
/**
|
|
250
|
-
* Intercepts `in` operator and existence checks.
|
|
251
|
-
*/
|
|
252
|
-
has(obj, prop) {
|
|
253
|
-
if (typeof prop === "string" && obj.__isset) return obj.__isset(prop);
|
|
254
|
-
return Reflect.has(obj, prop);
|
|
255
|
-
},
|
|
256
|
-
/**
|
|
257
|
-
* Intercepts `delete obj.prop`.
|
|
258
|
-
*/
|
|
259
|
-
deleteProperty(obj, prop) {
|
|
260
|
-
if (typeof prop === "string" && obj.__unset) {
|
|
261
|
-
obj.__unset(prop);
|
|
262
|
-
return true;
|
|
263
|
-
}
|
|
264
|
-
return Reflect.deleteProperty(obj, prop);
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Wraps a class constructor in a Proxy to emulate static PHP magic methods.
|
|
270
|
-
*
|
|
271
|
-
* Supported:
|
|
272
|
-
* - __callStatic(method, args)
|
|
273
|
-
* - static __get(property)
|
|
274
|
-
* - static __set(property, value)
|
|
275
|
-
* - static __isset(property)
|
|
276
|
-
* - static __unset(property)
|
|
277
|
-
*
|
|
278
|
-
* @param cls
|
|
279
|
-
* @returns
|
|
280
|
-
*/
|
|
281
|
-
function makeStaticMagic(cls) {
|
|
282
|
-
return new Proxy(cls, {
|
|
283
|
-
/**
|
|
284
|
-
* Intercepts static property access and missing static calls.
|
|
285
|
-
*/
|
|
286
|
-
get(target, prop) {
|
|
287
|
-
if (typeof prop === "string") {
|
|
288
|
-
if (prop in target) return target[prop];
|
|
289
|
-
if (target.__callStatic) return (...args) => target.__callStatic(prop, args);
|
|
290
|
-
if (target.__get) return target.__get(prop);
|
|
291
|
-
}
|
|
292
|
-
},
|
|
293
|
-
/**
|
|
294
|
-
* Intercepts static property assignment.
|
|
295
|
-
*/
|
|
296
|
-
set(target, prop, value) {
|
|
297
|
-
if (typeof prop === "string" && target.__set) {
|
|
298
|
-
target.__set(prop, value);
|
|
299
|
-
return true;
|
|
300
|
-
}
|
|
301
|
-
return Reflect.set(target, prop, value);
|
|
302
|
-
},
|
|
303
|
-
/**
|
|
304
|
-
* Intercepts `prop in Class`.
|
|
305
|
-
*/
|
|
306
|
-
has(target, prop) {
|
|
307
|
-
if (typeof prop === "string" && target.__isset) return target.__isset(prop);
|
|
308
|
-
return Reflect.has(target, prop);
|
|
309
|
-
},
|
|
310
|
-
/**
|
|
311
|
-
* Intercepts `delete Class.prop`.
|
|
312
|
-
*/
|
|
313
|
-
deleteProperty(target, prop) {
|
|
314
|
-
if (typeof prop === "string" && target.__unset) {
|
|
315
|
-
target.__unset(prop);
|
|
316
|
-
return true;
|
|
317
|
-
}
|
|
318
|
-
return Reflect.deleteProperty(target, prop);
|
|
319
|
-
}
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Base class that enables PHP-style magic methods automatically.
|
|
324
|
-
*
|
|
325
|
-
* Any subclass may implement:
|
|
326
|
-
* - __call
|
|
327
|
-
* - __get
|
|
328
|
-
* - __set
|
|
329
|
-
* - __isset
|
|
330
|
-
* - __unset
|
|
331
|
-
*
|
|
332
|
-
* The constructor returns a Proxy transparently.
|
|
333
|
-
*/
|
|
334
|
-
var Magic = class {
|
|
335
|
-
constructor() {
|
|
336
|
-
return makeMagic(this);
|
|
337
|
-
}
|
|
338
|
-
};
|
|
339
|
-
const UseMagic = trait((Base) => {
|
|
340
|
-
return class Magic extends Base {
|
|
341
|
-
constructor(...args) {
|
|
342
|
-
super(...args);
|
|
343
|
-
return makeMagic(this);
|
|
344
|
-
}
|
|
345
|
-
};
|
|
346
|
-
});
|
|
347
|
-
//#endregion
|
|
348
|
-
//#region src/Utils/Logger.ts
|
|
349
|
-
var Logger = class Logger {
|
|
350
|
-
/**
|
|
351
|
-
* Global verbosity configuration
|
|
352
|
-
*/
|
|
353
|
-
static verbosity = 0;
|
|
354
|
-
static isQuiet = false;
|
|
355
|
-
static isSilent = false;
|
|
356
|
-
/**
|
|
357
|
-
* Configure global verbosity levels
|
|
358
|
-
*/
|
|
359
|
-
static configure(options = {}) {
|
|
360
|
-
this.verbosity = options.verbosity ?? 0;
|
|
361
|
-
this.isQuiet = options.quiet ?? false;
|
|
362
|
-
this.isSilent = options.silent ?? false;
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Check if output should be suppressed
|
|
366
|
-
*/
|
|
367
|
-
static shouldSuppressOutput(level) {
|
|
368
|
-
if (this.isSilent) return true;
|
|
369
|
-
if (this.isQuiet && (level === "info" || level === "success")) return true;
|
|
370
|
-
if (level === "debug" && this.verbosity < 3) return true;
|
|
371
|
-
return false;
|
|
372
|
-
}
|
|
373
|
-
static twoColumnDetail(name, value, log = true, spacer = ".") {
|
|
374
|
-
const regex = /\x1b\[\d+m/g;
|
|
375
|
-
const width = Math.max(process.stdout.columns, 100);
|
|
376
|
-
const dots = Math.max(width - name.replace(regex, "").length - value.replace(regex, "").length - 10, 0);
|
|
377
|
-
if (log) return console.log(name, chalk.default.gray(spacer.repeat(dots)), value);
|
|
378
|
-
else return [
|
|
379
|
-
name,
|
|
380
|
-
chalk.default.gray(spacer.repeat(dots)),
|
|
381
|
-
value
|
|
382
|
-
];
|
|
383
|
-
}
|
|
384
|
-
static describe(name, desc, width = 50, log = true) {
|
|
385
|
-
width = Math.max(width, 30);
|
|
386
|
-
const dots = Math.max(width - name.replace(/\x1b\[\d+m/g, "").length, 0);
|
|
387
|
-
if (log) return console.log(name, " ".repeat(dots), desc);
|
|
388
|
-
else return [
|
|
389
|
-
name,
|
|
390
|
-
" ".repeat(dots),
|
|
391
|
-
desc
|
|
392
|
-
];
|
|
393
|
-
}
|
|
394
|
-
/**
|
|
395
|
-
* Logs the message in two columns but allways passing status
|
|
396
|
-
*
|
|
397
|
-
* @param name
|
|
398
|
-
* @param value
|
|
399
|
-
* @param status
|
|
400
|
-
* @param exit
|
|
401
|
-
* @param preserveCol
|
|
402
|
-
*/
|
|
403
|
-
static split(name, value, status, exit = false, preserveCol = false, spacer = ".") {
|
|
404
|
-
status ??= "info";
|
|
405
|
-
const color = {
|
|
406
|
-
success: chalk.default.bgGreen,
|
|
407
|
-
info: chalk.default.bgBlue,
|
|
408
|
-
error: chalk.default.bgRed
|
|
409
|
-
};
|
|
410
|
-
const [_name, dots, val] = this.twoColumnDetail(name, value, false, spacer);
|
|
411
|
-
console.log(this.textFormat(_name, color[status], preserveCol), dots, val);
|
|
412
|
-
if (exit) process.exit(0);
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* Wraps text with chalk
|
|
416
|
-
*
|
|
417
|
-
* @param txt
|
|
418
|
-
* @param color
|
|
419
|
-
* @param preserveCol
|
|
420
|
-
* @returns
|
|
421
|
-
*/
|
|
422
|
-
static textFormat(txt, color, preserveCol = false) {
|
|
423
|
-
if (txt instanceof Error) {
|
|
424
|
-
const err = txt;
|
|
425
|
-
const code = err.code ?? err.statusCode ? ` (${err.code ?? err.statusCode})` : "";
|
|
426
|
-
const output = [];
|
|
427
|
-
if (err.message) output.push(this.textFormat(`${err.constructor.name}${code}: ${err.message}`, chalk.default.bgRed, preserveCol));
|
|
428
|
-
if (err.stack) output.push(" " + chalk.default.white(err.stack.replace(`${err.name}: ${err.message}`, "").trim()));
|
|
429
|
-
return output.join("\n");
|
|
430
|
-
}
|
|
431
|
-
if (Array.isArray(txt)) return txt.map((e) => this.textFormat(e, color, preserveCol)).join("\n");
|
|
432
|
-
if (typeof txt === "object") return this.textFormat(Object.values(txt), color, preserveCol);
|
|
433
|
-
if (typeof txt !== "string") return color(txt);
|
|
434
|
-
const str = String(txt);
|
|
435
|
-
if (preserveCol) return str;
|
|
436
|
-
const [first, ...rest] = str.split(":");
|
|
437
|
-
if (rest.length === 0) return str;
|
|
438
|
-
return color(` ${first} `) + rest.join(":");
|
|
439
|
-
}
|
|
440
|
-
/**
|
|
441
|
-
* Logs a success message
|
|
442
|
-
*
|
|
443
|
-
* @param msg
|
|
444
|
-
* @param exit
|
|
445
|
-
* @param preserveCol
|
|
446
|
-
*/
|
|
447
|
-
static success(msg, exit = false, preserveCol = false) {
|
|
448
|
-
if (!this.shouldSuppressOutput("success")) console.log(chalk.default.green("✓"), this.textFormat(msg, chalk.default.bgGreen, preserveCol));
|
|
449
|
-
if (exit) process.exit(0);
|
|
450
|
-
}
|
|
451
|
-
/**
|
|
452
|
-
* Logs an informational message
|
|
453
|
-
*
|
|
454
|
-
* @param msg
|
|
455
|
-
* @param exit
|
|
456
|
-
* @param preserveCol
|
|
457
|
-
*/
|
|
458
|
-
static info(msg, exit = false, preserveCol = false) {
|
|
459
|
-
if (!this.shouldSuppressOutput("info")) console.log(chalk.default.blue("ℹ"), this.textFormat(msg, chalk.default.bgBlue, preserveCol));
|
|
460
|
-
if (exit) process.exit(0);
|
|
461
|
-
}
|
|
462
|
-
/**
|
|
463
|
-
* Logs an error message
|
|
464
|
-
*
|
|
465
|
-
* @param msg
|
|
466
|
-
* @param exit
|
|
467
|
-
* @param preserveCol
|
|
468
|
-
*/
|
|
469
|
-
static error(msg, exit = true, preserveCol = false) {
|
|
470
|
-
if (!this.shouldSuppressOutput("error")) if (msg instanceof Error) {
|
|
471
|
-
if (msg.message) console.error(chalk.default.red("✖"), this.textFormat("ERROR:" + msg.message, chalk.default.bgRed, preserveCol));
|
|
472
|
-
console.error(chalk.default.red(`${msg.detail ? `${msg.detail}\n` : ""}${msg.stack}`));
|
|
473
|
-
} else console.error(chalk.default.red("✖"), this.textFormat(msg, chalk.default.bgRed, preserveCol));
|
|
474
|
-
if (exit) process.exit(1);
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* Logs a warning message
|
|
478
|
-
*
|
|
479
|
-
* @param msg
|
|
480
|
-
* @param exit
|
|
481
|
-
* @param preserveCol
|
|
482
|
-
*/
|
|
483
|
-
static warn(msg, exit = false, preserveCol = false) {
|
|
484
|
-
if (!this.shouldSuppressOutput("warn")) console.warn(chalk.default.yellow("⚠"), this.textFormat(msg, chalk.default.bgYellow, preserveCol));
|
|
485
|
-
if (exit) process.exit(0);
|
|
486
|
-
}
|
|
487
|
-
/**
|
|
488
|
-
* Logs a debug message (only shown with verbosity >= 3)
|
|
489
|
-
*
|
|
490
|
-
* @param msg
|
|
491
|
-
* @param exit
|
|
492
|
-
* @param preserveCol
|
|
493
|
-
*/
|
|
494
|
-
static debug(msg, exit = false, preserveCol = false) {
|
|
495
|
-
if (!this.shouldSuppressOutput("debug")) if (Array.isArray(msg)) for (let i = 0; i < msg.length; i++) console.log(chalk.default.gray("🐛"), chalk.default.bgGray(i + 1), this.textFormat(msg[i], chalk.default.bgGray, preserveCol));
|
|
496
|
-
else console.log(chalk.default.gray("🐛"), this.textFormat(msg, chalk.default.bgGray, preserveCol));
|
|
497
|
-
if (exit) process.exit(0);
|
|
498
|
-
}
|
|
499
|
-
/**
|
|
500
|
-
* Terminates the process
|
|
501
|
-
*/
|
|
502
|
-
static quiet() {
|
|
503
|
-
process.exit(0);
|
|
504
|
-
}
|
|
505
|
-
static chalker(styles) {
|
|
506
|
-
return (input) => styles.reduce((acc, style) => {
|
|
507
|
-
if (style in chalk.default) return (typeof style === "function" ? style : chalk.default[style])(acc);
|
|
508
|
-
return acc;
|
|
509
|
-
}, input);
|
|
510
|
-
}
|
|
511
|
-
static parse(config, joiner = " ", log = true, sc) {
|
|
512
|
-
const string = config.map(([str, opt]) => {
|
|
513
|
-
if (Array.isArray(opt)) opt = Logger.chalker(opt);
|
|
514
|
-
const output = typeof opt === "string" && typeof chalk.default[opt] === "function" ? chalk.default[opt](str) : typeof opt === "function" ? opt(str) : str;
|
|
515
|
-
if (!sc) return output;
|
|
516
|
-
return this.textFormat(output, Logger.chalker(Array.isArray(sc) ? sc : [sc]));
|
|
517
|
-
}).join(joiner);
|
|
518
|
-
if (log && !this.shouldSuppressOutput("line")) console.log(string);
|
|
519
|
-
else return string;
|
|
520
|
-
}
|
|
521
|
-
/**
|
|
522
|
-
* Ouput formater object or format the output
|
|
523
|
-
*
|
|
524
|
-
* @returns
|
|
525
|
-
*/
|
|
526
|
-
static log = ((config, joiner, log = true, sc) => {
|
|
527
|
-
if (typeof config === "string") {
|
|
528
|
-
const conf = [[config, joiner]];
|
|
529
|
-
return this.parse(conf, "", log, sc);
|
|
530
|
-
} else if (Array.isArray(config)) return this.parse(config, String(joiner), log, sc);
|
|
531
|
-
else if (log && !this.shouldSuppressOutput("line")) return console.log(this.textFormat(config, Logger.chalker(["blue"])));
|
|
532
|
-
return this;
|
|
533
|
-
});
|
|
534
|
-
/**
|
|
535
|
-
* A simple console like output logger
|
|
536
|
-
*
|
|
537
|
-
* @returns
|
|
538
|
-
*/
|
|
539
|
-
static console() {
|
|
540
|
-
return Console;
|
|
541
|
-
}
|
|
542
|
-
};
|
|
543
|
-
//#endregion
|
|
544
|
-
//#region src/Utils/Console.ts
|
|
545
|
-
var Console = class {
|
|
546
|
-
static log = (...args) => Logger.log(args.map((e) => [e, "white"]));
|
|
547
|
-
static debug = (...args) => Logger.debug(args, false, true);
|
|
548
|
-
static warn = (...args) => args.map((e) => Logger.warn(e, false, true));
|
|
549
|
-
static info = (...args) => args.map((e) => Logger.info(e, false, true));
|
|
550
|
-
static error = (...args) => args.map((e) => Logger.error(e, false), true);
|
|
551
|
-
};
|
|
552
|
-
//#endregion
|
|
553
|
-
//#region src/Utils/EnvParser.ts
|
|
554
|
-
var EnvParser = class {
|
|
555
|
-
static parse(initial) {
|
|
556
|
-
const parsed = { ...initial };
|
|
557
|
-
for (const key in parsed) {
|
|
558
|
-
const value = parsed[key];
|
|
559
|
-
parsed[key] = this.parseValue(value);
|
|
560
|
-
}
|
|
561
|
-
return parsed;
|
|
562
|
-
}
|
|
563
|
-
static parseValue(value) {
|
|
564
|
-
/**
|
|
565
|
-
* Null/undefined stay untouched
|
|
566
|
-
*/
|
|
567
|
-
if (value === null || value === void 0) return value;
|
|
568
|
-
/**
|
|
569
|
-
* Convert string "true"/"false" to boolean
|
|
570
|
-
*/
|
|
571
|
-
if (value === "true") return true;
|
|
572
|
-
if (value === "false") return false;
|
|
573
|
-
/**
|
|
574
|
-
* Convert string numbers to number
|
|
575
|
-
*/
|
|
576
|
-
if (!isNaN(value) && value.trim() !== "") return Number(value);
|
|
577
|
-
/**
|
|
578
|
-
* Convert string "null" and "undefined"
|
|
579
|
-
*/
|
|
580
|
-
if (value === "null") return null;
|
|
581
|
-
if (value === "undefined") return void 0;
|
|
582
|
-
/**
|
|
583
|
-
* Otherwise return as-is (string)
|
|
584
|
-
*/
|
|
585
|
-
return value;
|
|
586
|
-
}
|
|
587
|
-
};
|
|
588
|
-
//#endregion
|
|
589
|
-
//#region src/Utils/FileSystem.ts
|
|
590
|
-
var FileSystem = class {
|
|
591
|
-
static findModulePkg(moduleId, cwd) {
|
|
592
|
-
const parts = moduleId.replace(/\\/g, "/").split("/");
|
|
593
|
-
let packageName = "";
|
|
594
|
-
if (parts.length > 0 && parts[0][0] === "@") packageName += parts.shift() + "/";
|
|
595
|
-
packageName += parts.shift();
|
|
596
|
-
const packageJson = path.default.join(cwd ?? process.cwd(), "node_modules", packageName);
|
|
597
|
-
const resolved = this.resolveFileUp("package", ["json"], packageJson);
|
|
598
|
-
if (!resolved) return;
|
|
599
|
-
return path.default.join(path.default.dirname(resolved), parts.join("/"));
|
|
600
|
-
}
|
|
601
|
-
/**
|
|
602
|
-
* Check if file exists
|
|
603
|
-
*
|
|
604
|
-
* @param path
|
|
605
|
-
* @returns
|
|
606
|
-
*/
|
|
607
|
-
static async fileExists(path$5) {
|
|
608
|
-
try {
|
|
609
|
-
await (0, fs_promises.access)(path$5);
|
|
610
|
-
return true;
|
|
611
|
-
} catch {
|
|
612
|
-
return false;
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
/**
|
|
616
|
-
* Recursively find files starting from given cwd
|
|
617
|
-
*
|
|
618
|
-
* @param name
|
|
619
|
-
* @param extensions
|
|
620
|
-
* @param cwd
|
|
621
|
-
*
|
|
622
|
-
* @returns
|
|
623
|
-
*/
|
|
624
|
-
static resolveFileUp(name, extensions, cwd) {
|
|
625
|
-
cwd ??= process.cwd();
|
|
626
|
-
return (0, escalade_sync.default)(cwd, (dir, filesNames) => {
|
|
627
|
-
if (typeof extensions === "function") return extensions(dir, filesNames);
|
|
628
|
-
const candidates = new Set(extensions.map((ext) => `${name}.${ext}`));
|
|
629
|
-
for (const filename of filesNames) if (candidates.has(filename)) return filename;
|
|
630
|
-
return false;
|
|
631
|
-
}) ?? void 0;
|
|
632
|
-
}
|
|
633
|
-
/**
|
|
634
|
-
* Recursively find files starting from given cwd
|
|
635
|
-
*
|
|
636
|
-
* @param name
|
|
637
|
-
* @param extensions
|
|
638
|
-
* @param cwd
|
|
639
|
-
*
|
|
640
|
-
* @returns
|
|
641
|
-
*/
|
|
642
|
-
static resolveModulePath(moduleId, pathName, cwd) {
|
|
643
|
-
pathName = Array.isArray(pathName) ? pathName : [pathName];
|
|
644
|
-
const module = this.findModulePkg(moduleId, cwd) ?? "";
|
|
645
|
-
for (const name of pathName) {
|
|
646
|
-
const file = path.default.join(module, name);
|
|
647
|
-
if ((0, fs.existsSync)(file)) return file;
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
};
|
|
651
|
-
//#endregion
|
|
652
|
-
//#region src/Utils/PathLoader.ts
|
|
653
|
-
var PathLoader = class {
|
|
654
|
-
paths = {
|
|
655
|
-
app: "/src/app",
|
|
656
|
-
src: "/src/",
|
|
657
|
-
base: "",
|
|
658
|
-
views: "/src/resources/views",
|
|
659
|
-
assets: "/public/assets",
|
|
660
|
-
routes: "/src/routes",
|
|
661
|
-
config: "/src/config",
|
|
662
|
-
public: "/public",
|
|
663
|
-
storage: "/storage",
|
|
664
|
-
database: "/src/database",
|
|
665
|
-
commands: "/src/app/Console/Commands"
|
|
666
|
-
};
|
|
667
|
-
/**
|
|
668
|
-
* Dynamically retrieves a path property from the class.
|
|
669
|
-
* Any property ending with "Path" is accessible automatically.
|
|
670
|
-
*
|
|
671
|
-
* @param name - The base name of the path property
|
|
672
|
-
* @param prefix - The base path to prefix to the path
|
|
673
|
-
* @returns
|
|
674
|
-
*/
|
|
675
|
-
getPath(name, prefix) {
|
|
676
|
-
let path$2;
|
|
677
|
-
if (prefix && name !== "base") path$2 = path.default.join(prefix, this.paths[name]);
|
|
678
|
-
else path$2 = this.paths[name];
|
|
679
|
-
if (name === "public") path$2 = path$2.replace("/public", path.default.join("/", process.env.DIST_DIR ?? ".h3ravel/serve", "public"));
|
|
680
|
-
else path$2 = path$2.replace("/src/", `/${process.env.DIST_DIR ?? ".h3ravel/serve"}/`);
|
|
681
|
-
return path.default.normalize(path$2);
|
|
682
|
-
}
|
|
683
|
-
/**
|
|
684
|
-
* Programatically set the paths.
|
|
685
|
-
*
|
|
686
|
-
* @param name - The base name of the path property
|
|
687
|
-
* @param path - The new path
|
|
688
|
-
* @param base - The base path to include to the path
|
|
689
|
-
*/
|
|
690
|
-
setPath(name, path$3, base) {
|
|
691
|
-
if (base && name !== "base") this.paths[name] = path.default.join(base, path$3);
|
|
692
|
-
this.paths[name] = path$3;
|
|
693
|
-
}
|
|
694
|
-
distPath(path$4, skipExt = false) {
|
|
695
|
-
path$4 = path$4.replace("/src/", `/${process.env.DIST_DIR ?? ".h3ravel/serve"}/`.replace(/([^:]\/)\/+/g, "$1"));
|
|
696
|
-
if (!skipExt) path$4 = path$4.replace(/\.(ts|tsx|mts|cts)$/, ".js");
|
|
697
|
-
return path.default.normalize(path$4);
|
|
698
|
-
}
|
|
699
|
-
};
|
|
700
|
-
//#endregion
|
|
701
|
-
//#region src/Utils/Prompts.ts
|
|
702
|
-
var Prompts = class extends Logger {
|
|
703
|
-
/**
|
|
704
|
-
* Allows users to pick from a predefined set of choices when asked a question.
|
|
705
|
-
*
|
|
706
|
-
* @param message Message to display
|
|
707
|
-
* @param choices The choices available to the user
|
|
708
|
-
* @param defaultIndex Item index front of which the cursor will initially appear
|
|
709
|
-
* @param pageSize The number of items to show per page
|
|
710
|
-
* @returns
|
|
711
|
-
*/
|
|
712
|
-
static async choice(message, choices, defaultIndex, pageSize) {
|
|
713
|
-
return (0, _inquirer_prompts.select)({
|
|
714
|
-
message,
|
|
715
|
-
choices,
|
|
716
|
-
default: defaultIndex ? choices.at(defaultIndex) : void 0,
|
|
717
|
-
pageSize
|
|
718
|
-
});
|
|
719
|
-
}
|
|
720
|
-
/**
|
|
721
|
-
* Ask the user for a simple "yes or no" confirmation.
|
|
722
|
-
* By default, this method returns `false`. However, if the user enters y or yes
|
|
723
|
-
* in response to the prompt, the method would return `true`.
|
|
724
|
-
*
|
|
725
|
-
* @param message Message to display
|
|
726
|
-
* @param defaultValue The default value
|
|
727
|
-
*/
|
|
728
|
-
static async confirm(message, defaultValue) {
|
|
729
|
-
return (0, _inquirer_prompts.confirm)({
|
|
730
|
-
message,
|
|
731
|
-
default: defaultValue
|
|
732
|
-
});
|
|
733
|
-
}
|
|
734
|
-
/**
|
|
735
|
-
* Prompt the user with the given question, accept their input,
|
|
736
|
-
* and then return the user's input back to your command.
|
|
737
|
-
*
|
|
738
|
-
* @param message Message to display
|
|
739
|
-
* @param defaultValue The default value
|
|
740
|
-
* @returns
|
|
741
|
-
*/
|
|
742
|
-
static async ask(message, defaultValue) {
|
|
743
|
-
return (0, _inquirer_prompts.input)({
|
|
744
|
-
message,
|
|
745
|
-
default: defaultValue
|
|
746
|
-
});
|
|
747
|
-
}
|
|
748
|
-
/**
|
|
749
|
-
* Prompt the user with the given question, accept their input which
|
|
750
|
-
* will not be visible to them as they type in the console,
|
|
751
|
-
* and then return the user's input back to your command.
|
|
752
|
-
*
|
|
753
|
-
* @param message Message to display
|
|
754
|
-
* @param mask Mask the user input
|
|
755
|
-
* @returns
|
|
756
|
-
*/
|
|
757
|
-
static async secret(message, mask) {
|
|
758
|
-
return (0, _inquirer_prompts.password)({
|
|
759
|
-
message,
|
|
760
|
-
mask
|
|
761
|
-
});
|
|
762
|
-
}
|
|
763
|
-
/**
|
|
764
|
-
* Provide auto-completion for possible choices.
|
|
765
|
-
* The user can still provide any answer, regardless of the auto-completion hints.
|
|
766
|
-
*/
|
|
767
|
-
/**
|
|
768
|
-
*
|
|
769
|
-
* @param message Message to dislpay
|
|
770
|
-
* @param source The source of completions
|
|
771
|
-
* @param defaultValue Set a default value
|
|
772
|
-
* @param pageSize The number of items to show per page
|
|
773
|
-
* @returns
|
|
774
|
-
*/
|
|
775
|
-
static async anticipate(message, source, defaultValue, pageSize) {
|
|
776
|
-
return (0, inquirer_autocomplete_standalone.default)({
|
|
777
|
-
message,
|
|
778
|
-
source: Array.isArray(source) ? async (term) => {
|
|
779
|
-
return (term ? source.filter((e) => e.includes(term)) : source).map((e) => ({ value: e }));
|
|
780
|
-
} : source,
|
|
781
|
-
suggestOnly: true,
|
|
782
|
-
default: defaultValue,
|
|
783
|
-
pageSize
|
|
784
|
-
});
|
|
785
|
-
}
|
|
786
|
-
/**
|
|
787
|
-
* Display a spinner while performing a long task
|
|
788
|
-
*
|
|
789
|
-
* @param options The spinner options
|
|
790
|
-
* @returns
|
|
791
|
-
*/
|
|
792
|
-
static spinner(options) {
|
|
793
|
-
return (0, ora.default)(options);
|
|
794
|
-
}
|
|
795
|
-
/**
|
|
796
|
-
* Allows users to select multiple options from a predefined list of choices.
|
|
797
|
-
*
|
|
798
|
-
* @param message Message to display
|
|
799
|
-
* @param choices The choices available to the user
|
|
800
|
-
* @param required Whether at least one choice is required
|
|
801
|
-
* @param prefix Prefix to display before the message
|
|
802
|
-
* @param pageSize The number of items to show per page
|
|
803
|
-
* @returns
|
|
804
|
-
*/
|
|
805
|
-
static async checkbox(message, choices, required, prefix, pageSize) {
|
|
806
|
-
return await (0, _inquirer_prompts.checkbox)({
|
|
807
|
-
message,
|
|
808
|
-
choices,
|
|
809
|
-
required,
|
|
810
|
-
prefix,
|
|
811
|
-
pageSize
|
|
812
|
-
});
|
|
813
|
-
}
|
|
814
|
-
/**
|
|
815
|
-
* Open the user's default text editor to accept multi-line input.
|
|
816
|
-
*
|
|
817
|
-
* @param message Message to display
|
|
818
|
-
* @param postfix The postfix of the file being edited [e.g., '.txt', '.md']
|
|
819
|
-
* @param defaultValue The default value to pre-fill in the editor
|
|
820
|
-
* @param validate A function to validate the input text
|
|
821
|
-
* @returns
|
|
822
|
-
*/
|
|
823
|
-
static async editor(message, postfix, defaultValue, validate) {
|
|
824
|
-
return await (0, _inquirer_prompts.editor)({
|
|
825
|
-
message: message ?? "Please provide your input in the editor below:",
|
|
826
|
-
postfix,
|
|
827
|
-
default: defaultValue,
|
|
828
|
-
validate
|
|
829
|
-
});
|
|
830
|
-
}
|
|
831
|
-
};
|
|
832
|
-
//#endregion
|
|
833
|
-
//#region src/Utils/Resolver.ts
|
|
834
|
-
var Resolver = class {
|
|
835
|
-
static async getPakageInstallCommand(pkg) {
|
|
836
|
-
const pm = (await (0, preferred_pm.default)(process.cwd()))?.name ?? "pnpm";
|
|
837
|
-
let cmd = "install ";
|
|
838
|
-
if (!pkg) if (pm === "npm" || pm === "pnpm" || pm === "bun") cmd = "install";
|
|
839
|
-
else cmd = "";
|
|
840
|
-
else if (pm === "yarn" || pm === "pnpm" || pm === "bun") cmd = "add ";
|
|
841
|
-
return `${pm} ${cmd}${pkg ?? ""}`;
|
|
842
|
-
}
|
|
843
|
-
static async getInstallCommand(pkg) {
|
|
844
|
-
const pm = (await (0, preferred_pm.default)(process.cwd()))?.name ?? "pnpm";
|
|
845
|
-
let cmd = "install";
|
|
846
|
-
if (pm === "yarn" || pm === "pnpm") cmd = "add";
|
|
847
|
-
else if (pm === "bun") cmd = "create";
|
|
848
|
-
return `${pm} ${cmd} ${pkg}`;
|
|
849
|
-
}
|
|
850
|
-
/**
|
|
851
|
-
* Create a hash for a function or an object
|
|
852
|
-
*
|
|
853
|
-
* @param provider
|
|
854
|
-
* @returns
|
|
855
|
-
*/
|
|
856
|
-
static hashObjectOrFunction(provider) {
|
|
857
|
-
return crypto.default.createHash("sha1").update(provider.toString()).digest("hex");
|
|
858
|
-
}
|
|
859
|
-
/**
|
|
860
|
-
* Checks if a function is asyncronous
|
|
861
|
-
*
|
|
862
|
-
* @param func
|
|
863
|
-
* @returns
|
|
864
|
-
*/
|
|
865
|
-
static isAsyncFunction(func) {
|
|
866
|
-
if (typeof func !== "function") return false;
|
|
867
|
-
return Object.prototype.toString.call(func) === "[object AsyncFunction]";
|
|
868
|
-
}
|
|
869
|
-
};
|
|
870
|
-
//#endregion
|
|
871
|
-
//#region src/Utils/scripts.ts
|
|
872
|
-
const mainTsconfig = {
|
|
873
|
-
extends: "@h3ravel/shared/tsconfig.base.json",
|
|
874
|
-
compilerOptions: {
|
|
875
|
-
paths: {
|
|
876
|
-
"src/*": ["./../src/*"],
|
|
877
|
-
"App/*": ["./../src/app/*"],
|
|
878
|
-
"root/*": ["./../*"],
|
|
879
|
-
"routes/*": ["./../src/routes/*"],
|
|
880
|
-
"config/*": ["./../src/config/*"],
|
|
881
|
-
"resources/*": ["./../src/resources/*"]
|
|
882
|
-
},
|
|
883
|
-
target: "es2022",
|
|
884
|
-
module: "es2022",
|
|
885
|
-
moduleResolution: "bundler",
|
|
886
|
-
esModuleInterop: true,
|
|
887
|
-
strict: true,
|
|
888
|
-
allowJs: true,
|
|
889
|
-
skipLibCheck: true,
|
|
890
|
-
resolveJsonModule: true,
|
|
891
|
-
noEmit: true,
|
|
892
|
-
experimentalDecorators: true,
|
|
893
|
-
emitDecoratorMetadata: true
|
|
894
|
-
},
|
|
895
|
-
include: ["./**/*.d.ts", "./../**/*"],
|
|
896
|
-
exclude: [
|
|
897
|
-
".",
|
|
898
|
-
"./../**/console/bin",
|
|
899
|
-
"./../dist",
|
|
900
|
-
"./../**/dist",
|
|
901
|
-
"./../**/node_modules",
|
|
902
|
-
"./../.node_modules",
|
|
903
|
-
"./../**/node_modules/*",
|
|
904
|
-
"./../**/public",
|
|
905
|
-
"./../public",
|
|
906
|
-
"./../**/storage",
|
|
907
|
-
"./../storage",
|
|
908
|
-
"./../**coverage**",
|
|
909
|
-
"./../eslint.config.js",
|
|
910
|
-
"./../jest.config.ts",
|
|
911
|
-
"./../arquebus.config.js"
|
|
912
|
-
]
|
|
913
|
-
};
|
|
914
|
-
const baseTsconfig = { extends: "./.h3ravel/tsconfig.json" };
|
|
915
|
-
const packageJsonScript = {
|
|
916
|
-
build: "NODE_ENV=production tsdown --config-loader unrun -c tsdown.default.config.ts",
|
|
917
|
-
dev: "NODE_ENV=development pnpm tsdown --config-loader unrun -c tsdown.default.config.ts",
|
|
918
|
-
start: "DIST_DIR=dist node -r source-map-support/register dist/server.js",
|
|
919
|
-
lint: "eslint . --ext .ts",
|
|
920
|
-
test: "NODE_NO_WARNINGS=1 NODE_ENV=testing jest --passWithNoTests",
|
|
921
|
-
postinstall: "pnpm prepare"
|
|
922
|
-
};
|
|
923
|
-
//#endregion
|
|
924
|
-
//#region src/Utils/TaskManager.ts
|
|
925
|
-
var TaskManager = class {
|
|
926
|
-
static async taskRunner(description, task) {
|
|
927
|
-
const startTime = process.hrtime();
|
|
928
|
-
let result = false;
|
|
929
|
-
try {
|
|
930
|
-
result = await Promise.all([(task || (() => true))()].flat());
|
|
931
|
-
} finally {
|
|
932
|
-
const endTime = process.hrtime(startTime);
|
|
933
|
-
const duration = (endTime[0] * 1e9 + endTime[1]) / 1e6;
|
|
934
|
-
Logger.twoColumnDetail(Logger.parse([[description, "green"]], "", false), [Logger.parse([[`${Math.floor(duration)}ms`, "gray"]], "", false), Logger.parse([[result !== false ? "✔" : "✘", result !== false ? "green" : "red"]], "", false)].join(" "));
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
static async advancedTaskRunner(info, task) {
|
|
938
|
-
const startTime = process.hrtime();
|
|
939
|
-
const [startInfo, stopInfo] = info;
|
|
940
|
-
if (stopInfo) Logger.twoColumnDetail(startInfo[0], Logger.log(startInfo[1], ["yellow", "bold"], false));
|
|
941
|
-
try {
|
|
942
|
-
return await Promise.race([task()]);
|
|
943
|
-
} catch (e) {
|
|
944
|
-
Logger.error("ERROR: " + e.message);
|
|
945
|
-
} finally {
|
|
946
|
-
const endTime = process.hrtime(startTime);
|
|
947
|
-
const duration = (endTime[0] * 1e9 + endTime[1]) / 1e6;
|
|
948
|
-
Logger.twoColumnDetail(stopInfo?.[0] ?? startInfo[0], [Logger.parse([[`${Math.floor(duration)}ms`, "gray"]], "", false), Logger.parse([[`✔ ${stopInfo?.[1] ?? startInfo[1]}`, ["green", "bold"]]], "", false)].join(" "));
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
};
|
|
952
|
-
//#endregion
|
|
953
|
-
exports.Console = Console;
|
|
954
|
-
exports.EnvParser = EnvParser;
|
|
955
|
-
exports.FileSystem = FileSystem;
|
|
956
|
-
exports.Finalizable = Finalizable;
|
|
957
|
-
exports.INTERNAL_METHODS = INTERNAL_METHODS;
|
|
958
|
-
exports.Logger = Logger;
|
|
959
|
-
exports.Magic = Magic;
|
|
960
|
-
exports.PathLoader = PathLoader;
|
|
961
|
-
exports.Prompts = Prompts;
|
|
962
|
-
exports.Resolver = Resolver;
|
|
963
|
-
exports.TaskManager = TaskManager;
|
|
964
|
-
exports.UseMagic = UseMagic;
|
|
965
|
-
exports.baseTsconfig = baseTsconfig;
|
|
966
|
-
exports.crc32 = crc32;
|
|
967
|
-
exports.internal = internal;
|
|
968
|
-
exports.isInternal = isInternal;
|
|
969
|
-
exports.mainTsconfig = mainTsconfig;
|
|
970
|
-
exports.makeMagic = makeMagic;
|
|
971
|
-
exports.makeStaticMagic = makeStaticMagic;
|
|
972
|
-
exports.mix = mix;
|
|
973
|
-
exports.packageJsonScript = packageJsonScript;
|
|
974
|
-
exports.trait = trait;
|
|
975
|
-
exports.use = use;
|
|
976
|
-
exports.uses = uses;
|