@moku-labs/web 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +38 -0
- package/dist/bin/moku.cjs +809 -0
- package/dist/bin/moku.d.cts +1 -0
- package/dist/bin/moku.d.mts +1 -0
- package/dist/bin/moku.mjs +809 -0
- package/dist/factory-BBVQO5ZG.d.mts +90 -0
- package/dist/factory-CixCpR9C.cjs +1710 -0
- package/dist/factory-D0m7Xil2.d.cts +90 -0
- package/dist/factory-DwpBwjDk.mjs +1602 -0
- package/dist/index-CWdZdegx.d.mts +349 -0
- package/dist/index.cjs +46 -0
- package/dist/index.d.cts +135 -0
- package/dist/index.d.mts +135 -0
- package/dist/index.mjs +36 -0
- package/dist/plugins/head/build.cjs +35 -0
- package/dist/plugins/head/build.d.cts +17 -0
- package/dist/plugins/head/build.d.mts +17 -0
- package/dist/plugins/head/build.mjs +27 -0
- package/dist/plugins/spa/index.cjs +26 -0
- package/dist/plugins/spa/index.d.cts +30 -0
- package/dist/plugins/spa/index.d.mts +30 -0
- package/dist/plugins/spa/index.mjs +24 -0
- package/dist/primitives-BBo4wxUL.d.cts +69 -0
- package/dist/primitives-BYUp6kae.cjs +100 -0
- package/dist/primitives-gO5i1tD8.mjs +58 -0
- package/dist/primitives-kuZFxqV7.d.mts +69 -0
- package/dist/project-BTNUWbGQ.mjs +1020 -0
- package/dist/project-C1vtMxE8.cjs +1081 -0
- package/dist/route-builder-Lv6HUVvP.d.cts +349 -0
- package/dist/test.cjs +82 -0
- package/dist/test.d.cts +61 -0
- package/dist/test.d.mts +61 -0
- package/dist/test.mjs +79 -0
- package/package.json +100 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
import { p as OGImageConfig } from "./primitives-BBo4wxUL.cjs";
|
|
2
|
+
import { n as ComponentDef } from "./factory-D0m7Xil2.cjs";
|
|
3
|
+
import { Processor } from "unified";
|
|
4
|
+
|
|
5
|
+
//#region src/plugins/log/types.d.ts
|
|
6
|
+
/** @file log plugin types — LogEntry, LogSink, ExpectChain, LogState, LogApi. */
|
|
7
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
8
|
+
type LogEntry = {
|
|
9
|
+
level: LogLevel;
|
|
10
|
+
event: string;
|
|
11
|
+
data?: unknown;
|
|
12
|
+
ts: number;
|
|
13
|
+
plugin?: string;
|
|
14
|
+
};
|
|
15
|
+
type LogSink = {
|
|
16
|
+
write(entry: LogEntry): void;
|
|
17
|
+
};
|
|
18
|
+
type ExpectChain = {
|
|
19
|
+
toHaveEvent(event: string, partial?: Record<string, unknown>): ExpectChain;
|
|
20
|
+
toHaveEventInOrder(events: string[]): ExpectChain;
|
|
21
|
+
toNotHaveEvent(event: string, partial?: Record<string, unknown>): ExpectChain;
|
|
22
|
+
};
|
|
23
|
+
type LogState = {
|
|
24
|
+
entries: LogEntry[];
|
|
25
|
+
sinks: LogSink[];
|
|
26
|
+
};
|
|
27
|
+
type LogApi = {
|
|
28
|
+
info(event: string, data?: unknown): void;
|
|
29
|
+
debug(event: string, data?: unknown): void;
|
|
30
|
+
warn(event: string, data?: unknown): void;
|
|
31
|
+
error(event: string, data?: unknown, error?: Error): void;
|
|
32
|
+
trace(): readonly LogEntry[];
|
|
33
|
+
expect(): ExpectChain;
|
|
34
|
+
addSink(sink: LogSink): void;
|
|
35
|
+
reset(): void;
|
|
36
|
+
};
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/plugins/env/types.d.ts
|
|
39
|
+
/** @file env plugin types — schema, provider, EnvApi. */
|
|
40
|
+
type EnvVarSpec = {
|
|
41
|
+
public: boolean;
|
|
42
|
+
required?: boolean;
|
|
43
|
+
default?: string;
|
|
44
|
+
secret?: boolean;
|
|
45
|
+
};
|
|
46
|
+
type EnvProvider = {
|
|
47
|
+
name: string;
|
|
48
|
+
load(): Record<string, string | undefined>;
|
|
49
|
+
};
|
|
50
|
+
type EnvConfig = {
|
|
51
|
+
schema: Record<string, EnvVarSpec>;
|
|
52
|
+
providers: EnvProvider[];
|
|
53
|
+
publicPrefix: string;
|
|
54
|
+
};
|
|
55
|
+
type EnvState = {
|
|
56
|
+
resolved: Map<string, string>;
|
|
57
|
+
publicMap: Map<string, string>;
|
|
58
|
+
};
|
|
59
|
+
type EnvApi = {
|
|
60
|
+
get<K extends string>(key: K): string | undefined;
|
|
61
|
+
require(key: string): string;
|
|
62
|
+
getPublic(): Readonly<Record<string, string>>;
|
|
63
|
+
getPublicMap(): ReadonlyMap<string, string>;
|
|
64
|
+
has(key: string): boolean;
|
|
65
|
+
};
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/config.d.ts
|
|
68
|
+
/** Top-level framework config — flows to all plugins via context. */
|
|
69
|
+
type Config = {
|
|
70
|
+
mode: 'production' | 'development';
|
|
71
|
+
};
|
|
72
|
+
/** Framework-level event map — plugin-specific events added by each plugin's events field. */
|
|
73
|
+
type Events = {
|
|
74
|
+
'content:ready': {
|
|
75
|
+
articles: Map<string, unknown[]>;
|
|
76
|
+
};
|
|
77
|
+
'content:invalidated': {
|
|
78
|
+
paths: string[];
|
|
79
|
+
};
|
|
80
|
+
'router:registered': {
|
|
81
|
+
routeCount: number;
|
|
82
|
+
};
|
|
83
|
+
'build:phase': {
|
|
84
|
+
phase: 'bundle' | 'content' | 'pages' | 'feeds' | 'sitemap' | 'og' | 'images';
|
|
85
|
+
};
|
|
86
|
+
'build:complete': {
|
|
87
|
+
pages: number;
|
|
88
|
+
durationMs: number;
|
|
89
|
+
};
|
|
90
|
+
'component:create': {
|
|
91
|
+
name: string;
|
|
92
|
+
element: Element;
|
|
93
|
+
};
|
|
94
|
+
'component:mount': {
|
|
95
|
+
name: string;
|
|
96
|
+
element: Element;
|
|
97
|
+
};
|
|
98
|
+
'component:unmount': {
|
|
99
|
+
name: string;
|
|
100
|
+
reason: 'navigation' | 'destroy';
|
|
101
|
+
};
|
|
102
|
+
'component:destroy': {
|
|
103
|
+
name: string;
|
|
104
|
+
};
|
|
105
|
+
'nav:start': {
|
|
106
|
+
url: string;
|
|
107
|
+
fromUrl: string;
|
|
108
|
+
};
|
|
109
|
+
'nav:end': {
|
|
110
|
+
url: string;
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/plugins/site/types.d.ts
|
|
115
|
+
/** @file site plugin types — SiteConfig + SiteState + SiteApi. */
|
|
116
|
+
type SiteConfig = {
|
|
117
|
+
/** Display name of the site. */name: string; /** Base URL of the site (no trailing slash). */
|
|
118
|
+
url: string; /** Default author name for content. */
|
|
119
|
+
author: string; /** Site description for feeds, meta tags, and preview pages. */
|
|
120
|
+
description: string;
|
|
121
|
+
};
|
|
122
|
+
type SiteState = {
|
|
123
|
+
config: Readonly<SiteConfig>;
|
|
124
|
+
};
|
|
125
|
+
type SiteApi = {
|
|
126
|
+
get(): Readonly<SiteConfig>;
|
|
127
|
+
name(): string;
|
|
128
|
+
url(): string;
|
|
129
|
+
author(): string;
|
|
130
|
+
description(): string;
|
|
131
|
+
};
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/plugins/i18n/types.d.ts
|
|
134
|
+
/** @file i18n plugin types — I18nConfig (generic over locale tuple), I18nState, I18nApi. */
|
|
135
|
+
type I18nConfig<TLocales extends readonly string[] = readonly string[]> = {
|
|
136
|
+
/** Active locale codes (literal tuple preserved). */locales: TLocales; /** Default locale (must be member of locales). */
|
|
137
|
+
defaultLocale: TLocales[number]; /** Display names per locale. */
|
|
138
|
+
localeNames: Record<TLocales[number], string>; /** OG locale format mapping (e.g., { en: 'en_US' }). */
|
|
139
|
+
ogLocaleMap?: Partial<Record<TLocales[number], string>>; /** UI translation strings per locale. */
|
|
140
|
+
translations?: Record<TLocales[number], Record<string, string>>;
|
|
141
|
+
};
|
|
142
|
+
type I18nState<TLocales extends readonly string[] = readonly string[]> = {
|
|
143
|
+
config: Readonly<I18nConfig<TLocales>>;
|
|
144
|
+
};
|
|
145
|
+
type I18nApi<TLocales extends readonly string[] = readonly string[]> = {
|
|
146
|
+
locales(): TLocales;
|
|
147
|
+
defaultLocale(): TLocales[number];
|
|
148
|
+
localeName(locale: TLocales[number]): string;
|
|
149
|
+
ogLocale(locale: TLocales[number]): string;
|
|
150
|
+
t(locale: TLocales[number], key: string): string;
|
|
151
|
+
};
|
|
152
|
+
//#endregion
|
|
153
|
+
//#region src/plugins/router/types.d.ts
|
|
154
|
+
/** @file router plugin types — RouteSpec (non-accumulating), RouteBuilder, RouterApi. */
|
|
155
|
+
/** Render context passed to route handlers. */
|
|
156
|
+
type RenderContext = {
|
|
157
|
+
url: string;
|
|
158
|
+
locale: string;
|
|
159
|
+
params: Record<string, string>;
|
|
160
|
+
data?: unknown;
|
|
161
|
+
};
|
|
162
|
+
type LayoutComponent = unknown;
|
|
163
|
+
type VNode = unknown;
|
|
164
|
+
type HeadConfig = unknown;
|
|
165
|
+
type RouteSpec = {
|
|
166
|
+
pattern: string;
|
|
167
|
+
load?: (params: Record<string, string>) => unknown;
|
|
168
|
+
layout?: LayoutComponent;
|
|
169
|
+
render?: (ctx: RenderContext) => VNode;
|
|
170
|
+
generate?: (locale: string) => Array<{
|
|
171
|
+
params: Record<string, string>;
|
|
172
|
+
}>;
|
|
173
|
+
head?: (ctx: RenderContext) => HeadConfig;
|
|
174
|
+
meta?: Record<string, unknown>;
|
|
175
|
+
toJson?: (ctx: RenderContext) => object;
|
|
176
|
+
toFile?: (ctx: RenderContext) => {
|
|
177
|
+
name: string;
|
|
178
|
+
content: string | Uint8Array;
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Non-accumulating fluent builder. Methods mutate an internal spec and return `this`
|
|
183
|
+
* typed as the same `RouteBuilder` — type information captured in `RouteSpec` shape,
|
|
184
|
+
* not builder generics. Prevents TS inference performance collapse at 50+ routes.
|
|
185
|
+
*/
|
|
186
|
+
type RouteBuilder = {
|
|
187
|
+
load<T>(fn: (params: Record<string, string>) => T | Promise<T>): RouteBuilder;
|
|
188
|
+
layout(component: LayoutComponent): RouteBuilder;
|
|
189
|
+
render(fn: (ctx: RenderContext) => VNode): RouteBuilder;
|
|
190
|
+
generate(fn: (locale: string) => Array<{
|
|
191
|
+
params: Record<string, string>;
|
|
192
|
+
}>): RouteBuilder;
|
|
193
|
+
head(fn: (ctx: RenderContext) => HeadConfig): RouteBuilder;
|
|
194
|
+
meta(data: Record<string, unknown>): RouteBuilder;
|
|
195
|
+
toJson(fn: (ctx: RenderContext) => object): RouteBuilder;
|
|
196
|
+
toFile(fn: (ctx: RenderContext) => {
|
|
197
|
+
name: string;
|
|
198
|
+
content: string | Uint8Array;
|
|
199
|
+
}): RouteBuilder; /** Internal: produce the RouteSpec object. */
|
|
200
|
+
_spec(): RouteSpec;
|
|
201
|
+
};
|
|
202
|
+
type RouteEntry = {
|
|
203
|
+
name: string;
|
|
204
|
+
spec: RouteSpec;
|
|
205
|
+
specificity: number;
|
|
206
|
+
};
|
|
207
|
+
type RouterConfig<Routes extends Record<string, RouteSpec> = Record<string, RouteSpec>> = {
|
|
208
|
+
routes: Routes;
|
|
209
|
+
defaultPage?: keyof Routes & string;
|
|
210
|
+
};
|
|
211
|
+
type RouterState<Routes extends Record<string, RouteSpec> = Record<string, RouteSpec>> = {
|
|
212
|
+
routes: Routes;
|
|
213
|
+
entries: ReadonlyArray<RouteEntry>;
|
|
214
|
+
};
|
|
215
|
+
type RouterApi<Routes extends Record<string, RouteSpec> = Record<string, RouteSpec>> = {
|
|
216
|
+
routes: Routes;
|
|
217
|
+
toUrl<K extends keyof Routes>(name: K, params: Record<string, string>): string;
|
|
218
|
+
match(url: string): {
|
|
219
|
+
entry: RouteEntry;
|
|
220
|
+
params: Record<string, string>;
|
|
221
|
+
} | null;
|
|
222
|
+
entries(): ReadonlyArray<RouteEntry>;
|
|
223
|
+
};
|
|
224
|
+
//#endregion
|
|
225
|
+
//#region src/plugins/content/types.d.ts
|
|
226
|
+
type Frontmatter = {
|
|
227
|
+
title: string;
|
|
228
|
+
date: string;
|
|
229
|
+
description: string;
|
|
230
|
+
tags: string[];
|
|
231
|
+
language: string;
|
|
232
|
+
author?: string;
|
|
233
|
+
draft?: boolean;
|
|
234
|
+
[key: string]: unknown;
|
|
235
|
+
};
|
|
236
|
+
type ComputedFields = {
|
|
237
|
+
contentId: string;
|
|
238
|
+
readingTimeMinutes: number;
|
|
239
|
+
wordCount: number;
|
|
240
|
+
};
|
|
241
|
+
type Article = {
|
|
242
|
+
slug: string;
|
|
243
|
+
locale: string;
|
|
244
|
+
frontmatter: Frontmatter;
|
|
245
|
+
html: string;
|
|
246
|
+
computed: ComputedFields;
|
|
247
|
+
};
|
|
248
|
+
type RehypePluginEntry = readonly [unknown, Record<string, unknown>?];
|
|
249
|
+
type RemarkPluginEntry = readonly [unknown, Record<string, unknown>?];
|
|
250
|
+
type ContentConfig = {
|
|
251
|
+
dir: string;
|
|
252
|
+
defaultAuthor?: string;
|
|
253
|
+
trustedContent: boolean;
|
|
254
|
+
rehypePlugins?: RehypePluginEntry[];
|
|
255
|
+
remarkPlugins?: RemarkPluginEntry[];
|
|
256
|
+
};
|
|
257
|
+
type ContentState = {
|
|
258
|
+
processor: Processor | null;
|
|
259
|
+
articles: Map<string, Map<string, Article>>;
|
|
260
|
+
slugs: string[] | null;
|
|
261
|
+
lastPaths: Set<string>; /** Paths marked stale by `invalidate()` — re-read on next `loadAll()` then cleared. */
|
|
262
|
+
dirtyPaths: Set<string>;
|
|
263
|
+
};
|
|
264
|
+
type ContentApi = {
|
|
265
|
+
loadAll(): Promise<Map<string, Article[]>>;
|
|
266
|
+
load(slug: string, locale: string): Promise<Article | null>;
|
|
267
|
+
discoverSlugs(): Promise<string[]>;
|
|
268
|
+
render(markdown: string): Promise<string>;
|
|
269
|
+
invalidate(paths: string[]): void;
|
|
270
|
+
reset(): void;
|
|
271
|
+
};
|
|
272
|
+
//#endregion
|
|
273
|
+
//#region src/plugins/build/types.d.ts
|
|
274
|
+
type BuildConfig = {
|
|
275
|
+
outdir: string;
|
|
276
|
+
mode: 'production' | 'development';
|
|
277
|
+
renderMode: 'ssg' | 'spa' | 'hybrid';
|
|
278
|
+
cssEntry?: string;
|
|
279
|
+
jsEntry?: string;
|
|
280
|
+
articleRouteKey?: string;
|
|
281
|
+
sourcemap?: 'none' | 'external' | 'inline';
|
|
282
|
+
};
|
|
283
|
+
type BundleManifest = {
|
|
284
|
+
cssPaths: string[];
|
|
285
|
+
jsPaths: string[];
|
|
286
|
+
assets: Map<string, string>;
|
|
287
|
+
};
|
|
288
|
+
type BuildState = {
|
|
289
|
+
manifest: BundleManifest | null;
|
|
290
|
+
lastResult: BuildResult | null;
|
|
291
|
+
};
|
|
292
|
+
type BuildResult = {
|
|
293
|
+
pages: number;
|
|
294
|
+
durationMs: number;
|
|
295
|
+
manifest: BundleManifest;
|
|
296
|
+
};
|
|
297
|
+
type BuildApi = {
|
|
298
|
+
run(): Promise<BuildResult>;
|
|
299
|
+
getManifest(): Readonly<BundleManifest> | null;
|
|
300
|
+
};
|
|
301
|
+
//#endregion
|
|
302
|
+
//#region src/project.d.ts
|
|
303
|
+
/**
|
|
304
|
+
* Map each consumer `RouteBuilder` to the `RouteSpec` shape the router stores.
|
|
305
|
+
*
|
|
306
|
+
* Keys are preserved so `toUrl(name, ...)` and `defaultPage` stay typed.
|
|
307
|
+
*/
|
|
308
|
+
type RouteSpecMap<Routes extends Record<string, RouteBuilder>> = { [K in keyof Routes]: RouteSpec };
|
|
309
|
+
/**
|
|
310
|
+
* Consumer-facing flat config shape.
|
|
311
|
+
*
|
|
312
|
+
* Generic over Routes (a record of `RouteBuilder`) so the literal route-name
|
|
313
|
+
* keys flow through to `app.router.routes` after the wrapper assembles the app.
|
|
314
|
+
*/
|
|
315
|
+
type WebAppConfig<Routes extends Record<string, RouteBuilder>> = {
|
|
316
|
+
mode?: 'production' | 'development';
|
|
317
|
+
site: SiteConfig;
|
|
318
|
+
i18n: I18nConfig;
|
|
319
|
+
routes: Routes;
|
|
320
|
+
components?: ComponentDef[];
|
|
321
|
+
spa?: {
|
|
322
|
+
viewTransitions?: boolean;
|
|
323
|
+
progressBar?: boolean;
|
|
324
|
+
};
|
|
325
|
+
ogImage?: OGImageConfig;
|
|
326
|
+
contentDir: string;
|
|
327
|
+
defaultPage?: keyof Routes & string;
|
|
328
|
+
trustedContent?: boolean;
|
|
329
|
+
};
|
|
330
|
+
//#endregion
|
|
331
|
+
//#region src/plugins/router/route-builder.d.ts
|
|
332
|
+
/**
|
|
333
|
+
* Build a `RouteSpec` via a fluent, non-accumulating builder.
|
|
334
|
+
*
|
|
335
|
+
* Methods mutate a single internal `RouteSpec` and return the same builder typed
|
|
336
|
+
* as `RouteBuilder` (NOT `RouteBuilder<T>`). Type information lives on the
|
|
337
|
+
* `RouteSpec` shape, not in builder generics — this keeps TS inference O(1) per
|
|
338
|
+
* route and prevents the 50+ route inference collapse described in D5.
|
|
339
|
+
*
|
|
340
|
+
* @param pattern - URL pattern (e.g. `/about`, `/{slug}`, `/{lang:?}/{slug}/`).
|
|
341
|
+
* @returns A `RouteBuilder` that mutates an internal spec.
|
|
342
|
+
* @example
|
|
343
|
+
* ```ts
|
|
344
|
+
* const home = route('/{lang:?}/').render(({ locale }) => <Home locale={locale} />)
|
|
345
|
+
* ```
|
|
346
|
+
*/
|
|
347
|
+
declare function route(pattern: string): RouteBuilder;
|
|
348
|
+
//#endregion
|
|
349
|
+
export { EnvApi as C, EnvVarSpec as D, EnvState as E, LogApi as O, Events as S, EnvProvider as T, I18nConfig as _, BuildConfig as a, SiteState as b, ContentApi as c, RouteBuilder as d, RouteSpec as f, I18nApi as g, RouterState as h, BuildApi as i, LogState as k, ContentConfig as l, RouterConfig as m, RouteSpecMap as n, BuildState as o, RouterApi as p, WebAppConfig as r, Article as s, route as t, ContentState as u, I18nState as v, EnvConfig as w, Config as x, SiteApi as y };
|
package/dist/test.cjs
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_project = require('./project-C1vtMxE8.cjs');
|
|
3
|
+
const require_factory = require('./factory-CixCpR9C.cjs');
|
|
4
|
+
const require_index = require('./index.cjs');
|
|
5
|
+
let _moku_labs_core = require("@moku-labs/core");
|
|
6
|
+
|
|
7
|
+
//#region src/test.ts
|
|
8
|
+
/** @file Test sub-path — createTestApp + createTestLog + createTestEnv factories. NEVER module-level singletons. */
|
|
9
|
+
/**
|
|
10
|
+
* Returns a FRESH log core-plugin instance per call — never a shared singleton.
|
|
11
|
+
*
|
|
12
|
+
* Each invocation constructs a new `createCorePlugin('log', ...)` so two calls
|
|
13
|
+
* produce two distinct plugin instances with isolated state. Use when you
|
|
14
|
+
* need a standalone trace separate from a running app's log.
|
|
15
|
+
*
|
|
16
|
+
* @returns A new log core-plugin instance, forced to `mode: 'test'`.
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* import { createTestLog } from '@moku-labs/web/test'
|
|
20
|
+
* const log = createTestLog()
|
|
21
|
+
* // pass to createCore({ plugins: [log] }) for an isolated test app
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
const createTestLog = () => (0, _moku_labs_core.createCorePlugin)("log", {
|
|
25
|
+
config: {
|
|
26
|
+
level: "debug",
|
|
27
|
+
mode: "test"
|
|
28
|
+
},
|
|
29
|
+
createState: require_factory.createLogState,
|
|
30
|
+
api: require_factory.createLogApi
|
|
31
|
+
});
|
|
32
|
+
/**
|
|
33
|
+
* Returns a FRESH env core-plugin instance per call — never a shared singleton.
|
|
34
|
+
*
|
|
35
|
+
* Useful for testing env-dependent behavior in isolation: pass a stub `providers`
|
|
36
|
+
* array of inline `{ name, load }` objects to inject deterministic values without
|
|
37
|
+
* touching `process.env`, `.env.local`, or Cloudflare globals.
|
|
38
|
+
*
|
|
39
|
+
* @param config - Partial EnvConfig overrides. Defaults: empty schema, no providers, `PUBLIC_` prefix.
|
|
40
|
+
* @returns A new env core-plugin instance.
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { createTestEnv } from '@moku-labs/web/test'
|
|
44
|
+
* const env = createTestEnv({
|
|
45
|
+
* schema: { PUBLIC_X: { public: true, required: true } },
|
|
46
|
+
* providers: [{ name: 'inline', load: () => ({ PUBLIC_X: 'value' }) }],
|
|
47
|
+
* })
|
|
48
|
+
* // pass to createCore({ plugins: [env] }) for an isolated test app
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
const createTestEnv = (config = {}) => (0, _moku_labs_core.createCorePlugin)("env", {
|
|
52
|
+
config: {
|
|
53
|
+
schema: {},
|
|
54
|
+
providers: [],
|
|
55
|
+
publicPrefix: "PUBLIC_",
|
|
56
|
+
...config
|
|
57
|
+
},
|
|
58
|
+
createState: require_factory.createEnvState,
|
|
59
|
+
api: require_factory.createEnvApi,
|
|
60
|
+
onInit: require_factory.validateSchema
|
|
61
|
+
});
|
|
62
|
+
/**
|
|
63
|
+
* Returns a fresh app instance configured for tests.
|
|
64
|
+
*
|
|
65
|
+
* Forces `mode: 'development'` so plugins skip production-only side effects
|
|
66
|
+
* (eager bundle, watchers) and routes consumers through the standard Layer-2
|
|
67
|
+
* assembly so cross-plugin wiring is exercised the same way a real app would.
|
|
68
|
+
*
|
|
69
|
+
* @param input - The same flat `WebAppConfig` you'd pass to `createApp`.
|
|
70
|
+
* @returns The assembled app with the consumer's typed routes.
|
|
71
|
+
*/
|
|
72
|
+
function createTestApp(input) {
|
|
73
|
+
return require_index.createApp({
|
|
74
|
+
...input,
|
|
75
|
+
mode: "development"
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
//#endregion
|
|
80
|
+
exports.createTestApp = createTestApp;
|
|
81
|
+
exports.createTestEnv = createTestEnv;
|
|
82
|
+
exports.createTestLog = createTestLog;
|
package/dist/test.d.cts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { C as EnvApi, D as EnvVarSpec, E as EnvState, O as LogApi, T as EnvProvider, d as RouteBuilder, k as LogState, r as WebAppConfig, w as EnvConfig } from "./route-builder-Lv6HUVvP.cjs";
|
|
2
|
+
import { WebApp } from "./index.cjs";
|
|
3
|
+
import * as _moku_labs_core0 from "@moku-labs/core";
|
|
4
|
+
|
|
5
|
+
//#region src/test.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Returns a FRESH log core-plugin instance per call — never a shared singleton.
|
|
8
|
+
*
|
|
9
|
+
* Each invocation constructs a new `createCorePlugin('log', ...)` so two calls
|
|
10
|
+
* produce two distinct plugin instances with isolated state. Use when you
|
|
11
|
+
* need a standalone trace separate from a running app's log.
|
|
12
|
+
*
|
|
13
|
+
* @returns A new log core-plugin instance, forced to `mode: 'test'`.
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { createTestLog } from '@moku-labs/web/test'
|
|
17
|
+
* const log = createTestLog()
|
|
18
|
+
* // pass to createCore({ plugins: [log] }) for an isolated test app
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
declare const createTestLog: () => _moku_labs_core0.CorePluginInstance<"log", {
|
|
22
|
+
level: "debug";
|
|
23
|
+
mode: "test";
|
|
24
|
+
}, LogState, LogApi>;
|
|
25
|
+
/**
|
|
26
|
+
* Returns a FRESH env core-plugin instance per call — never a shared singleton.
|
|
27
|
+
*
|
|
28
|
+
* Useful for testing env-dependent behavior in isolation: pass a stub `providers`
|
|
29
|
+
* array of inline `{ name, load }` objects to inject deterministic values without
|
|
30
|
+
* touching `process.env`, `.env.local`, or Cloudflare globals.
|
|
31
|
+
*
|
|
32
|
+
* @param config - Partial EnvConfig overrides. Defaults: empty schema, no providers, `PUBLIC_` prefix.
|
|
33
|
+
* @returns A new env core-plugin instance.
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* import { createTestEnv } from '@moku-labs/web/test'
|
|
37
|
+
* const env = createTestEnv({
|
|
38
|
+
* schema: { PUBLIC_X: { public: true, required: true } },
|
|
39
|
+
* providers: [{ name: 'inline', load: () => ({ PUBLIC_X: 'value' }) }],
|
|
40
|
+
* })
|
|
41
|
+
* // pass to createCore({ plugins: [env] }) for an isolated test app
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
declare const createTestEnv: (config?: Partial<EnvConfig>) => _moku_labs_core0.CorePluginInstance<"env", {
|
|
45
|
+
schema: Record<string, EnvVarSpec>;
|
|
46
|
+
providers: EnvProvider[];
|
|
47
|
+
publicPrefix: string;
|
|
48
|
+
}, EnvState, EnvApi>;
|
|
49
|
+
/**
|
|
50
|
+
* Returns a fresh app instance configured for tests.
|
|
51
|
+
*
|
|
52
|
+
* Forces `mode: 'development'` so plugins skip production-only side effects
|
|
53
|
+
* (eager bundle, watchers) and routes consumers through the standard Layer-2
|
|
54
|
+
* assembly so cross-plugin wiring is exercised the same way a real app would.
|
|
55
|
+
*
|
|
56
|
+
* @param input - The same flat `WebAppConfig` you'd pass to `createApp`.
|
|
57
|
+
* @returns The assembled app with the consumer's typed routes.
|
|
58
|
+
*/
|
|
59
|
+
declare function createTestApp<Routes extends Record<string, RouteBuilder>>(input: WebAppConfig<Routes>): WebApp<Routes>;
|
|
60
|
+
//#endregion
|
|
61
|
+
export { createTestApp, createTestEnv, createTestLog };
|
package/dist/test.d.mts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { C as EnvApi, D as EnvVarSpec, E as EnvState, O as LogApi, T as EnvProvider, d as RouteBuilder, k as LogState, r as WebAppConfig, w as EnvConfig } from "./index-CWdZdegx.mjs";
|
|
2
|
+
import { WebApp } from "./index.mjs";
|
|
3
|
+
import * as _moku_labs_core0 from "@moku-labs/core";
|
|
4
|
+
|
|
5
|
+
//#region src/test.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Returns a FRESH log core-plugin instance per call — never a shared singleton.
|
|
8
|
+
*
|
|
9
|
+
* Each invocation constructs a new `createCorePlugin('log', ...)` so two calls
|
|
10
|
+
* produce two distinct plugin instances with isolated state. Use when you
|
|
11
|
+
* need a standalone trace separate from a running app's log.
|
|
12
|
+
*
|
|
13
|
+
* @returns A new log core-plugin instance, forced to `mode: 'test'`.
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { createTestLog } from '@moku-labs/web/test'
|
|
17
|
+
* const log = createTestLog()
|
|
18
|
+
* // pass to createCore({ plugins: [log] }) for an isolated test app
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
declare const createTestLog: () => _moku_labs_core0.CorePluginInstance<"log", {
|
|
22
|
+
level: "debug";
|
|
23
|
+
mode: "test";
|
|
24
|
+
}, LogState, LogApi>;
|
|
25
|
+
/**
|
|
26
|
+
* Returns a FRESH env core-plugin instance per call — never a shared singleton.
|
|
27
|
+
*
|
|
28
|
+
* Useful for testing env-dependent behavior in isolation: pass a stub `providers`
|
|
29
|
+
* array of inline `{ name, load }` objects to inject deterministic values without
|
|
30
|
+
* touching `process.env`, `.env.local`, or Cloudflare globals.
|
|
31
|
+
*
|
|
32
|
+
* @param config - Partial EnvConfig overrides. Defaults: empty schema, no providers, `PUBLIC_` prefix.
|
|
33
|
+
* @returns A new env core-plugin instance.
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* import { createTestEnv } from '@moku-labs/web/test'
|
|
37
|
+
* const env = createTestEnv({
|
|
38
|
+
* schema: { PUBLIC_X: { public: true, required: true } },
|
|
39
|
+
* providers: [{ name: 'inline', load: () => ({ PUBLIC_X: 'value' }) }],
|
|
40
|
+
* })
|
|
41
|
+
* // pass to createCore({ plugins: [env] }) for an isolated test app
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
declare const createTestEnv: (config?: Partial<EnvConfig>) => _moku_labs_core0.CorePluginInstance<"env", {
|
|
45
|
+
schema: Record<string, EnvVarSpec>;
|
|
46
|
+
providers: EnvProvider[];
|
|
47
|
+
publicPrefix: string;
|
|
48
|
+
}, EnvState, EnvApi>;
|
|
49
|
+
/**
|
|
50
|
+
* Returns a fresh app instance configured for tests.
|
|
51
|
+
*
|
|
52
|
+
* Forces `mode: 'development'` so plugins skip production-only side effects
|
|
53
|
+
* (eager bundle, watchers) and routes consumers through the standard Layer-2
|
|
54
|
+
* assembly so cross-plugin wiring is exercised the same way a real app would.
|
|
55
|
+
*
|
|
56
|
+
* @param input - The same flat `WebAppConfig` you'd pass to `createApp`.
|
|
57
|
+
* @returns The assembled app with the consumer's typed routes.
|
|
58
|
+
*/
|
|
59
|
+
declare function createTestApp<Routes extends Record<string, RouteBuilder>>(input: WebAppConfig<Routes>): WebApp<Routes>;
|
|
60
|
+
//#endregion
|
|
61
|
+
export { createTestApp, createTestEnv, createTestLog };
|
package/dist/test.mjs
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { _ as createEnvState, g as validateSchema, h as createLogApi, m as createLogState, v as createEnvApi } from "./factory-DwpBwjDk.mjs";
|
|
2
|
+
import "./project-BTNUWbGQ.mjs";
|
|
3
|
+
import { createApp } from "./index.mjs";
|
|
4
|
+
import { createCorePlugin } from "@moku-labs/core";
|
|
5
|
+
|
|
6
|
+
//#region src/test.ts
|
|
7
|
+
/** @file Test sub-path — createTestApp + createTestLog + createTestEnv factories. NEVER module-level singletons. */
|
|
8
|
+
/**
|
|
9
|
+
* Returns a FRESH log core-plugin instance per call — never a shared singleton.
|
|
10
|
+
*
|
|
11
|
+
* Each invocation constructs a new `createCorePlugin('log', ...)` so two calls
|
|
12
|
+
* produce two distinct plugin instances with isolated state. Use when you
|
|
13
|
+
* need a standalone trace separate from a running app's log.
|
|
14
|
+
*
|
|
15
|
+
* @returns A new log core-plugin instance, forced to `mode: 'test'`.
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { createTestLog } from '@moku-labs/web/test'
|
|
19
|
+
* const log = createTestLog()
|
|
20
|
+
* // pass to createCore({ plugins: [log] }) for an isolated test app
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
const createTestLog = () => createCorePlugin("log", {
|
|
24
|
+
config: {
|
|
25
|
+
level: "debug",
|
|
26
|
+
mode: "test"
|
|
27
|
+
},
|
|
28
|
+
createState: createLogState,
|
|
29
|
+
api: createLogApi
|
|
30
|
+
});
|
|
31
|
+
/**
|
|
32
|
+
* Returns a FRESH env core-plugin instance per call — never a shared singleton.
|
|
33
|
+
*
|
|
34
|
+
* Useful for testing env-dependent behavior in isolation: pass a stub `providers`
|
|
35
|
+
* array of inline `{ name, load }` objects to inject deterministic values without
|
|
36
|
+
* touching `process.env`, `.env.local`, or Cloudflare globals.
|
|
37
|
+
*
|
|
38
|
+
* @param config - Partial EnvConfig overrides. Defaults: empty schema, no providers, `PUBLIC_` prefix.
|
|
39
|
+
* @returns A new env core-plugin instance.
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* import { createTestEnv } from '@moku-labs/web/test'
|
|
43
|
+
* const env = createTestEnv({
|
|
44
|
+
* schema: { PUBLIC_X: { public: true, required: true } },
|
|
45
|
+
* providers: [{ name: 'inline', load: () => ({ PUBLIC_X: 'value' }) }],
|
|
46
|
+
* })
|
|
47
|
+
* // pass to createCore({ plugins: [env] }) for an isolated test app
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
const createTestEnv = (config = {}) => createCorePlugin("env", {
|
|
51
|
+
config: {
|
|
52
|
+
schema: {},
|
|
53
|
+
providers: [],
|
|
54
|
+
publicPrefix: "PUBLIC_",
|
|
55
|
+
...config
|
|
56
|
+
},
|
|
57
|
+
createState: createEnvState,
|
|
58
|
+
api: createEnvApi,
|
|
59
|
+
onInit: validateSchema
|
|
60
|
+
});
|
|
61
|
+
/**
|
|
62
|
+
* Returns a fresh app instance configured for tests.
|
|
63
|
+
*
|
|
64
|
+
* Forces `mode: 'development'` so plugins skip production-only side effects
|
|
65
|
+
* (eager bundle, watchers) and routes consumers through the standard Layer-2
|
|
66
|
+
* assembly so cross-plugin wiring is exercised the same way a real app would.
|
|
67
|
+
*
|
|
68
|
+
* @param input - The same flat `WebAppConfig` you'd pass to `createApp`.
|
|
69
|
+
* @returns The assembled app with the consumer's typed routes.
|
|
70
|
+
*/
|
|
71
|
+
function createTestApp(input) {
|
|
72
|
+
return createApp({
|
|
73
|
+
...input,
|
|
74
|
+
mode: "development"
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
export { createTestApp, createTestEnv, createTestLog };
|