@t09tanaka/stoneage 0.1.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/LICENSE +21 -0
  3. package/README.md +768 -0
  4. package/dist/agent-skill.d.ts +1 -0
  5. package/dist/agent-skill.js +140 -0
  6. package/dist/assets.d.ts +125 -0
  7. package/dist/assets.js +341 -0
  8. package/dist/cli.d.ts +236 -0
  9. package/dist/cli.js +3077 -0
  10. package/dist/core.d.ts +473 -0
  11. package/dist/core.js +2897 -0
  12. package/dist/data.d.ts +121 -0
  13. package/dist/data.js +358 -0
  14. package/dist/deploy.d.ts +34 -0
  15. package/dist/deploy.js +203 -0
  16. package/dist/dev.d.ts +36 -0
  17. package/dist/dev.js +313 -0
  18. package/dist/example.d.ts +134 -0
  19. package/dist/example.js +1272 -0
  20. package/dist/fragment/client.d.ts +13 -0
  21. package/dist/fragment/client.js +150 -0
  22. package/dist/fragment.d.ts +15 -0
  23. package/dist/fragment.js +27 -0
  24. package/dist/html.d.ts +57 -0
  25. package/dist/html.js +208 -0
  26. package/dist/images.d.ts +95 -0
  27. package/dist/images.js +292 -0
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.js +1 -0
  30. package/dist/migration.d.ts +157 -0
  31. package/dist/migration.js +983 -0
  32. package/dist/optimize.d.ts +15 -0
  33. package/dist/optimize.js +215 -0
  34. package/dist/pagination.d.ts +26 -0
  35. package/dist/pagination.js +62 -0
  36. package/dist/paths.d.ts +1 -0
  37. package/dist/paths.js +10 -0
  38. package/dist/search.d.ts +32 -0
  39. package/dist/search.js +55 -0
  40. package/dist/testing.d.ts +66 -0
  41. package/dist/testing.js +97 -0
  42. package/dist/validate.d.ts +2 -0
  43. package/dist/validate.js +1 -0
  44. package/jsx-loader.mjs +52 -0
  45. package/jsx-register.mjs +7 -0
  46. package/package.json +135 -0
  47. package/tsconfig.base.json +16 -0
package/dist/core.d.ts ADDED
@@ -0,0 +1,473 @@
1
+ import { type ClientAssetRegistry, type ClientStylesheetAsset, type PublicAssetInput } from "./assets.js";
2
+ import { type DeferredFragmentDefaults } from "./fragment.js";
3
+ export * from "./data.js";
4
+ export type RouteParams = Record<string, string | number>;
5
+ export type RouteParamMatcher = (value: string) => boolean;
6
+ export type RouteParamMatchers = Partial<Record<string, RouteParamMatcher>>;
7
+ type RouteParamName<Segment extends string> = Segment extends `${infer Name}.${string}` ? Name : Segment extends `${infer Name}?${string}` ? Name : Segment extends `${infer Name}#${string}` ? Name : Segment;
8
+ type RouteParamRest<Segment extends string> = Segment extends `${string}/${infer Rest}` ? Rest : "";
9
+ export type RouteParamKeys<Pattern extends string> = Pattern extends `${string}:${infer Segment}` ? RouteParamName<Segment extends `${infer BeforeSlash}/${string}` ? BeforeSlash : Segment> | RouteParamKeys<RouteParamRest<Segment>> : never;
10
+ export type RouteParamsFor<Pattern extends string> = [RouteParamKeys<Pattern>] extends [never] ? Record<string, never> : {
11
+ [Key in RouteParamKeys<Pattern>]: string | number;
12
+ };
13
+ export type RouteParamMatchersFor<Pattern extends string> = [RouteParamKeys<Pattern>] extends [
14
+ never
15
+ ] ? Record<string, never> : Partial<Record<RouteParamKeys<Pattern>, RouteParamMatcher>>;
16
+ export type Dependency = string | {
17
+ key: string;
18
+ file: string;
19
+ } | {
20
+ key: string;
21
+ value: unknown;
22
+ } | {
23
+ key: string;
24
+ hash: string;
25
+ };
26
+ export type SiteConfig = {
27
+ baseUrl: string;
28
+ title: string;
29
+ titleTemplate?: string;
30
+ description: string;
31
+ lang?: string;
32
+ favicon?: string;
33
+ openGraph?: boolean | SiteOpenGraphMetadata;
34
+ ogImage?: string;
35
+ ogImageWidth?: number;
36
+ ogImageHeight?: number;
37
+ twitter?: TwitterMetadata;
38
+ head?: HeadTag[];
39
+ /**
40
+ * Path-based metadata resolution hook. Called by `buildSite` once per page
41
+ * with that page's normalized pathname (after `trailingSlash` is applied,
42
+ * e.g. `/blog/post/`). Return a `Partial<PageMetadata>` to apply section
43
+ * images, default OG metadata, canonical overrides, etc. in one place
44
+ * instead of wiring them onto every route family.
45
+ *
46
+ * Resolution precedence (lowest to highest):
47
+ * site defaults < route `metadata` < this hook < page-level `metadata`
48
+ *
49
+ * Returning `undefined` (or omitting keys) leaves existing values untouched.
50
+ * The hook is expected to be pure; if it throws, the build fails.
51
+ * Artifacts (non-HTML entries) never invoke this hook.
52
+ */
53
+ metadata?: (pathname: string) => Partial<PageMetadata> | undefined;
54
+ };
55
+ export type SiteOpenGraphMetadata = {
56
+ siteName?: string;
57
+ };
58
+ export type TwitterMetadata = {
59
+ card?: string;
60
+ site?: string;
61
+ creator?: string;
62
+ title?: string;
63
+ description?: string;
64
+ image?: string;
65
+ };
66
+ export type HeadTag = {
67
+ tag: "link" | "meta";
68
+ attrs: Record<string, string | number | boolean | null | undefined>;
69
+ };
70
+ export type RobotsRule = {
71
+ userAgent: string | string[];
72
+ allow?: string[];
73
+ disallow?: string[];
74
+ crawlDelay?: number;
75
+ };
76
+ export type RobotsConfig = {
77
+ rules?: RobotsRule[];
78
+ sitemap?: boolean | string[];
79
+ };
80
+ export type RedirectStatus = 301 | 302 | 303 | 307 | 308;
81
+ export type RedirectRule = {
82
+ from: string;
83
+ to: string;
84
+ status?: RedirectStatus;
85
+ };
86
+ export type TypedRedirectRule<FromPattern extends string, ToPattern extends string> = {
87
+ from: FromPattern;
88
+ fromParams: RouteParamsFor<FromPattern>;
89
+ to: ToPattern;
90
+ toParams: RouteParamsFor<ToPattern>;
91
+ status?: RedirectStatus;
92
+ };
93
+ export type RedirectsFromRecordsOptions<RecordItem, FromPattern extends string, ToPattern extends string> = {
94
+ from: FromPattern;
95
+ fromParams: (record: RecordItem, index: number) => RouteParamsFor<FromPattern>;
96
+ to: ToPattern;
97
+ toParams: (record: RecordItem, index: number) => RouteParamsFor<ToPattern>;
98
+ status?: RedirectStatus | ((record: RecordItem, index: number) => RedirectStatus);
99
+ };
100
+ export type PublishingConfig = {
101
+ robots?: RobotsConfig | false;
102
+ redirects?: RedirectRule[];
103
+ /**
104
+ * When `true`, emit a static `<meta http-equiv="refresh">` HTML page at each
105
+ * internal redirect's `from` path. This makes redirects work on plain static
106
+ * hosts that do not interpret `redirects.json` / `_redirects`. Off by default
107
+ * to preserve the existing manifest-only behaviour.
108
+ */
109
+ redirectHtml?: boolean;
110
+ /**
111
+ * Emit host-native redirect artifacts in addition to the host-neutral
112
+ * publishing manifests. "netlify" writes Netlify-compatible `_redirects` and
113
+ * `_headers` files, which Cloudflare Pages also understands.
114
+ */
115
+ nativeRedirects?: "netlify" | false;
116
+ headers?: boolean;
117
+ };
118
+ export type SitemapConfig = {
119
+ maxUrlsPerFile?: number;
120
+ };
121
+ export type PageMetadata = {
122
+ title: string;
123
+ description: string;
124
+ canonical?: string;
125
+ openGraph?: boolean;
126
+ ogTitle?: string;
127
+ ogDescription?: string;
128
+ ogImage?: string;
129
+ ogImageWidth?: number;
130
+ ogImageHeight?: number;
131
+ ogType?: string;
132
+ twitter?: TwitterMetadata;
133
+ head?: HeadTag[];
134
+ noindex?: boolean;
135
+ prefetch?: string[];
136
+ assets?: string[];
137
+ islands?: string[];
138
+ sitemap?: boolean;
139
+ };
140
+ export type PageMetadataInput = Partial<PageMetadata>;
141
+ export type RouteMetadataDefaults = PageMetadataInput;
142
+ export type RouteEntry = {
143
+ params: RouteParams;
144
+ path?: string;
145
+ dependencies?: Dependency[];
146
+ links?: string[];
147
+ metadata?: PageMetadataInput;
148
+ render: () => string | Promise<string>;
149
+ };
150
+ export type RouteFamily = {
151
+ name: string;
152
+ pattern: string;
153
+ metadata?: RouteMetadataDefaults;
154
+ paramMatchers?: RouteParamMatchers;
155
+ entries: () => RouteEntry[] | Promise<RouteEntry[]>;
156
+ };
157
+ export type ArtifactBody = string | Buffer | Uint8Array;
158
+ export type ArtifactHeaders = Record<string, string>;
159
+ export type ArtifactResponse = {
160
+ body: ArtifactBody;
161
+ contentType?: string;
162
+ status?: number;
163
+ headers?: ArtifactHeaders;
164
+ };
165
+ export type ArtifactResponseInit = {
166
+ contentType?: string;
167
+ status?: number;
168
+ headers?: Record<string, string | number | boolean>;
169
+ };
170
+ export type JsonArtifactOptions = ArtifactResponseInit & {
171
+ pretty?: boolean;
172
+ };
173
+ export type ArtifactContent = ArtifactBody | ArtifactResponse;
174
+ export type ArtifactEntry = {
175
+ params: RouteParams;
176
+ path?: string;
177
+ dependencies?: Dependency[];
178
+ render: () => ArtifactContent | Promise<ArtifactContent>;
179
+ };
180
+ export type ArtifactFamily = {
181
+ name: string;
182
+ pattern: string;
183
+ paramMatchers?: RouteParamMatchers;
184
+ entries: () => ArtifactEntry[] | Promise<ArtifactEntry[]>;
185
+ };
186
+ export type FragmentEntry = {
187
+ params: RouteParams;
188
+ path?: string;
189
+ dependencies?: Dependency[];
190
+ render: () => string | Promise<string>;
191
+ };
192
+ export type FragmentFamily<Params extends RouteParams = RouteParams> = {
193
+ name: string;
194
+ pattern: string;
195
+ paramMatchers?: RouteParamMatchers;
196
+ path: (params: Params) => string;
197
+ entries: () => FragmentEntry[] | Promise<FragmentEntry[]>;
198
+ };
199
+ export type SvgAssetEntry<Params extends RouteParams = RouteParams> = {
200
+ params: Params;
201
+ dependencies?: Dependency[];
202
+ width?: number;
203
+ height?: number;
204
+ render: () => string | Promise<string>;
205
+ };
206
+ export type SvgAssetFamily<Params extends RouteParams = RouteParams> = {
207
+ name: string;
208
+ dir: string;
209
+ paramMatchers?: RouteParamMatchers;
210
+ path: (params: Params) => string;
211
+ entries: () => SvgAssetEntry<Params>[] | Promise<SvgAssetEntry<Params>[]>;
212
+ };
213
+ export type TypedRouteEntry<Pattern extends string> = Omit<RouteEntry, "params"> & {
214
+ params: RouteParamsFor<Pattern>;
215
+ };
216
+ export type TypedRouteFamily<Pattern extends string> = Omit<RouteFamily, "pattern" | "paramMatchers" | "entries"> & {
217
+ pattern: Pattern;
218
+ paramMatchers?: RouteParamMatchersFor<Pattern>;
219
+ path: (params: RouteParamsFor<Pattern>) => string;
220
+ entries: () => TypedRouteEntry<Pattern>[] | Promise<TypedRouteEntry<Pattern>[]>;
221
+ };
222
+ export type TypedArtifactEntry<Pattern extends string> = Omit<ArtifactEntry, "params"> & {
223
+ params: RouteParamsFor<Pattern>;
224
+ };
225
+ export type TypedFragmentEntry<Pattern extends string> = Omit<FragmentEntry, "params"> & {
226
+ params: RouteParamsFor<Pattern>;
227
+ };
228
+ export type TypedFragmentFamily<Pattern extends string> = Omit<FragmentFamily, "pattern" | "paramMatchers" | "path" | "entries"> & {
229
+ pattern: Pattern;
230
+ paramMatchers?: RouteParamMatchersFor<Pattern>;
231
+ path: (params: RouteParamsFor<Pattern>) => string;
232
+ entries: () => TypedFragmentEntry<Pattern>[] | Promise<TypedFragmentEntry<Pattern>[]>;
233
+ };
234
+ export type TypedSvgAssetFamily<Params extends RouteParams = RouteParams> = Omit<SvgAssetFamily<Params>, "paramMatchers" | "entries"> & {
235
+ paramMatchers?: Partial<Record<Extract<keyof Params, string>, RouteParamMatcher>>;
236
+ entries: () => SvgAssetEntry<Params>[] | Promise<SvgAssetEntry<Params>[]>;
237
+ };
238
+ export type NotFoundConfig = {
239
+ metadata?: PageMetadataInput;
240
+ render: () => string | Promise<string>;
241
+ };
242
+ export type BuildConfig = {
243
+ outDir: string;
244
+ /**
245
+ * Optional caller-owned fingerprint for all inputs needed to know whether
246
+ * the route/artifact plan can be reused. When it matches the previous build
247
+ * report, StoneAge can return the previous manifest/report without
248
+ * enumerating routes.
249
+ */
250
+ buildFingerprint?: string;
251
+ /**
252
+ * Optional caller-owned fingerprint for renderer-wide inputs such as source
253
+ * templates, CSS inputs, and artifact renderers. This is included in
254
+ * per-output fingerprints so unchanged data dependencies cannot reuse stale
255
+ * HTML or artifacts after a renderer-only change.
256
+ */
257
+ renderFingerprint?: string;
258
+ site: SiteConfig;
259
+ assets?: {
260
+ stylesheets?: ClientStylesheetAsset[];
261
+ client?: ClientAssetRegistry;
262
+ public?: PublicAssetInput[];
263
+ /**
264
+ * Directory whose tree is copied verbatim onto the output root. Each file
265
+ * is expanded into a managed public asset (e.g. `public/images/logo.png`
266
+ * becomes `/images/logo.png`, `public/CNAME` becomes `/CNAME`). Entries
267
+ * are tracked in the build report so re-runs are idempotent and removed
268
+ * source files are pruned from the output.
269
+ */
270
+ publicDir?: string;
271
+ };
272
+ concurrency?: number;
273
+ partial?: boolean;
274
+ prefetch?: {
275
+ serviceWorker?: boolean;
276
+ linkRel?: boolean;
277
+ cacheName?: string;
278
+ scriptPath?: string;
279
+ workerPath?: string;
280
+ };
281
+ publishing?: PublishingConfig;
282
+ sitemap?: SitemapConfig;
283
+ trailingSlash?: "always" | "never";
284
+ validation?: ValidationConfig;
285
+ notFound?: NotFoundConfig;
286
+ routes: RouteFamily[];
287
+ artifacts?: ArtifactFamily[];
288
+ fragments?: FragmentConfig;
289
+ svgAssets?: SvgAssetFamily<any>[];
290
+ };
291
+ export type FragmentConfig = FragmentFamily<any>[] | (DeferredFragmentDefaults & {
292
+ families?: FragmentFamily<any>[];
293
+ client?: boolean | {
294
+ publicPath?: string;
295
+ };
296
+ });
297
+ export type ValidationConfig = {
298
+ configPath?: string;
299
+ configHash?: string;
300
+ requiredMetadata?: RequiredMetadataKey[];
301
+ budgets?: SizeBudgetConfig;
302
+ };
303
+ export type RequiredMetadataKey = (typeof requiredMetadataKeys)[number];
304
+ export type SizeBudgetConfig = {
305
+ maxPages?: number;
306
+ maxArtifacts?: number;
307
+ maxRouteFamilyPages?: Record<string, number>;
308
+ maxArtifactFamilyOutputs?: Record<string, number>;
309
+ maxHtmlBytes?: number;
310
+ maxCssBytes?: number;
311
+ maxJsBytes?: number;
312
+ maxPublicFileBytes?: number;
313
+ maxTotalPublicBytes?: number;
314
+ maxImageBytes?: number;
315
+ maxBrotliBytes?: number;
316
+ maxGzipBytes?: number;
317
+ maxDependencyFanout?: number;
318
+ };
319
+ declare const requiredMetadataKeys: readonly ["title", "description", "canonical", "favicon", "ogImage", "twitterImage"];
320
+ export declare function loadValidationConfig(path: string): Promise<ValidationConfig>;
321
+ export type ManifestPage = {
322
+ route: string;
323
+ path: string;
324
+ outputPath: string;
325
+ dependencies: Record<string, string>;
326
+ links: string[];
327
+ htmlBytes: number;
328
+ sitemap: boolean;
329
+ };
330
+ export type ManifestArtifact = {
331
+ route: string;
332
+ path: string;
333
+ outputPath: string;
334
+ dependencies: Record<string, string>;
335
+ bytes: number;
336
+ contentType?: string;
337
+ status?: number;
338
+ headers?: ArtifactHeaders;
339
+ };
340
+ export type Manifest = {
341
+ version: 1;
342
+ pages: ManifestPage[];
343
+ artifacts: ManifestArtifact[];
344
+ };
345
+ export type BuildReport = {
346
+ buildFingerprint?: string;
347
+ renderFingerprint?: string;
348
+ fragmentDefaultFallbackText?: string;
349
+ fragmentClientPublicPath?: string;
350
+ pageCount: number;
351
+ pagesWritten: number;
352
+ artifactCount: number;
353
+ artifactsWritten: number;
354
+ publicAssetsCopied: number;
355
+ publicAssetsSkipped: number;
356
+ publicAssets: string[];
357
+ staleOutputsRemoved: number;
358
+ sitemapRendered: boolean;
359
+ sitemapFiles: string[];
360
+ routeFamilies: Record<string, number>;
361
+ routeWrites: Record<string, number>;
362
+ artifactFamilies: Record<string, number>;
363
+ artifactWrites: Record<string, number>;
364
+ missingLinks: string[];
365
+ largestHtml: Array<{
366
+ path: string;
367
+ bytes: number;
368
+ }>;
369
+ largestArtifacts: Array<{
370
+ path: string;
371
+ bytes: number;
372
+ }>;
373
+ validation: BuildValidationReport;
374
+ };
375
+ export type DataFlowFamilySummary = {
376
+ name: string;
377
+ outputs: number;
378
+ written: number;
379
+ skipped: number;
380
+ bytes: number;
381
+ };
382
+ export type DataFlowDependencySummary = {
383
+ key: string;
384
+ outputs: number;
385
+ pages: number;
386
+ artifacts: number;
387
+ routes: Record<string, number>;
388
+ artifactRoutes: Record<string, number>;
389
+ };
390
+ export type DataFlowReport = {
391
+ version: 1;
392
+ outputs: {
393
+ pages: number;
394
+ artifacts: number;
395
+ total: number;
396
+ };
397
+ routeFamilies: DataFlowFamilySummary[];
398
+ artifactFamilies: DataFlowFamilySummary[];
399
+ dependencies: DataFlowDependencySummary[];
400
+ };
401
+ export type DataFlowSummaryReport = Omit<DataFlowReport, "dependencies">;
402
+ export type DataFlowDependenciesReport = {
403
+ version: 1;
404
+ dependencies: DataFlowDependencySummary[];
405
+ };
406
+ export type BuildValidationReport = {
407
+ ok: boolean;
408
+ configPath?: string;
409
+ configHash?: string;
410
+ issues: ValidationIssue[];
411
+ };
412
+ export type ValidationIssue = {
413
+ code: string;
414
+ message: string;
415
+ path?: string;
416
+ bytes?: number;
417
+ dependency?: string;
418
+ outputs?: number;
419
+ limit?: number;
420
+ };
421
+ export type BuildResult = {
422
+ pagesWritten: number;
423
+ artifactsWritten: number;
424
+ publicAssetsCopied: number;
425
+ publicAssetsSkipped: number;
426
+ manifest: Manifest;
427
+ report: BuildReport;
428
+ };
429
+ export type HtmlComponent<Props> = (props: Props) => string;
430
+ export declare const notFoundRouteName = "\0stoneage:not-found";
431
+ export declare const notFoundOutputPath = "404.html";
432
+ export declare function component<Props>(render: HtmlComponent<Props>): HtmlComponent<Props>;
433
+ export declare function routePath(pattern: string, params: RouteParams): string;
434
+ export declare function artifactPath(pattern: string, params: RouteParams): string;
435
+ export declare function fragmentPath(pattern: string, params: RouteParams): string;
436
+ export declare function patternParamMatcher(pattern: RegExp): RouteParamMatcher;
437
+ export declare function pathForRoute<const Pattern extends string>(pattern: Pattern, params: RouteParamsFor<Pattern>): string;
438
+ export declare function pathForArtifact<const Pattern extends string>(pattern: Pattern, params: RouteParamsFor<Pattern>): string;
439
+ export declare function pathForRedirect<const Pattern extends string>(pattern: Pattern, params: RouteParamsFor<Pattern>): string;
440
+ export declare function redirectToRoute<const FromPattern extends string, const ToPattern extends string>(redirect: TypedRedirectRule<FromPattern, ToPattern>): RedirectRule;
441
+ export declare function redirectsFromRecords<RecordItem, const FromPattern extends string, const ToPattern extends string>(records: readonly RecordItem[], options: RedirectsFromRecordsOptions<RecordItem, FromPattern, ToPattern>): RedirectRule[];
442
+ export declare function defineRouteFamily<const Pattern extends string>(config: {
443
+ name: string;
444
+ pattern: Pattern;
445
+ metadata?: RouteMetadataDefaults;
446
+ paramMatchers?: RouteParamMatchersFor<Pattern>;
447
+ entries: () => TypedRouteEntry<Pattern>[] | Promise<TypedRouteEntry<Pattern>[]>;
448
+ }): TypedRouteFamily<Pattern>;
449
+ export declare function defineArtifactFamily<const Pattern extends string>(config: {
450
+ name: string;
451
+ pattern: Pattern;
452
+ paramMatchers?: RouteParamMatchersFor<Pattern>;
453
+ entries: () => TypedArtifactEntry<Pattern>[] | Promise<TypedArtifactEntry<Pattern>[]>;
454
+ }): ArtifactFamily;
455
+ export declare function defineFragmentFamily<const Pattern extends string>(config: {
456
+ name: string;
457
+ pattern: Pattern;
458
+ paramMatchers?: RouteParamMatchersFor<Pattern>;
459
+ entries: () => TypedFragmentEntry<Pattern>[] | Promise<TypedFragmentEntry<Pattern>[]>;
460
+ }): TypedFragmentFamily<Pattern>;
461
+ export declare function defineSvgAssetFamily<Params extends RouteParams = RouteParams>(config: {
462
+ name: string;
463
+ dir?: string;
464
+ paramMatchers?: Partial<Record<Extract<keyof Params, string>, RouteParamMatcher>>;
465
+ entries: () => SvgAssetEntry<Params>[] | Promise<SvgAssetEntry<Params>[]>;
466
+ }): TypedSvgAssetFamily<Params>;
467
+ export declare function artifactResponse(body: ArtifactBody, init?: ArtifactResponseInit): ArtifactResponse;
468
+ export declare function jsonArtifact(value: unknown, options?: JsonArtifactOptions): ArtifactResponse;
469
+ export declare function textArtifact(body: string, init?: ArtifactResponseInit): ArtifactResponse;
470
+ export declare function csvArtifact(body: string, init?: ArtifactResponseInit): ArtifactResponse;
471
+ export declare function xmlArtifact(body: string, init?: ArtifactResponseInit): ArtifactResponse;
472
+ export declare function buildSite(config: BuildConfig): Promise<BuildResult>;
473
+ export declare function hashValue(value: unknown): string;