@blueprint-ts/core 4.0.0-beta.4 → 4.0.0-beta.6
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/CHANGELOG.md +23 -0
- package/docs/upgrading/v3-to-v4.md +27 -0
- package/docs/vue/forms/arrays.md +57 -0
- package/package.json +1 -1
- package/src/pagination/BasePaginator.ts +1 -1
- package/src/pagination/index.ts +0 -2
- package/src/vue/forms/BaseForm.ts +22 -7
- package/src/vue/requests/factories/VueRequestLoaderFactory.ts +1 -1
- package/src/pagination/Paginator.ts +0 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
## v4.0.0-beta.6 - 2026-02-27 (beta)
|
|
2
|
+
|
|
3
|
+
# [4.0.0-beta.6](/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2026-02-27)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* bind BaseForm getters to preserve this 5e44296
|
|
9
|
+
* Type propertyAwareToRaw properly 1fe2f28
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
* Make state protected readonly in BaseForm e6e2f81
|
|
15
|
+
* Removed deprecated Paginator alias 7f07617
|
|
16
|
+
## v4.0.0-beta.5 - 2026-02-27 (beta)
|
|
17
|
+
|
|
18
|
+
# [4.0.0-beta.5](/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2026-02-27)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Bug Fixes
|
|
22
|
+
|
|
23
|
+
* satisfy paginator updater typing and type-only import in VueRequestLoaderFactory 6468368
|
|
1
24
|
## v4.0.0-beta.4 - 2026-02-26 (beta)
|
|
2
25
|
|
|
3
26
|
# [4.0.0-beta.4](/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2026-02-26)
|
|
@@ -78,6 +78,24 @@ Page navigation helpers (`toNextPage`, `toPreviousPage`, `toFirstPage`, `toLastP
|
|
|
78
78
|
`PaginationParamsContract` was removed from the Laravel pagination exports because it was unused. Define your own params
|
|
79
79
|
interface in your app instead.
|
|
80
80
|
|
|
81
|
+
## Deprecated `Paginator` alias removed
|
|
82
|
+
|
|
83
|
+
`Paginator` (and the related `PaginatorOptions` alias) was an old alias for `PageAwarePaginator`. The alias file has been removed, so importing `Paginator` or `PaginatorOptions` now results in a build error.
|
|
84
|
+
|
|
85
|
+
### How to Fix
|
|
86
|
+
|
|
87
|
+
- Replace `import { Paginator } from '@blueprint-ts/core/pagination'` with:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { PageAwarePaginator } from '@blueprint-ts/core/pagination'
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
- Replace `import { type PaginatorOptions } from '@blueprint-ts/core/pagination'` with:
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { type PageAwarePaginatorOptions } from '@blueprint-ts/core/pagination'
|
|
97
|
+
```
|
|
98
|
+
|
|
81
99
|
## Core Modules Moved out of `service/`
|
|
82
100
|
|
|
83
101
|
Core (non-framework) modules moved from `@blueprint-ts/core/service/*` to `@blueprint-ts/core/*`.
|
|
@@ -169,3 +187,12 @@ with:
|
|
|
169
187
|
```typescript
|
|
170
188
|
import { JsonBaseRequest } from '@blueprint-ts/core/laravel/requests'
|
|
171
189
|
```
|
|
190
|
+
|
|
191
|
+
## BaseForm `state` is now protected
|
|
192
|
+
|
|
193
|
+
`BaseForm.state` was public in previous versions, but it is now `protected readonly`. That means external consumers can no longer import form instances and access `form.state`. Subclasses can still read/write state internally, so any code that depended on reading it from outside the form must switch to supported accessors such as `form.properties`.
|
|
194
|
+
|
|
195
|
+
### How to Fix
|
|
196
|
+
|
|
197
|
+
- Replace direct `form.state` usage with the public helpers (`form.properties`, getters, or explicit payload builders).
|
|
198
|
+
- If you were creating helpers that accessed `state` from outside the form, move those helpers inside the form class so they can rely on the protected field.
|
package/docs/vue/forms/arrays.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Arrays
|
|
2
2
|
|
|
3
|
+
## PropertyAwareArray
|
|
4
|
+
|
|
3
5
|
Use `PropertyAwareArray` for arrays with per-item `v-model`, errors, and dirty state when your array contains objects.
|
|
4
6
|
|
|
5
7
|
```ts
|
|
@@ -43,3 +45,58 @@ Example component usage:
|
|
|
43
45
|
```
|
|
44
46
|
|
|
45
47
|
Nested error keys like `positions.0.value` map into `position.value.errors`.
|
|
48
|
+
|
|
49
|
+
## propertyAwareToRaw
|
|
50
|
+
|
|
51
|
+
`propertyAwareToRaw` converts a property-aware object (each field wrapped in `{ model: { value } }`) into a plain object by unwrapping every field's `model.value`. It is purely a transformation: metadata such as `errors`, `dirty`, and `touched` is dropped, while arrays and nested objects are processed recursively. Keys starting with `_` are omitted from the result, and arrays are mapped element-by-element via the same unwrapping.
|
|
52
|
+
|
|
53
|
+
### Input shape (property-aware)
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
const propertyAwarePosition = {
|
|
57
|
+
id: {
|
|
58
|
+
model: { value: 'pos-1' },
|
|
59
|
+
errors: [],
|
|
60
|
+
dirty: false,
|
|
61
|
+
touched: false
|
|
62
|
+
},
|
|
63
|
+
sort_order: {
|
|
64
|
+
model: { value: 10 },
|
|
65
|
+
errors: [],
|
|
66
|
+
dirty: false,
|
|
67
|
+
touched: false
|
|
68
|
+
},
|
|
69
|
+
description: {
|
|
70
|
+
model: { value: 'Service' },
|
|
71
|
+
errors: [],
|
|
72
|
+
dirty: false,
|
|
73
|
+
touched: false
|
|
74
|
+
},
|
|
75
|
+
net_amount: {
|
|
76
|
+
model: { value: 100 },
|
|
77
|
+
errors: [],
|
|
78
|
+
dirty: false,
|
|
79
|
+
touched: false
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Note that this is only an example of how the input shape looks When used in a form the model is a WritableComputedRef.
|
|
85
|
+
|
|
86
|
+
### Output shape (raw)
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
const rawPosition = {
|
|
90
|
+
id: 'pos-1',
|
|
91
|
+
sort_order: 10,
|
|
92
|
+
description: 'Service',
|
|
93
|
+
net_amount: 100
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Notes
|
|
98
|
+
|
|
99
|
+
- Arrays are mapped element-by-element.
|
|
100
|
+
- Nested objects are unwrapped recursively.
|
|
101
|
+
- Any keys starting with `_` are ignored.
|
|
102
|
+
- Only the `model.value` remains; form metadata is dropped.
|
package/package.json
CHANGED
package/src/pagination/index.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { PaginationDataDto } from './dtos/PaginationDataDto'
|
|
|
2
2
|
import { StatePaginationDataDto } from './dtos/StatePaginationDataDto'
|
|
3
3
|
import { VuePaginationDriver } from './frontendDrivers/VuePaginationDriver'
|
|
4
4
|
import { VueBaseViewDriver } from './frontendDrivers/VueBaseViewDriver'
|
|
5
|
-
import { Paginator } from './Paginator'
|
|
6
5
|
import { BasePaginator } from './BasePaginator'
|
|
7
6
|
import { PageAwarePaginator } from './PageAwarePaginator'
|
|
8
7
|
import { StatePaginator } from './StatePaginator'
|
|
@@ -25,7 +24,6 @@ export {
|
|
|
25
24
|
StatePaginationDataDto,
|
|
26
25
|
VuePaginationDriver,
|
|
27
26
|
VueBaseViewDriver,
|
|
28
|
-
Paginator,
|
|
29
27
|
BasePaginator,
|
|
30
28
|
PageAwarePaginator,
|
|
31
29
|
StatePaginator,
|
|
@@ -27,6 +27,15 @@ type FieldProperty<T> = {
|
|
|
27
27
|
touched: boolean
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
type PropertyAwareToRaw<T> =
|
|
31
|
+
T extends Array<infer U>
|
|
32
|
+
? Array<PropertyAwareToRaw<U>>
|
|
33
|
+
: T extends { model: { value: infer V } }
|
|
34
|
+
? V
|
|
35
|
+
: T extends object
|
|
36
|
+
? { [K in keyof T]: PropertyAwareToRaw<T[K]> }
|
|
37
|
+
: T
|
|
38
|
+
|
|
30
39
|
type FormKey<FormBody extends object> = Extract<keyof FormBody, string>
|
|
31
40
|
type RequestKey<RequestBody extends object> = Extract<keyof RequestBody, string>
|
|
32
41
|
type ArrayItem<T> = T extends Array<infer Item> ? Item : never
|
|
@@ -54,13 +63,13 @@ function isErrorObject(value: unknown): value is ErrorObject {
|
|
|
54
63
|
return isRecord(value)
|
|
55
64
|
}
|
|
56
65
|
|
|
57
|
-
export function propertyAwareToRaw<T>(propertyAwareObject: T): T {
|
|
66
|
+
export function propertyAwareToRaw<T>(propertyAwareObject: T): PropertyAwareToRaw<T> {
|
|
58
67
|
if (Array.isArray(propertyAwareObject)) {
|
|
59
|
-
return propertyAwareObject.map((item) => propertyAwareToRaw(item)) as T
|
|
68
|
+
return propertyAwareObject.map((item) => propertyAwareToRaw(item)) as PropertyAwareToRaw<T>
|
|
60
69
|
}
|
|
61
70
|
|
|
62
71
|
if (!isRecord(propertyAwareObject)) {
|
|
63
|
-
return propertyAwareObject
|
|
72
|
+
return propertyAwareObject as PropertyAwareToRaw<T>
|
|
64
73
|
}
|
|
65
74
|
|
|
66
75
|
const result: Record<string, unknown> = {}
|
|
@@ -87,7 +96,7 @@ export function propertyAwareToRaw<T>(propertyAwareObject: T): T {
|
|
|
87
96
|
result[key] = value
|
|
88
97
|
}
|
|
89
98
|
|
|
90
|
-
return result as T
|
|
99
|
+
return result as PropertyAwareToRaw<T>
|
|
91
100
|
}
|
|
92
101
|
|
|
93
102
|
/** Helper: shallow-merge source object into target. */
|
|
@@ -160,7 +169,7 @@ function propertyAwareDeepEqual<T>(a: T, b: T): boolean {
|
|
|
160
169
|
* (We assume that for every key in RequestBody there is a corresponding key in FormBody.)
|
|
161
170
|
*/
|
|
162
171
|
export abstract class BaseForm<RequestBody extends object, FormBody extends object> {
|
|
163
|
-
|
|
172
|
+
protected readonly state: FormBody
|
|
164
173
|
private readonly dirty: DirtyMap<FormBody>
|
|
165
174
|
private readonly touched: Record<keyof FormBody, boolean>
|
|
166
175
|
private readonly original: FormBody
|
|
@@ -795,12 +804,18 @@ export abstract class BaseForm<RequestBody extends object, FormBody extends obje
|
|
|
795
804
|
|
|
796
805
|
private getValueGetter(name: string): ((value: unknown) => unknown) | undefined {
|
|
797
806
|
const candidate = (this as Record<string, unknown>)[name]
|
|
798
|
-
|
|
807
|
+
if (typeof candidate !== 'function') {
|
|
808
|
+
return undefined
|
|
809
|
+
}
|
|
810
|
+
return (candidate as (value: unknown) => unknown).bind(this)
|
|
799
811
|
}
|
|
800
812
|
|
|
801
813
|
private getNoArgGetter(name: string): (() => unknown) | undefined {
|
|
802
814
|
const candidate = (this as Record<string, unknown>)[name]
|
|
803
|
-
|
|
815
|
+
if (typeof candidate !== 'function') {
|
|
816
|
+
return undefined
|
|
817
|
+
}
|
|
818
|
+
return (candidate as () => unknown).bind(this)
|
|
804
819
|
}
|
|
805
820
|
|
|
806
821
|
private transformValue(value: unknown, parentKey?: string): unknown {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VueRequestLoader } from '../loaders/VueRequestLoader'
|
|
2
2
|
import { type RequestLoaderContract } from '../../../requests/contracts/RequestLoaderContract'
|
|
3
3
|
import { type Ref } from 'vue'
|
|
4
|
-
import { RequestLoaderFactoryContract } from '../../../requests'
|
|
4
|
+
import type { RequestLoaderFactoryContract } from '../../../requests'
|
|
5
5
|
|
|
6
6
|
export class VueRequestLoaderFactory implements RequestLoaderFactoryContract<Ref<boolean>> {
|
|
7
7
|
public make(): RequestLoaderContract<Ref<boolean>> {
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { PageAwarePaginator, type PageAwarePaginatorOptions } from './PageAwarePaginator'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @deprecated Use PageAwarePaginator instead. This alias is kept for backward compatibility.
|
|
5
|
-
*/
|
|
6
|
-
export const Paginator = PageAwarePaginator
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @deprecated Use PageAwarePaginatorOptions instead. This alias is kept for backward compatibility.
|
|
10
|
-
*/
|
|
11
|
-
export type PaginatorOptions = PageAwarePaginatorOptions
|