entropic-bond 1.59.4 → 1.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,7 +19,7 @@ Typically, you will derive all your business logic entities from the `EntropicCo
19
19
 
20
20
  ### API
21
21
 
22
- You can find the API documentation [here](docs/modules.md).
22
+ You can find the API documentation in the [docs/](./docs) directory.
23
23
 
24
24
  ### Persistence
25
25
 
@@ -31,7 +31,7 @@ The properties or attributes that you want to be streamed should be preceded by
31
31
 
32
32
  ```ts
33
33
  @registerPersistentClass( 'MyEntity' )
34
- class MyEntity extends EntropicBond {
34
+ class MyEntity extends Persistent {
35
35
  @persistent private _persistentProp1: string
36
36
  @persistent private _persistentProp2: boolean
37
37
  @persistent private _persistentProp3: AnotherPersistentObject
@@ -45,7 +45,7 @@ class MyEntity extends EntropicBond {
45
45
 
46
46
  #### Storing and querying the persistent entities
47
47
 
48
- The database abstraction is provided by the `Store` object. To learn how to set up a concrete database, [see below](setup_the_database_access).
48
+ The database abstraction is provided by the `Store` object.
49
49
 
50
50
  The `Store.getModel` method will return an object with methods to access the database.
51
51
 
@@ -80,7 +80,7 @@ Currently, there is an official plugin to connect to a **Firebase** _Firestore_
80
80
  npm i entropic-bond-firebase
81
81
  ```
82
82
 
83
- You can develop new plugins following the [plugin developer's](plugin_development) section.
83
+ You can develop new plugins following the plugin developer's section.
84
84
 
85
85
  You should instantiate the concrete implementation of the `DataSource` and pass it to the `useDataSource` method of the `Store` object.
86
86
 
@@ -88,10 +88,214 @@ You should instantiate the concrete implementation of the `DataSource` and pass
88
88
  Store.useDataSource( new JsonDataSource() )
89
89
  ```
90
90
 
91
+ > See the complete example at [samples/01-persistence.ts](./samples/01-persistence.ts)
92
+
91
93
  ### Observability
92
94
 
95
+ The observability mechanism allows entities to notify when their properties change. Derive your class from `EntropicComponent` (which extends `Persistent`) and use `changeProp` in setters or `pushAndNotify`/`removeAndNotify` for arrays.
96
+
97
+ ```ts
98
+ import { EntropicComponent } from 'entropic-bond'
99
+
100
+ class MyEntity extends EntropicComponent {
101
+ private _name: string = ''
102
+
103
+ get name(): string { return this._name }
104
+ set name(value: string) { this.changeProp('name', value) }
105
+ }
106
+
107
+ const entity = new MyEntity()
108
+ const unsub = entity.onChange(event => console.log('Changed:', event))
109
+
110
+ entity.name = 'new value' // triggers the onChange listener
111
+ unsub() // removes the listener
112
+ ```
113
+
114
+ You can also directly use the generic `Observable<T>` class for standalone observer patterns.
115
+
116
+ ```ts
117
+ import { Observable } from 'entropic-bond'
118
+
119
+ const observable = new Observable<string>()
120
+ const unsubscribe = observable.subscribe(event => console.log(event))
121
+ observable.notify('hello')
122
+ ```
123
+
124
+ > See the complete example at [samples/02-observability.ts](./samples/02-observability.ts)
125
+
93
126
  ### Auth
94
127
 
128
+ Authentication is abstracted via `AuthService`. Register a concrete implementation and use the `Auth` singleton.
129
+
130
+ ```ts
131
+ import { Auth, AuthMock } from 'entropic-bond'
132
+
133
+ Auth.useAuthService(new AuthMock())
134
+
135
+ async function example() {
136
+ const user = await Auth.instance.login({ authProvider: 'email', email: 'user@test.com', password: '123456' })
137
+ console.log(user.id, user.email)
138
+
139
+ Auth.instance.onAuthStateChange(credentials => {
140
+ console.log('Auth state changed:', credentials)
141
+ })
142
+ }
143
+ ```
144
+
145
+ Plugins exist for production providers (e.g., Firebase Authentication). To create a custom provider, implement the `AuthService` abstract class.
146
+
147
+ > See the complete example at [samples/03-auth.ts](./samples/03-auth.ts)
148
+
149
+ ### Server Auth
150
+
151
+ For admin-level user management (list, update, delete users), use `ServerAuth`.
152
+
153
+ ```ts
154
+ import { ServerAuth, ServerAuthMock } from 'entropic-bond'
155
+
156
+ ServerAuth.useServerAuthService(new ServerAuthMock())
157
+
158
+ const user = await ServerAuth.instance.getUser('user-id')
159
+ await ServerAuth.instance.updateUser('user-id', { name: 'Updated Name' })
160
+ await ServerAuth.instance.deleteUser('user-id')
161
+ ```
162
+
163
+ > See the complete example at [samples/04-server-auth.ts](./samples/04-server-auth.ts)
164
+
165
+ ### Cloud Storage
166
+
167
+ File storage is abstracted via `CloudStorage`. Register a provider and use the singleton, or use the `StoredFile` persistent entity.
168
+
169
+ ```ts
170
+ import { CloudStorage, MockCloudStorage, StoredFile } from 'entropic-bond'
171
+
172
+ CloudStorage.useCloudStorage(new MockCloudStorage())
173
+
174
+ // Direct usage
175
+ const url = await CloudStorage.defaultCloudStorage.save('my-file', fileData)
176
+ const downloadUrl = await CloudStorage.defaultCloudStorage.getUrl('my-file')
177
+
178
+ // Or with StoredFile (persistent entity)
179
+ const file = new StoredFile()
180
+ file.setDataToStore(someBlob)
181
+ await file.save()
182
+ console.log(file.url)
183
+ ```
184
+
185
+ > See the complete example at [samples/05-cloud-storage.ts](./samples/05-cloud-storage.ts)
186
+
187
+ ### Cloud Functions
188
+
189
+ Call serverless functions through an abstract interface.
190
+
191
+ ```ts
192
+ import { CloudFunctions, CloudFunctionsMock } from 'entropic-bond'
193
+
194
+ const mockService = new CloudFunctionsMock({
195
+ myFunction: async (params) => `Hello ${params.name}`
196
+ })
197
+ CloudFunctions.useCloudFunctionsService(mockService)
198
+
199
+ const fn = CloudFunctions.instance.getFunction('myFunction')
200
+ const result = await fn({ name: 'World' })
201
+ ```
202
+
203
+ > See the complete example at [samples/06-cloud-functions.ts](./samples/06-cloud-functions.ts)
204
+
205
+ ### Realtime document listeners
206
+
207
+ The `Model` supports realtime updates on documents and collections.
208
+
209
+ ```ts
210
+ const model = Store.getModel<MyEntity>('MyEntity')
211
+
212
+ // Listen to a single document
213
+ const unsubscribe1 = model.onDocumentChange('doc-id', change => {
214
+ console.log('Before:', change.before, 'After:', change.after)
215
+ })
216
+
217
+ // Listen to a collection query
218
+ const unsubscribe2 = model.onCollectionChange(
219
+ model.find().where('name', '==', 'foo'),
220
+ change => console.log('Collection changed:', change)
221
+ )
222
+
223
+ // Listen to a wildcard collection template
224
+ const unsubscribe3 = model.onCollectionTemplateChange('{userId}/Posts', change => {
225
+ console.log('Post changed in', change.collectionPath)
226
+ })
227
+ ```
228
+
229
+ > See the complete example at [samples/07-realtime-listeners.ts](./samples/07-realtime-listeners.ts)
230
+
231
+ ### DataSource plugins
232
+
233
+ The persistence layer uses a `DataSource` to communicate with the database. Implement the abstract `DataSource` class to support new backends.
234
+
235
+ ```ts
236
+ import { DataSource, Store } from 'entropic-bond'
237
+
238
+ class MyDatabase extends DataSource {
239
+ // implement all abstract methods: findById, find, save, delete, etc.
240
+ }
241
+
242
+ Store.useDataSource(new MyDatabase())
243
+ ```
244
+
245
+ The official Firebase plugin is available as `entropic-bond-firebase`.
246
+
247
+ ```sh
248
+ npm i entropic-bond-firebase
249
+ ```
250
+
251
+ > See the complete example at [samples/10-datasource-plugin.ts](./samples/10-datasource-plugin.ts)
252
+
253
+ ### Cached property references
254
+
255
+ When a property holds a reference to another persistent entity, you can embed selected primitive fields directly in the reference to avoid extra queries.
256
+
257
+ ```ts
258
+ @registerPersistentClass('Team')
259
+ class Team extends EntropicComponent {
260
+ @persistent private _name: string
261
+ }
262
+
263
+ @registerPersistentClass('User')
264
+ class User extends EntropicComponent {
265
+ @persistentReferenceWithCachedProps(['_name'], 'Team')
266
+ private _team: Team
267
+ }
268
+ ```
269
+
270
+ The `CachedPropsUpdater` (installed via `DataSource.installCachedPropsUpdater()`) will propagate changes to cached props across all referencing documents.
271
+
272
+ > See the complete example at [samples/08-cached-props.ts](./samples/08-cached-props.ts)
273
+
274
+ ### Utility functions
275
+
276
+ ```ts
277
+ import { camelCase, snakeCase, replaceValue, getDeepValue } from 'entropic-bond'
278
+
279
+ camelCase('hello-world') // 'helloWorld'
280
+ snakeCase('helloWorld') // 'hello-world'
281
+ replaceValue('Hi ${name}', { name: 'John' }) // 'Hi John'
282
+ ```
283
+
284
+ > See the complete example at [samples/09-utils.ts](./samples/09-utils.ts)
95
285
 
286
+ ### Samples
96
287
 
288
+ Complete, runnable examples are available in the [`samples/`](./samples) directory:
97
289
 
290
+ | Section | Sample |
291
+ |---------|--------|
292
+ | Persistence | [01-persistence.ts](./samples/01-persistence.ts) |
293
+ | Observability | [02-observability.ts](./samples/02-observability.ts) |
294
+ | Auth | [03-auth.ts](./samples/03-auth.ts) |
295
+ | Server Auth | [04-server-auth.ts](./samples/04-server-auth.ts) |
296
+ | Cloud Storage | [05-cloud-storage.ts](./samples/05-cloud-storage.ts) |
297
+ | Cloud Functions | [06-cloud-functions.ts](./samples/06-cloud-functions.ts) |
298
+ | Realtime listeners | [07-realtime-listeners.ts](./samples/07-realtime-listeners.ts) |
299
+ | Cached property references | [08-cached-props.ts](./samples/08-cached-props.ts) |
300
+ | Utility functions | [09-utils.ts](./samples/09-utils.ts) |
301
+ | DataSource plugins | [10-datasource-plugin.ts](./samples/10-datasource-plugin.ts) |