baobox 0.1.0 → 0.1.1-rc.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/README.md +184 -90
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +314 -0
- package/dist/cli/index.js.map +14 -0
- package/dist/cli/migrate.d.ts +23 -0
- package/dist/cli/migrate.d.ts.map +1 -0
- package/dist/cli/report.d.ts +4 -0
- package/dist/cli/report.d.ts.map +1 -0
- package/dist/cli/transforms/api-calls.d.ts +9 -0
- package/dist/cli/transforms/api-calls.d.ts.map +1 -0
- package/dist/cli/transforms/imports.d.ts +8 -0
- package/dist/cli/transforms/imports.d.ts.map +1 -0
- package/dist/compile/bun-fast-path.d.ts +1 -1
- package/dist/compile/bun-fast-path.d.ts.map +1 -1
- package/dist/compile/index.js +652 -505
- package/dist/compile/index.js.map +24 -24
- package/dist/elysia/index.d.ts +95 -0
- package/dist/elysia/index.d.ts.map +1 -0
- package/dist/elysia/index.js +7473 -0
- package/dist/elysia/index.js.map +91 -0
- package/dist/elysia/symbols.d.ts +4 -0
- package/dist/elysia/symbols.d.ts.map +1 -0
- package/dist/error/collector/collections-basic.d.ts.map +1 -1
- package/dist/error/index.js +387 -288
- package/dist/error/index.js.map +15 -15
- package/dist/format/format.d.ts.map +1 -1
- package/dist/format/index.js +263 -89
- package/dist/format/index.js.map +9 -8
- package/dist/guard/index.js +2 -1
- package/dist/guard/index.js.map +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2321 -2070
- package/dist/index.js.map +46 -45
- package/dist/locale/index.js +2 -1
- package/dist/locale/index.js.map +2 -2
- package/dist/schema/core.d.ts.map +1 -1
- package/dist/schema/emitter.d.ts.map +1 -1
- package/dist/schema/engine.d.ts +2 -1
- package/dist/schema/engine.d.ts.map +1 -1
- package/dist/schema/index.js +344 -255
- package/dist/schema/index.js.map +13 -13
- package/dist/script/index.d.ts.map +1 -1
- package/dist/script/index.js +437 -336
- package/dist/script/index.js.map +20 -20
- package/dist/script/literals.d.ts.map +1 -1
- package/dist/shared/bytes.d.ts.map +1 -1
- package/dist/shared/format-constants.d.ts +25 -0
- package/dist/shared/format-constants.d.ts.map +1 -1
- package/dist/shared/format-validators.d.ts +2 -2
- package/dist/shared/format-validators.d.ts.map +1 -1
- package/dist/shared/object-utils.d.ts.map +1 -1
- package/dist/shared/runtime-guards.d.ts +20 -0
- package/dist/shared/runtime-guards.d.ts.map +1 -1
- package/dist/shared/schema-access.d.ts +1 -1
- package/dist/shared/schema-access.d.ts.map +1 -1
- package/dist/shared/url-like.d.ts +16 -0
- package/dist/shared/url-like.d.ts.map +1 -0
- package/dist/shared/utils.d.ts +1 -1
- package/dist/shared/utils.d.ts.map +1 -1
- package/dist/shared/utils.js +255 -73
- package/dist/shared/utils.js.map +8 -7
- package/dist/standard/index.d.ts +2 -1
- package/dist/standard/index.d.ts.map +1 -1
- package/dist/standard/index.js +546 -422
- package/dist/standard/index.js.map +22 -22
- package/dist/system/index.js +364 -152
- package/dist/system/index.js.map +12 -11
- package/dist/system/system.d.ts.map +1 -1
- package/dist/type/codec-builtins.d.ts +3 -1
- package/dist/type/codec-builtins.d.ts.map +1 -1
- package/dist/type/containers-types.d.ts +7 -0
- package/dist/type/containers-types.d.ts.map +1 -1
- package/dist/type/containers.d.ts +2 -1
- package/dist/type/containers.d.ts.map +1 -1
- package/dist/type/extensions.d.ts +1 -0
- package/dist/type/extensions.d.ts.map +1 -1
- package/dist/type/index.d.ts +2 -1
- package/dist/type/index.d.ts.map +1 -1
- package/dist/type/index.js +409 -315
- package/dist/type/index.js.map +18 -18
- package/dist/type/instantiation.d.ts.map +1 -1
- package/dist/type/primitives.d.ts.map +1 -1
- package/dist/type/root-helpers.d.ts.map +1 -1
- package/dist/type/root-shared.d.ts +1 -1
- package/dist/type/root-shared.d.ts.map +1 -1
- package/dist/type/static-types.d.ts +23 -4
- package/dist/type/static-types.d.ts.map +1 -1
- package/dist/type/uint8array-codec.d.ts +8 -1
- package/dist/type/uint8array-codec.d.ts.map +1 -1
- package/dist/typebox.d.ts +3 -0
- package/dist/typebox.d.ts.map +1 -1
- package/dist/typebox.js +3749 -386
- package/dist/typebox.js.map +58 -20
- package/dist/value/check.d.ts.map +1 -1
- package/dist/value/clean.d.ts.map +1 -1
- package/dist/value/convert.d.ts.map +1 -1
- package/dist/value/create.d.ts.map +1 -1
- package/dist/value/decode.d.ts.map +1 -1
- package/dist/value/default.d.ts.map +1 -1
- package/dist/value/diff.d.ts.map +1 -1
- package/dist/value/encode.d.ts.map +1 -1
- package/dist/value/equal.d.ts.map +1 -1
- package/dist/value/errors-compat.d.ts +54 -0
- package/dist/value/errors-compat.d.ts.map +1 -0
- package/dist/value/has-codec.d.ts.map +1 -1
- package/dist/value/hash.d.ts +0 -1
- package/dist/value/hash.d.ts.map +1 -1
- package/dist/value/index.d.ts +5 -0
- package/dist/value/index.d.ts.map +1 -1
- package/dist/value/index.js +792 -551
- package/dist/value/index.js.map +30 -29
- package/dist/value/mutate.d.ts.map +1 -1
- package/dist/value/patch.d.ts.map +1 -1
- package/dist/value/repair.d.ts.map +1 -1
- package/docs/package-contract.md +9 -1
- package/package.json +19 -5
- package/src/cli/index.ts +75 -0
- package/src/cli/migrate.ts +138 -0
- package/src/cli/report.ts +56 -0
- package/src/cli/transforms/api-calls.ts +76 -0
- package/src/cli/transforms/imports.ts +32 -0
- package/src/compile/bun-fast-path.ts +312 -0
- package/src/compile/emit.ts +166 -0
- package/src/compile/index.ts +317 -0
- package/src/elysia/index.ts +253 -0
- package/src/elysia/symbols.ts +3 -0
- package/src/error/catalog-types.ts +72 -0
- package/src/error/collector/advanced.ts +272 -0
- package/src/error/collector/collections-basic.ts +193 -0
- package/src/error/collector/collections-derived.ts +93 -0
- package/src/error/collector/collections-parameters.ts +74 -0
- package/src/error/collector/collections.ts +27 -0
- package/src/error/collector/primitives.ts +238 -0
- package/src/error/collector/shared.ts +15 -0
- package/src/error/collector.ts +28 -0
- package/src/error/errors.ts +53 -0
- package/src/error/index.ts +32 -0
- package/src/error/locales/de.ts +50 -0
- package/src/error/locales/en.ts +50 -0
- package/src/error/locales/es.ts +50 -0
- package/src/error/locales/fr.ts +50 -0
- package/src/error/locales/ja.ts +50 -0
- package/src/error/locales/ko.ts +50 -0
- package/src/error/locales/pt.ts +50 -0
- package/src/error/locales/shared.ts +9 -0
- package/src/error/locales/zh.ts +80 -0
- package/src/error/messages.ts +45 -0
- package/src/format/format.ts +132 -0
- package/src/format/index.ts +6 -0
- package/src/guard/guard.ts +274 -0
- package/src/guard/index.ts +8 -0
- package/src/index.ts +86 -0
- package/src/locale/index.ts +99 -0
- package/src/schema/build.ts +77 -0
- package/src/schema/check.ts +12 -0
- package/src/schema/compile.ts +47 -0
- package/src/schema/core-keywords.ts +272 -0
- package/src/schema/core.ts +112 -0
- package/src/schema/emitter-advanced.ts +22 -0
- package/src/schema/emitter-base.ts +91 -0
- package/src/schema/emitter-derived.ts +95 -0
- package/src/schema/emitter-reference.ts +66 -0
- package/src/schema/emitter-types.ts +10 -0
- package/src/schema/emitter-wrapper.ts +79 -0
- package/src/schema/emitter.ts +235 -0
- package/src/schema/engine.ts +240 -0
- package/src/schema/error-collector.ts +133 -0
- package/src/schema/errors.ts +14 -0
- package/src/schema/index.ts +5 -0
- package/src/schema/parse.ts +44 -0
- package/src/schema/pointer.ts +92 -0
- package/src/schema/predicates.ts +75 -0
- package/src/schema/resolve.ts +93 -0
- package/src/schema/runtime-keywords.ts +162 -0
- package/src/schema/schema.ts +13 -0
- package/src/schema/shared.ts +141 -0
- package/src/script/generic.ts +86 -0
- package/src/script/index.ts +125 -0
- package/src/script/literals.ts +72 -0
- package/src/script/shared.ts +94 -0
- package/src/shared/bytes.ts +74 -0
- package/src/shared/format-constants.ts +61 -0
- package/src/shared/format-validators.ts +133 -0
- package/src/shared/locale.ts +43 -0
- package/src/shared/object-utils.ts +159 -0
- package/src/shared/regex-json.ts +290 -0
- package/src/shared/registries.ts +83 -0
- package/src/shared/runtime-context.ts +196 -0
- package/src/shared/runtime-guards.ts +77 -0
- package/src/shared/schema-access.ts +149 -0
- package/src/shared/url-like.ts +15 -0
- package/src/shared/utils.ts +73 -0
- package/src/standard/index.ts +211 -0
- package/src/system/index.ts +6 -0
- package/src/system/system.ts +115 -0
- package/src/type/actions.ts +214 -0
- package/src/type/base-types.ts +5 -0
- package/src/type/codec-builtins.ts +31 -0
- package/src/type/combinator-core.ts +129 -0
- package/src/type/combinator-functions.ts +49 -0
- package/src/type/combinator-objects.ts +155 -0
- package/src/type/combinators.ts +34 -0
- package/src/type/composite-types.ts +46 -0
- package/src/type/containers-types.ts +65 -0
- package/src/type/containers.ts +87 -0
- package/src/type/extends.ts +156 -0
- package/src/type/extensions.ts +246 -0
- package/src/type/guards.ts +92 -0
- package/src/type/index.ts +249 -0
- package/src/type/instantiation.ts +307 -0
- package/src/type/kind.ts +75 -0
- package/src/type/narrow-types.ts +26 -0
- package/src/type/primitives-types.ts +116 -0
- package/src/type/primitives.ts +283 -0
- package/src/type/root-constants.ts +169 -0
- package/src/type/root-cyclic.ts +158 -0
- package/src/type/root-deferred.ts +77 -0
- package/src/type/root-guards.ts +91 -0
- package/src/type/root-helpers.ts +233 -0
- package/src/type/root-instantiate.ts +268 -0
- package/src/type/root-shared.ts +59 -0
- package/src/type/root-template.ts +206 -0
- package/src/type/schema.ts +81 -0
- package/src/type/static-const-types.ts +177 -0
- package/src/type/static-shared-types.ts +84 -0
- package/src/type/static-types.ts +259 -0
- package/src/type/string-action-types.ts +28 -0
- package/src/type/transform-types.ts +68 -0
- package/src/type/uint8array-codec.ts +55 -0
- package/src/type/wrapper-types.ts +89 -0
- package/src/typebox.ts +5 -0
- package/src/value/assert.ts +19 -0
- package/src/value/check-collections-derived.ts +198 -0
- package/src/value/check-collections.ts +130 -0
- package/src/value/check-extensions.ts +66 -0
- package/src/value/check-primitives.ts +132 -0
- package/src/value/check.ts +67 -0
- package/src/value/clean.ts +134 -0
- package/src/value/clone.ts +10 -0
- package/src/value/convert.ts +193 -0
- package/src/value/create.ts +167 -0
- package/src/value/decode.ts +146 -0
- package/src/value/default.ts +119 -0
- package/src/value/diff.ts +68 -0
- package/src/value/encode.ts +137 -0
- package/src/value/equal.ts +42 -0
- package/src/value/errors-compat.ts +126 -0
- package/src/value/has-codec.ts +61 -0
- package/src/value/hash.ts +97 -0
- package/src/value/index.ts +154 -0
- package/src/value/mutate.ts +21 -0
- package/src/value/parse.ts +55 -0
- package/src/value/patch.ts +55 -0
- package/src/value/pipeline.ts +15 -0
- package/src/value/pointer.ts +169 -0
- package/src/value/repair.ts +183 -0
- package/src/value/result.ts +55 -0
package/README.md
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
# Baobox
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/d4551/baobox/actions/workflows/publish.yml)
|
|
4
|
+
[](https://github.com/d4551/baobox)
|
|
5
|
+
[](https://bun.sh)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
|
|
8
|
+
Baobox is a Bun-first, TypeScript-first schema library that keeps the familiar TypeBox-style authoring surface while adding result-first runtime APIs, scoped runtime contexts, compile caching, portable validator artifacts, and schema-interop helpers.
|
|
9
|
+
|
|
10
|
+
## ELI5
|
|
11
|
+
|
|
12
|
+
- You describe what valid data looks like once.
|
|
13
|
+
- Baobox can then answer different questions with the same schema:
|
|
14
|
+
- Is this value valid: `Check`
|
|
15
|
+
- Can you clean and coerce it safely: `TryParse`
|
|
16
|
+
- What exactly failed: `Explain` or `Errors`
|
|
17
|
+
- Can I reuse this on a hot path: `CompileCached`
|
|
18
|
+
- Can another tool consume the same schema: `StandardSchemaV1`
|
|
19
|
+
- If you do not want exception-driven control flow, use the `Try*` family.
|
|
20
|
+
|
|
21
|
+
## Why Baobox
|
|
22
|
+
|
|
23
|
+
- TypeBox-compatible root surface with baobox-only additions at the root entrypoint.
|
|
24
|
+
- Result-first runtime helpers: `TryParse`, `TryDecode`, `TryEncode`, `TryCreate`, and `TryRepair`.
|
|
25
|
+
- Scoped runtime contexts so locale catalogs, registries, settings, and compile caches do not have to be process-global.
|
|
26
|
+
- Compiled validators with cache reuse and portable `Validator.Artifact()` output.
|
|
27
|
+
- Standard Schema V1 adapters for typed baobox schemas and raw JSON-schema-style objects.
|
|
28
|
+
- Built-in codecs for common interop-heavy values: `Uint8Array`, `Date`, `URL`, and `bigint`.
|
|
29
|
+
- Localized validation errors with official bundles for every declared locale code through `baobox/locale`.
|
|
4
30
|
|
|
5
31
|
## Install
|
|
6
32
|
|
|
@@ -29,15 +55,17 @@ const User = Type.Object({
|
|
|
29
55
|
id: Type.String(),
|
|
30
56
|
email: Type.String({ format: 'email' }),
|
|
31
57
|
age: Type.Number({ minimum: 0 }),
|
|
32
|
-
}
|
|
58
|
+
})
|
|
33
59
|
|
|
34
60
|
Check(User, { id: 'usr_1', email: 'ada@example.com', age: 37 })
|
|
61
|
+
// true
|
|
35
62
|
|
|
36
63
|
TryParse(Type.Object({ count: Type.Number() }), { count: '5' })
|
|
37
64
|
// { success: true, value: { count: 5 } }
|
|
38
65
|
|
|
39
66
|
const validator = CompileCached(User)
|
|
40
67
|
validator.Check({ id: 'usr_1', email: 'ada@example.com', age: 37 })
|
|
68
|
+
// true
|
|
41
69
|
|
|
42
70
|
TryDecode(DateCodec(), '2024-01-01T00:00:00.000Z')
|
|
43
71
|
// { success: true, value: new Date('2024-01-01T00:00:00.000Z') }
|
|
@@ -47,68 +75,103 @@ StandardUser['~standard'].validate({ id: 'usr_1', email: 'ada@example.com', age:
|
|
|
47
75
|
// { value: { id: 'usr_1', email: 'ada@example.com', age: 37 } }
|
|
48
76
|
```
|
|
49
77
|
|
|
50
|
-
##
|
|
51
|
-
|
|
52
|
-
- `Check(schema, value)` returns a boolean. Use it when you only need pass/fail validation.
|
|
53
|
-
- `TryParse(schema, value)` runs the full normalization pipeline and returns `{ success, value | errors }`. Use it when the caller needs a non-throwing normalization path.
|
|
54
|
-
- `TryDecode`, `TryEncode`, `TryCreate`, and `TryRepair` extend the same result-first contract to codecs, default generation, and repair flows.
|
|
55
|
-
- `Parse(schema, value)` runs the full value pipeline: clone, default, convert, clean, then validate. It throws `ParseError` when validation still fails.
|
|
56
|
-
- `Explain(schema, value)` returns raw issue metadata plus the localized message and active locale.
|
|
57
|
-
- `Compile(schema)` creates a reusable validator for hot paths, now with per-context compile caching and portable `Validator.Artifact()` output. `Validator.Errors()` uses the same localized error messages as `Value.Errors()`.
|
|
78
|
+
## API Map
|
|
58
79
|
|
|
59
|
-
|
|
80
|
+
| Problem | API | Result |
|
|
81
|
+
| --- | --- | --- |
|
|
82
|
+
| Fast pass/fail validation | `Check(schema, value)` | `boolean` |
|
|
83
|
+
| Normalize without exceptions | `TryParse(schema, value)` | `ParseResult<T>` |
|
|
84
|
+
| Throwing parity path | `Parse(schema, value)` | normalized value or `ParseError` |
|
|
85
|
+
| Codec decode without exceptions | `TryDecode(schema, value)` | `ParseResult<T>` |
|
|
86
|
+
| Codec encode without exceptions | `TryEncode(schema, value)` | `ParseResult<T>` |
|
|
87
|
+
| Default generation without exceptions | `TryCreate(schema)` | `ParseResult<T>` |
|
|
88
|
+
| Repair without exceptions | `TryRepair(schema, value)` | `ParseResult<T>` |
|
|
89
|
+
| Raw issue metadata plus localized messages | `Explain(schema, value)` | diagnostics array |
|
|
90
|
+
| Reusable hot-path validator | `Compile(schema)` or `CompileCached(schema)` | `Validator` |
|
|
91
|
+
| Reload a prebuilt validator body | `CompileFromArtifact(schema, artifact)` | `Validator` |
|
|
92
|
+
| TypeBox-compatible error iterator | `ErrorsIterator(schema, value)` | `IterableIterator<ValueError>` |
|
|
93
|
+
| Adapt to Standard Schema V1 | `StandardSchemaV1(schema)` | standard-compatible wrapper |
|
|
60
94
|
|
|
61
|
-
|
|
62
|
-
import { StandardSchemaV1, Type } from 'baobox'
|
|
95
|
+
## Result-First Runtime
|
|
63
96
|
|
|
64
|
-
|
|
65
|
-
name: Type.String(),
|
|
66
|
-
age: Type.Number(),
|
|
67
|
-
}, { required: ['name', 'age'] }))
|
|
97
|
+
Baobox keeps `Parse(schema, value)` as the upstream-style throwing path, but the default baobox direction is result-first:
|
|
68
98
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
99
|
+
- `TryParse` runs `Clone -> Default -> Convert -> Clean -> Check`
|
|
100
|
+
- `TryDecode` and `TryEncode` apply codec transforms without exception control flow
|
|
101
|
+
- `TryCreate` and `TryRepair` make default-generation and corrective flows explicit
|
|
102
|
+
- `Explain` preserves issue codes, params, locale, and final message
|
|
72
103
|
|
|
73
|
-
|
|
104
|
+
If you are writing request handling, config loading, env parsing, or service boundaries, the `Try*` APIs are usually the better fit.
|
|
74
105
|
|
|
75
|
-
|
|
106
|
+
## Compiled Validators
|
|
76
107
|
|
|
77
|
-
|
|
108
|
+
`Compile()` builds a reusable validator object. `CompileCached()` adds per-runtime-context cache reuse. `CompileFromArtifact()` reloads previously emitted validator code.
|
|
78
109
|
|
|
79
110
|
```ts
|
|
80
|
-
import {
|
|
81
|
-
import { System } from 'baobox/system'
|
|
111
|
+
import { CompileCached, CompileFromArtifact, Number, Object } from 'baobox'
|
|
82
112
|
|
|
83
|
-
|
|
113
|
+
const schema = Object({
|
|
114
|
+
count: Number({ minimum: 1 }),
|
|
115
|
+
})
|
|
84
116
|
|
|
85
|
-
|
|
86
|
-
|
|
117
|
+
const validator = CompileCached(schema)
|
|
118
|
+
const artifact = validator.Artifact()
|
|
119
|
+
const loaded = CompileFromArtifact(schema, artifact)
|
|
120
|
+
|
|
121
|
+
loaded.TryParse({ count: '2' })
|
|
122
|
+
// { success: true, value: { count: 2 } }
|
|
87
123
|
```
|
|
88
124
|
|
|
89
|
-
|
|
125
|
+
Technical details:
|
|
90
126
|
|
|
91
|
-
|
|
127
|
+
- compile caching is scoped to the active runtime context
|
|
128
|
+
- artifacts let you ship emitted validator code instead of regenerating it at startup
|
|
129
|
+
- Bun-specific byte-oriented fast paths are used only when the schema shape makes that safe
|
|
130
|
+
|
|
131
|
+
## Standard Schema Interop
|
|
132
|
+
|
|
133
|
+
Baobox can expose the same validation logic through the Standard Schema V1 contract.
|
|
92
134
|
|
|
93
135
|
```ts
|
|
94
|
-
import {
|
|
136
|
+
import { FromJsonSchema, StandardSchemaV1, Type, ToStandardSchema } from 'baobox'
|
|
95
137
|
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
138
|
+
const typed = StandardSchemaV1(Type.Object({
|
|
139
|
+
name: Type.String(),
|
|
140
|
+
age: Type.Number(),
|
|
141
|
+
}))
|
|
142
|
+
|
|
143
|
+
const raw = FromJsonSchema({
|
|
144
|
+
type: 'object',
|
|
145
|
+
properties: {
|
|
146
|
+
name: { type: 'string' },
|
|
147
|
+
age: { type: 'number' },
|
|
148
|
+
},
|
|
149
|
+
required: ['name', 'age'],
|
|
100
150
|
})
|
|
101
|
-
context.Locale.Set('en_TEST')
|
|
102
151
|
|
|
103
|
-
|
|
104
|
-
// [{ path: '/', code: 'INVALID_TYPE', message: 'yarrr-invalid-type' }]
|
|
152
|
+
ToStandardSchema(raw)['~standard'].validate({ name: 'Ada', age: 37 })
|
|
105
153
|
```
|
|
106
154
|
|
|
107
|
-
|
|
155
|
+
Use:
|
|
156
|
+
|
|
157
|
+
- `StandardSchemaV1()` when you want the canonical baobox adapter
|
|
158
|
+
- `ToStandardSchema()` when the input may already be typed or raw
|
|
159
|
+
- `FromJsonSchema()` when the source is explicitly a raw JSON-schema-style object
|
|
160
|
+
|
|
161
|
+
For schema-agnostic integrations, you can also import from `baobox/standard`.
|
|
162
|
+
|
|
163
|
+
## Locales And Runtime Contexts
|
|
164
|
+
|
|
165
|
+
The default runtime context is preloaded with an official bundle for every declared locale code. Native translated catalogs currently ship for `de_DE`, `en_US`, the Spanish family, the French family, `ja_JP`, `ko_KR`, the Portuguese family, and both Chinese packs. Remaining official bundles currently alias the English catalog until native translations are added.
|
|
108
166
|
|
|
109
167
|
```ts
|
|
110
168
|
import LocalePacks from 'baobox/locale'
|
|
111
169
|
import { CreateRuntimeContext, Errors, LocaleCodes, String } from 'baobox'
|
|
170
|
+
import { System } from 'baobox/system'
|
|
171
|
+
|
|
172
|
+
System.Locale.Set(System.Locale.ko_KR)
|
|
173
|
+
Errors(String(), 42)
|
|
174
|
+
// [{ path: '/', code: 'INVALID_TYPE', message: 'string이어야 합니다. 현재 값 유형: number' }]
|
|
112
175
|
|
|
113
176
|
const context = CreateRuntimeContext({ localeCatalogs: [] })
|
|
114
177
|
context.Locale.Register(LocaleCodes.it_IT, LocalePacks.it_IT)
|
|
@@ -118,25 +181,87 @@ Errors(String(), 42, context)
|
|
|
118
181
|
// [{ path: '/', code: 'INVALID_TYPE', message: 'Expected string, got number' }]
|
|
119
182
|
```
|
|
120
183
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
-
|
|
124
|
-
-
|
|
125
|
-
-
|
|
126
|
-
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
184
|
+
Use runtime contexts when you need:
|
|
185
|
+
|
|
186
|
+
- per-test or per-worker isolation
|
|
187
|
+
- tenant-specific registries or locale catalogs
|
|
188
|
+
- explicit compile-cache boundaries
|
|
189
|
+
- non-global settings and type-policy changes
|
|
190
|
+
|
|
191
|
+
## Elysia Integration
|
|
192
|
+
|
|
193
|
+
Baobox ships a dedicated Elysia adapter at `baobox/elysia`. It re-exports all type builders through a `t` namespace that automatically stamps the `[Kind]` symbol property required by Elysia's TypeBox 0.x type guards, alongside the standard `'~kind'` string.
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
import { t } from 'baobox/elysia'
|
|
197
|
+
|
|
198
|
+
const UserBody = t.Object({
|
|
199
|
+
name: t.String({ minLength: 1 }),
|
|
200
|
+
email: t.Email(),
|
|
201
|
+
role: t.Enum(['admin', 'user']),
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
// Use with Elysia routes:
|
|
205
|
+
// app.post('/user', handler, { body: UserBody })
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
The adapter also re-exports `Value`, `Compile`, and `decorateSchema()` for manual decoration of custom schemas. Eden Treaty type inference works because the `t.*` wrappers preserve full generic type parameters.
|
|
209
|
+
|
|
210
|
+
## TypeBox Migration
|
|
211
|
+
|
|
212
|
+
The `baobox migrate` CLI rewrites TypeBox imports and API calls to their baobox equivalents.
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# Preview changes without writing files
|
|
216
|
+
baobox migrate --dry-run --path ./src
|
|
217
|
+
|
|
218
|
+
# Apply changes
|
|
219
|
+
baobox migrate --write --path ./src
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
The migration tool:
|
|
223
|
+
- Rewrites `@sinclair/typebox` imports to `baobox` equivalents
|
|
224
|
+
- Rewrites `@sinclair/typebox/value` to `baobox/value`, `/compiler` to `baobox/compile`, etc.
|
|
225
|
+
- Transforms `TypeCompiler.Compile(schema)` to `Compile(schema)`
|
|
226
|
+
- Flags patterns that need manual review (e.g., `[Kind]` symbol usage, `Value.Errors()` iterator differences)
|
|
227
|
+
|
|
228
|
+
For incremental migration, the `baobox/typebox` subpath provides a TypeBox-compatible surface:
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
import { Value, Compile, Object, String } from 'baobox/typebox'
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Built-In Codecs
|
|
235
|
+
|
|
236
|
+
Baobox ships codec helpers for common wire-format boundaries:
|
|
237
|
+
|
|
238
|
+
- `Uint8ArrayCodec()` for base64 JSON payloads and runtime byte arrays
|
|
239
|
+
- `DateCodec()` for ISO datetime strings to `Date`
|
|
240
|
+
- `URLCodec()` for string to `URL`
|
|
241
|
+
- `BigIntCodec()` for integer-string to `bigint`
|
|
242
|
+
|
|
243
|
+
These work with the same value and compile APIs as ordinary schemas.
|
|
244
|
+
|
|
245
|
+
## Public Entrypoints
|
|
246
|
+
|
|
247
|
+
| Entrypoint | Purpose |
|
|
248
|
+
| --- | --- |
|
|
249
|
+
| `baobox` | Root builders, value helpers, compile helpers, and baobox additions |
|
|
250
|
+
| `baobox/type` | Type builders and static type exports |
|
|
251
|
+
| `baobox/value` | Runtime value operations such as `Check`, `Parse`, `Errors`, `Repair`, `Diff`, and `Patch` |
|
|
252
|
+
| `baobox/schema` | Raw schema runtime plus baobox schema-emitter helpers |
|
|
253
|
+
| `baobox/error` | Structured validation error surface |
|
|
254
|
+
| `baobox/compile` | `Compile`, `Code`, and `Validator` |
|
|
255
|
+
| `baobox/format` | Format registry and format helpers |
|
|
256
|
+
| `baobox/guard` | Guard namespaces aligned with the TypeBox-style guard surface |
|
|
257
|
+
| `baobox/system` | Runtime settings, locale, hashing, memory, and environment helpers |
|
|
258
|
+
| `baobox/script` | Script DSL helpers |
|
|
259
|
+
| `baobox/locale` | Official locale bundles for the declared locale registry |
|
|
260
|
+
| `baobox/standard` | Standard Schema V1 adapter helpers |
|
|
261
|
+
| `baobox/typebox` | TypeBox-compatible re-export surface with `Value` and `Compile` |
|
|
262
|
+
| `baobox/elysia` | Elysia adapter with `[Kind]` symbol decoration and `t` namespace |
|
|
263
|
+
|
|
264
|
+
Published consumers should only rely on package entrypoints. Direct `src/*` imports are internal to this repository and its tests.
|
|
140
265
|
|
|
141
266
|
## Guides
|
|
142
267
|
|
|
@@ -146,21 +271,6 @@ Errors(String(), 42, context)
|
|
|
146
271
|
- [Package contract and supported imports](docs/package-contract.md)
|
|
147
272
|
- [Parity policy and baobox-only additions](docs/parity-and-extensions.md)
|
|
148
273
|
|
|
149
|
-
## Parity Policy
|
|
150
|
-
|
|
151
|
-
- Root exports are maintained as an upstream-complete superset.
|
|
152
|
-
- The `compile`, `error`, `format`, `guard`, `system`, and `value` subpaths are parity-tested against the installed `typebox` package.
|
|
153
|
-
- `baobox/schema` intentionally combines a `typebox/schema`-style raw schema runtime with baobox's schema emitter helpers.
|
|
154
|
-
|
|
155
|
-
## Bun-Native Fast Paths
|
|
156
|
-
|
|
157
|
-
- `Compile()` can specialize hot validation paths for Bun when the schema shape makes that safe.
|
|
158
|
-
- `CompileCached()` is the root convenience wrapper for cached validators, and `CompileFromArtifact()` reloads portable artifacts without re-emitting code.
|
|
159
|
-
- `Uint8ArrayCodec()` adds a Bun-first base64 codec surface for binary payloads and supports constant-payload specialization in compiled validators.
|
|
160
|
-
- `DateCodec()`, `URLCodec()`, and `BigIntCodec()` provide built-in codec surfaces for common interop-heavy values.
|
|
161
|
-
- Raw `Uint8Array` constant-byte comparisons can use a Bun `bun:ffi` memcmp fast path when the platform supports it.
|
|
162
|
-
- Bun documents `bun:ffi` as experimental, so baobox keeps the fast path narrow and falls back to non-FFI compiled validation whenever the schema does not require native byte comparison.
|
|
163
|
-
|
|
164
274
|
## Repository Scripts
|
|
165
275
|
|
|
166
276
|
```bash
|
|
@@ -168,25 +278,9 @@ bun run build
|
|
|
168
278
|
bun run typecheck
|
|
169
279
|
bun test
|
|
170
280
|
bun run bench
|
|
171
|
-
bun run publish:dry-run
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
`bun run bench` prints comparative validation and codec throughput against the installed `typebox` package so benchmark output stays tied to the current upstream implementation.
|
|
175
|
-
|
|
176
|
-
## Publishing
|
|
177
|
-
|
|
178
|
-
Baobox is configured to publish to npm with `bun`.
|
|
179
|
-
|
|
180
|
-
```bash
|
|
181
|
-
bun run publish:dry-run
|
|
182
|
-
bun publish --access public
|
|
183
281
|
```
|
|
184
282
|
|
|
185
|
-
|
|
186
|
-
- GitHub Actions will attempt a publish on pushes to `main`, on published GitHub releases, and through manual workflow dispatch when `package.json` contains a version that is not already on npm.
|
|
187
|
-
- The workflow configures the npm registry on the runner and then requires the repository secret `NPM_TOKEN` before attempting a live publish.
|
|
188
|
-
- For a local first publish, authenticate once with `bunx npm login` before running `bun publish --access public`.
|
|
189
|
-
- Local `.npmrc` files are gitignored so auth tokens do not end up in the repository.
|
|
283
|
+
`bun run bench` compares validation and codec throughput against the installed `typebox` package so performance numbers stay tied to the current upstream implementation.
|
|
190
284
|
|
|
191
285
|
## License
|
|
192
286
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,wDAAwD"}
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// @bun
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __returnValue = (v) => v;
|
|
5
|
+
function __exportSetter(name, newValue) {
|
|
6
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
7
|
+
}
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, {
|
|
11
|
+
get: all[name],
|
|
12
|
+
enumerable: true,
|
|
13
|
+
configurable: true,
|
|
14
|
+
set: __exportSetter.bind(all, name)
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
var __require = import.meta.require;
|
|
18
|
+
|
|
19
|
+
// src/cli/transforms/imports.ts
|
|
20
|
+
var IMPORT_TRANSFORMS = [
|
|
21
|
+
{ from: /['"]@sinclair\/typebox\/value['"]/, to: "'baobox/value'" },
|
|
22
|
+
{ from: /['"]@sinclair\/typebox\/compiler['"]/, to: "'baobox/compile'" },
|
|
23
|
+
{ from: /['"]@sinclair\/typebox\/type['"]/, to: "'baobox/type'" },
|
|
24
|
+
{ from: /['"]@sinclair\/typebox\/errors['"]/, to: "'baobox/error'" },
|
|
25
|
+
{ from: /['"]@sinclair\/typebox['"]/, to: "'baobox'" }
|
|
26
|
+
];
|
|
27
|
+
function transformImport(line) {
|
|
28
|
+
for (const rule of IMPORT_TRANSFORMS) {
|
|
29
|
+
if (rule.from.test(line)) {
|
|
30
|
+
return {
|
|
31
|
+
line: line.replace(rule.from, rule.to),
|
|
32
|
+
changed: true
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return { line, changed: false };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/cli/transforms/api-calls.ts
|
|
40
|
+
var API_TRANSFORMS = [
|
|
41
|
+
{
|
|
42
|
+
pattern: /TypeCompiler\.Compile\(/g,
|
|
43
|
+
replacement: "Compile(",
|
|
44
|
+
note: "TypeCompiler.Compile \u2192 Compile (add import from baobox/compile)"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
pattern: /TypeCompiler\.Code\(/g,
|
|
48
|
+
replacement: "Code(",
|
|
49
|
+
note: "TypeCompiler.Code \u2192 Code (add import from baobox/compile)"
|
|
50
|
+
}
|
|
51
|
+
];
|
|
52
|
+
var MANUAL_REVIEW_PATTERNS = [
|
|
53
|
+
{ pattern: /\[Kind\]/, message: "Uses [Kind] symbol \u2014 baobox uses '~kind' string property instead" },
|
|
54
|
+
{ pattern: /\[Hint\]/, message: "Uses [Hint] symbol \u2014 baobox does not use Hint symbols" },
|
|
55
|
+
{ pattern: /Value\.Errors\(/, message: "Value.Errors() returns SchemaError[] in baobox (not an iterator). Use ErrorsIterator() for TypeBox-compatible iterator format" },
|
|
56
|
+
{ pattern: /FormatRegistry\.Set/, message: "Format registry is scoped to RuntimeContext in baobox \u2014 use CreateRuntimeContext() instead of global registry" },
|
|
57
|
+
{ pattern: /TypeRegistry\.Set/, message: "Type registry is scoped to RuntimeContext in baobox" }
|
|
58
|
+
];
|
|
59
|
+
function isCodeLine(line) {
|
|
60
|
+
const trimmed = line.trimStart();
|
|
61
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("*") || trimmed.startsWith("/*")) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
function transformApiCalls(line) {
|
|
67
|
+
if (!isCodeLine(line)) {
|
|
68
|
+
return { line, changed: false };
|
|
69
|
+
}
|
|
70
|
+
let result = line;
|
|
71
|
+
let changed = false;
|
|
72
|
+
const notes = [];
|
|
73
|
+
for (const rule of API_TRANSFORMS) {
|
|
74
|
+
const replaced = result.replace(rule.pattern, rule.replacement);
|
|
75
|
+
if (replaced !== result) {
|
|
76
|
+
result = replaced;
|
|
77
|
+
changed = true;
|
|
78
|
+
if (rule.note)
|
|
79
|
+
notes.push(rule.note);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return { line: result, changed, note: notes.length > 0 ? notes.join("; ") : undefined };
|
|
83
|
+
}
|
|
84
|
+
function detectManualReviewItems(line, lineNumber) {
|
|
85
|
+
const items = [];
|
|
86
|
+
for (const rule of MANUAL_REVIEW_PATTERNS) {
|
|
87
|
+
if (rule.pattern.test(line)) {
|
|
88
|
+
items.push(`Line ${lineNumber}: ${rule.message}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return items;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/cli/migrate.ts
|
|
95
|
+
var SKIP_DIRS = new Set([
|
|
96
|
+
"node_modules",
|
|
97
|
+
".git",
|
|
98
|
+
"dist",
|
|
99
|
+
"build",
|
|
100
|
+
"out",
|
|
101
|
+
".turbo",
|
|
102
|
+
".cache",
|
|
103
|
+
".next",
|
|
104
|
+
".nuxt",
|
|
105
|
+
".output"
|
|
106
|
+
]);
|
|
107
|
+
function isTypeScriptFile(path) {
|
|
108
|
+
return path.endsWith(".ts") || path.endsWith(".tsx");
|
|
109
|
+
}
|
|
110
|
+
function hasTypeBoxImport(content) {
|
|
111
|
+
return content.includes("@sinclair/typebox");
|
|
112
|
+
}
|
|
113
|
+
async function scanDirectory(dir) {
|
|
114
|
+
const { readdir } = await import("fs/promises");
|
|
115
|
+
const { join } = await import("path");
|
|
116
|
+
const results = [];
|
|
117
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
118
|
+
for (const entry of entries) {
|
|
119
|
+
const fullPath = join(dir, entry.name);
|
|
120
|
+
if (SKIP_DIRS.has(entry.name)) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (entry.isDirectory()) {
|
|
124
|
+
results.push(...await scanDirectory(fullPath));
|
|
125
|
+
} else if (isTypeScriptFile(entry.name)) {
|
|
126
|
+
results.push(fullPath);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return results;
|
|
130
|
+
}
|
|
131
|
+
function migrateFileContent(content, filePath) {
|
|
132
|
+
const lines = content.split(`
|
|
133
|
+
`);
|
|
134
|
+
const transformedLines = [];
|
|
135
|
+
const changedLineNumbers = [];
|
|
136
|
+
const notes = [];
|
|
137
|
+
const manualReviewItems = [];
|
|
138
|
+
for (let i = 0;i < lines.length; i++) {
|
|
139
|
+
const originalLine = lines[i];
|
|
140
|
+
let line = originalLine;
|
|
141
|
+
let changed = false;
|
|
142
|
+
manualReviewItems.push(...detectManualReviewItems(originalLine, i + 1));
|
|
143
|
+
const importResult = transformImport(line);
|
|
144
|
+
if (importResult.changed) {
|
|
145
|
+
line = importResult.line;
|
|
146
|
+
changed = true;
|
|
147
|
+
if (importResult.note)
|
|
148
|
+
notes.push(`Line ${i + 1}: ${importResult.note}`);
|
|
149
|
+
}
|
|
150
|
+
const apiResult = transformApiCalls(line);
|
|
151
|
+
if (apiResult.changed) {
|
|
152
|
+
line = apiResult.line;
|
|
153
|
+
changed = true;
|
|
154
|
+
if (apiResult.note)
|
|
155
|
+
notes.push(`Line ${i + 1}: ${apiResult.note}`);
|
|
156
|
+
}
|
|
157
|
+
transformedLines.push(line);
|
|
158
|
+
if (changed)
|
|
159
|
+
changedLineNumbers.push(i + 1);
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
filePath,
|
|
163
|
+
originalLines: lines,
|
|
164
|
+
transformedLines,
|
|
165
|
+
changedLineNumbers,
|
|
166
|
+
notes,
|
|
167
|
+
manualReviewItems
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
async function migrate(options) {
|
|
171
|
+
const { readFile, writeFile } = await import("fs/promises");
|
|
172
|
+
const files = await scanDirectory(options.path);
|
|
173
|
+
const changes = [];
|
|
174
|
+
let totalTransforms = 0;
|
|
175
|
+
let totalManualReviewItems = 0;
|
|
176
|
+
for (const filePath of files) {
|
|
177
|
+
const content = await readFile(filePath, "utf8");
|
|
178
|
+
if (!hasTypeBoxImport(content))
|
|
179
|
+
continue;
|
|
180
|
+
const change = migrateFileContent(content, filePath);
|
|
181
|
+
if (change.changedLineNumbers.length > 0 || change.manualReviewItems.length > 0) {
|
|
182
|
+
changes.push(change);
|
|
183
|
+
totalTransforms += change.changedLineNumbers.length;
|
|
184
|
+
totalManualReviewItems += change.manualReviewItems.length;
|
|
185
|
+
if (!options.dryRun && change.changedLineNumbers.length > 0) {
|
|
186
|
+
await writeFile(filePath, change.transformedLines.join(`
|
|
187
|
+
`));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
filesScanned: files.length,
|
|
193
|
+
filesChanged: changes.filter((c) => c.changedLineNumbers.length > 0).length,
|
|
194
|
+
changes,
|
|
195
|
+
totalTransforms,
|
|
196
|
+
totalManualReviewItems
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// src/cli/report.ts
|
|
201
|
+
function formatDiff(change) {
|
|
202
|
+
const lines = [];
|
|
203
|
+
lines.push(` ${change.filePath}`);
|
|
204
|
+
for (const lineNum of change.changedLineNumbers) {
|
|
205
|
+
const original = change.originalLines[lineNum - 1];
|
|
206
|
+
const transformed = change.transformedLines[lineNum - 1];
|
|
207
|
+
lines.push(` L${lineNum}:`);
|
|
208
|
+
lines.push(` - ${original}`);
|
|
209
|
+
lines.push(` + ${transformed}`);
|
|
210
|
+
}
|
|
211
|
+
if (change.manualReviewItems.length > 0) {
|
|
212
|
+
lines.push(" Manual review needed:");
|
|
213
|
+
for (const item of change.manualReviewItems) {
|
|
214
|
+
lines.push(` ! ${item}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return lines.join(`
|
|
218
|
+
`);
|
|
219
|
+
}
|
|
220
|
+
function formatMigrationReport(report, dryRun) {
|
|
221
|
+
const lines = [];
|
|
222
|
+
lines.push("");
|
|
223
|
+
lines.push(`baobox migrate${dryRun ? " (dry run)" : ""}`);
|
|
224
|
+
lines.push("=".repeat(40));
|
|
225
|
+
lines.push("");
|
|
226
|
+
lines.push(`Files scanned: ${report.filesScanned}`);
|
|
227
|
+
lines.push(`Files ${dryRun ? "would change" : "changed"}: ${report.filesChanged}`);
|
|
228
|
+
lines.push(`Total transforms: ${report.totalTransforms}`);
|
|
229
|
+
lines.push(`Manual review items: ${report.totalManualReviewItems}`);
|
|
230
|
+
lines.push("");
|
|
231
|
+
if (report.changes.length > 0) {
|
|
232
|
+
lines.push("Changes:");
|
|
233
|
+
lines.push("");
|
|
234
|
+
for (const change of report.changes) {
|
|
235
|
+
lines.push(formatDiff(change));
|
|
236
|
+
lines.push("");
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (report.totalManualReviewItems > 0) {
|
|
240
|
+
lines.push("Note: Items flagged for manual review need human attention.");
|
|
241
|
+
lines.push("These patterns have no direct baobox equivalent or behave differently.");
|
|
242
|
+
lines.push("");
|
|
243
|
+
}
|
|
244
|
+
return lines.join(`
|
|
245
|
+
`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// src/cli/index.ts
|
|
249
|
+
import { resolve } from "path";
|
|
250
|
+
function printUsage() {
|
|
251
|
+
const usage = `
|
|
252
|
+
Usage: baobox migrate [options]
|
|
253
|
+
|
|
254
|
+
Migrate TypeBox imports and API calls to baobox equivalents.
|
|
255
|
+
|
|
256
|
+
Options:
|
|
257
|
+
--dry-run Show what would change without writing files (default)
|
|
258
|
+
--write Apply changes to files
|
|
259
|
+
--path <dir> Target directory to scan (default: current directory)
|
|
260
|
+
--help Show this help message
|
|
261
|
+
|
|
262
|
+
Examples:
|
|
263
|
+
baobox migrate # dry run in current directory
|
|
264
|
+
baobox migrate --path ./src # dry run in ./src
|
|
265
|
+
baobox migrate --write # apply changes
|
|
266
|
+
baobox migrate --dry-run --path . # explicit dry run
|
|
267
|
+
`;
|
|
268
|
+
process.stdout.write(usage);
|
|
269
|
+
}
|
|
270
|
+
function parseArgs(args) {
|
|
271
|
+
let command = "";
|
|
272
|
+
let dryRun = true;
|
|
273
|
+
let path = process.cwd();
|
|
274
|
+
let help = false;
|
|
275
|
+
for (let i = 0;i < args.length; i++) {
|
|
276
|
+
const arg = args[i];
|
|
277
|
+
if (arg === "migrate") {
|
|
278
|
+
command = "migrate";
|
|
279
|
+
} else if (arg === "--dry-run") {
|
|
280
|
+
dryRun = true;
|
|
281
|
+
} else if (arg === "--write") {
|
|
282
|
+
dryRun = false;
|
|
283
|
+
} else if (arg === "--path" && i + 1 < args.length) {
|
|
284
|
+
path = resolve(args[++i]);
|
|
285
|
+
} else if (arg === "--help" || arg === "-h") {
|
|
286
|
+
help = true;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return { command, dryRun, path, help };
|
|
290
|
+
}
|
|
291
|
+
async function main() {
|
|
292
|
+
const cliArgs = process.argv.slice(2);
|
|
293
|
+
const { command, dryRun, path, help } = parseArgs(cliArgs);
|
|
294
|
+
if (help || !command) {
|
|
295
|
+
printUsage();
|
|
296
|
+
process.exit(help ? 0 : 1);
|
|
297
|
+
}
|
|
298
|
+
if (command === "migrate") {
|
|
299
|
+
const report = await migrate({ dryRun, path, report: true });
|
|
300
|
+
process.stdout.write(formatMigrationReport(report, dryRun));
|
|
301
|
+
if (report.filesChanged === 0 && report.totalManualReviewItems === 0) {
|
|
302
|
+
process.stdout.write(`No TypeBox imports found.
|
|
303
|
+
`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
main().catch((error) => {
|
|
308
|
+
process.stderr.write(`Error: ${error instanceof Error ? error.message : String(error)}
|
|
309
|
+
`);
|
|
310
|
+
process.exit(1);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
//# debugId=444B65DC8107EF7D64756E2164756E21
|
|
314
|
+
//# sourceMappingURL=index.js.map
|