@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 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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blueprint-ts/core",
3
- "version": "4.0.0-beta.4",
3
+ "version": "4.0.0-beta.6",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -42,7 +42,7 @@ export abstract class BasePaginator<ResourceInterface, ViewDriver extends BaseVi
42
42
  const result = updater(row, i, data)
43
43
 
44
44
  if (result !== undefined) {
45
- data[i] = result
45
+ data[i] = result as ResourceInterface
46
46
  }
47
47
 
48
48
  updated++
@@ -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
- public readonly state: FormBody
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
- return typeof candidate === 'function' ? (candidate as (value: unknown) => unknown) : undefined
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
- return typeof candidate === 'function' ? (candidate as () => unknown) : undefined
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