@holo-js/kernel 0.3.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/chunk-UIGMROG3.mjs +105 -0
- package/dist/http-errors.d.ts +11 -0
- package/dist/http-errors.mjs +8 -0
- package/dist/index.d.ts +222 -0
- package/dist/index.mjs +421 -0
- package/package.json +36 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// src/httpErrors.ts
|
|
2
|
+
var httpStatuses = /* @__PURE__ */ new Set([
|
|
3
|
+
400,
|
|
4
|
+
401,
|
|
5
|
+
402,
|
|
6
|
+
403,
|
|
7
|
+
404,
|
|
8
|
+
405,
|
|
9
|
+
406,
|
|
10
|
+
407,
|
|
11
|
+
408,
|
|
12
|
+
409,
|
|
13
|
+
410,
|
|
14
|
+
411,
|
|
15
|
+
412,
|
|
16
|
+
413,
|
|
17
|
+
414,
|
|
18
|
+
415,
|
|
19
|
+
416,
|
|
20
|
+
417,
|
|
21
|
+
418,
|
|
22
|
+
421,
|
|
23
|
+
422,
|
|
24
|
+
423,
|
|
25
|
+
424,
|
|
26
|
+
425,
|
|
27
|
+
426,
|
|
28
|
+
428,
|
|
29
|
+
429,
|
|
30
|
+
431,
|
|
31
|
+
451,
|
|
32
|
+
500,
|
|
33
|
+
501,
|
|
34
|
+
502,
|
|
35
|
+
503,
|
|
36
|
+
504,
|
|
37
|
+
505,
|
|
38
|
+
506,
|
|
39
|
+
507,
|
|
40
|
+
508,
|
|
41
|
+
510,
|
|
42
|
+
511
|
|
43
|
+
]);
|
|
44
|
+
function isObject(value) {
|
|
45
|
+
return !!value && typeof value === "object";
|
|
46
|
+
}
|
|
47
|
+
function readNumber(value) {
|
|
48
|
+
return typeof value === "number" && Number.isInteger(value) ? value : void 0;
|
|
49
|
+
}
|
|
50
|
+
function readString(value) {
|
|
51
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
52
|
+
}
|
|
53
|
+
function readStatus(error) {
|
|
54
|
+
if (!isObject(error)) {
|
|
55
|
+
return void 0;
|
|
56
|
+
}
|
|
57
|
+
const directStatus = readNumber(error.status);
|
|
58
|
+
if (directStatus) {
|
|
59
|
+
return directStatus;
|
|
60
|
+
}
|
|
61
|
+
const statusCode = readNumber(error.statusCode);
|
|
62
|
+
if (statusCode) {
|
|
63
|
+
return statusCode;
|
|
64
|
+
}
|
|
65
|
+
const digest = readString(error.digest);
|
|
66
|
+
const nextHttpStatus = digest?.match(/^NEXT_HTTP_ERROR_FALLBACK;(\d{3})$/)?.[1];
|
|
67
|
+
return nextHttpStatus ? Number(nextHttpStatus) : void 0;
|
|
68
|
+
}
|
|
69
|
+
function readMessage(error) {
|
|
70
|
+
if (error instanceof Error && error.message.length > 0) {
|
|
71
|
+
return error.message;
|
|
72
|
+
}
|
|
73
|
+
const message = readString(error.message);
|
|
74
|
+
if (message) {
|
|
75
|
+
return message;
|
|
76
|
+
}
|
|
77
|
+
const statusText = readString(error.statusText);
|
|
78
|
+
if (statusText) {
|
|
79
|
+
return statusText;
|
|
80
|
+
}
|
|
81
|
+
return "An unexpected error occurred.";
|
|
82
|
+
}
|
|
83
|
+
function readCode(error) {
|
|
84
|
+
return readString(error.code);
|
|
85
|
+
}
|
|
86
|
+
function isHoloHttpErrorStatus(status) {
|
|
87
|
+
return httpStatuses.has(status);
|
|
88
|
+
}
|
|
89
|
+
function normalizeHoloHttpError(error) {
|
|
90
|
+
const status = readStatus(error);
|
|
91
|
+
if (!status || !isHoloHttpErrorStatus(status)) {
|
|
92
|
+
return void 0;
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
status,
|
|
96
|
+
message: readMessage(error),
|
|
97
|
+
code: readCode(error),
|
|
98
|
+
cause: error
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export {
|
|
103
|
+
isHoloHttpErrorStatus,
|
|
104
|
+
normalizeHoloHttpError
|
|
105
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type HoloHttpErrorStatus = 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511;
|
|
2
|
+
type NormalizedHoloHttpError = {
|
|
3
|
+
readonly status: HoloHttpErrorStatus;
|
|
4
|
+
readonly message: string;
|
|
5
|
+
readonly code?: string;
|
|
6
|
+
readonly cause: unknown;
|
|
7
|
+
};
|
|
8
|
+
declare function isHoloHttpErrorStatus(status: number): status is HoloHttpErrorStatus;
|
|
9
|
+
declare function normalizeHoloHttpError(error: unknown): NormalizedHoloHttpError | undefined;
|
|
10
|
+
|
|
11
|
+
export { type HoloHttpErrorStatus, type NormalizedHoloHttpError, isHoloHttpErrorStatus, normalizeHoloHttpError };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
export { HoloHttpErrorStatus, NormalizedHoloHttpError, isHoloHttpErrorStatus, normalizeHoloHttpError } from './http-errors.js';
|
|
2
|
+
|
|
3
|
+
interface RuntimeLifecycleContext {
|
|
4
|
+
readonly projectRoot: string;
|
|
5
|
+
}
|
|
6
|
+
interface RuntimeContribution<TContext extends RuntimeLifecycleContext = RuntimeLifecycleContext> {
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly dependsOn?: readonly string[];
|
|
9
|
+
initialize(context: TContext): void | Promise<void>;
|
|
10
|
+
dispose?(context: TContext): void | Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
declare class RuntimeLifecycle<TContext extends RuntimeLifecycleContext = RuntimeLifecycleContext> {
|
|
13
|
+
private readonly ordered;
|
|
14
|
+
private initialized;
|
|
15
|
+
constructor(contributions: readonly RuntimeContribution<TContext>[]);
|
|
16
|
+
initialize(context: TContext): Promise<void>;
|
|
17
|
+
dispose(context: TContext): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
declare function createRuntimeLifecycle<TContext extends RuntimeLifecycleContext>(contributions: readonly RuntimeContribution<TContext>[]): RuntimeLifecycle<TContext>;
|
|
20
|
+
|
|
21
|
+
type HoloPluginDependencyContributions = {
|
|
22
|
+
readonly runtime?: readonly string[];
|
|
23
|
+
readonly holo?: readonly `@holo-js/${string}`[];
|
|
24
|
+
};
|
|
25
|
+
type HoloPluginConfigContributions = {
|
|
26
|
+
readonly files?: readonly string[];
|
|
27
|
+
readonly env?: readonly string[];
|
|
28
|
+
};
|
|
29
|
+
type HoloPluginRuntimeMapContributions<TKey extends 'drivers' | 'channels'> = Readonly<Record<TKey, Readonly<Record<string, {
|
|
30
|
+
readonly runtime: string;
|
|
31
|
+
}>>>>;
|
|
32
|
+
type HoloPluginBroadcastContributions = HoloPluginRuntimeMapContributions<'drivers'>;
|
|
33
|
+
type HoloPluginCacheContributions = HoloPluginRuntimeMapContributions<'drivers'>;
|
|
34
|
+
type HoloPluginQueueContributions = HoloPluginRuntimeMapContributions<'drivers'>;
|
|
35
|
+
type HoloPluginMailContributions = HoloPluginRuntimeMapContributions<'drivers'>;
|
|
36
|
+
type HoloPluginNotificationContributions = HoloPluginRuntimeMapContributions<'channels'>;
|
|
37
|
+
type HoloPluginRuntimeContributions = {
|
|
38
|
+
readonly boot?: string;
|
|
39
|
+
};
|
|
40
|
+
type HoloPluginCliContributions = {
|
|
41
|
+
readonly commands?: string;
|
|
42
|
+
};
|
|
43
|
+
type HoloPluginMigrationContributions = {
|
|
44
|
+
readonly publish?: string;
|
|
45
|
+
};
|
|
46
|
+
type HoloPluginFrameworkTsconfigKind = 'nuxt' | 'next' | 'sveltekit';
|
|
47
|
+
type HoloPluginPackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';
|
|
48
|
+
type HoloPluginFrameworkContribution = {
|
|
49
|
+
readonly id: string;
|
|
50
|
+
readonly displayName: string;
|
|
51
|
+
readonly detectPackages: readonly string[];
|
|
52
|
+
readonly adapterPackage: `@holo-js/${string}`;
|
|
53
|
+
readonly fluxPackage?: `@holo-js/${string}`;
|
|
54
|
+
readonly scaffold: {
|
|
55
|
+
readonly dependencies: Readonly<Record<string, string>>;
|
|
56
|
+
readonly devDependencies: Readonly<Record<string, string>>;
|
|
57
|
+
readonly scripts: Readonly<Record<string, string>>;
|
|
58
|
+
readonly lintScript: string;
|
|
59
|
+
readonly typecheckScript: string;
|
|
60
|
+
readonly defaultUrl: string;
|
|
61
|
+
readonly tsconfig: HoloPluginFrameworkTsconfigKind;
|
|
62
|
+
readonly vscodeVueHybridMode?: boolean;
|
|
63
|
+
};
|
|
64
|
+
readonly runner: {
|
|
65
|
+
readonly commandName: string;
|
|
66
|
+
readonly buildArgs: readonly string[];
|
|
67
|
+
readonly start: readonly string[];
|
|
68
|
+
readonly startUsesFrameworkBinary: boolean;
|
|
69
|
+
readonly preloadNextRuntime: boolean;
|
|
70
|
+
readonly suppressSvelteKitOutput: boolean;
|
|
71
|
+
readonly nextDevServerConflictHandling: boolean;
|
|
72
|
+
};
|
|
73
|
+
readonly sync?: {
|
|
74
|
+
readonly commands: Readonly<Record<HoloPluginPackageManager, readonly [string, ...string[]]>>;
|
|
75
|
+
readonly errorLabel: string;
|
|
76
|
+
};
|
|
77
|
+
readonly capabilities: {
|
|
78
|
+
readonly managedBroadcastAuthRoute: boolean;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
type HoloPluginContributions = {
|
|
82
|
+
readonly dependencies?: HoloPluginDependencyContributions;
|
|
83
|
+
readonly config?: HoloPluginConfigContributions;
|
|
84
|
+
readonly framework?: HoloPluginFrameworkContribution;
|
|
85
|
+
readonly broadcast?: HoloPluginBroadcastContributions;
|
|
86
|
+
readonly cache?: HoloPluginCacheContributions;
|
|
87
|
+
readonly queue?: HoloPluginQueueContributions;
|
|
88
|
+
readonly mail?: HoloPluginMailContributions;
|
|
89
|
+
readonly notifications?: HoloPluginNotificationContributions;
|
|
90
|
+
readonly runtime?: HoloPluginRuntimeContributions;
|
|
91
|
+
readonly cli?: HoloPluginCliContributions;
|
|
92
|
+
readonly migrations?: HoloPluginMigrationContributions;
|
|
93
|
+
};
|
|
94
|
+
type HoloPluginDefinition = {
|
|
95
|
+
readonly id: string;
|
|
96
|
+
readonly name?: string;
|
|
97
|
+
readonly description?: string;
|
|
98
|
+
readonly contributes?: HoloPluginContributions;
|
|
99
|
+
};
|
|
100
|
+
type LoadedHoloPluginDefinition = {
|
|
101
|
+
readonly packageName: string;
|
|
102
|
+
readonly packageRoot: string;
|
|
103
|
+
readonly entryPath: string;
|
|
104
|
+
readonly definition: HoloPluginDefinition;
|
|
105
|
+
};
|
|
106
|
+
type HoloPluginRuntimeModule = {
|
|
107
|
+
readonly plugin: LoadedHoloPluginDefinition;
|
|
108
|
+
readonly name: string;
|
|
109
|
+
readonly runtime: string;
|
|
110
|
+
readonly module: unknown;
|
|
111
|
+
};
|
|
112
|
+
type PluginLoadOptions = {
|
|
113
|
+
readonly moduleVersion?: string;
|
|
114
|
+
};
|
|
115
|
+
declare function normalizeHoloPluginDefinition(value: unknown): HoloPluginDefinition;
|
|
116
|
+
declare function defineHoloPlugin<TPlugin extends HoloPluginDefinition>(plugin: TPlugin): Readonly<TPlugin>;
|
|
117
|
+
declare function resolveHoloPluginModulePath(projectRoot: string, plugin: LoadedHoloPluginDefinition, specifier: string): string;
|
|
118
|
+
declare function loadHoloPluginDefinitions(projectRoot: string, packageNames: readonly string[], options?: PluginLoadOptions): Promise<readonly LoadedHoloPluginDefinition[]>;
|
|
119
|
+
declare function loadHoloPluginContributionModules(projectRoot: string, plugins: readonly LoadedHoloPluginDefinition[], scope: string, key: string, options?: PluginLoadOptions): Promise<readonly HoloPluginRuntimeModule[]>;
|
|
120
|
+
declare function loadHoloPluginBootModules(projectRoot: string, plugins: readonly LoadedHoloPluginDefinition[], options?: PluginLoadOptions): Promise<readonly HoloPluginRuntimeModule[]>;
|
|
121
|
+
|
|
122
|
+
type HoloDatabaseDriver = 'sqlite' | 'postgres' | 'mysql';
|
|
123
|
+
interface HoloProjectPaths {
|
|
124
|
+
models: string;
|
|
125
|
+
migrations: string;
|
|
126
|
+
generatedSchema: string;
|
|
127
|
+
seeders: string;
|
|
128
|
+
observers: string;
|
|
129
|
+
factories: string;
|
|
130
|
+
commands: string;
|
|
131
|
+
jobs: string;
|
|
132
|
+
events: string;
|
|
133
|
+
listeners: string;
|
|
134
|
+
authorizationPolicies: string;
|
|
135
|
+
authorizationAbilities: string;
|
|
136
|
+
}
|
|
137
|
+
interface HoloProjectConnectionConfig {
|
|
138
|
+
driver?: HoloDatabaseDriver;
|
|
139
|
+
url?: string;
|
|
140
|
+
host?: string;
|
|
141
|
+
port?: number | string;
|
|
142
|
+
username?: string;
|
|
143
|
+
password?: string;
|
|
144
|
+
database?: string;
|
|
145
|
+
filename?: string;
|
|
146
|
+
schema?: string;
|
|
147
|
+
ssl?: boolean | Record<string, unknown>;
|
|
148
|
+
logging?: boolean;
|
|
149
|
+
}
|
|
150
|
+
interface HoloProjectDatabaseConfig {
|
|
151
|
+
defaultConnection?: string;
|
|
152
|
+
connections?: Record<string, HoloProjectConnectionConfig | string>;
|
|
153
|
+
}
|
|
154
|
+
interface HoloProjectConfig {
|
|
155
|
+
paths?: Partial<HoloProjectPaths>;
|
|
156
|
+
database?: HoloProjectDatabaseConfig;
|
|
157
|
+
models?: readonly string[];
|
|
158
|
+
migrations?: readonly string[];
|
|
159
|
+
seeders?: readonly string[];
|
|
160
|
+
}
|
|
161
|
+
interface NormalizedHoloProjectConfig {
|
|
162
|
+
readonly paths: Readonly<HoloProjectPaths>;
|
|
163
|
+
readonly database?: HoloProjectDatabaseConfig;
|
|
164
|
+
readonly models: readonly string[];
|
|
165
|
+
readonly migrations: readonly string[];
|
|
166
|
+
readonly seeders: readonly string[];
|
|
167
|
+
}
|
|
168
|
+
declare const DEFAULT_HOLO_PROJECT_PATHS: Readonly<HoloProjectPaths>;
|
|
169
|
+
declare function normalizeHoloProjectConfig(config?: HoloProjectConfig): NormalizedHoloProjectConfig;
|
|
170
|
+
declare function defineHoloProject<TConfig extends HoloProjectConfig>(config: TConfig): NormalizedHoloProjectConfig & TConfig;
|
|
171
|
+
|
|
172
|
+
interface HoloRedisConnectionConfig {
|
|
173
|
+
readonly url?: string;
|
|
174
|
+
readonly clusters?: readonly HoloRedisClusterNodeConfig[];
|
|
175
|
+
readonly socketPath?: string;
|
|
176
|
+
readonly host?: string;
|
|
177
|
+
readonly port?: number | string;
|
|
178
|
+
readonly username?: string;
|
|
179
|
+
readonly password?: string;
|
|
180
|
+
readonly db?: number | string;
|
|
181
|
+
}
|
|
182
|
+
interface HoloRedisClusterNodeConfig {
|
|
183
|
+
readonly url?: string;
|
|
184
|
+
readonly socketPath?: string;
|
|
185
|
+
readonly host?: string;
|
|
186
|
+
readonly port?: number | string;
|
|
187
|
+
}
|
|
188
|
+
interface HoloRedisConfig {
|
|
189
|
+
readonly default?: string;
|
|
190
|
+
readonly connections?: Readonly<Record<string, HoloRedisConnectionConfig>>;
|
|
191
|
+
}
|
|
192
|
+
interface NormalizedHoloRedisConnectionConfig {
|
|
193
|
+
readonly name: string;
|
|
194
|
+
readonly url?: string;
|
|
195
|
+
readonly clusters?: readonly NormalizedHoloRedisClusterNodeConfig[];
|
|
196
|
+
readonly socketPath?: string;
|
|
197
|
+
readonly host: string;
|
|
198
|
+
readonly port: number;
|
|
199
|
+
readonly username?: string;
|
|
200
|
+
readonly password?: string;
|
|
201
|
+
readonly db: number;
|
|
202
|
+
}
|
|
203
|
+
interface NormalizedHoloRedisClusterNodeConfig {
|
|
204
|
+
readonly url?: string;
|
|
205
|
+
readonly socketPath?: string;
|
|
206
|
+
readonly host: string;
|
|
207
|
+
readonly port: number;
|
|
208
|
+
}
|
|
209
|
+
interface NormalizedHoloRedisConfig {
|
|
210
|
+
readonly default: string;
|
|
211
|
+
readonly connections: Readonly<Record<string, NormalizedHoloRedisConnectionConfig>>;
|
|
212
|
+
}
|
|
213
|
+
declare const DEFAULT_REDIS_CONNECTION = "default";
|
|
214
|
+
declare const DEFAULT_REDIS_HOST = "127.0.0.1";
|
|
215
|
+
declare const DEFAULT_REDIS_PORT = 6379;
|
|
216
|
+
declare const DEFAULT_REDIS_DB = 0;
|
|
217
|
+
declare const holoRedisDefaults: Readonly<NormalizedHoloRedisConfig>;
|
|
218
|
+
declare function resolveNormalizedRedisConnection(config: NormalizedHoloRedisConfig, connectionName: string, label: string): NormalizedHoloRedisConnectionConfig;
|
|
219
|
+
declare function normalizeRedisConfig(config?: HoloRedisConfig): NormalizedHoloRedisConfig;
|
|
220
|
+
declare function defineRedisConfig<TConfig extends HoloRedisConfig>(config: TConfig): Readonly<TConfig>;
|
|
221
|
+
|
|
222
|
+
export { DEFAULT_HOLO_PROJECT_PATHS, DEFAULT_REDIS_CONNECTION, DEFAULT_REDIS_DB, DEFAULT_REDIS_HOST, DEFAULT_REDIS_PORT, type HoloDatabaseDriver, type HoloPluginBroadcastContributions, type HoloPluginCacheContributions, type HoloPluginCliContributions, type HoloPluginConfigContributions, type HoloPluginContributions, type HoloPluginDefinition, type HoloPluginDependencyContributions, type HoloPluginFrameworkContribution, type HoloPluginFrameworkTsconfigKind, type HoloPluginMailContributions, type HoloPluginMigrationContributions, type HoloPluginNotificationContributions, type HoloPluginPackageManager, type HoloPluginQueueContributions, type HoloPluginRuntimeContributions, type HoloPluginRuntimeMapContributions, type HoloPluginRuntimeModule, type HoloProjectConfig, type HoloProjectConnectionConfig, type HoloProjectDatabaseConfig, type HoloProjectPaths, type HoloRedisClusterNodeConfig, type HoloRedisConfig, type HoloRedisConnectionConfig, type LoadedHoloPluginDefinition, type NormalizedHoloProjectConfig, type NormalizedHoloRedisClusterNodeConfig, type NormalizedHoloRedisConfig, type NormalizedHoloRedisConnectionConfig, type PluginLoadOptions, type RuntimeContribution, RuntimeLifecycle, type RuntimeLifecycleContext, createRuntimeLifecycle, defineHoloPlugin, defineHoloProject, defineRedisConfig, holoRedisDefaults, loadHoloPluginBootModules, loadHoloPluginContributionModules, loadHoloPluginDefinitions, normalizeHoloPluginDefinition, normalizeHoloProjectConfig, normalizeRedisConfig, resolveHoloPluginModulePath, resolveNormalizedRedisConnection };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isHoloHttpErrorStatus,
|
|
3
|
+
normalizeHoloHttpError
|
|
4
|
+
} from "./chunk-UIGMROG3.mjs";
|
|
5
|
+
|
|
6
|
+
// src/lifecycle.ts
|
|
7
|
+
function orderContributions(contributions) {
|
|
8
|
+
const byName = new Map(contributions.map((contribution) => [contribution.name, contribution]));
|
|
9
|
+
if (byName.size !== contributions.length) {
|
|
10
|
+
throw new Error("[Holo Runtime] Runtime contribution names must be unique.");
|
|
11
|
+
}
|
|
12
|
+
const ordered = [];
|
|
13
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
14
|
+
const visited = /* @__PURE__ */ new Set();
|
|
15
|
+
const visit = (contribution) => {
|
|
16
|
+
if (visited.has(contribution.name)) return;
|
|
17
|
+
if (visiting.has(contribution.name)) {
|
|
18
|
+
throw new Error(`[Holo Runtime] Circular runtime dependency at "${contribution.name}".`);
|
|
19
|
+
}
|
|
20
|
+
visiting.add(contribution.name);
|
|
21
|
+
for (const dependencyName of contribution.dependsOn ?? []) {
|
|
22
|
+
const dependency = byName.get(dependencyName);
|
|
23
|
+
if (!dependency) {
|
|
24
|
+
throw new Error(`[Holo Runtime] Contribution "${contribution.name}" requires missing contribution "${dependencyName}".`);
|
|
25
|
+
}
|
|
26
|
+
visit(dependency);
|
|
27
|
+
}
|
|
28
|
+
visiting.delete(contribution.name);
|
|
29
|
+
visited.add(contribution.name);
|
|
30
|
+
ordered.push(contribution);
|
|
31
|
+
};
|
|
32
|
+
contributions.forEach(visit);
|
|
33
|
+
return Object.freeze(ordered);
|
|
34
|
+
}
|
|
35
|
+
var RuntimeLifecycle = class {
|
|
36
|
+
ordered;
|
|
37
|
+
initialized = [];
|
|
38
|
+
constructor(contributions) {
|
|
39
|
+
this.ordered = orderContributions(contributions);
|
|
40
|
+
}
|
|
41
|
+
async initialize(context) {
|
|
42
|
+
if (this.initialized.length > 0) {
|
|
43
|
+
throw new Error("[Holo Runtime] Runtime lifecycle is already initialized.");
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
for (const contribution of this.ordered) {
|
|
47
|
+
this.initialized.push(contribution);
|
|
48
|
+
await contribution.initialize(context);
|
|
49
|
+
}
|
|
50
|
+
} catch (error) {
|
|
51
|
+
try {
|
|
52
|
+
await this.dispose(context);
|
|
53
|
+
} catch (cleanupError) {
|
|
54
|
+
throw new AggregateError([error, cleanupError], "[Holo Runtime] Initialization and rollback both failed.");
|
|
55
|
+
}
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async dispose(context) {
|
|
60
|
+
const initialized = this.initialized;
|
|
61
|
+
this.initialized = [];
|
|
62
|
+
const failures = [];
|
|
63
|
+
for (const contribution of initialized.reverse()) {
|
|
64
|
+
try {
|
|
65
|
+
await contribution.dispose?.(context);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
failures.push(error);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (failures.length === 1) {
|
|
71
|
+
throw failures[0];
|
|
72
|
+
}
|
|
73
|
+
if (failures.length > 1) {
|
|
74
|
+
throw new AggregateError(failures, "[Holo Runtime] Multiple runtime contributions failed to dispose.");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
function createRuntimeLifecycle(contributions) {
|
|
79
|
+
return new RuntimeLifecycle(contributions);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/plugins.ts
|
|
83
|
+
import { createRequire } from "module";
|
|
84
|
+
import { readFile } from "fs/promises";
|
|
85
|
+
import { dirname, isAbsolute, join, relative, resolve } from "path";
|
|
86
|
+
import { pathToFileURL } from "url";
|
|
87
|
+
function isRecord(value) {
|
|
88
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
89
|
+
}
|
|
90
|
+
function normalizeString(value) {
|
|
91
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
92
|
+
}
|
|
93
|
+
function assertValidPackageName(packageName) {
|
|
94
|
+
if (!(/^@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/i.test(packageName) || /^[a-z0-9][a-z0-9._-]*$/i.test(packageName))) {
|
|
95
|
+
throw new Error(`[Holo Plugins] Invalid plugin package name: ${packageName}.`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function assertPackageRelativePath(packageName, value) {
|
|
99
|
+
if (isAbsolute(value)) {
|
|
100
|
+
throw new Error(`[Holo Plugins] Plugin ${packageName} declared an absolute module path.`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function resolvePackageJsonPath(projectRoot, packageName) {
|
|
104
|
+
assertValidPackageName(packageName);
|
|
105
|
+
try {
|
|
106
|
+
return createRequire(join(projectRoot, "package.json")).resolve(`${packageName}/package.json`);
|
|
107
|
+
} catch {
|
|
108
|
+
return join(projectRoot, "node_modules", ...packageName.split("/"), "package.json");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async function loadModule(projectRoot, modulePath, options = {}) {
|
|
112
|
+
const resolvedPath = createRequire(join(projectRoot, "package.json")).resolve(modulePath);
|
|
113
|
+
const moduleUrl = pathToFileURL(resolvedPath).href;
|
|
114
|
+
const versionedUrl = options.moduleVersion ? `${moduleUrl}?v=${encodeURIComponent(options.moduleVersion)}` : moduleUrl;
|
|
115
|
+
return await import(
|
|
116
|
+
/* webpackIgnore: true */
|
|
117
|
+
versionedUrl
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
function normalizeHoloPluginDefinition(value) {
|
|
121
|
+
const module = value;
|
|
122
|
+
const candidate = "default" in module ? module.default : "plugin" in module ? module.plugin : module;
|
|
123
|
+
if (!isRecord(candidate) || !normalizeString(candidate.id)) {
|
|
124
|
+
throw new Error("[Holo Plugins] Plugin entry must export a plugin definition with an id.");
|
|
125
|
+
}
|
|
126
|
+
return Object.freeze({ ...candidate });
|
|
127
|
+
}
|
|
128
|
+
function defineHoloPlugin(plugin) {
|
|
129
|
+
return Object.freeze({ ...plugin });
|
|
130
|
+
}
|
|
131
|
+
function resolveHoloPluginModulePath(projectRoot, plugin, specifier) {
|
|
132
|
+
const normalized = specifier.trim();
|
|
133
|
+
if (!normalized) throw new Error(`[Holo Plugins] Plugin ${plugin.packageName} declared an empty module specifier.`);
|
|
134
|
+
assertPackageRelativePath(plugin.packageName, normalized);
|
|
135
|
+
if (!normalized.startsWith(".")) {
|
|
136
|
+
return createRequire(join(resolve(projectRoot), "package.json")).resolve(normalized);
|
|
137
|
+
}
|
|
138
|
+
const modulePath = resolve(plugin.packageRoot, normalized);
|
|
139
|
+
const relativePath = relative(plugin.packageRoot, modulePath);
|
|
140
|
+
if (relativePath.startsWith("..") || isAbsolute(relativePath)) {
|
|
141
|
+
throw new Error(`[Holo Plugins] Plugin ${plugin.packageName} module must stay inside the package root.`);
|
|
142
|
+
}
|
|
143
|
+
return modulePath;
|
|
144
|
+
}
|
|
145
|
+
async function loadHoloPluginDefinitions(projectRoot, packageNames, options = {}) {
|
|
146
|
+
const root = resolve(projectRoot);
|
|
147
|
+
const loaded = [];
|
|
148
|
+
const ids = /* @__PURE__ */ new Set();
|
|
149
|
+
for (const packageName of packageNames) {
|
|
150
|
+
const packageJsonPath = resolvePackageJsonPath(root, packageName);
|
|
151
|
+
let manifest;
|
|
152
|
+
try {
|
|
153
|
+
manifest = JSON.parse(await readFile(packageJsonPath, "utf8"));
|
|
154
|
+
} catch (error) {
|
|
155
|
+
if (isRecord(error) && error.code === "ENOENT") throw new Error(`Cannot find module '${packageName}/package.json'`);
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
if (!isRecord(manifest.holo) || !normalizeString(manifest.holo.plugin)) {
|
|
159
|
+
throw new Error(`[Holo Plugins] Plugin ${packageName} does not declare holo.plugin.`);
|
|
160
|
+
}
|
|
161
|
+
const entry = normalizeString(manifest.holo.plugin);
|
|
162
|
+
assertPackageRelativePath(packageName, entry);
|
|
163
|
+
const packageRoot = dirname(packageJsonPath);
|
|
164
|
+
const entryPath = resolve(packageRoot, entry);
|
|
165
|
+
const relativeEntry = relative(packageRoot, entryPath);
|
|
166
|
+
if (relativeEntry.startsWith("..") || isAbsolute(relativeEntry)) {
|
|
167
|
+
throw new Error(`[Holo Plugins] Plugin ${packageName} entry must stay inside the package root.`);
|
|
168
|
+
}
|
|
169
|
+
const definition = normalizeHoloPluginDefinition(await loadModule(root, entryPath, options));
|
|
170
|
+
if (ids.has(definition.id)) throw new Error(`[Holo Plugins] Duplicate plugin id "${definition.id}".`);
|
|
171
|
+
ids.add(definition.id);
|
|
172
|
+
loaded.push(Object.freeze({ packageName, packageRoot, entryPath, definition }));
|
|
173
|
+
}
|
|
174
|
+
return Object.freeze(loaded);
|
|
175
|
+
}
|
|
176
|
+
function contributionMap(plugin, scope, key) {
|
|
177
|
+
const contributions = plugin.definition.contributes;
|
|
178
|
+
const scopeValue = contributions?.[scope];
|
|
179
|
+
if (!isRecord(scopeValue) || !isRecord(scopeValue[key])) return Object.freeze({});
|
|
180
|
+
return Object.freeze(Object.fromEntries(Object.entries(scopeValue[key]).flatMap(([name, value]) => {
|
|
181
|
+
const runtime = isRecord(value) ? normalizeString(value.runtime) : void 0;
|
|
182
|
+
return runtime ? [[name, runtime]] : [];
|
|
183
|
+
})));
|
|
184
|
+
}
|
|
185
|
+
async function loadHoloPluginContributionModules(projectRoot, plugins, scope, key, options = {}) {
|
|
186
|
+
const modules = [];
|
|
187
|
+
const names = /* @__PURE__ */ new Set();
|
|
188
|
+
for (const plugin of plugins) {
|
|
189
|
+
for (const [name, runtime] of Object.entries(contributionMap(plugin, scope, key))) {
|
|
190
|
+
if (names.has(name)) throw new Error(`[Holo Plugins] Duplicate ${scope}.${key} contribution "${name}".`);
|
|
191
|
+
names.add(name);
|
|
192
|
+
modules.push(Object.freeze({
|
|
193
|
+
plugin,
|
|
194
|
+
name,
|
|
195
|
+
runtime,
|
|
196
|
+
module: await loadModule(projectRoot, resolveHoloPluginModulePath(projectRoot, plugin, runtime), options)
|
|
197
|
+
}));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return Object.freeze(modules);
|
|
201
|
+
}
|
|
202
|
+
async function loadHoloPluginBootModules(projectRoot, plugins, options = {}) {
|
|
203
|
+
const modules = [];
|
|
204
|
+
for (const plugin of plugins) {
|
|
205
|
+
const runtimeScope = plugin.definition.contributes?.runtime;
|
|
206
|
+
const runtime = isRecord(runtimeScope) ? normalizeString(runtimeScope.boot) : void 0;
|
|
207
|
+
if (!runtime) continue;
|
|
208
|
+
modules.push(Object.freeze({
|
|
209
|
+
plugin,
|
|
210
|
+
name: "boot",
|
|
211
|
+
runtime,
|
|
212
|
+
module: await loadModule(projectRoot, resolveHoloPluginModulePath(projectRoot, plugin, runtime), options)
|
|
213
|
+
}));
|
|
214
|
+
}
|
|
215
|
+
return Object.freeze(modules);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// src/project.ts
|
|
219
|
+
var DEFAULT_HOLO_PROJECT_PATHS = Object.freeze({
|
|
220
|
+
models: "server/models",
|
|
221
|
+
migrations: "server/db/migrations",
|
|
222
|
+
generatedSchema: ".holo-js/generated/schema.generated.ts",
|
|
223
|
+
seeders: "server/db/seeders",
|
|
224
|
+
observers: "server/db/observers",
|
|
225
|
+
factories: "server/db/factories",
|
|
226
|
+
commands: "server/commands",
|
|
227
|
+
jobs: "server/jobs",
|
|
228
|
+
events: "server/events",
|
|
229
|
+
listeners: "server/listeners",
|
|
230
|
+
authorizationPolicies: "server/policies",
|
|
231
|
+
authorizationAbilities: "server/abilities"
|
|
232
|
+
});
|
|
233
|
+
function normalizeHoloProjectConfig(config = {}) {
|
|
234
|
+
return Object.freeze({
|
|
235
|
+
paths: Object.freeze({ ...DEFAULT_HOLO_PROJECT_PATHS, ...config.paths ?? {} }),
|
|
236
|
+
...config.database ? { database: { ...config.database } } : {},
|
|
237
|
+
models: Object.freeze([...config.models ?? []]),
|
|
238
|
+
migrations: Object.freeze([...config.migrations ?? []]),
|
|
239
|
+
seeders: Object.freeze([...config.seeders ?? []])
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
function defineHoloProject(config) {
|
|
243
|
+
return normalizeHoloProjectConfig(config);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// src/redis.ts
|
|
247
|
+
var DEFAULT_REDIS_CONNECTION = "default";
|
|
248
|
+
var DEFAULT_REDIS_HOST = "127.0.0.1";
|
|
249
|
+
var DEFAULT_REDIS_PORT = 6379;
|
|
250
|
+
var DEFAULT_REDIS_DB = 0;
|
|
251
|
+
var holoRedisDefaults = Object.freeze({
|
|
252
|
+
default: DEFAULT_REDIS_CONNECTION,
|
|
253
|
+
connections: Object.freeze({
|
|
254
|
+
[DEFAULT_REDIS_CONNECTION]: Object.freeze({
|
|
255
|
+
name: DEFAULT_REDIS_CONNECTION,
|
|
256
|
+
host: DEFAULT_REDIS_HOST,
|
|
257
|
+
port: DEFAULT_REDIS_PORT,
|
|
258
|
+
username: void 0,
|
|
259
|
+
password: void 0,
|
|
260
|
+
db: DEFAULT_REDIS_DB
|
|
261
|
+
})
|
|
262
|
+
})
|
|
263
|
+
});
|
|
264
|
+
function normalizeName(value, label) {
|
|
265
|
+
const normalized = value?.trim();
|
|
266
|
+
if (!normalized) {
|
|
267
|
+
throw new Error(`[Holo Redis] ${label} must be a non-empty string.`);
|
|
268
|
+
}
|
|
269
|
+
return normalized;
|
|
270
|
+
}
|
|
271
|
+
function parseInteger(value, fallback, label, minimum) {
|
|
272
|
+
if (typeof value === "undefined") {
|
|
273
|
+
return fallback;
|
|
274
|
+
}
|
|
275
|
+
const normalized = typeof value === "number" ? value : /^\d+$/.test(value.trim()) ? Number.parseInt(value.trim(), 10) : Number.NaN;
|
|
276
|
+
if (!Number.isSafeInteger(normalized)) {
|
|
277
|
+
throw new Error(`[Holo Redis] ${label} must be an integer.`);
|
|
278
|
+
}
|
|
279
|
+
if (normalized < minimum) {
|
|
280
|
+
throw new Error(`[Holo Redis] ${label} must be greater than or equal to ${minimum}.`);
|
|
281
|
+
}
|
|
282
|
+
return normalized;
|
|
283
|
+
}
|
|
284
|
+
function normalizeUrl(value, label) {
|
|
285
|
+
if (typeof value === "undefined") {
|
|
286
|
+
return void 0;
|
|
287
|
+
}
|
|
288
|
+
const normalized = normalizeName(value, label);
|
|
289
|
+
try {
|
|
290
|
+
const parsed = new URL(normalized);
|
|
291
|
+
if (parsed.protocol !== "redis:" && parsed.protocol !== "rediss:") {
|
|
292
|
+
throw new Error(`[Holo Redis] ${label} must use the redis:// or rediss:// scheme.`);
|
|
293
|
+
}
|
|
294
|
+
} catch (error) {
|
|
295
|
+
if (error instanceof Error && error.message.startsWith("[Holo Redis]")) {
|
|
296
|
+
throw error;
|
|
297
|
+
}
|
|
298
|
+
throw new Error(`[Holo Redis] ${label} must be a valid redis:// or rediss:// URL.`);
|
|
299
|
+
}
|
|
300
|
+
return normalized;
|
|
301
|
+
}
|
|
302
|
+
function parseDatabaseFromUrl(url, label, allowPath) {
|
|
303
|
+
if (typeof url === "undefined") {
|
|
304
|
+
return void 0;
|
|
305
|
+
}
|
|
306
|
+
try {
|
|
307
|
+
const pathname = new URL(url).pathname.replace(/^\/+/, "");
|
|
308
|
+
if (!pathname) {
|
|
309
|
+
return void 0;
|
|
310
|
+
}
|
|
311
|
+
if (!allowPath) {
|
|
312
|
+
throw new Error(`[Holo Redis] ${label} cannot include a database path in cluster mode.`);
|
|
313
|
+
}
|
|
314
|
+
const [databaseSegment] = pathname.split("/");
|
|
315
|
+
if (!databaseSegment || !/^\d+$/.test(databaseSegment) || pathname !== databaseSegment) {
|
|
316
|
+
throw new Error(`[Holo Redis] ${label} database path must be a single integer segment.`);
|
|
317
|
+
}
|
|
318
|
+
return Number.parseInt(databaseSegment, 10);
|
|
319
|
+
} catch (error) {
|
|
320
|
+
if (error instanceof Error && error.message.startsWith("[Holo Redis]")) {
|
|
321
|
+
throw error;
|
|
322
|
+
}
|
|
323
|
+
return void 0;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
function normalizeClusterNode(connectionName, index, config) {
|
|
327
|
+
const label = `redis connection "${connectionName}" cluster node ${index + 1}`;
|
|
328
|
+
const url = normalizeUrl(config.url, `${label} url`);
|
|
329
|
+
const socketPath = config.socketPath?.trim();
|
|
330
|
+
const hostValue = config.host?.trim();
|
|
331
|
+
if (socketPath || hostValue?.startsWith("unix://") || hostValue?.startsWith("/")) {
|
|
332
|
+
throw new Error(`[Holo Redis] ${label} cannot use socketPath in cluster mode.`);
|
|
333
|
+
}
|
|
334
|
+
parseDatabaseFromUrl(url, `${label} url`, false);
|
|
335
|
+
return Object.freeze({
|
|
336
|
+
...typeof url === "undefined" ? {} : { url },
|
|
337
|
+
host: hostValue || DEFAULT_REDIS_HOST,
|
|
338
|
+
port: parseInteger(config.port, DEFAULT_REDIS_PORT, `${label} port`, 1)
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
function normalizeConnection(name, config) {
|
|
342
|
+
const url = normalizeUrl(config.url, `redis connection "${name}" url`);
|
|
343
|
+
const clusters = config.clusters?.length ? Object.freeze(config.clusters.map((node, index) => normalizeClusterNode(name, index, node))) : void 0;
|
|
344
|
+
const explicitSocketPath = config.socketPath?.trim();
|
|
345
|
+
const hostValue = config.host?.trim();
|
|
346
|
+
const socketPath = explicitSocketPath || (hostValue?.startsWith("unix://") ? hostValue.slice("unix://".length) : void 0) || (hostValue?.startsWith("/") ? hostValue : void 0);
|
|
347
|
+
const targetCount = [url, clusters, socketPath].filter((value) => typeof value !== "undefined").length;
|
|
348
|
+
if (targetCount > 1) {
|
|
349
|
+
throw new Error(`[Holo Redis] redis connection "${name}" must configure exactly one target mode: url, clusters, or socketPath.`);
|
|
350
|
+
}
|
|
351
|
+
const database = parseInteger(
|
|
352
|
+
config.db ?? parseDatabaseFromUrl(url, `redis connection "${name}" url`, true),
|
|
353
|
+
DEFAULT_REDIS_DB,
|
|
354
|
+
`redis connection "${name}" db`,
|
|
355
|
+
0
|
|
356
|
+
);
|
|
357
|
+
if (clusters && database !== 0) {
|
|
358
|
+
throw new Error(`[Holo Redis] redis connection "${name}" cannot select redis.db=${database} in cluster mode; Redis Cluster only supports database 0.`);
|
|
359
|
+
}
|
|
360
|
+
return Object.freeze({
|
|
361
|
+
name,
|
|
362
|
+
...typeof url === "undefined" ? {} : { url },
|
|
363
|
+
...typeof clusters === "undefined" ? {} : { clusters },
|
|
364
|
+
...typeof socketPath === "undefined" ? {} : { socketPath },
|
|
365
|
+
host: hostValue || socketPath || DEFAULT_REDIS_HOST,
|
|
366
|
+
port: parseInteger(config.port, DEFAULT_REDIS_PORT, `redis connection "${name}" port`, 1),
|
|
367
|
+
username: config.username?.trim() || void 0,
|
|
368
|
+
password: config.password?.trim() || void 0,
|
|
369
|
+
db: database
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
function resolveNormalizedRedisConnection(config, connectionName, label) {
|
|
373
|
+
const connection = config.connections[connectionName];
|
|
374
|
+
if (!connection) {
|
|
375
|
+
throw new Error(`[Holo Redis] ${label} "${connectionName}" is not configured.`);
|
|
376
|
+
}
|
|
377
|
+
return connection;
|
|
378
|
+
}
|
|
379
|
+
function normalizeRedisConfig(config = {}) {
|
|
380
|
+
const connections = !config.connections || Object.keys(config.connections).length === 0 ? holoRedisDefaults.connections : Object.freeze(Object.fromEntries(Object.entries(config.connections).map(([name, connection]) => {
|
|
381
|
+
const normalizedName = normalizeName(name, "Redis connection name");
|
|
382
|
+
return [normalizedName, normalizeConnection(normalizedName, connection)];
|
|
383
|
+
})));
|
|
384
|
+
const connectionNames = Object.keys(connections);
|
|
385
|
+
const defaultConnection = config.default?.trim() || connectionNames[0];
|
|
386
|
+
if (!connections[defaultConnection]) {
|
|
387
|
+
throw new Error(
|
|
388
|
+
`[Holo Redis] default redis connection "${defaultConnection}" is not configured. Available connections: ${connectionNames.join(", ")}`
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
return Object.freeze({
|
|
392
|
+
default: defaultConnection,
|
|
393
|
+
connections
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
function defineRedisConfig(config) {
|
|
397
|
+
return Object.freeze({ ...config });
|
|
398
|
+
}
|
|
399
|
+
export {
|
|
400
|
+
DEFAULT_HOLO_PROJECT_PATHS,
|
|
401
|
+
DEFAULT_REDIS_CONNECTION,
|
|
402
|
+
DEFAULT_REDIS_DB,
|
|
403
|
+
DEFAULT_REDIS_HOST,
|
|
404
|
+
DEFAULT_REDIS_PORT,
|
|
405
|
+
RuntimeLifecycle,
|
|
406
|
+
createRuntimeLifecycle,
|
|
407
|
+
defineHoloPlugin,
|
|
408
|
+
defineHoloProject,
|
|
409
|
+
defineRedisConfig,
|
|
410
|
+
holoRedisDefaults,
|
|
411
|
+
isHoloHttpErrorStatus,
|
|
412
|
+
loadHoloPluginBootModules,
|
|
413
|
+
loadHoloPluginContributionModules,
|
|
414
|
+
loadHoloPluginDefinitions,
|
|
415
|
+
normalizeHoloHttpError,
|
|
416
|
+
normalizeHoloPluginDefinition,
|
|
417
|
+
normalizeHoloProjectConfig,
|
|
418
|
+
normalizeRedisConfig,
|
|
419
|
+
resolveHoloPluginModulePath,
|
|
420
|
+
resolveNormalizedRedisConnection
|
|
421
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@holo-js/kernel",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Holo-JS Framework - dependency-free contracts, plugins, and runtime lifecycle",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.mjs",
|
|
11
|
+
"default": "./dist/index.mjs"
|
|
12
|
+
},
|
|
13
|
+
"./http-errors": {
|
|
14
|
+
"types": "./dist/http-errors.d.ts",
|
|
15
|
+
"import": "./dist/http-errors.mjs",
|
|
16
|
+
"default": "./dist/http-errors.mjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"main": "./dist/index.mjs",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"stub": "tsup",
|
|
27
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
28
|
+
"test": "vitest --run"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^22.10.2",
|
|
32
|
+
"tsup": "^8.3.5",
|
|
33
|
+
"typescript": "^5.7.2",
|
|
34
|
+
"vitest": "^4.1.5"
|
|
35
|
+
}
|
|
36
|
+
}
|