@furystack/repository 10.1.11 → 11.0.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +74 -36
  3. package/esm/data-set-setting.d.ts +30 -44
  4. package/esm/data-set-setting.d.ts.map +1 -1
  5. package/esm/data-set.d.ts +17 -68
  6. package/esm/data-set.d.ts.map +1 -1
  7. package/esm/data-set.js +18 -69
  8. package/esm/data-set.js.map +1 -1
  9. package/esm/data-set.spec.d.ts +2 -0
  10. package/esm/data-set.spec.d.ts.map +1 -0
  11. package/esm/data-set.spec.js +348 -0
  12. package/esm/data-set.spec.js.map +1 -0
  13. package/esm/define-data-set.d.ts +71 -0
  14. package/esm/define-data-set.d.ts.map +1 -0
  15. package/esm/define-data-set.js +65 -0
  16. package/esm/define-data-set.js.map +1 -0
  17. package/esm/define-data-set.spec.d.ts +2 -0
  18. package/esm/define-data-set.spec.d.ts.map +1 -0
  19. package/esm/define-data-set.spec.js +134 -0
  20. package/esm/define-data-set.spec.js.map +1 -0
  21. package/esm/helpers.d.ts +12 -29
  22. package/esm/helpers.d.ts.map +1 -1
  23. package/esm/helpers.js +8 -28
  24. package/esm/helpers.js.map +1 -1
  25. package/esm/index.d.ts +2 -2
  26. package/esm/index.d.ts.map +1 -1
  27. package/esm/index.js +2 -2
  28. package/esm/index.js.map +1 -1
  29. package/package.json +5 -5
  30. package/src/data-set-setting.ts +32 -46
  31. package/src/data-set.spec.ts +397 -0
  32. package/src/data-set.ts +28 -72
  33. package/src/define-data-set.spec.ts +145 -0
  34. package/src/define-data-set.ts +122 -0
  35. package/src/helpers.ts +14 -33
  36. package/src/index.ts +2 -2
  37. package/esm/dataset.spec.d.ts +0 -2
  38. package/esm/dataset.spec.d.ts.map +0 -1
  39. package/esm/dataset.spec.js +0 -552
  40. package/esm/dataset.spec.js.map +0 -1
  41. package/esm/repository.d.ts +0 -15
  42. package/esm/repository.d.ts.map +0 -1
  43. package/esm/repository.js +0 -50
  44. package/esm/repository.js.map +0 -1
  45. package/esm/repository.spec.d.ts +0 -2
  46. package/esm/repository.spec.d.ts.map +0 -1
  47. package/esm/repository.spec.js +0 -18
  48. package/esm/repository.spec.js.map +0 -1
  49. package/src/dataset.spec.ts +0 -641
  50. package/src/repository.spec.ts +0 -19
  51. package/src/repository.ts +0 -50
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## [11.0.1] - 2026-05-21
4
+
5
+ ### 📚 Documentation
6
+
7
+ - Rewrote JSDoc on `DataSet`, `DataSetSetting`, `defineDataSet`, and the helpers to follow the new value-test guidance: dropped restate-the-type narration, kept intent / trade-offs / constraints around authorization, validation, and the lifecycle hooks.
8
+
9
+ ### ⬆️ Dependencies
10
+
11
+ - Bump dev `vitest` to `^4.1.5`.
12
+ - Bumped `vitest` to `^4.1.7`. No source changes — dev-tooling bump only.
13
+
14
+ ## [11.0.0] - 2026-04-25
15
+
16
+ ### 💥 Breaking Changes
17
+
18
+ The `Repository` class is gone — DataSets are now first-class DI tokens. See the [v7 migration guide](../../docs/migrations/v7-functional-di.md) for rationale, recipes, and pitfalls.
19
+
20
+ - Removed `Repository`, `getRepository(injector)`, `Repository.createDataSet(Model, 'pk', settings)`. Declare DataSets with `defineDataSet({ name, store, settings? })` at module scope; the returned `DataSetToken<T, PK>` resolves a configured `DataSet`.
21
+ - `getDataSetFor(injector, DataSetToken)` now takes a single token argument. The old `(injector, Model, 'pk')` overload is gone.
22
+ - Every consumer that used to take `{ model, primaryKey }` (endpoint generators, `registerModel`, etc.) now takes a `DataSetToken` directly.
23
+
3
24
  ## [10.1.11] - 2026-04-17
4
25
 
5
26
  ### ⬆️ Dependencies
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @furystack/repository
2
2
 
3
- Repository implementation for FuryStack.
4
- With a repository, you can implement entity-level business logic in an easy and structured way.
5
- You can authorize, manipulate, and observe CRUD operations.
3
+ DataSet implementation for FuryStack. A DataSet wraps a physical store with
4
+ entity-level business logic — authorization, modification hooks, and change
5
+ events — in a structured way.
6
6
 
7
7
  ## Installation
8
8
 
@@ -12,14 +12,17 @@ npm install @furystack/repository
12
12
  yarn add @furystack/repository
13
13
  ```
14
14
 
15
- ## Setting Up a Repository
15
+ ## Setting Up a DataSet
16
16
 
17
- You can set up a repository as follows:
17
+ A DataSet is declared with `defineDataSet`. It takes the underlying
18
+ `StoreToken` (from `@furystack/core` or a backend adapter) and optional
19
+ settings (authorizers, modifiers, event callbacks). The returned
20
+ `DataSetToken` is a DI token that resolves to a ready-to-use `DataSet`.
18
21
 
19
22
  ```ts
20
- import { Injector } from '@furystack/inject'
21
- import { InMemoryStore, addStore } from '@furystack/core'
22
- import { getRepository, getDataSetFor } from '@furystack/repository'
23
+ import { createInjector } from '@furystack/inject'
24
+ import { InMemoryStore, defineStore } from '@furystack/core'
25
+ import { defineDataSet, getDataSetFor } from '@furystack/repository'
23
26
  import { getLogger } from '@furystack/logging'
24
27
 
25
28
  class MyModel {
@@ -27,57 +30,88 @@ class MyModel {
27
30
  declare value: string
28
31
  }
29
32
 
30
- const myInjector = new Injector()
31
- addStore(myInjector, new InMemoryStore({ model: MyModel, primaryKey: 'id' }))
32
- getRepository(myInjector).createDataSet(MyModel, 'id', {
33
- onEntityAdded: ({ injector, entity }) => {
34
- getLogger(injector).verbose({ message: `An entity was added with value '${entity.value}'` })
33
+ const MyStore = defineStore({
34
+ name: 'my-app/MyStore',
35
+ model: MyModel,
36
+ primaryKey: 'id',
37
+ factory: () => new InMemoryStore({ model: MyModel, primaryKey: 'id' }),
38
+ })
39
+
40
+ const MyDataSet = defineDataSet({
41
+ name: 'my-app/MyDataSet',
42
+ store: MyStore,
43
+ settings: {
44
+ onEntityAdded: ({ injector, entity }) => {
45
+ getLogger(injector).verbose({ message: `An entity was added with value '${entity.value}'` })
46
+ },
47
+ authorizeUpdate: async () => ({
48
+ isAllowed: false,
49
+ message: 'This is a read-only dataset. No update is allowed. :(',
50
+ }),
35
51
  },
36
- authorizeUpdate: async () => ({
37
- isAllowed: false,
38
- message: 'This is a read-only dataset. No update is allowed. :(',
39
- }),
40
52
  })
41
- ```
42
53
 
43
- In the example above, we've created a physical InMemory store for the model `MyModel`, and we've configured a repository with a DataSet.
44
- It will log to a logger when an entity has been added, and it won't allow updates to entities.
54
+ const myInjector = createInjector()
55
+ ```
45
56
 
46
57
  ### Working with the DataSet
47
58
 
48
- A DataSet is similar to a physical store, but it can have custom event callbacks and authorization logic.
49
- You can retrieve the dataset as follows:
59
+ Resolve via `injector.get(MyDataSet)` or the convenience helper
60
+ `getDataSetFor(injector, MyDataSet)`:
50
61
 
51
62
  ```ts
52
- const dataSet = getDataSetFor(myInjector, MyModel, 'id')
53
- dataSet.add(myInjector, { id: 1, value: 'foo' }) // <-- this will log to a logger
54
- dataSet.update(myInjector, 1, { id: 1, value: 'bar' }) // <--- this one will be rejected
63
+ const dataSet = getDataSetFor(myInjector, MyDataSet)
64
+ await dataSet.add(myInjector, { id: 1, value: 'foo' }) // <-- logs via onEntityAdded
65
+ await dataSet.update(myInjector, 1, { id: 1, value: 'bar' }) // <-- rejected by authorizeUpdate
55
66
  ```
56
67
 
57
68
  ### Events
58
69
 
59
- Events are great for logging or monitoring DataSet changes or distributing changes to clients. They are simple optional callbacks – if defined, they will be called on a specific event. These events are `onEntityAdded`, `onEntityUpdated`, and `onEntityRemoved`
70
+ Events are great for logging, monitoring DataSet changes, or distributing
71
+ changes to clients. They are optional callbacks — if defined, they are called
72
+ on a specific event. Supported events: `onEntityAdded`, `onEntityUpdated`,
73
+ `onEntityRemoved`.
60
74
 
61
75
  ### Authorizing operations
62
76
 
63
- **Authorizers** are similar callbacks but they have to return a promise with an `AuthorizationResult` object - you can allow or deny CRUD operations or add additional filters to collections with these Authorize callbacks. These are `authorizeAdd`, `authorizeUpdate`, `authorizeUpdateEntity` (this needs an additional reload of entity but can compare with the original one), `authorizeRemove`, `authorizeRemoveEntity` (also needs reloading), `authorizeGet`, `authorizeGetEntity` (also needs reloading),
77
+ **Authorizers** are similar callbacks that return a promise with an
78
+ `AuthorizationResult`. You can allow or deny CRUD operations, or add
79
+ additional filters to collections. Supported authorizers: `authorizeAdd`,
80
+ `authorizeUpdate`, `authorizeUpdateEntity` (reloads the entity, compares with
81
+ the original), `authorizeRemove`, `authorizeRemoveEntity`, `authorizeGet`,
82
+ `authorizeGetEntity`.
64
83
 
65
84
  ### Modifiers and additional filters
66
85
 
67
- There are some callbacks that modify an entity before persisting (like `modifyOnAdd` or `modifyOnUpdate`). For example, you can fill createdByUser or lastModifiedByUser fields with these.
68
- There is an additional property called `addFilter`, you can use that to add a pre-filter condition **before** a filter expression will be evaluated in the data store - ensuring e.g. that the user can _retrieve_ only stuff from the physical store that they have permission for.
86
+ `modifyOnAdd` / `modifyOnUpdate` transform entities before persisting (e.g.
87
+ fill `createdByUser` / `lastModifiedByUser`). `addFilter` injects a
88
+ pre-filter condition **before** a user-supplied filter expression is
89
+ evaluated, ensuring the caller only ever sees entities they have permission
90
+ for.
69
91
 
70
92
  ### Getting the Context
71
93
 
72
- All methods above have an _injector instance_ on the call parameter - you can use that injector to get service instances from the right caller context. It means that you can use e.g. HttpUserContext to get the current user.
94
+ Every callback receives an `injector` — use it to resolve request-scoped
95
+ services like `HttpUserContext` to identify the caller.
73
96
 
74
97
  ### Server-side writes and the elevated IdentityContext
75
98
 
76
- The DataSet is the **recommended write gateway** for all entity mutations. Writing through the DataSet ensures that authorization rules, modification hooks, and change events (`onEntityAdded`, `onEntityUpdated`, `onEntityRemoved`) are all triggered. These events are required for features like [entity sync](./../entity-sync-service/README.md) to work correctly.
99
+ The DataSet is the **recommended write gateway** for all entity mutations.
100
+ Writing through the DataSet ensures that authorization rules, modification
101
+ hooks, and change events (`onEntityAdded`, `onEntityUpdated`,
102
+ `onEntityRemoved`) all fire. These events are required for features like
103
+ [entity sync](./../entity-sync-service/README.md) to work correctly.
77
104
 
78
- > **Warning:** Writing directly to the underlying physical store bypasses the DataSet layer entirely. No authorization checks, hooks, or events will fire, and downstream consumers (such as entity sync) will **not** be notified of the change.
105
+ > **Warning:** Writing directly to the underlying physical store bypasses
106
+ > the DataSet layer entirely. No authorization checks, hooks, or events
107
+ > fire, and downstream consumers (such as entity sync) will **not** be
108
+ > notified of the change. The `furystack/no-direct-store-token` lint rule
109
+ > guards against this in application code.
79
110
 
80
- For server-side or background operations that don't originate from an HTTP request (e.g. scheduled jobs, migrations, seed scripts), you won't have a user session. Use `useSystemIdentityContext` from `@furystack/core` to create a scoped child injector with elevated privileges:
111
+ For server-side or background operations that don't originate from an HTTP
112
+ request (e.g. scheduled jobs, migrations, seed scripts), you won't have a
113
+ user session. Use `useSystemIdentityContext` from `@furystack/core` to
114
+ create a scoped child injector with elevated privileges:
81
115
 
82
116
  ```ts
83
117
  import { useSystemIdentityContext } from '@furystack/core'
@@ -85,12 +119,16 @@ import { getDataSetFor } from '@furystack/repository'
85
119
  import { usingAsync } from '@furystack/utils'
86
120
 
87
121
  await usingAsync(useSystemIdentityContext({ injector, username: 'background-job' }), async (systemInjector) => {
88
- const dataSet = getDataSetFor(systemInjector, MyModel, 'id')
122
+ const dataSet = getDataSetFor(systemInjector, MyDataSet)
89
123
  await dataSet.add(systemInjector, { value: 'created by background job' })
90
124
  })
91
125
  // systemInjector is disposed here -- all scoped instances cleaned up
92
126
  ```
93
127
 
94
- > **Warning:** `useSystemIdentityContext` bypasses **all** authorization checks. Only use it in trusted server-side contexts. Never pass the returned injector to user-facing request handlers.
128
+ > **Warning:** `useSystemIdentityContext` bypasses **all** authorization
129
+ > checks. Only use it in trusted server-side contexts. Never pass the
130
+ > returned injector to user-facing request handlers.
95
131
 
96
- This pattern ensures that all writes go through the same pipeline, keeping authorization, hooks, and event-driven features consistent regardless of the caller.
132
+ This pattern ensures that all writes go through the same pipeline, keeping
133
+ authorization, hooks, and event-driven features consistent regardless of
134
+ the caller.
@@ -1,98 +1,84 @@
1
1
  import type { FindOptions, PhysicalStore, WithOptionalId } from '@furystack/core';
2
2
  import type { Injector } from '@furystack/inject';
3
- /**
4
- * The result model returned by authorizers
5
- */
3
+ /** Discriminated union returned by authorizer callbacks. */
6
4
  export type AuthorizationResult = SuccessfullyValidationResult | FailedValidationResult;
7
5
  export interface SuccessfullyValidationResult {
8
- /**
9
- * Indicates if the validation was successful
10
- */
11
6
  isAllowed: true;
12
7
  }
13
8
  export interface FailedValidationResult {
14
- /**
15
- * Indicates if the validation was successful
16
- */
17
9
  isAllowed: false;
18
- /**
19
- * The error message string
20
- */
10
+ /** Surfaced as the message of the thrown {@link AuthorizationError}. */
21
11
  message: string;
22
12
  }
23
13
  /**
24
- * Model for authorizers
14
+ * Configuration for a {@link DataSet}: backing store + authorization +
15
+ * modification hooks + filter post-processing. Every callback is optional —
16
+ * an empty `DataSetSettings` performs no checks and forwards calls straight
17
+ * to the physical store.
18
+ *
19
+ * Authorization callbacks come in two flavours:
20
+ *
21
+ * - `authorizeX` — runs **before** the entity is loaded. Use for cheap,
22
+ * identity-only checks ("is the user logged in?", "is the user an admin?").
23
+ * When omitted, no pre-check is performed.
24
+ * - `authorizeXEntity` — runs **after** the entity is loaded, with the
25
+ * loaded entity in scope. Use for ownership / row-level checks. Missing
26
+ * entities skip the per-entity check entirely.
27
+ *
28
+ * A callback returning `{ isAllowed: false }` makes the operation throw
29
+ * {@link AuthorizationError}.
25
30
  */
26
31
  export interface DataSetSettings<T, TPrimaryKey extends keyof T, TWritableData = WithOptionalId<T, TPrimaryKey>> {
27
- /**
28
- * An instance of a physical store
29
- */
30
32
  physicalStore: PhysicalStore<T, TPrimaryKey, TWritableData>;
31
- /**
32
- * Authorizes the entity creation
33
- */
33
+ /** Pre-persist authorization for `add`. */
34
34
  authorizeAdd?: (options: {
35
35
  injector: Injector;
36
36
  entity: TWritableData;
37
37
  }) => Promise<AuthorizationResult>;
38
- /**
39
- * modifies an entity before persisting on creation
40
- */
38
+ /** Pre-persist mutation for `add` (default fields, hashing, normalisation). */
41
39
  modifyOnAdd?: (options: {
42
40
  injector: Injector;
43
41
  entity: TWritableData;
44
42
  }) => Promise<TWritableData>;
45
- /**
46
- * Authorizes entity updates (before the entity gets loaded from the store)
47
- */
43
+ /** Pre-load authorization for `update`. Sees the change, not the entity. */
48
44
  authorizeUpdate?: (options: {
49
45
  injector: Injector;
50
46
  change: Partial<T>;
51
47
  }) => Promise<AuthorizationResult>;
52
- /**
53
- * Authorizes entity updates per loaded entity
54
- */
48
+ /** Post-load authorization for `update`. Sees both the loaded entity and the change. */
55
49
  authorizeUpdateEntity?: (options: {
56
50
  injector: Injector;
57
51
  entity: T;
58
52
  change: Partial<T>;
59
53
  }) => Promise<AuthorizationResult>;
60
- /**
61
- * modifies an entity before persisting on update
62
- */
54
+ /** Pre-persist mutation for `update`. */
63
55
  modifyOnUpdate?: (options: {
64
56
  injector: Injector;
65
57
  id: T[keyof T];
66
58
  entity: Partial<T>;
67
59
  }) => Promise<Partial<T>>;
68
- /**
69
- * Authorizes entity removal (before the entity gets loaded from the store)
70
- */
60
+ /** Pre-load authorization for `remove`. */
71
61
  authorizeRemove?: (options: {
72
62
  injector: Injector;
73
63
  }) => Promise<AuthorizationResult>;
74
- /**
75
- * Authorizes entity removal per loaded entity
76
- */
64
+ /** Post-load authorization for `remove`, per loaded entity. */
77
65
  authorizeRemoveEntity?: (options: {
78
66
  injector: Injector;
79
67
  entity: T;
80
68
  }) => Promise<AuthorizationResult>;
81
- /**
82
- * Authorizes entity retrieval without entity loading
83
- */
69
+ /** Pre-load authorization for `get` / `find` / `count`. No entity in scope. */
84
70
  authorizeGet?: (options: {
85
71
  injector: Injector;
86
72
  }) => Promise<AuthorizationResult>;
87
- /**
88
- * Authorizes entity retrieval
89
- */
73
+ /** Post-load authorization for `get`, per loaded entity. */
90
74
  authorizeGetEntity?: (options: {
91
75
  injector: Injector;
92
76
  entity: T;
93
77
  }) => Promise<AuthorizationResult>;
94
78
  /**
95
- * Additional filter parsing to be appended per filter / query
79
+ * Filter post-processor. Receives the caller's {@link FindOptions} and
80
+ * returns a (potentially augmented) one. Use to inject mandatory clauses
81
+ * (tenant scoping, soft-delete masks) the caller cannot bypass.
96
82
  */
97
83
  addFilter?: <TFields extends Array<keyof T>>(options: {
98
84
  injector: Injector;
@@ -1 +1 @@
1
- {"version":3,"file":"data-set-setting.d.ts","sourceRoot":"","sources":["../src/data-set-setting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjD;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,4BAA4B,GAAG,sBAAsB,CAAA;AAEvF,MAAM,WAAW,4BAA4B;IAC3C;;OAEG;IACH,SAAS,EAAE,IAAI,CAAA;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IAEH,SAAS,EAAE,KAAK,CAAA;IAChB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,EAAE,WAAW,SAAS,MAAM,CAAC,EAAE,aAAa,GAAG,cAAc,CAAC,CAAC,EAAE,WAAW,CAAC;IAC7G;;OAEG;IACH,aAAa,EAAE,aAAa,CAAC,CAAC,EAAE,WAAW,EAAE,aAAa,CAAC,CAAA;IAE3D;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAEvG;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,KAAK,OAAO,CAAC,aAAa,CAAC,CAAA;IAEhG;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAEvG;;OAEG;IACH,qBAAqB,CAAC,EAAE,CAAC,OAAO,EAAE;QAChC,QAAQ,EAAE,QAAQ,CAAA;QAClB,MAAM,EAAE,CAAC,CAAA;QACT,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KACnB,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAElC;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;IAE7G;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAA;KAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAEnF;;OAEG;IACH,qBAAqB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAEpG;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAA;KAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAEhF;;OAEG;IACH,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAEjG;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE;QACpD,QAAQ,EAAE,QAAQ,CAAA;QAClB,MAAM,EAAE,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA;KAChC,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAA;CACvC"}
1
+ {"version":3,"file":"data-set-setting.d.ts","sourceRoot":"","sources":["../src/data-set-setting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACrG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAGjD,4DAA4D;AAC5D,MAAM,MAAM,mBAAmB,GAAG,4BAA4B,GAAG,sBAAsB,CAAA;AAEvF,MAAM,WAAW,4BAA4B;IAC3C,SAAS,EAAE,IAAI,CAAA;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,KAAK,CAAA;IAChB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,EAAE,WAAW,SAAS,MAAM,CAAC,EAAE,aAAa,GAAG,cAAc,CAAC,CAAC,EAAE,WAAW,CAAC;IAC7G,aAAa,EAAE,aAAa,CAAC,CAAC,EAAE,WAAW,EAAE,aAAa,CAAC,CAAA;IAE3D,2CAA2C;IAC3C,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAEvG,+EAA+E;IAC/E,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,KAAK,OAAO,CAAC,aAAa,CAAC,CAAA;IAEhG,4EAA4E;IAC5E,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAEvG,wFAAwF;IACxF,qBAAqB,CAAC,EAAE,CAAC,OAAO,EAAE;QAChC,QAAQ,EAAE,QAAQ,CAAA;QAClB,MAAM,EAAE,CAAC,CAAA;QACT,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KACnB,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAElC,yCAAyC;IACzC,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;IAE7G,2CAA2C;IAC3C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAA;KAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAEnF,+DAA+D;IAC/D,qBAAqB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAEpG,+EAA+E;IAC/E,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAA;KAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAEhF,4DAA4D;IAC5D,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAEjG;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE;QACpD,QAAQ,EAAE,QAAQ,CAAA;QAClB,MAAM,EAAE,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA;KAChC,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAA;CACvC"}
package/esm/data-set.d.ts CHANGED
@@ -3,30 +3,25 @@ import type { Injector } from '@furystack/inject';
3
3
  import { EventHub, type ListenerErrorPayload } from '@furystack/utils';
4
4
  import type { DataSetSettings } from './data-set-setting.js';
5
5
  /**
6
- * An authorized Repository Store instance that wraps a {@link PhysicalStore} with authorization,
7
- * modification hooks, and event dispatching.
6
+ * Authorization-enforcing wrapper around a {@link PhysicalStore}. The
7
+ * recommended write gateway for application code — `furystack/no-direct-store-token`
8
+ * enforces this. Each mutation runs the relevant `authorize*` and
9
+ * `modify*` callbacks from {@link DataSetSettings}, persists, then emits
10
+ * `onEntityAdded` / `onEntityUpdated` / `onEntityRemoved` (consumed by
11
+ * entity sync, audit logs).
8
12
  *
9
- * The DataSet is the **recommended write gateway** for all entity mutations. Writing through the DataSet
10
- * ensures that authorization rules are enforced, modification hooks are applied, and change events
11
- * (`onEntityAdded`, `onEntityUpdated`, `onEntityRemoved`) are emitted -- which are required for features
12
- * like entity sync to function correctly.
13
- *
14
- * All mutating methods require an `injector` parameter that provides the caller's context (e.g. the current
15
- * user's identity). For server-side or background operations that don't originate from an HTTP request,
16
- * use {@link useSystemIdentityContext} to create a scoped child injector with elevated privileges.
13
+ * Mutating methods take an `injector` parameter to surface caller identity
14
+ * to the authorizers. For server-side / background work without an HTTP
15
+ * request, wrap the injector with `useSystemIdentityContext` from
16
+ * `@furystack/core`.
17
17
  *
18
18
  * @example
19
19
  * ```ts
20
- * import { useSystemIdentityContext } from '@furystack/core'
21
- * import { getDataSetFor } from '@furystack/repository'
22
- * import { usingAsync } from '@furystack/utils'
23
- *
24
- * // Server-side write with an elevated identity
25
20
  * await usingAsync(
26
21
  * useSystemIdentityContext({ injector, username: 'background-job' }),
27
22
  * async (systemInjector) => {
28
- * const dataSet = getDataSetFor(systemInjector, MyModel, 'id')
29
- * await dataSet.add(systemInjector, newEntity)
23
+ * const dataSet = getDataSetFor(systemInjector, UserDataSet)
24
+ * await dataSet.add(systemInjector, { username: 'alice', roles: [] })
30
25
  * },
31
26
  * )
32
27
  * ```
@@ -48,64 +43,18 @@ export declare class DataSet<T, TPrimaryKey extends keyof T, TWritableData = Wit
48
43
  onListenerError: ListenerErrorPayload;
49
44
  }> implements Disposable {
50
45
  readonly settings: DataSetSettings<T, TPrimaryKey, TWritableData>;
51
- /**
52
- * Primary key of the contained entity
53
- */
54
46
  primaryKey: TPrimaryKey;
55
- /**
56
- * Adds an entity to the DataSet.
57
- * Runs authorization checks, applies modification hooks, persists to the physical store,
58
- * and emits an `onEntityAdded` event for each created entity.
59
- * @param injector The injector from the caller's context. For server-side or background operations
60
- * without an HTTP request, use a child injector with an elevated {@link IdentityContext}.
61
- * @param entities The entities to add
62
- * @returns The CreateResult with the created entities
63
- */
64
47
  add(injector: Injector, ...entities: TWritableData[]): Promise<CreateResult<T>>;
65
- /**
66
- * Updates an entity in the store.
67
- * Runs authorization checks, applies modification hooks, persists to the physical store,
68
- * and emits an `onEntityUpdated` event.
69
- * @param injector The injector from the caller's context. For server-side or background operations
70
- * without an HTTP request, use a child injector with an elevated {@link IdentityContext}.
71
- * @param id The identifier of the entity
72
- * @param change The update
73
- */
74
48
  update(injector: Injector, id: T[TPrimaryKey], change: Partial<T>): Promise<void>;
75
- /**
76
- * Returns a Promise with the entity count
77
- * @param injector The Injector from the context
78
- * @param filter The Filter that will be applied
79
- * @returns the Count
80
- */
81
49
  count(injector: Injector, filter?: FilterType<T>): Promise<number>;
82
- /**
83
- * Returns a filtered subset of the entity
84
- * @param injector The Injector from the context
85
- * @param filter The Filter definition
86
- * @returns A result with the current items
87
- */
88
50
  find<TFields extends Array<keyof T>>(injector: Injector, filter: FindOptions<T, TFields>): Promise<Array<PartialResult<T, TFields>>>;
89
- /**
90
- * Returns an entity based on its primary key
91
- * @param injector The injector from the context
92
- * @param key The identifier of the entity
93
- * @param select A field list used for projection
94
- * @returns An item with the current unique key or Undefined
95
- */
96
51
  get<TSelect extends Array<keyof T>>(injector: Injector, key: T[TPrimaryKey], select?: TSelect): Promise<PartialResult<T, TSelect> | undefined>;
97
52
  /**
98
- * Removes one or more entities based on their primary keys.
99
- * Runs authorization checks (all-or-nothing), persists to the physical store,
100
- * and emits an `onEntityRemoved` event for each removed entity.
101
- *
102
- * When `authorizeRemoveEntity` is configured, only entities that exist in the store
103
- * are authorized. Keys that don't match any entity are silently forwarded to the
104
- * physical store's `remove()` call.
105
- * @param injector The injector from the caller's context. For server-side or background operations
106
- * without an HTTP request, use a child injector with an elevated {@link IdentityContext}.
107
- * @param keys The primary keys of the entities to remove
108
- * @returns A promise that will be resolved / rejected based on the remove success
53
+ * Removes by primary key. Pre-load `authorizeRemove` and per-entity
54
+ * `authorizeRemoveEntity` are all-or-nothing — any rejection aborts the
55
+ * whole batch before any persist call. When `authorizeRemoveEntity` is
56
+ * configured, missing keys are silently forwarded to the physical store
57
+ * (no entity to authorize).
109
58
  */
110
59
  remove(injector: Injector, ...keys: Array<T[TPrimaryKey]>): Promise<void>;
111
60
  constructor(settings: DataSetSettings<T, TPrimaryKey, TWritableData>);
@@ -1 +1 @@
1
- {"version":3,"file":"data-set.d.ts","sourceRoot":"","sources":["../src/data-set.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAE3G,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,OAAO,CAAC,CAAC,EAAE,WAAW,SAAS,MAAM,CAAC,EAAE,aAAa,GAAG,cAAc,CAAC,CAAC,EAAE,WAAW,CAAC,CACjG,SAAQ,QAAQ,CAAC;IACf,aAAa,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,CAAC,CAAA;KAAE,CAAA;IAChD,eAAe,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE,CAAA;IAC/E,eAAe,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAA;KAAE,CAAA;IAC5D,eAAe,EAAE,oBAAoB,CAAA;CACtC,CACD,YAAW,UAAU;aAwLO,QAAQ,EAAE,eAAe,CAAC,CAAC,EAAE,WAAW,EAAE,aAAa,CAAC;IAtLpF;;OAEG;IACI,UAAU,EAAE,WAAW,CAAA;IAE9B;;;;;;;;OAQG;IACU,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAyB5F;;;;;;;;OAQG;IACU,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB9F;;;;;OAKG;IACU,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAU/E;;;;;OAKG;IACU,IAAI,CAAC,OAAO,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,EAC9C,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IAW5C;;;;;;OAMG;IACU,GAAG,CAAC,OAAO,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,EAC7C,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,EACnB,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAwBjD;;;;;;;;;;;;OAYG;IACU,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;gBA2B1D,QAAQ,EAAE,eAAe,CAAC,CAAC,EAAE,WAAW,EAAE,aAAa,CAAC;CAIrF"}
1
+ {"version":3,"file":"data-set.d.ts","sourceRoot":"","sources":["../src/data-set.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,aAAa,EAEb,cAAc,EACf,MAAM,iBAAiB,CAAA;AAExB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAE5D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,OAAO,CAAC,CAAC,EAAE,WAAW,SAAS,MAAM,CAAC,EAAE,aAAa,GAAG,cAAc,CAAC,CAAC,EAAE,WAAW,CAAC,CACjG,SAAQ,QAAQ,CAAC;IACf,aAAa,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,CAAC,CAAA;KAAE,CAAA;IAChD,eAAe,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE,CAAA;IAC/E,eAAe,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAA;KAAE,CAAA;IAC5D,eAAe,EAAE,oBAAoB,CAAA;CACtC,CACD,YAAW,UAAU;aA0IO,QAAQ,EAAE,eAAe,CAAC,CAAC,EAAE,WAAW,EAAE,aAAa,CAAC;IAxI7E,UAAU,EAAE,WAAW,CAAA;IAEjB,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAyB/E,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBjF,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAUlE,IAAI,CAAC,OAAO,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,EAC9C,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IAW/B,GAAG,CAAC,OAAO,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,EAC7C,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,EACnB,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAwBjD;;;;;;OAMG;IACU,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;gBA2B1D,QAAQ,EAAE,eAAe,CAAC,CAAC,EAAE,WAAW,EAAE,aAAa,CAAC;CAIrF"}
package/esm/data-set.js CHANGED
@@ -1,49 +1,32 @@
1
1
  import { AuthorizationError, selectFields } from '@furystack/core';
2
2
  import { EventHub } from '@furystack/utils';
3
3
  /**
4
- * An authorized Repository Store instance that wraps a {@link PhysicalStore} with authorization,
5
- * modification hooks, and event dispatching.
4
+ * Authorization-enforcing wrapper around a {@link PhysicalStore}. The
5
+ * recommended write gateway for application code — `furystack/no-direct-store-token`
6
+ * enforces this. Each mutation runs the relevant `authorize*` and
7
+ * `modify*` callbacks from {@link DataSetSettings}, persists, then emits
8
+ * `onEntityAdded` / `onEntityUpdated` / `onEntityRemoved` (consumed by
9
+ * entity sync, audit logs).
6
10
  *
7
- * The DataSet is the **recommended write gateway** for all entity mutations. Writing through the DataSet
8
- * ensures that authorization rules are enforced, modification hooks are applied, and change events
9
- * (`onEntityAdded`, `onEntityUpdated`, `onEntityRemoved`) are emitted -- which are required for features
10
- * like entity sync to function correctly.
11
- *
12
- * All mutating methods require an `injector` parameter that provides the caller's context (e.g. the current
13
- * user's identity). For server-side or background operations that don't originate from an HTTP request,
14
- * use {@link useSystemIdentityContext} to create a scoped child injector with elevated privileges.
11
+ * Mutating methods take an `injector` parameter to surface caller identity
12
+ * to the authorizers. For server-side / background work without an HTTP
13
+ * request, wrap the injector with `useSystemIdentityContext` from
14
+ * `@furystack/core`.
15
15
  *
16
16
  * @example
17
17
  * ```ts
18
- * import { useSystemIdentityContext } from '@furystack/core'
19
- * import { getDataSetFor } from '@furystack/repository'
20
- * import { usingAsync } from '@furystack/utils'
21
- *
22
- * // Server-side write with an elevated identity
23
18
  * await usingAsync(
24
19
  * useSystemIdentityContext({ injector, username: 'background-job' }),
25
20
  * async (systemInjector) => {
26
- * const dataSet = getDataSetFor(systemInjector, MyModel, 'id')
27
- * await dataSet.add(systemInjector, newEntity)
21
+ * const dataSet = getDataSetFor(systemInjector, UserDataSet)
22
+ * await dataSet.add(systemInjector, { username: 'alice', roles: [] })
28
23
  * },
29
24
  * )
30
25
  * ```
31
26
  */
32
27
  export class DataSet extends EventHub {
33
28
  settings;
34
- /**
35
- * Primary key of the contained entity
36
- */
37
29
  primaryKey;
38
- /**
39
- * Adds an entity to the DataSet.
40
- * Runs authorization checks, applies modification hooks, persists to the physical store,
41
- * and emits an `onEntityAdded` event for each created entity.
42
- * @param injector The injector from the caller's context. For server-side or background operations
43
- * without an HTTP request, use a child injector with an elevated {@link IdentityContext}.
44
- * @param entities The entities to add
45
- * @returns The CreateResult with the created entities
46
- */
47
30
  async add(injector, ...entities) {
48
31
  await Promise.all(entities.map(async (entity) => {
49
32
  if (this.settings.authorizeAdd) {
@@ -62,15 +45,6 @@ export class DataSet extends EventHub {
62
45
  });
63
46
  return createResult;
64
47
  }
65
- /**
66
- * Updates an entity in the store.
67
- * Runs authorization checks, applies modification hooks, persists to the physical store,
68
- * and emits an `onEntityUpdated` event.
69
- * @param injector The injector from the caller's context. For server-side or background operations
70
- * without an HTTP request, use a child injector with an elevated {@link IdentityContext}.
71
- * @param id The identifier of the entity
72
- * @param change The update
73
- */
74
48
  async update(injector, id, change) {
75
49
  if (this.settings.authorizeUpdate) {
76
50
  const result = await this.settings.authorizeUpdate({ injector, change });
@@ -93,12 +67,6 @@ export class DataSet extends EventHub {
93
67
  await this.settings.physicalStore.update(id, parsed);
94
68
  this.emit('onEntityUpdated', { injector, change: parsed, id });
95
69
  }
96
- /**
97
- * Returns a Promise with the entity count
98
- * @param injector The Injector from the context
99
- * @param filter The Filter that will be applied
100
- * @returns the Count
101
- */
102
70
  async count(injector, filter) {
103
71
  if (this.settings.authorizeGet) {
104
72
  const result = await this.settings.authorizeGet({ injector });
@@ -108,12 +76,6 @@ export class DataSet extends EventHub {
108
76
  }
109
77
  return await this.settings.physicalStore.count(filter);
110
78
  }
111
- /**
112
- * Returns a filtered subset of the entity
113
- * @param injector The Injector from the context
114
- * @param filter The Filter definition
115
- * @returns A result with the current items
116
- */
117
79
  async find(injector, filter) {
118
80
  if (this.settings.authorizeGet) {
119
81
  const result = await this.settings.authorizeGet({ injector });
@@ -124,13 +86,6 @@ export class DataSet extends EventHub {
124
86
  const parsedFilter = this.settings.addFilter ? await this.settings.addFilter({ injector, filter }) : filter;
125
87
  return this.settings.physicalStore.find(parsedFilter);
126
88
  }
127
- /**
128
- * Returns an entity based on its primary key
129
- * @param injector The injector from the context
130
- * @param key The identifier of the entity
131
- * @param select A field list used for projection
132
- * @returns An item with the current unique key or Undefined
133
- */
134
89
  async get(injector, key, select) {
135
90
  if (this.settings.authorizeGet) {
136
91
  const result = await this.settings.authorizeGet({ injector });
@@ -155,17 +110,11 @@ export class DataSet extends EventHub {
155
110
  return await this.settings.physicalStore.get(key, select);
156
111
  }
157
112
  /**
158
- * Removes one or more entities based on their primary keys.
159
- * Runs authorization checks (all-or-nothing), persists to the physical store,
160
- * and emits an `onEntityRemoved` event for each removed entity.
161
- *
162
- * When `authorizeRemoveEntity` is configured, only entities that exist in the store
163
- * are authorized. Keys that don't match any entity are silently forwarded to the
164
- * physical store's `remove()` call.
165
- * @param injector The injector from the caller's context. For server-side or background operations
166
- * without an HTTP request, use a child injector with an elevated {@link IdentityContext}.
167
- * @param keys The primary keys of the entities to remove
168
- * @returns A promise that will be resolved / rejected based on the remove success
113
+ * Removes by primary key. Pre-load `authorizeRemove` and per-entity
114
+ * `authorizeRemoveEntity` are all-or-nothing — any rejection aborts the
115
+ * whole batch before any persist call. When `authorizeRemoveEntity` is
116
+ * configured, missing keys are silently forwarded to the physical store
117
+ * (no entity to authorize).
169
118
  */
170
119
  async remove(injector, ...keys) {
171
120
  if (keys.length === 0) {
@@ -182,7 +131,7 @@ export class DataSet extends EventHub {
182
131
  filter: { [this.primaryKey]: { $in: keys } },
183
132
  });
184
133
  await Promise.all(entities.map(async (entity) => {
185
- const removeResult = await this.settings.authorizeRemoveEntity({ injector, entity: entity });
134
+ const removeResult = await this.settings.authorizeRemoveEntity({ injector, entity });
186
135
  if (!removeResult.isAllowed) {
187
136
  throw new AuthorizationError(removeResult.message);
188
137
  }
@@ -1 +1 @@
1
- {"version":3,"file":"data-set.js","sourceRoot":"","sources":["../src/data-set.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-set.js","sourceRoot":"","sources":["../src/data-set.ts"],"names":[],"mappings":"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"}