@elliots/typical 0.2.0-beta.1 → 0.2.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/README.md +61 -6
- package/dist/src/config.d.ts +12 -0
- package/dist/src/config.js +2 -0
- package/dist/src/config.js.map +1 -1
- package/package.json +2 -2
- package/src/config.ts +14 -0
package/README.md
CHANGED
|
@@ -286,12 +286,57 @@ Create a `typical.json` file in your project root (optional):
|
|
|
286
286
|
|
|
287
287
|
### Options
|
|
288
288
|
|
|
289
|
-
| Option
|
|
290
|
-
|
|
|
291
|
-
| `include`
|
|
292
|
-
| `exclude`
|
|
293
|
-
| `validateFunctions`
|
|
294
|
-
| `validateCasts`
|
|
289
|
+
| Option | Default | Description |
|
|
290
|
+
| ------------------------ | --------------------------------------------------------- | ----------------------------------------------------------------- |
|
|
291
|
+
| `include` | `["**/*.ts", "**/*.tsx"]` | Files to transform |
|
|
292
|
+
| `exclude` | `["node_modules/**", "**/*.d.ts", "dist/**", "build/**"]` | Files to skip |
|
|
293
|
+
| `validateFunctions` | `true` | Validate function parameters and return types |
|
|
294
|
+
| `validateCasts` | `false` | Validate type assertions (`as Type`) |
|
|
295
|
+
| `transformJSONParse` | `true` | Transform `JSON.parse` to validate and filter to typed properties |
|
|
296
|
+
| `transformJSONStringify` | `true` | Transform `JSON.stringify` to only include typed properties |
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## JSON Transformations
|
|
301
|
+
|
|
302
|
+
Typical automatically transforms `JSON.parse` and `JSON.stringify` calls when type information is available.
|
|
303
|
+
|
|
304
|
+
### JSON.parse
|
|
305
|
+
|
|
306
|
+
When you cast the result of `JSON.parse`, Typical validates the parsed data and filters it to only include properties defined in your type:
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
interface User {
|
|
310
|
+
name: string;
|
|
311
|
+
age: number;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Input: '{"name":"Alice","age":30,"password":"secret"}'
|
|
315
|
+
const user = JSON.parse(jsonString) as User;
|
|
316
|
+
// Result: { name: "Alice", age: 30 } - password is filtered out!
|
|
317
|
+
// Throws TypeError if name isn't a string or age isn't a number
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### JSON.stringify
|
|
321
|
+
|
|
322
|
+
When you use a type assertion with `JSON.stringify`, only properties defined in your type are included - preventing accidental data leaks:
|
|
323
|
+
|
|
324
|
+
```ts
|
|
325
|
+
interface PublicUser {
|
|
326
|
+
name: string;
|
|
327
|
+
age: number;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const user = { name: "Alice", age: 30, password: "secret", ssn: "123-45-6789" };
|
|
331
|
+
const json = JSON.stringify(user as PublicUser);
|
|
332
|
+
// Result: '{"name":"Alice","age":30}' - sensitive data excluded!
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Both patterns detect type information from:
|
|
336
|
+
|
|
337
|
+
- Type assertions: `JSON.parse(str) as User` or `JSON.stringify(obj as User)`
|
|
338
|
+
- Variable declarations: `const user: User = JSON.parse(str)`
|
|
339
|
+
- Function return types: `function getUser(): User { return JSON.parse(str) }`
|
|
295
340
|
|
|
296
341
|
---
|
|
297
342
|
|
|
@@ -301,6 +346,16 @@ Typical uses a Go-based compiler that leverages the TypeScript type checker to a
|
|
|
301
346
|
|
|
302
347
|
Types that can't be validated at runtime (like generic type parameters `T`) are skipped. You can still use `any` and `unknown` to opt out of validation.
|
|
303
348
|
|
|
349
|
+
## Compiler Optimizations
|
|
350
|
+
|
|
351
|
+
The generated validation code is optimized for runtime performance:
|
|
352
|
+
|
|
353
|
+
- **Skip redundant validation** - When returning a validated parameter directly, the return validation is skipped (e.g., `return x` where `x: string` was already validated)
|
|
354
|
+
- **Subtype-aware skipping** - If a validated type is assignable to the return type, validation is skipped (e.g., `string` parameter returned as `string | null`)
|
|
355
|
+
- **Property chain tracking** - Accessing properties of validated objects skips re-validation (e.g., `return user.name` when `user: User` was validated)
|
|
356
|
+
- **Type-aware dirty tracking** - Primitives stay validated after being passed to functions (they're copied), but objects are re-validated (they could be mutated)
|
|
357
|
+
- **Union early bail-out** - Union type checks use if-else chains so the first matching type succeeds immediately
|
|
358
|
+
|
|
304
359
|
## Debugging
|
|
305
360
|
|
|
306
361
|
Set `DEBUG=1` for verbose logging:
|
package/dist/src/config.d.ts
CHANGED
|
@@ -43,6 +43,18 @@ export interface TypicalConfig {
|
|
|
43
43
|
* Default: true
|
|
44
44
|
*/
|
|
45
45
|
validateFunctions?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Transform JSON.parse<T>() calls to validate and filter the parsed result
|
|
48
|
+
* to only include properties defined in type T.
|
|
49
|
+
* Default: true
|
|
50
|
+
*/
|
|
51
|
+
transformJSONParse?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Transform JSON.stringify<T>() calls to only stringify properties defined
|
|
54
|
+
* in type T, preventing accidental data leaks.
|
|
55
|
+
* Default: true
|
|
56
|
+
*/
|
|
57
|
+
transformJSONStringify?: boolean;
|
|
46
58
|
/**
|
|
47
59
|
* Source map generation settings.
|
|
48
60
|
* Controls whether and how source maps are generated for transformed code.
|
package/dist/src/config.js
CHANGED
|
@@ -4,6 +4,8 @@ export const defaultConfig = {
|
|
|
4
4
|
reusableValidators: false, // Off by default for accurate source maps (set to true for production)
|
|
5
5
|
validateCasts: false,
|
|
6
6
|
validateFunctions: true,
|
|
7
|
+
transformJSONParse: true,
|
|
8
|
+
transformJSONStringify: true,
|
|
7
9
|
hoistRegex: true,
|
|
8
10
|
ignoreDOMTypes: true,
|
|
9
11
|
debug: {
|
package/dist/src/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elliots/typical",
|
|
3
|
-
"version": "0.2.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Runtime safe TypeScript transformer using typia",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"runtime",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"commander": "14.0.2",
|
|
43
|
-
"@elliots/typical-compiler": "0.2.0
|
|
43
|
+
"@elliots/typical-compiler": "0.2.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/node": "22",
|
package/src/config.ts
CHANGED
|
@@ -45,6 +45,18 @@ export interface TypicalConfig {
|
|
|
45
45
|
* Default: true
|
|
46
46
|
*/
|
|
47
47
|
validateFunctions?: boolean
|
|
48
|
+
/**
|
|
49
|
+
* Transform JSON.parse<T>() calls to validate and filter the parsed result
|
|
50
|
+
* to only include properties defined in type T.
|
|
51
|
+
* Default: true
|
|
52
|
+
*/
|
|
53
|
+
transformJSONParse?: boolean
|
|
54
|
+
/**
|
|
55
|
+
* Transform JSON.stringify<T>() calls to only stringify properties defined
|
|
56
|
+
* in type T, preventing accidental data leaks.
|
|
57
|
+
* Default: true
|
|
58
|
+
*/
|
|
59
|
+
transformJSONStringify?: boolean
|
|
48
60
|
/**
|
|
49
61
|
* Source map generation settings.
|
|
50
62
|
* Controls whether and how source maps are generated for transformed code.
|
|
@@ -71,6 +83,8 @@ export const defaultConfig: TypicalConfig = {
|
|
|
71
83
|
reusableValidators: false, // Off by default for accurate source maps (set to true for production)
|
|
72
84
|
validateCasts: false,
|
|
73
85
|
validateFunctions: true,
|
|
86
|
+
transformJSONParse: true,
|
|
87
|
+
transformJSONStringify: true,
|
|
74
88
|
hoistRegex: true,
|
|
75
89
|
ignoreDOMTypes: true,
|
|
76
90
|
debug: {
|