@timber-js/app 0.2.0-alpha.86 → 0.2.0-alpha.88
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/client/index.d.ts +44 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/link.d.ts +7 -44
- package/dist/client/link.d.ts.map +1 -1
- package/dist/config-types.d.ts +39 -0
- package/dist/config-types.d.ts.map +1 -1
- package/dist/fonts/bundle.d.ts +48 -0
- package/dist/fonts/bundle.d.ts.map +1 -0
- package/dist/fonts/dev-middleware.d.ts +22 -0
- package/dist/fonts/dev-middleware.d.ts.map +1 -0
- package/dist/fonts/pipeline.d.ts +138 -0
- package/dist/fonts/pipeline.d.ts.map +1 -0
- package/dist/fonts/transform.d.ts +72 -0
- package/dist/fonts/transform.d.ts.map +1 -0
- package/dist/fonts/types.d.ts +45 -1
- package/dist/fonts/types.d.ts.map +1 -1
- package/dist/fonts/virtual-modules.d.ts +59 -0
- package/dist/fonts/virtual-modules.d.ts.map +1 -0
- package/dist/index.js +773 -574
- package/dist/index.js.map +1 -1
- package/dist/plugins/dev-error-overlay.d.ts +1 -0
- package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts +16 -83
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/server/action-client.d.ts +8 -0
- package/dist/server/action-client.d.ts.map +1 -1
- package/dist/server/action-handler.d.ts +7 -0
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/index.js +158 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/route-matcher.d.ts +7 -0
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/sensitive-fields.d.ts +74 -0
- package/dist/server/sensitive-fields.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/client/index.ts +77 -1
- package/src/client/link.tsx +15 -65
- package/src/config-types.ts +39 -0
- package/src/fonts/bundle.ts +142 -0
- package/src/fonts/dev-middleware.ts +74 -0
- package/src/fonts/pipeline.ts +275 -0
- package/src/fonts/transform.ts +353 -0
- package/src/fonts/types.ts +50 -1
- package/src/fonts/virtual-modules.ts +159 -0
- package/src/plugins/dev-error-overlay.ts +47 -3
- package/src/plugins/entries.ts +37 -0
- package/src/plugins/fonts.ts +102 -704
- package/src/plugins/routing.ts +6 -5
- package/src/server/action-client.ts +34 -4
- package/src/server/action-handler.ts +32 -2
- package/src/server/route-matcher.ts +7 -0
- package/src/server/rsc-entry/index.ts +19 -3
- package/src/server/sensitive-fields.ts +230 -0
|
@@ -70,6 +70,7 @@ export interface RscDebugComponentInfo {
|
|
|
70
70
|
* Returns an empty string if no components are provided.
|
|
71
71
|
*/
|
|
72
72
|
export declare function formatRscDebugContext(components: RscDebugComponentInfo[]): string;
|
|
73
|
+
export declare function calculateModuleRunnerOffset(): number;
|
|
73
74
|
/**
|
|
74
75
|
* Source-map an error's stack trace using the Vite dev server's module graph.
|
|
75
76
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-error-overlay.d.ts","sourceRoot":"","sources":["../../src/plugins/dev-error-overlay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,MAAM,CAAC;AAoC1D,0DAA0D;AAC1D,MAAM,MAAM,UAAU,GAClB,kBAAkB,GAClB,OAAO,GACP,YAAY,GACZ,QAAQ,GACR,QAAQ,GACR,SAAS,CAAC;AAEd,kCAAkC;AAClC,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAOnD,CAAC;AAIF,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,WAAW,GAAG,UAAU,CAAC;AAEzD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,CAU/E;AAID;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAUnE;AAID,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAqB5F;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,GAAG,UAAU,CAehF;AAOD,OAAO,EAAE,mBAAmB,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACtF,eAAO,MAAM,mBAAmB,6BAAuB,CAAC;AAIxD;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAiCjF;
|
|
1
|
+
{"version":3,"file":"dev-error-overlay.d.ts","sourceRoot":"","sources":["../../src/plugins/dev-error-overlay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,MAAM,CAAC;AAoC1D,0DAA0D;AAC1D,MAAM,MAAM,UAAU,GAClB,kBAAkB,GAClB,OAAO,GACP,YAAY,GACZ,QAAQ,GACR,QAAQ,GACR,SAAS,CAAC;AAEd,kCAAkC;AAClC,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAOnD,CAAC;AAIF,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,WAAW,GAAG,UAAU,CAAC;AAEzD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,CAU/E;AAID;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAUnE;AAID,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAqB5F;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,GAAG,UAAU,CAehF;AAOD,OAAO,EAAE,mBAAmB,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACtF,eAAO,MAAM,mBAAmB,6BAAuB,CAAC;AAIxD;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAiCjF;AAkBD,wBAAgB,2BAA2B,IAAI,MAAM,CAyBpD;AAmHD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,IAAI,CAMhG;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,MAAM,EACnB,kBAAkB,CAAC,EAAE,qBAAqB,EAAE,GAC3C,IAAI,CA0CN"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entries.d.ts","sourceRoot":"","sources":["../../src/plugins/entries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAInC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"entries.d.ts","sourceRoot":"","sources":["../../src/plugins/entries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAInC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AA0J1D;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUrE;AAED;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAAC,mBAAmB,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAwBxF;AAiDD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAkFxD"}
|
package/dist/plugins/fonts.d.ts
CHANGED
|
@@ -1,94 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* timber-fonts — Vite sub-plugin for build-time font processing.
|
|
2
|
+
* timber-fonts — Vite sub-plugin shell for build-time font processing.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* - @font-face CSS generation and scoped class output
|
|
8
|
-
* - Size-adjusted fallback font generation
|
|
4
|
+
* This file is intentionally thin: it wires the Vite plugin hooks to the
|
|
5
|
+
* pipeline + per-concern modules under `../fonts/`. All real logic lives
|
|
6
|
+
* in:
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
8
|
+
* - `../fonts/pipeline.ts` — `FontPipeline` (state, mutators)
|
|
9
|
+
* - `../fonts/transform.ts` — transform-hook logic, parsing helpers
|
|
10
|
+
* - `../fonts/dev-middleware.ts` — dev font binary server
|
|
11
|
+
* - `../fonts/virtual-modules.ts` — virtual module ID constants + source
|
|
12
|
+
*
|
|
13
|
+
* The public exports below are the stable API that the test suite and
|
|
14
|
+
* other parts of the framework import. Anything new should be added to
|
|
15
|
+
* one of the per-concern modules and re-exported here only if external
|
|
16
|
+
* consumers need it.
|
|
13
17
|
*
|
|
14
18
|
* Design doc: 24-fonts.md
|
|
15
19
|
*/
|
|
16
20
|
import type { Plugin } from 'vite';
|
|
17
21
|
import type { PluginContext } from '../plugin-context.js';
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
* Registry of fonts extracted during transform.
|
|
22
|
-
* Keyed by a unique font ID derived from family + config.
|
|
23
|
-
*/
|
|
24
|
-
export type FontRegistry = Map<string, ExtractedFont>;
|
|
25
|
-
/**
|
|
26
|
-
* Generate a unique font ID from family + config hash.
|
|
27
|
-
*/
|
|
28
|
-
export declare function generateFontId(family: string, config: GoogleFontConfig): string;
|
|
29
|
-
/**
|
|
30
|
-
* Extract static font config from a font function call in source code.
|
|
31
|
-
*
|
|
32
|
-
* Parses patterns like:
|
|
33
|
-
* const inter = Inter({ subsets: ['latin'], weight: '400', display: 'swap', variable: '--font-sans' })
|
|
34
|
-
*
|
|
35
|
-
* Returns null if the call cannot be statically analyzed.
|
|
36
|
-
*
|
|
37
|
-
* Uses acorn AST parsing for robust handling of comments, trailing commas,
|
|
38
|
-
* and multi-line configs.
|
|
39
|
-
*/
|
|
40
|
-
export declare function extractFontConfig(callSource: string): GoogleFontConfig | null;
|
|
41
|
-
/**
|
|
42
|
-
* Detect if a source file contains dynamic/computed font function calls
|
|
43
|
-
* that cannot be statically analyzed.
|
|
44
|
-
*
|
|
45
|
-
* Returns the offending expression if found, null if all calls are static.
|
|
46
|
-
*
|
|
47
|
-
* Uses acorn AST parsing for accurate detection.
|
|
48
|
-
*/
|
|
49
|
-
export declare function detectDynamicFontCall(source: string, importedNames: string[]): string | null;
|
|
50
|
-
/**
|
|
51
|
-
* Parse import specifiers from a source file that imports from
|
|
52
|
-
* `@timber/fonts/google` or `next/font/google`.
|
|
53
|
-
*
|
|
54
|
-
* Returns the list of imported font names (e.g. ['Inter', 'JetBrains_Mono']).
|
|
55
|
-
*/
|
|
56
|
-
export declare function parseGoogleFontImports(source: string): string[];
|
|
57
|
-
/**
|
|
58
|
-
* Parse the original (remote) font family names from imports.
|
|
59
|
-
*
|
|
60
|
-
* Returns a map of local name → family name.
|
|
61
|
-
* e.g. { Inter: 'Inter', JetBrains_Mono: 'JetBrains Mono' }
|
|
62
|
-
*/
|
|
63
|
-
export declare function parseGoogleFontFamilies(source: string): Map<string, string>;
|
|
64
|
-
/**
|
|
65
|
-
* Generate CSS for a single extracted font.
|
|
66
|
-
*
|
|
67
|
-
* Includes @font-face rules (for local and Google fonts), fallback @font-face,
|
|
68
|
-
* and the scoped class rule.
|
|
69
|
-
*
|
|
70
|
-
* For Google fonts, pass the resolved FontFaceDescriptor[] from either
|
|
71
|
-
* `generateProductionFontFaces()` (production) or `resolveDevFontFaces()` (dev).
|
|
72
|
-
*/
|
|
73
|
-
export declare function generateFontCss(font: ExtractedFont, googleFaces?: FontFaceDescriptor[]): string;
|
|
74
|
-
/**
|
|
75
|
-
* Generate the CSS output for all extracted fonts.
|
|
76
|
-
*
|
|
77
|
-
* Includes @font-face rules for local and Google fonts, fallback @font-face
|
|
78
|
-
* rules, and scoped classes.
|
|
79
|
-
*
|
|
80
|
-
* `googleFontFacesMap` provides pre-resolved FontFaceDescriptor[] for each
|
|
81
|
-
* Google font ID (keyed by ExtractedFont.id).
|
|
82
|
-
*/
|
|
83
|
-
export declare function generateAllFontCss(registry: FontRegistry, googleFontFacesMap?: Map<string, FontFaceDescriptor[]>): string;
|
|
84
|
-
/**
|
|
85
|
-
* Parse the local name used for the default import of `@timber/fonts/local`.
|
|
86
|
-
*
|
|
87
|
-
* Handles:
|
|
88
|
-
* import localFont from '@timber/fonts/local'
|
|
89
|
-
* import myLoader from '@timber/fonts/local'
|
|
90
|
-
*/
|
|
91
|
-
export declare function parseLocalFontImportName(source: string): string | null;
|
|
22
|
+
export { FontPipeline, pruneRegistryEntries, type FontRegistry } from '../fonts/pipeline.js';
|
|
23
|
+
export { generateFontId, extractFontConfig, detectDynamicFontCall, parseGoogleFontImports, parseGoogleFontFamilies, parseLocalFontImportName, } from '../fonts/transform.js';
|
|
24
|
+
export { generateFontCss, generateAllFontCss } from '../fonts/virtual-modules.js';
|
|
92
25
|
/**
|
|
93
26
|
* Create the timber-fonts Vite plugin.
|
|
94
27
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fonts.d.ts","sourceRoot":"","sources":["../../src/plugins/fonts.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"fonts.d.ts","sourceRoot":"","sources":["../../src/plugins/fonts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,MAAM,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AA4B1D,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC7F,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAElF;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAuItD"}
|
|
@@ -116,6 +116,13 @@ interface ActionClientConfig<TCtx> {
|
|
|
116
116
|
middleware?: ActionMiddleware<TCtx> | ActionMiddleware<Record<string, unknown>>[];
|
|
117
117
|
/** Max file size in bytes. Files exceeding this are rejected with validation errors. */
|
|
118
118
|
fileSizeLimit?: number;
|
|
119
|
+
/**
|
|
120
|
+
* Override the sensitive-field deny-list for this action client.
|
|
121
|
+
* See `SensitiveFieldsOption` in `./sensitive-fields.ts`. Per-action config
|
|
122
|
+
* takes precedence over the global `forms.stripSensitiveFields` option in
|
|
123
|
+
* `timber.config.ts`. See design/08-forms-and-actions.md and TIM-816.
|
|
124
|
+
*/
|
|
125
|
+
stripSensitiveFields?: SensitiveFieldsOption;
|
|
119
126
|
}
|
|
120
127
|
/** Intermediate builder returned by createActionClient(). */
|
|
121
128
|
export interface ActionBuilder<TCtx> {
|
|
@@ -165,6 +172,7 @@ export type ActionFn<TData = unknown, TInput = unknown> = {
|
|
|
165
172
|
/** React useActionState: action(prevState, formData) */
|
|
166
173
|
(prevState: ActionResult<TData> | null, formData: FormData): Promise<ActionResult<TData>>;
|
|
167
174
|
};
|
|
175
|
+
import { type SensitiveFieldsOption } from './sensitive-fields.js';
|
|
168
176
|
/**
|
|
169
177
|
* Wrap unexpected errors into a safe server error result.
|
|
170
178
|
* ActionError → typed result. Other errors → INTERNAL_ERROR (no leak).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-client.d.ts","sourceRoot":"","sources":["../../src/server/action-client.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"action-client.d.ts","sourceRoot":"","sources":["../../src/server/action-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { type CsrfConfig } from './csrf.js';
|
|
16
16
|
import { type RevalidateRenderer } from './actions.js';
|
|
17
17
|
import { type BodyLimitsConfig } from './body-limits.js';
|
|
18
|
+
import { type SensitiveFieldsOption } from './sensitive-fields.js';
|
|
18
19
|
import type { FormFlashData } from './form-flash.js';
|
|
19
20
|
/** Configuration for the action handler. */
|
|
20
21
|
export interface ActionDispatchConfig {
|
|
@@ -24,6 +25,12 @@ export interface ActionDispatchConfig {
|
|
|
24
25
|
revalidateRenderer?: RevalidateRenderer;
|
|
25
26
|
/** Body size limits (from timber.config.ts). */
|
|
26
27
|
bodyLimits?: BodyLimitsConfig;
|
|
28
|
+
/**
|
|
29
|
+
* Override the sensitive-field deny-list for the no-JS form POST path.
|
|
30
|
+
* Defaults to the global `forms.stripSensitiveFields` from `timber.config.ts`.
|
|
31
|
+
* See `SensitiveFieldsOption` in `./sensitive-fields.ts` and TIM-816.
|
|
32
|
+
*/
|
|
33
|
+
sensitiveFields?: SensitiveFieldsOption;
|
|
27
34
|
}
|
|
28
35
|
/**
|
|
29
36
|
* Check if a request is a server action invocation.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-handler.d.ts","sourceRoot":"","sources":["../../src/server/action-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAOtE,OAAO,EAAwC,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAE/F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAMrD,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,0BAA0B;IAC1B,IAAI,EAAE,UAAU,CAAC;IACjB,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,gDAAgD;IAChD,UAAU,CAAC,EAAE,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"action-handler.d.ts","sourceRoot":"","sources":["../../src/server/action-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAOtE,OAAO,EAAwC,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAE/F,OAAO,EAIL,KAAK,qBAAqB,EAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAMrD,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,0BAA0B;IAC1B,IAAI,EAAE,UAAU,CAAC;IACjB,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,gDAAgD;IAChD,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,qBAAqB,CAAC;CACzC;AAQD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAarD;AAID,iGAAiG;AACjG,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,aAAa,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,QAAQ,GAAG,YAAY,GAAG,IAAI,CAAC,CAuDzC"}
|
package/dist/server/index.js
CHANGED
|
@@ -146,6 +146,156 @@ var coerce = {
|
|
|
146
146
|
}
|
|
147
147
|
};
|
|
148
148
|
//#endregion
|
|
149
|
+
//#region src/server/sensitive-fields.ts
|
|
150
|
+
/**
|
|
151
|
+
* Sensitive field stripping — removes password/token/CVV-style fields
|
|
152
|
+
* from form values before they are echoed back to the client as
|
|
153
|
+
* `submittedValues` for form repopulation.
|
|
154
|
+
*
|
|
155
|
+
* Applied to both action paths:
|
|
156
|
+
* - With-JS action path: `createActionClient()` in `action-client.ts`
|
|
157
|
+
* - No-JS form POST path: `handleFormAction()` in `action-handler.ts`
|
|
158
|
+
*
|
|
159
|
+
* Why: on a validation failure, timber echoes submitted form values back so
|
|
160
|
+
* the user doesn't have to re-type everything. Without filtering, plaintext
|
|
161
|
+
* passwords / credit-card numbers / TOTP codes would travel through the RSC
|
|
162
|
+
* stream (with-JS) or land in the HTML as `defaultValue` attributes (no-JS)
|
|
163
|
+
* — ending up in browser history, proxy logs, disk caches, and the
|
|
164
|
+
* back-forward cache.
|
|
165
|
+
*
|
|
166
|
+
* Safe by default: the built-in deny-list is applied unconditionally unless
|
|
167
|
+
* the user explicitly opts out via `forms.stripSensitiveFields: false` in
|
|
168
|
+
* `timber.config.ts` or per-action via `createActionClient({ stripSensitiveFields: false })`.
|
|
169
|
+
*
|
|
170
|
+
* See design/08-forms-and-actions.md §"Validation errors"
|
|
171
|
+
* See design/13-security.md §"Sensitive field stripping"
|
|
172
|
+
* See TIM-816
|
|
173
|
+
*/
|
|
174
|
+
/**
|
|
175
|
+
* Substring patterns matched against the normalized field name.
|
|
176
|
+
* Normalization = lowercase + strip `_` and `-`.
|
|
177
|
+
*
|
|
178
|
+
* Any field whose normalized name *contains* one of these strings is
|
|
179
|
+
* considered sensitive. Entries like `currentPassword`, `passwordConfirmation`,
|
|
180
|
+
* and `user.password` all match via the `password` substring.
|
|
181
|
+
*/
|
|
182
|
+
var BUILTIN_SUBSTRING_PATTERNS = [
|
|
183
|
+
"password",
|
|
184
|
+
"passwd",
|
|
185
|
+
"pwd",
|
|
186
|
+
"secret",
|
|
187
|
+
"apikey",
|
|
188
|
+
"accesstoken",
|
|
189
|
+
"refreshtoken",
|
|
190
|
+
"cvv",
|
|
191
|
+
"cvc",
|
|
192
|
+
"cardnumber",
|
|
193
|
+
"cardcvc",
|
|
194
|
+
"ssn",
|
|
195
|
+
"socialsecuritynumber",
|
|
196
|
+
"otp",
|
|
197
|
+
"totp",
|
|
198
|
+
"mfacode",
|
|
199
|
+
"twofactorcode",
|
|
200
|
+
"privatekey"
|
|
201
|
+
];
|
|
202
|
+
/**
|
|
203
|
+
* Exact matches against the normalized field name. These are field names that
|
|
204
|
+
* are too short or too common to substring-match safely. e.g. `token` alone
|
|
205
|
+
* would match `csrfToken`, which is not sensitive — so `token` is exact-only,
|
|
206
|
+
* while legitimate token fields are covered by `accesstoken` / `refreshtoken`.
|
|
207
|
+
*/
|
|
208
|
+
var BUILTIN_EXACT_PATTERNS = ["token"];
|
|
209
|
+
/**
|
|
210
|
+
* Normalize a field name for deny-list comparison.
|
|
211
|
+
* Lowercases the string and strips `_` and `-` so camelCase, snake_case, and
|
|
212
|
+
* kebab-case variants all compare equal (`api_key` / `apiKey` / `api-key` →
|
|
213
|
+
* `apikey`).
|
|
214
|
+
*/
|
|
215
|
+
function normalize(name) {
|
|
216
|
+
let out = "";
|
|
217
|
+
for (let i = 0; i < name.length; i++) {
|
|
218
|
+
const ch = name.charCodeAt(i);
|
|
219
|
+
if (ch === 95 || ch === 45) continue;
|
|
220
|
+
if (ch >= 65 && ch <= 90) out += String.fromCharCode(ch + 32);
|
|
221
|
+
else out += name[i];
|
|
222
|
+
}
|
|
223
|
+
return out;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Check whether a name matches the built-in deny-list (with optional extras).
|
|
227
|
+
* Extras are merged into the substring pattern list after normalization.
|
|
228
|
+
*/
|
|
229
|
+
function isBuiltinSensitive(name, extras) {
|
|
230
|
+
const normalized = normalize(name);
|
|
231
|
+
if (BUILTIN_EXACT_PATTERNS.includes(normalized)) return true;
|
|
232
|
+
for (const pattern of BUILTIN_SUBSTRING_PATTERNS) if (normalized.includes(pattern)) return true;
|
|
233
|
+
if (extras && extras.length > 0) for (const extra of extras) {
|
|
234
|
+
const normExtra = normalize(extra);
|
|
235
|
+
if (normExtra.length === 0) continue;
|
|
236
|
+
if (normalized.includes(normExtra)) return true;
|
|
237
|
+
}
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Resolve a `SensitiveFieldsOption` into a concrete predicate.
|
|
242
|
+
* Precedence: per-action > global > built-in default.
|
|
243
|
+
*
|
|
244
|
+
* - Per-action `undefined` → fall back to global.
|
|
245
|
+
* - Global `undefined` → use built-in list.
|
|
246
|
+
* - Either level set to `false` → disable stripping entirely (returns `null`).
|
|
247
|
+
* - `true` → built-in list.
|
|
248
|
+
* - `string[]` → built-in ∪ extras.
|
|
249
|
+
* - function → custom, replaces the built-in list entirely.
|
|
250
|
+
*/
|
|
251
|
+
function resolveSensitivePredicate(perAction, global) {
|
|
252
|
+
const chosen = perAction !== void 0 ? perAction : global;
|
|
253
|
+
if (chosen === false) return null;
|
|
254
|
+
if (chosen === void 0 || chosen === true) return (name) => isBuiltinSensitive(name);
|
|
255
|
+
if (typeof chosen === "function") return chosen;
|
|
256
|
+
const extras = chosen;
|
|
257
|
+
return (name) => isBuiltinSensitive(name, extras);
|
|
258
|
+
}
|
|
259
|
+
var globalConfig;
|
|
260
|
+
/** Read the global `forms.stripSensitiveFields` config. */
|
|
261
|
+
function getGlobalSensitiveFieldsConfig() {
|
|
262
|
+
return globalConfig;
|
|
263
|
+
}
|
|
264
|
+
var warnedFields = /* @__PURE__ */ new Set();
|
|
265
|
+
function warnStripped(name) {
|
|
266
|
+
if (!isDebug()) return;
|
|
267
|
+
if (warnedFields.has(name)) return;
|
|
268
|
+
warnedFields.add(name);
|
|
269
|
+
console.warn(`[timber] stripped sensitive field "${name}" from submittedValues. Override via forms.stripSensitiveFields in timber.config.ts.`);
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Walk an object (recursively) and return a copy with every key matching
|
|
273
|
+
* `predicate` removed. Nested objects like `{ user: { password: '...' } }`
|
|
274
|
+
* are handled — `user.password` is stripped while other `user.*` fields remain.
|
|
275
|
+
*
|
|
276
|
+
* - Arrays are walked element-wise (object entries inside arrays are cleaned).
|
|
277
|
+
* - Non-plain values (strings, numbers, Files, Dates, etc.) are returned as-is.
|
|
278
|
+
* - When a stripped key is encountered, it is omitted from the result entirely
|
|
279
|
+
* — we do NOT set it to an empty string, because that would overwrite a
|
|
280
|
+
* valid `defaultValue` the form author might have set.
|
|
281
|
+
*/
|
|
282
|
+
function stripSensitiveFields(value, predicate) {
|
|
283
|
+
if (predicate === null) return value;
|
|
284
|
+
if (value === null || value === void 0) return value;
|
|
285
|
+
if (typeof value !== "object") return value;
|
|
286
|
+
if (value instanceof File || value instanceof Date) return value;
|
|
287
|
+
if (Array.isArray(value)) return value.map((item) => stripSensitiveFields(item, predicate));
|
|
288
|
+
const result = {};
|
|
289
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
290
|
+
if (predicate(key)) {
|
|
291
|
+
warnStripped(key);
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
result[key] = stripSensitiveFields(nested, predicate);
|
|
295
|
+
}
|
|
296
|
+
return result;
|
|
297
|
+
}
|
|
298
|
+
//#endregion
|
|
149
299
|
//#region src/server/action-client.ts
|
|
150
300
|
/**
|
|
151
301
|
* createActionClient — typed middleware and schema validation for server actions.
|
|
@@ -277,14 +427,20 @@ function createActionClient(config = {}) {
|
|
|
277
427
|
if (args.length === 2 && args[1] instanceof FormData) rawInput = schema ? parseFormData(args[1]) : args[1];
|
|
278
428
|
else if (args.length === 1 && args[0] instanceof FormData) rawInput = schema ? parseFormData(args[0]) : args[0];
|
|
279
429
|
else rawInput = args[0];
|
|
430
|
+
const sensitivePredicate = resolveSensitivePredicate(config.stripSensitiveFields, getGlobalSensitiveFieldsConfig());
|
|
431
|
+
const buildSubmittedValues = () => {
|
|
432
|
+
const withoutFiles = stripFiles(rawInput);
|
|
433
|
+
if (withoutFiles === void 0) return void 0;
|
|
434
|
+
return stripSensitiveFields(withoutFiles, sensitivePredicate);
|
|
435
|
+
};
|
|
280
436
|
if (config.fileSizeLimit !== void 0 && rawInput && typeof rawInput === "object") {
|
|
281
437
|
const fileSizeErrors = validateFileSizes(rawInput, config.fileSizeLimit);
|
|
282
438
|
if (fileSizeErrors) return {
|
|
283
439
|
validationErrors: fileSizeErrors,
|
|
284
|
-
submittedValues:
|
|
440
|
+
submittedValues: buildSubmittedValues()
|
|
285
441
|
};
|
|
286
442
|
}
|
|
287
|
-
const submittedValues = schema ?
|
|
443
|
+
const submittedValues = schema ? buildSubmittedValues() : void 0;
|
|
288
444
|
let input;
|
|
289
445
|
if (schema) if (isStandardSchema(schema)) {
|
|
290
446
|
const result = schema["~standard"].validate(rawInput);
|