tinybase 4.3.10 → 4.3.12
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/lib/cjs/persisters/persister-partykit-client.cjs +1 -1
- package/lib/cjs/persisters/persister-partykit-client.cjs.gz +0 -0
- package/lib/cjs/persisters/persister-partykit-server.cjs +1 -1
- package/lib/cjs/persisters/persister-partykit-server.cjs.gz +0 -0
- package/lib/cjs/ui-react-dom-debug.cjs +1 -1
- package/lib/cjs/ui-react-dom-debug.cjs.gz +0 -0
- package/lib/cjs/ui-react-dom.cjs +1 -1
- package/lib/cjs/ui-react-dom.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-partykit-client.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-partykit-client.cjs.gz +0 -0
- package/lib/cjs-es6/persisters/persister-partykit-server.cjs +1 -1
- package/lib/cjs-es6/persisters/persister-partykit-server.cjs.gz +0 -0
- package/lib/cjs-es6/ui-react-dom-debug.cjs +1 -1
- package/lib/cjs-es6/ui-react-dom-debug.cjs.gz +0 -0
- package/lib/cjs-es6/ui-react-dom.cjs +1 -1
- package/lib/cjs-es6/ui-react-dom.cjs.gz +0 -0
- package/lib/debug/persisters/persister-partykit-client.js +29 -19
- package/lib/debug/persisters/persister-partykit-server.js +155 -64
- package/lib/debug/ui-react-dom.js +45 -30
- package/lib/es6/persisters/persister-partykit-client.js +1 -1
- package/lib/es6/persisters/persister-partykit-client.js.gz +0 -0
- package/lib/es6/persisters/persister-partykit-server.js +1 -1
- package/lib/es6/persisters/persister-partykit-server.js.gz +0 -0
- package/lib/es6/ui-react-dom-debug.js +1 -1
- package/lib/es6/ui-react-dom-debug.js.gz +0 -0
- package/lib/es6/ui-react-dom.js +1 -1
- package/lib/es6/ui-react-dom.js.gz +0 -0
- package/lib/persisters/persister-partykit-client.js +1 -1
- package/lib/persisters/persister-partykit-client.js.gz +0 -0
- package/lib/persisters/persister-partykit-server.js +1 -1
- package/lib/persisters/persister-partykit-server.js.gz +0 -0
- package/lib/types/persisters/persister-indexed-db.d.ts +4 -5
- package/lib/types/persisters/persister-partykit-client.d.ts +18 -7
- package/lib/types/persisters/persister-partykit-server.d.ts +335 -7
- package/lib/types/tools.d.ts +4 -6
- package/lib/types/ui-react-dom.d.ts +13 -2
- package/lib/types/ui-react.d.ts +4 -4
- package/lib/types/with-schemas/persisters/persister-indexed-db.d.ts +4 -5
- package/lib/types/with-schemas/persisters/persister-partykit-client.d.ts +18 -7
- package/lib/types/with-schemas/persisters/persister-partykit-server.d.ts +359 -7
- package/lib/types/with-schemas/tools.d.ts +4 -6
- package/lib/types/with-schemas/ui-react-dom.d.ts +21 -4
- package/lib/types/with-schemas/ui-react.d.ts +4 -4
- package/lib/ui-react-dom.js +1 -1
- package/lib/ui-react-dom.js.gz +0 -0
- package/lib/umd/persisters/persister-partykit-client.js +1 -1
- package/lib/umd/persisters/persister-partykit-client.js.gz +0 -0
- package/lib/umd/persisters/persister-partykit-server.js +1 -1
- package/lib/umd/persisters/persister-partykit-server.js.gz +0 -0
- package/lib/umd/ui-react-dom-debug.js +1 -1
- package/lib/umd/ui-react-dom-debug.js.gz +0 -0
- package/lib/umd/ui-react-dom.js +1 -1
- package/lib/umd/ui-react-dom.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-partykit-client.js +1 -1
- package/lib/umd-es6/persisters/persister-partykit-client.js.gz +0 -0
- package/lib/umd-es6/persisters/persister-partykit-server.js +1 -1
- package/lib/umd-es6/persisters/persister-partykit-server.js.gz +0 -0
- package/lib/umd-es6/ui-react-dom-debug.js +1 -1
- package/lib/umd-es6/ui-react-dom-debug.js.gz +0 -0
- package/lib/umd-es6/ui-react-dom.js +1 -1
- package/lib/umd-es6/ui-react-dom.js.gz +0 -0
- package/package.json +10 -10
- package/readme.md +2 -2
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
* @since 4.3.0
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
import {Cell, NoTablesSchema, NoValuesSchema, Value} from '../store';
|
|
21
22
|
import {Connection, Party, Request, Server} from 'partykit/server';
|
|
23
|
+
import {Id} from '../common';
|
|
22
24
|
|
|
23
25
|
/**
|
|
24
26
|
* The TinyBasePartyKitServerConfig type describes the configuration of a
|
|
@@ -38,13 +40,13 @@ import {Connection, Party, Request, Server} from 'partykit/server';
|
|
|
38
40
|
* 'tinybase_' in case you are worried about colliding with other data stored
|
|
39
41
|
* in the room.
|
|
40
42
|
*
|
|
41
|
-
* ```js
|
|
42
|
-
*
|
|
43
|
+
* ```js
|
|
44
|
+
* class MyServer extends TinyBasePartyKitServer {
|
|
43
45
|
* readonly config: TinyBasePartyKitServerConfig = {
|
|
44
46
|
* storePath: '/my_tinybase',
|
|
45
47
|
* storagePrefix: 'tinybase_',
|
|
46
48
|
* };
|
|
47
|
-
* }
|
|
49
|
+
* }
|
|
48
50
|
* ```
|
|
49
51
|
* @category Configuration
|
|
50
52
|
* @since v4.3.9
|
|
@@ -56,6 +58,14 @@ export type TinyBasePartyKitServerConfig = {
|
|
|
56
58
|
* on the client. Both default to '/store'.
|
|
57
59
|
*/
|
|
58
60
|
storePath?: string;
|
|
61
|
+
/**
|
|
62
|
+
* The prefix at the beginning of the web socket messages between the client
|
|
63
|
+
* and the server when synchronizing the Store. Use this to make sure they do
|
|
64
|
+
* not collide with any other message syntax that your room is using. This
|
|
65
|
+
* must match the messagePrefix property of the PartyKitPersisterConfig object
|
|
66
|
+
* used on the client. Both default to an empty string.
|
|
67
|
+
*/
|
|
68
|
+
messagePrefix?: string;
|
|
59
69
|
/**
|
|
60
70
|
* The prefix used before all the keys in the server's durable storage. Use
|
|
61
71
|
* this in case you are worried about the Store data colliding with other data
|
|
@@ -98,7 +108,7 @@ export type TinyBasePartyKitServerConfig = {
|
|
|
98
108
|
* ```js
|
|
99
109
|
* // This is your PartyKit server entry point.
|
|
100
110
|
*
|
|
101
|
-
*
|
|
111
|
+
* class MyServer extends TinyBasePartyKitServer {
|
|
102
112
|
* constructor(party) {
|
|
103
113
|
* super(party);
|
|
104
114
|
* // custom constructor code
|
|
@@ -124,6 +134,8 @@ export type TinyBasePartyKitServerConfig = {
|
|
|
124
134
|
* See the [PartyKit server API
|
|
125
135
|
* documentation](https://docs.partykit.io/reference/partyserver-api/) for
|
|
126
136
|
* more details.
|
|
137
|
+
* @category Creation
|
|
138
|
+
* @since v4.3.0
|
|
127
139
|
*/
|
|
128
140
|
export class TinyBasePartyKitServer implements Server {
|
|
129
141
|
constructor(party: Party);
|
|
@@ -132,6 +144,8 @@ export class TinyBasePartyKitServer implements Server {
|
|
|
132
144
|
* object of the TinyBasePartyKitServerConfig type.
|
|
133
145
|
*
|
|
134
146
|
* See the documentation for that type for more details.
|
|
147
|
+
* @category Configuration
|
|
148
|
+
* @since v4.3.9
|
|
135
149
|
*/
|
|
136
150
|
readonly config: TinyBasePartyKitServerConfig;
|
|
137
151
|
/**
|
|
@@ -143,7 +157,7 @@ export class TinyBasePartyKitServer implements Server {
|
|
|
143
157
|
* synchronization stays supported:
|
|
144
158
|
*
|
|
145
159
|
* ```js
|
|
146
|
-
*
|
|
160
|
+
* class MyServer extends TinyBasePartyKitServer {
|
|
147
161
|
* async onRequest(request) {
|
|
148
162
|
* // custom onRequest code, else:
|
|
149
163
|
* return await super.onRequest(request);
|
|
@@ -154,6 +168,8 @@ export class TinyBasePartyKitServer implements Server {
|
|
|
154
168
|
* See the [PartyKit server API
|
|
155
169
|
* documentation](https://docs.partykit.io/reference/partyserver-api/) for
|
|
156
170
|
* more details.
|
|
171
|
+
* @category Connection
|
|
172
|
+
* @since v4.3.0
|
|
157
173
|
*/
|
|
158
174
|
onRequest(request: Request): Promise<Response>;
|
|
159
175
|
/**
|
|
@@ -165,7 +181,7 @@ export class TinyBasePartyKitServer implements Server {
|
|
|
165
181
|
* synchronization stays supported:
|
|
166
182
|
*
|
|
167
183
|
* ```js
|
|
168
|
-
*
|
|
184
|
+
* class MyServer extends TinyBasePartyKitServer {
|
|
169
185
|
* async onMessage(message, client) {
|
|
170
186
|
* await super.onMessage(message, client);
|
|
171
187
|
* // custom onMessage code
|
|
@@ -176,6 +192,342 @@ export class TinyBasePartyKitServer implements Server {
|
|
|
176
192
|
* See the [PartyKit server API
|
|
177
193
|
* documentation](https://docs.partykit.io/reference/partyserver-api/) for
|
|
178
194
|
* more details.
|
|
195
|
+
* @category Connection
|
|
196
|
+
* @since v4.3.0
|
|
197
|
+
*/
|
|
198
|
+
onMessage(message: string, client: Connection): Promise<void>;
|
|
199
|
+
/**
|
|
200
|
+
* The canSetTable method lets you allow or disallow any changes to a Table
|
|
201
|
+
* stored on the server, as sent from a client.
|
|
202
|
+
*
|
|
203
|
+
* This is one of the functions use to sanitize the data that is being sent
|
|
204
|
+
* from a client. Perhaps you might want to make sure the server-stored data
|
|
205
|
+
* adheres to a particular schema, or you might want to make certain data
|
|
206
|
+
* read-only. Remember that you cannot trust the client to only send data that
|
|
207
|
+
* the server considers valid or safe.
|
|
208
|
+
*
|
|
209
|
+
* This method is passed the Table Id that the client is trying to change. The
|
|
210
|
+
* `initialSave` parameter distinguishes between the first bulk save of the
|
|
211
|
+
* Store to the PartyKit room over HTTP (`true`), and subsequent incremental
|
|
212
|
+
* updates over a web sockets (`false`).
|
|
213
|
+
*
|
|
214
|
+
* The final `requestOrConnection` parameter will either be the HTTP(S)
|
|
215
|
+
* request or the web socket connection, in those two cases respectively. You
|
|
216
|
+
* can, for instance, use this to distinguish between different users.
|
|
217
|
+
*
|
|
218
|
+
* Return `false` from this method to disallow changes to this Table on the
|
|
219
|
+
* server, or `true` to allow them (subject to subsequent canSetRow method,
|
|
220
|
+
* canDelRow method, canSetCell method, and canSetCell method checks). The
|
|
221
|
+
* default implementation returns `true` to allow all changes.
|
|
222
|
+
* @example
|
|
223
|
+
* The following implementation will strip out any attempts by the client to
|
|
224
|
+
* update any 'user' tabular data after the initial save:
|
|
225
|
+
*
|
|
226
|
+
* ```js
|
|
227
|
+
* class MyServer extends TinyBasePartyKitServer {
|
|
228
|
+
* canSetTable(tableId, initialSave) {
|
|
229
|
+
* return initialSave || tableId != 'user';
|
|
230
|
+
* }
|
|
231
|
+
* }
|
|
232
|
+
* ```
|
|
233
|
+
* @category Sanitization
|
|
234
|
+
* @since v4.3.12
|
|
235
|
+
*/
|
|
236
|
+
canSetTable(
|
|
237
|
+
tableId: Id,
|
|
238
|
+
initialSave: boolean,
|
|
239
|
+
requestOrConnection: Request | Connection,
|
|
240
|
+
): boolean;
|
|
241
|
+
/**
|
|
242
|
+
* The canDelTable method lets you allow or disallow deletions of a Table
|
|
243
|
+
* stored on the server, as sent from a client.
|
|
244
|
+
*
|
|
245
|
+
* This is one of the functions use to sanitize the data that is being sent
|
|
246
|
+
* from a client. Perhaps you might want to make sure the server-stored data
|
|
247
|
+
* adheres to a particular schema, or you might want to make certain data
|
|
248
|
+
* read-only. Remember that you cannot trust the client to only send data that
|
|
249
|
+
* the server considers valid or safe.
|
|
250
|
+
*
|
|
251
|
+
* This method is passed the Table Id that the client is trying to delete. The
|
|
252
|
+
* `connection` parameter will be the web socket connection of that client.
|
|
253
|
+
* You can, for instance, use this to distinguish between different users.
|
|
254
|
+
*
|
|
255
|
+
* Return `false` from this method to disallow this Table from being deleted
|
|
256
|
+
* on the server, or `true` to allow it. The default implementation returns
|
|
257
|
+
* `true` to allow deletion.
|
|
258
|
+
* @example
|
|
259
|
+
* The following implementation will strip out any attempts by the client to
|
|
260
|
+
* delete the 'user' Table:
|
|
261
|
+
*
|
|
262
|
+
* ```js
|
|
263
|
+
* class MyServer extends TinyBasePartyKitServer {
|
|
264
|
+
* canDelTable(tableId) {
|
|
265
|
+
* return tableId != 'user';
|
|
266
|
+
* }
|
|
267
|
+
* }
|
|
268
|
+
* ```
|
|
269
|
+
* @category Sanitization
|
|
270
|
+
* @since v4.3.12
|
|
271
|
+
*/
|
|
272
|
+
canDelTable(tableId: Id, connection: Connection): boolean;
|
|
273
|
+
/**
|
|
274
|
+
* The canSetRow method lets you allow or disallow any changes to a Row stored
|
|
275
|
+
* on the server, as sent from a client.
|
|
276
|
+
*
|
|
277
|
+
* This is one of the functions use to sanitize the data that is being sent
|
|
278
|
+
* from a client. Perhaps you might want to make sure the server-stored data
|
|
279
|
+
* adheres to a particular schema, or you might want to make certain data
|
|
280
|
+
* read-only. Remember that you cannot trust the client to only send data that
|
|
281
|
+
* the server considers valid or safe.
|
|
282
|
+
*
|
|
283
|
+
* This method is passed the Table Id and Row Id that the client is trying to
|
|
284
|
+
* change. The `initialSave` parameter distinguishes between the first bulk
|
|
285
|
+
* save of the Store to the PartyKit room over HTTP (`true`), and subsequent
|
|
286
|
+
* incremental updates over a web sockets (`false`).
|
|
287
|
+
*
|
|
288
|
+
* The final `requestOrConnection` parameter will either be the HTTP(S)
|
|
289
|
+
* request or the web socket connection, in those two cases respectively. You
|
|
290
|
+
* can, for instance, use this to distinguish between different users.
|
|
291
|
+
*
|
|
292
|
+
* Return `false` from this method to disallow changes to this Row on the
|
|
293
|
+
* server, or `true` to allow them (subject to subsequent canSetCell method
|
|
294
|
+
* and canSetCell method checks). The default implementation returns `true` to
|
|
295
|
+
* allow all changes.
|
|
296
|
+
* @example
|
|
297
|
+
* The following implementation will strip out any attempts by the client to
|
|
298
|
+
* update the 'me' Row of the 'user' Table after the initial save:
|
|
299
|
+
*
|
|
300
|
+
* ```js
|
|
301
|
+
* class MyServer extends TinyBasePartyKitServer {
|
|
302
|
+
* canSetRow(tableId, rowId, initialSave) {
|
|
303
|
+
* return initialSave || tableId != 'user' || rowId != 'me';
|
|
304
|
+
* }
|
|
305
|
+
* }
|
|
306
|
+
* ```
|
|
307
|
+
* @category Sanitization
|
|
308
|
+
* @since v4.3.12
|
|
309
|
+
*/
|
|
310
|
+
canSetRow(
|
|
311
|
+
tableId: Id,
|
|
312
|
+
rowId: Id,
|
|
313
|
+
initialSave: boolean,
|
|
314
|
+
requestOrConnection: Request | Connection,
|
|
315
|
+
): boolean;
|
|
316
|
+
/**
|
|
317
|
+
* The canDelRow method lets you allow or disallow deletions of a Row stored
|
|
318
|
+
* on the server, as sent from a client.
|
|
319
|
+
*
|
|
320
|
+
* This is one of the functions use to sanitize the data that is being sent
|
|
321
|
+
* from a client. Perhaps you might want to make sure the server-stored data
|
|
322
|
+
* adheres to a particular schema, or you might want to make certain data
|
|
323
|
+
* read-only. Remember that you cannot trust the client to only send data that
|
|
324
|
+
* the server considers valid or safe.
|
|
325
|
+
*
|
|
326
|
+
* This method is passed the Table Id and Row Id that the client is trying to
|
|
327
|
+
* delete. The `connection` parameter will be the web socket connection of
|
|
328
|
+
* that client. You can, for instance, use this to distinguish between
|
|
329
|
+
* different users.
|
|
330
|
+
*
|
|
331
|
+
* Return `false` from this method to disallow this Row from being deleted
|
|
332
|
+
* on the server, or `true` to allow it. The default implementation returns
|
|
333
|
+
* `true` to allow deletion.
|
|
334
|
+
* @example
|
|
335
|
+
* The following implementation will strip out any attempts by the client to
|
|
336
|
+
* delete the 'me' Row of the 'user' Table:
|
|
337
|
+
*
|
|
338
|
+
* ```js
|
|
339
|
+
* class MyServer extends TinyBasePartyKitServer {
|
|
340
|
+
* canDelRow(tableId, rowId) {
|
|
341
|
+
* return tableId != 'user' || rowId != 'me';
|
|
342
|
+
* }
|
|
343
|
+
* }
|
|
344
|
+
* ```
|
|
345
|
+
* @category Sanitization
|
|
346
|
+
* @since v4.3.12
|
|
347
|
+
*/
|
|
348
|
+
canDelRow(tableId: Id, rowId: Id, connection: Connection): boolean;
|
|
349
|
+
/**
|
|
350
|
+
* The canSetCell method lets you allow or disallow any changes to a Cell
|
|
351
|
+
* stored on the server, as sent from a client.
|
|
352
|
+
*
|
|
353
|
+
* This has schema-based typing. The following is a simplified representation:
|
|
354
|
+
*
|
|
355
|
+
* ```ts override
|
|
356
|
+
* canSetCell(
|
|
357
|
+
* tableId: Id,
|
|
358
|
+
* rowId: Id,
|
|
359
|
+
* cellId: Id,
|
|
360
|
+
* cell: Cell,
|
|
361
|
+
* initialSave: boolean,
|
|
362
|
+
* requestOrConnection: Request | Connection,
|
|
363
|
+
* ): boolean;
|
|
364
|
+
* ```
|
|
365
|
+
*
|
|
366
|
+
* This is one of the functions use to sanitize the data that is being sent
|
|
367
|
+
* from a client. Perhaps you might want to make sure the server-stored data
|
|
368
|
+
* adheres to a particular schema, or you might want to make certain data
|
|
369
|
+
* read-only. Remember that you cannot trust the client to only send data that
|
|
370
|
+
* the server considers valid or safe.
|
|
371
|
+
*
|
|
372
|
+
* This method is passed the Table Id, Row Id, and Cell Id that the client is
|
|
373
|
+
* trying to change - as well as the Cell value itself. The `initialSave`
|
|
374
|
+
* parameter distinguishes between the first bulk save of the Store to the
|
|
375
|
+
* PartyKit room over HTTP (`true`), and subsequent incremental updates over a
|
|
376
|
+
* web sockets (`false`).
|
|
377
|
+
*
|
|
378
|
+
* The final `requestOrConnection` parameter will either be the HTTP(S)
|
|
379
|
+
* request or the web socket connection, in those two cases respectively. You
|
|
380
|
+
* can, for instance, use this to distinguish between different users.
|
|
381
|
+
*
|
|
382
|
+
* Return `false` from this method to disallow changes to this Cell on the
|
|
383
|
+
* server, or `true` to allow them. The default implementation returns `true`
|
|
384
|
+
* to allow all changes.
|
|
385
|
+
* @example
|
|
386
|
+
* The following implementation will strip out any attempts by the client to
|
|
387
|
+
* update the 'name' Cell of the 'me' Row of the 'user' Table after the
|
|
388
|
+
* initial save:
|
|
389
|
+
*
|
|
390
|
+
* ```js
|
|
391
|
+
* class MyServer extends TinyBasePartyKitServer {
|
|
392
|
+
* canSetCell(tableId, rowId, cellId, cell, initialSave) {
|
|
393
|
+
* return (
|
|
394
|
+
* initialSave || tableId != 'user' || rowId != 'me' || cellId != 'name'
|
|
395
|
+
* );
|
|
396
|
+
* }
|
|
397
|
+
* }
|
|
398
|
+
* ```
|
|
399
|
+
* @category Sanitization
|
|
400
|
+
* @since v4.3.12
|
|
401
|
+
*/
|
|
402
|
+
canSetCell(
|
|
403
|
+
tableId: Id,
|
|
404
|
+
rowId: Id,
|
|
405
|
+
cellId: Id,
|
|
406
|
+
cell: Cell<NoTablesSchema, Id, Id>,
|
|
407
|
+
initialSave: boolean,
|
|
408
|
+
requestOrConnection: Request | Connection,
|
|
409
|
+
): boolean;
|
|
410
|
+
/**
|
|
411
|
+
* The canDelCell method lets you allow or disallow deletions of a Cell stored
|
|
412
|
+
* on the server, as sent from a client.
|
|
413
|
+
*
|
|
414
|
+
* This is one of the functions use to sanitize the data that is being sent
|
|
415
|
+
* from a client. Perhaps you might want to make sure the server-stored data
|
|
416
|
+
* adheres to a particular schema, or you might want to make certain data
|
|
417
|
+
* read-only. Remember that you cannot trust the client to only send data that
|
|
418
|
+
* the server considers valid or safe.
|
|
419
|
+
*
|
|
420
|
+
* This method is passed the Table Id, Row Id, and Cell Id that the client is
|
|
421
|
+
* trying to delete. The `connection` parameter will be the web socket
|
|
422
|
+
* connection of that client. You can, for instance, use this to distinguish
|
|
423
|
+
* between different users.
|
|
424
|
+
*
|
|
425
|
+
* Return `false` from this method to disallow this Cell from being deleted on
|
|
426
|
+
* the server, or `true` to allow it. The default implementation returns
|
|
427
|
+
* `true` to allow deletion.
|
|
428
|
+
* @example
|
|
429
|
+
* The following implementation will strip out any attempts by the client to
|
|
430
|
+
* delete the 'name' Cell of the 'me' Row of the 'user' Table:
|
|
431
|
+
*
|
|
432
|
+
* ```js
|
|
433
|
+
* class MyServer extends TinyBasePartyKitServer {
|
|
434
|
+
* canDelCell(tableId, rowId, cellId) {
|
|
435
|
+
* return tableId != 'user' || rowId != 'me' || cellId != 'name';
|
|
436
|
+
* }
|
|
437
|
+
* }
|
|
438
|
+
* ```
|
|
439
|
+
* @category Sanitization
|
|
440
|
+
* @since v4.3.12
|
|
441
|
+
*/
|
|
442
|
+
canDelCell(
|
|
443
|
+
tableId: Id,
|
|
444
|
+
rowId: Id,
|
|
445
|
+
cellId: Id,
|
|
446
|
+
connection: Connection,
|
|
447
|
+
): boolean;
|
|
448
|
+
/**
|
|
449
|
+
* The canSetValue method lets you allow or disallow any changes to a Value
|
|
450
|
+
* stored on the server, as sent from a client.
|
|
451
|
+
*
|
|
452
|
+
* This has schema-based typing. The following is a simplified representation:
|
|
453
|
+
*
|
|
454
|
+
* ```ts override
|
|
455
|
+
* canSetValue(
|
|
456
|
+
* valueId: Id,
|
|
457
|
+
* value: Value,
|
|
458
|
+
* initialSave: boolean,
|
|
459
|
+
* requestOrConnection: Request | Connection,
|
|
460
|
+
* ): boolean;
|
|
461
|
+
* ```
|
|
462
|
+
*
|
|
463
|
+
* This is one of the functions use to sanitize the data that is being sent
|
|
464
|
+
* from a client. Perhaps you might want to make sure the server-stored data
|
|
465
|
+
* adheres to a particular schema, or you might want to make certain data
|
|
466
|
+
* read-only. Remember that you cannot trust the client to only send data that
|
|
467
|
+
* the server considers valid or safe.
|
|
468
|
+
*
|
|
469
|
+
* This method is passed the Value Id that the client is trying to change - as
|
|
470
|
+
* well as the Value itself. The `initialSave` parameter distinguishes between
|
|
471
|
+
* the first bulk save of the Store to the PartyKit room over HTTP (`true`),
|
|
472
|
+
* and subsequent incremental updates over a web sockets (`false`).
|
|
473
|
+
*
|
|
474
|
+
* The final `requestOrConnection` parameter will either be the HTTP(S)
|
|
475
|
+
* request or the web socket connection, in those two cases respectively. You
|
|
476
|
+
* can, for instance, use this to distinguish between different users.
|
|
477
|
+
*
|
|
478
|
+
* Return `false` from this method to disallow changes to this Value on the
|
|
479
|
+
* server, or `true` to allow them. The default implementation returns `true`
|
|
480
|
+
* to allow all changes.
|
|
481
|
+
* @example
|
|
482
|
+
* The following implementation will strip out any attempts by the client to
|
|
483
|
+
* update the 'userId' Value after the initial save:
|
|
484
|
+
*
|
|
485
|
+
* ```js
|
|
486
|
+
* class MyServer extends TinyBasePartyKitServer {
|
|
487
|
+
* canSetValue(valueId, value, initialSave) {
|
|
488
|
+
* return initialSave || userId != 'userId';
|
|
489
|
+
* }
|
|
490
|
+
* }
|
|
491
|
+
* ```
|
|
492
|
+
* @category Sanitization
|
|
493
|
+
* @since v4.3.12
|
|
494
|
+
*/
|
|
495
|
+
canSetValue(
|
|
496
|
+
valueId: Id,
|
|
497
|
+
value: Value<NoValuesSchema, Id>,
|
|
498
|
+
initialSave: boolean,
|
|
499
|
+
requestOrConnection: Request | Connection,
|
|
500
|
+
): boolean;
|
|
501
|
+
/**
|
|
502
|
+
* The canDelValue method lets you allow or disallow deletions of a Value
|
|
503
|
+
* stored on the server, as sent from a client.
|
|
504
|
+
*
|
|
505
|
+
* This is one of the functions use to sanitize the data that is being sent
|
|
506
|
+
* from a client. Perhaps you might want to make sure the server-stored data
|
|
507
|
+
* adheres to a particular schema, or you might want to make certain data
|
|
508
|
+
* read-only. Remember that you cannot trust the client to only send data that
|
|
509
|
+
* the server considers valid or safe.
|
|
510
|
+
*
|
|
511
|
+
* This method is passed the Value Id that the client is trying to delete. The
|
|
512
|
+
* `connection` parameter will be the web socket connection of that client.
|
|
513
|
+
* You can, for instance, use this to distinguish between different users.
|
|
514
|
+
*
|
|
515
|
+
* Return `false` from this method to disallow this Value from being deleted
|
|
516
|
+
* on the server, or `true` to allow it. The default implementation returns
|
|
517
|
+
* `true` to allow deletion.
|
|
518
|
+
* @example
|
|
519
|
+
* The following implementation will strip out any attempts by the client to
|
|
520
|
+
* delete the 'userId' Value:
|
|
521
|
+
*
|
|
522
|
+
* ```js
|
|
523
|
+
* class MyServer extends TinyBasePartyKitServer {
|
|
524
|
+
* canDelValue(valueId) {
|
|
525
|
+
* return valueId != 'userId';
|
|
526
|
+
* }
|
|
527
|
+
* }
|
|
528
|
+
* ```
|
|
529
|
+
* @category Sanitization
|
|
530
|
+
* @since v4.3.12
|
|
179
531
|
*/
|
|
180
|
-
|
|
532
|
+
canDelValue(valueId: Id, connection: Connection): boolean;
|
|
181
533
|
}
|
|
@@ -412,9 +412,8 @@ export interface Tools<in out Schemas extends OptionalSchemas> {
|
|
|
412
412
|
* },
|
|
413
413
|
* });
|
|
414
414
|
* const tools = createTools(store);
|
|
415
|
-
* const [dTs, ts, uiReactDTs, uiReactTsx] =
|
|
416
|
-
* store
|
|
417
|
-
* ).getPrettyStoreApi('shop');
|
|
415
|
+
* const [dTs, ts, uiReactDTs, uiReactTsx] =
|
|
416
|
+
* await createTools(store).getPrettyStoreApi('shop');
|
|
418
417
|
*
|
|
419
418
|
* const dTsLines = dTs.split('\n');
|
|
420
419
|
* console.log(dTsLines[17]);
|
|
@@ -433,9 +432,8 @@ export interface Tools<in out Schemas extends OptionalSchemas> {
|
|
|
433
432
|
* felix: {price: 4},
|
|
434
433
|
* });
|
|
435
434
|
* const tools = createTools(store);
|
|
436
|
-
* const [dTs, ts, uiReactDTs, uiReactTsx] =
|
|
437
|
-
* store
|
|
438
|
-
* ).getPrettyStoreApi('shop');
|
|
435
|
+
* const [dTs, ts, uiReactDTs, uiReactTsx] =
|
|
436
|
+
* await createTools(store).getPrettyStoreApi('shop');
|
|
439
437
|
*
|
|
440
438
|
* const dTsLines = dTs.split('\n');
|
|
441
439
|
* console.log(dTsLines[17]);
|
|
@@ -1577,7 +1577,7 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
|
|
|
1577
1577
|
*
|
|
1578
1578
|
* ```ts override
|
|
1579
1579
|
* EditableCellView(
|
|
1580
|
-
* props: CellProps & {readonly className?: string},
|
|
1580
|
+
* props: CellProps & {readonly className?: string; readonly showType?: boolean},
|
|
1581
1581
|
* ): ComponentReturnType;
|
|
1582
1582
|
* ```
|
|
1583
1583
|
*
|
|
@@ -1590,6 +1590,10 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
|
|
|
1590
1590
|
* A Cell contains a string, number, or boolean, so the value is rendered in an
|
|
1591
1591
|
* appropriate <input> tag and a button lets the user change type, if possible.
|
|
1592
1592
|
*
|
|
1593
|
+
* Set the `showType` prop to false to remove the ability for the user to see or
|
|
1594
|
+
* change the Cell type. They will also not be able to change the type if there
|
|
1595
|
+
* is a TablesSchema applied to the Store.
|
|
1596
|
+
*
|
|
1593
1597
|
* This component uses the useCell hook under the covers, which means that any
|
|
1594
1598
|
* changes to the specified Cell outside of this component will cause a
|
|
1595
1599
|
* re-render.
|
|
@@ -1630,7 +1634,10 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
|
|
|
1630
1634
|
* @since v4.1.0
|
|
1631
1635
|
*/
|
|
1632
1636
|
EditableCellView: (
|
|
1633
|
-
props: CellProps<Schemas> & {
|
|
1637
|
+
props: CellProps<Schemas> & {
|
|
1638
|
+
className?: string;
|
|
1639
|
+
readonly showType?: boolean;
|
|
1640
|
+
},
|
|
1634
1641
|
) => ComponentReturnType;
|
|
1635
1642
|
|
|
1636
1643
|
/**
|
|
@@ -1642,7 +1649,10 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
|
|
|
1642
1649
|
*
|
|
1643
1650
|
* ```ts override
|
|
1644
1651
|
* EditableValueView(
|
|
1645
|
-
* props: ValueProps & {
|
|
1652
|
+
* props: ValueProps & {
|
|
1653
|
+
* readonly className?: string;
|
|
1654
|
+
* readonly showType?: boolean;
|
|
1655
|
+
* },
|
|
1646
1656
|
* ): ComponentReturnType;
|
|
1647
1657
|
* ```
|
|
1648
1658
|
*
|
|
@@ -1655,6 +1665,10 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
|
|
|
1655
1665
|
* A Value contains a string, number, or boolean, so the value is rendered in an
|
|
1656
1666
|
* appropriate <input> tag and a button lets the user change type, if possible.
|
|
1657
1667
|
*
|
|
1668
|
+
* Set the `showType` prop to false to remove the ability for the user to see or
|
|
1669
|
+
* change the Value type. They will also not be able to change the type if there
|
|
1670
|
+
* is a ValuesSchema applied to the Store.
|
|
1671
|
+
*
|
|
1658
1672
|
* This component uses the useValue hook under the covers, which means that any
|
|
1659
1673
|
* changes to the specified Value outside of this component will cause a
|
|
1660
1674
|
* re-render.
|
|
@@ -1693,7 +1707,10 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
|
|
|
1693
1707
|
* @since v4.1.0
|
|
1694
1708
|
*/
|
|
1695
1709
|
EditableValueView: (
|
|
1696
|
-
props: ValueProps<Schemas> & {
|
|
1710
|
+
props: ValueProps<Schemas> & {
|
|
1711
|
+
className?: string;
|
|
1712
|
+
readonly showType?: boolean;
|
|
1713
|
+
},
|
|
1697
1714
|
) => ComponentReturnType;
|
|
1698
1715
|
|
|
1699
1716
|
/**
|
|
@@ -4393,8 +4393,8 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
|
|
|
4393
4393
|
* </Provider>
|
|
4394
4394
|
* );
|
|
4395
4395
|
* const Pane = () => {
|
|
4396
|
-
* useWillFinishTransactionListener(
|
|
4397
|
-
*
|
|
4396
|
+
* useWillFinishTransactionListener(() =>
|
|
4397
|
+
* console.log('Will finish transaction'),
|
|
4398
4398
|
* );
|
|
4399
4399
|
* return <span>App</span>;
|
|
4400
4400
|
* };
|
|
@@ -4462,8 +4462,8 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
|
|
|
4462
4462
|
* </Provider>
|
|
4463
4463
|
* );
|
|
4464
4464
|
* const Pane = () => {
|
|
4465
|
-
* useDidFinishTransactionListener(
|
|
4466
|
-
*
|
|
4465
|
+
* useDidFinishTransactionListener(() =>
|
|
4466
|
+
* console.log('Did finish transaction'),
|
|
4467
4467
|
* );
|
|
4468
4468
|
* return <span>App</span>;
|
|
4469
4469
|
* };
|
package/lib/ui-react-dom.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"react";import{useRowIds as t,useTableCellIds as l,useRowCount as a,useSortedRowIds as n,useValueIds as o,ValueView as r,useIndexesOrIndexesById as i,useSliceRowIds as s,useRelationshipsOrRelationshipsById as d,useResultRowIds as m,useResultTableCellIds as c,useResultRowCount as h,useResultSortedRowIds as u,useCell as g,useSetCellCallback as p,useStoreOrStoreById as b,useValue as f,useSetValueCallback as w,useRemoteRowId as k,CellView as v,ResultCellView as y}from"./ui-react";const C=e=>typeof e,x=C(""),I=C(!0),N=C(0),z="Value",M="currentTarget",$="value",S=isFinite,T=e=>null==e,{PureComponent:F,Fragment:R,createElement:q,useCallback:E,useLayoutEffect:P,useRef:O,useState:V}=e,j=(e,...t)=>T(e)?{}:e(...t),A=(e,t)=>e.map(t),B=Object,D=(e=[])=>B.fromEntries(e),L=(e,t)=>A(B.entries(e),(([e,l])=>t(l,e))),G="M20 80l5-15l40-40l10 10l-40 40l-15 5m5-15l10 10",H='content:url("',J=H+"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' stroke-width='4' stroke='white' fill='none'>",K='</svg>")',Q=H+"data:image/svg+xml,%3csvg viewBox='0 0 680 680' xmlns='http://www.w3.org/2000/svg' style='width:680px%3bheight:680px'%3e %3cpath stroke='white' stroke-width='80' fill='none' d='M340 617a84 241 90 11.01 0zM131 475a94 254 70 10428-124 114 286 70 01-428 124zm0-140a94 254 70 10428-124 114 286 70 01-428 124zm-12-127a94 254 70 00306 38 90 260 90 01-306-38zm221 3a74 241 90 11.01 0z' /%3e %3cpath fill='%23d81b60' d='M131 475a94 254 70 10428-124 114 286 70 01-428 124zm0-140a94 254 70 10428-124 114 286 70 01-428 124z' /%3e %3cpath d='M249 619a94 240 90 00308-128 114 289 70 01-308 128zM119 208a94 254 70 00306 38 90 260 90 01-306-38zm221 3a74 241 90 11.01 0z' /%3e%3c/svg%3e\")",U=A([[20,20,20,60],[20,20,60,20],[20,60,60,20],[60,20,20,60],[30,30,40,40]],(([e,t,l,a])=>J+`<rect x='20' y='20' width='60' height='60' fill='grey'/><rect x='${e}' y='${t}' width='${l}' height='${a}' fill='white'/>`+K)),W=J+"<path d='M20 20l60 60M20 80l60-60' />"+K,X=J+`<path d='${G}' />`+K,Y=J+`<path d='${G}M20 20l60 60' />`+K,Z="*::-webkit-scrollbar";((e,t="")=>{e.join(t)})(L({"*":"all:revert","*::before":"all:revert","*::after":"all:revert",[Z]:"width:0.5rem;height:0.5rem;",[Z+"-track"]:"background:#111",[Z+"-thumb"]:"background:#999;border:1px solid #111",[Z+"-thumb:hover"]:"background:#fff",[Z+"-corner"]:"background:#111",img:"width:1rem;height:1rem;background:#111;border:0;vertical-align:text-bottom",">img":"padding:0.25rem;bottom:0;right:0;position:fixed;"+Q,...D(A(["bottom:0;left:0","top:0;right:0"],((e,t)=>[`>img[data-position='${t}']`,e]))),main:"display:flex;flex-direction:column;background:#111d;color:#fff;position:fixed;",...D(A(["bottom:0;left:0;width:35vw;height:100vh","top:0;right:0;width:100vw;height:30vh","bottom:0;left:0;width:100vw;height:30vh","top:0;right:0;width:35vw;height:100vh","top:0;right:0;width:100vw;height:100vh"],((e,t)=>[`main[data-position='${t}']`,e]))),header:"display:flex;padding:0.25rem;background:#000;align-items:center","header>img:nth-of-type(1)":Q,"header>img:nth-of-type(6)":W,...D(A(U,((e,t)=>[`header>img[data-id='${t}']`,e]))),"header>span":"flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-left:0.25rem",article:"padding:0.25rem 0.25rem 0.25rem 0.5rem;overflow:auto;flex:1",details:"margin-left:0.75rem;width:fit-content;","details img":"display:none","details[open]>summary img":"display:unset;background:none;margin-left:0.25rem","details[open]>summary img.edit":X,"details[open]>summary img.done":Y,summary:"margin-left:-0.75rem;line-height:1.25rem;user-select:none;width:fit-content",table:"border-collapse:collapse;table-layout:fixed;margin-bottom:0.5rem","table input":"background:#111;color:unset;padding:0 0.25rem;border:0;font-size:unset;vertical-align:top;margin:0",'table input[type="number"]':"width:4rem","table tbody button":"font-size:0;background:#fff;border-radius:50%;margin:0 0.125rem 0 0;width:0.85rem;color:#111","table button:first-letter":"font-size:0.75rem",thead:"background:#222","th:nth-of-type(1)":"min-width:2rem;","th.sorted":"background:#000","table caption":"text-align:left;white-space:nowrap;line-height:1.25rem",button:"width:1.5rem;border:none;background:none;color:#fff;padding:0","button[disabled]":"color:#777","button.next":"margin-right:0.5rem","th,td":"overflow:hidden;text-overflow:ellipsis;padding:0.25rem 0.5rem;max-width:12rem;white-space:nowrap;border-width:1px 0;border-style:solid;border-color:#777;text-align:left","span.warn":"margin:0.25rem;color:#d81b60"},((e,t)=>e?`& ${t}{${e}}`:"")));const _=(e,t,l,a)=>e==x?t:e==N?l:a,{useCallback:ee,useMemo:te,useState:le}=e,ae="editable",ne=(e,t)=>A(l(e,t),(t=>e+"."+t)),oe=(e,t,l)=>{const a=ee(e,t);return l?a:void 0},re=(...e)=>te((()=>e),e),ie=(e,t)=>te((()=>({store:e,tableId:t})),[e,t]),se=(e,t)=>te((()=>({queries:e,queryId:t})),[e,t]),de=(e,t=!1,l,a=0,n,o,r,i)=>{const[[s,d,m],c]=le([e,t,a]),h=ee((e=>{c(e),i?.(e)}),[i]),u=oe((e=>h([e,e==s&&!d,m])),[h,s,d,m],l),g=ee((e=>h([s,d,e])),[h,s,d]),p=!0===r?Ie:r;return[[s,d,m],u,te((()=>!1===r?null:q(p,{offset:m,limit:n,total:o,onChange:g})),[r,p,m,n,o,g])]},me=(e,t,l)=>te((()=>{const a=t??e;return D(L(Array.isArray(a)?D(A(a,(e=>[e,e]))):a,((e,t)=>{return[t,{label:t,component:l,...(a=e,C(a)==x?{label:e}:e)}];var a})))}),[t,l,e]),ce=({className:e,headerRow:t,idColumn:l,params:[a,n,o,r,i,s]})=>q("table",{className:e},s?q("caption",null,s):null,!1===t?null:q("thead",null,q("tr",null,!1===l?null:q(he,{sort:r??[],label:"Id",onClick:i}),L(a,(({label:e},t)=>q(he,{key:t,cellId:t,label:e,sort:r??[],onClick:i}))))),q("tbody",null,A(o,(e=>q("tr",{key:e},!1===l?null:q("th",null,e),L(a,(({component:t,getComponentProps:l},a)=>q("td",{key:a},q(t,{...j(l,e,a),...n,rowId:e,cellId:a}))))))))),he=({cellId:e,sort:[t,l],label:a=e??"",onClick:n})=>q("th",{onClick:oe((()=>n?.(e)),[n,e],n),className:T(l)||t!=e?void 0:`sorted ${l?"de":"a"}scending`},T(l)||t!=e?null:(l?"↓":"↑")+" ",a),ue=({localRowId:t,params:[l,a,n,o,r,i,s]})=>{const d=k(r,t,i);return q("tr",null,!1===l?null:q(e.Fragment,null,q("th",null,t),q("th",null,d)),L(a,(({component:e,getComponentProps:l},a)=>{const[r,i]=a.split(".",2),m=r===n?t:r===o?d:null;return T(m)?null:q("td",{key:a},q(e,{...j(l,m,i),store:s,tableId:r,rowId:m,cellId:i}))})))},ge=({thing:e,onThingChange:t,className:l,hasSchema:a})=>{const[n,o]=le(),[r,i]=le(),[s,d]=le(),[m,c]=le(),[h,u]=le();r!==e&&(o((e=>{const t=C(e);return(e=>e==x||e==I)(t)||t==N&&S(e)?t:void 0})(e)),i(e),d(e+""),c(Number(e)||0),u(!!e));const g=ee(((e,l)=>{l(e),i(e),t(e)}),[t]);return q("div",{className:l},q("button",{className:n,onClick:ee((()=>{if(!a?.()){const e=_(n,N,I,x),l=_(e,s,m,h);o(e),i(l),t(l)}}),[a,t,s,m,h,n])},n),_(n,q("input",{key:n,value:s,onChange:ee((e=>g(e[M][$]+"",d)),[g])}),q("input",{key:n,type:"number",value:m,onChange:ee((e=>g(Number(e[M][$]||0),c)),[g])}),q("input",{key:n,type:"checkbox",checked:h,onChange:ee((e=>g(!!e[M].checked,u)),[g])})))},pe=({tableId:e,store:a,editable:n,customCells:o,...r})=>q(ce,{...r,params:re(me(l(e,a),o,n?Ce:v),ie(a,e),t(e,a))}),be=({tableId:e,cellId:t,descending:o,offset:r,limit:i,store:s,editable:d,sortOnClick:m,paginator:c=!1,onChange:h,customCells:u,...g})=>{const[p,b,f]=de(t,o,m,r,i,a(e,s),c,h);return q(ce,{...g,params:re(me(l(e,s),u,d?Ce:v),ie(s,e),n(e,...p,i,s),p,b,f)})},fe=({store:e,editable:t=!1,valueComponent:l=(t?xe:r),getValueComponentProps:a,className:n,headerRow:i,idColumn:s})=>q("table",{className:n},!1===i?null:q("thead",null,q("tr",null,!1===s?null:q("th",null,"Id"),q("th",null,z))),q("tbody",null,A(o(e),(t=>q("tr",{key:t},!1===s?null:q("th",null,t),q("td",null,q(l,{...j(a,t),valueId:t,store:e}))))))),we=({indexId:e,sliceId:t,indexes:a,editable:n,customCells:o,...r})=>{const[d,m,c]=((e,t)=>[e,e?.getStore(),e?.getTableId(t)])(i(a),e);return q(ce,{...r,params:re(me(l(c,m),o,n?Ce:v),ie(m,c),s(e,t,d))})},ke=({relationshipId:l,relationships:a,editable:n,customCells:o,className:r,headerRow:i,idColumn:s=!0})=>{const[m,c,h,u]=((e,t)=>[e,e?.getStore(),e?.getLocalTableId(t),e?.getRemoteTableId(t)])(d(a),l),g=me([...ne(h,c),...ne(u,c)],o,n?Ce:v),p=re(s,g,h,u,l,m,c);return q("table",{className:r},!1===i?null:q("thead",null,q("tr",null,!1===s?null:q(e.Fragment,null,q("th",null,h,".Id"),q("th",null,u,".Id")),L(g,(({label:e},t)=>q("th",{key:t},e))))),q("tbody",null,A(t(h,c),(e=>q(ue,{key:e,localRowId:e,params:p})))))},ve=({queryId:e,queries:t,customCells:l,...a})=>q(ce,{...a,params:re(me(c(e,t),l,y),se(t,e),m(e,t))}),ye=({queryId:e,cellId:t,descending:l,offset:a,limit:n,queries:o,sortOnClick:r,paginator:i=!1,customCells:s,onChange:d,...m})=>{const[g,p,b]=de(t,l,r,a,n,h(e,o),i,d);return q(ce,{...m,params:re(me(c(e,o),s,y),se(o,e),u(e,...g,n,o),g,p,b)})},Ce=({tableId:e,rowId:t,cellId:l,store:a,className:n})=>q(ge,{thing:g(e,t,l,a),onThingChange:p(e,t,l,(e=>e),[],a),className:n??ae+"Cell",hasSchema:b(a)?.hasTablesSchema}),xe=({valueId:e,store:t,className:l})=>q(ge,{thing:f(e,t),onThingChange:w(e,(e=>e),[],t),className:l??ae+z,hasSchema:b(t)?.hasValuesSchema}),Ie=({onChange:t,total:l,offset:a=0,limit:n=l,singular:o="row",plural:r=o+"s"})=>{(a>l||a<0)&&(a=0,t(0));const i=oe((()=>t(a-n)),[t,a,n],a>0),s=oe((()=>t(a+n)),[t,a,n],a+n<l);return q(e.Fragment,null,l>n&&q(e.Fragment,null,q("button",{className:"previous",disabled:0==a,onClick:i},"←"),q("button",{className:"next",disabled:a+n>=l,onClick:s},"→"),a+1," to ",Math.min(l,a+n)," of "),l," ",1!=l?r:o)};class Ne extends F{constructor(e){super(e),this.componentDidCatch=(e,t)=>console.error(e,t.componentStack),this.state={e:0}}static{this.getDerivedStateFromError=()=>({e:1})}render(){return this.state.e?q("span",{className:"warn"},"Inspector error: please see console for details."):this.props.children}}const ze=e=>new Map(e);ze(),ze();const Me=e=>null;export{Ce as EditableCellView,xe as EditableValueView,ke as RelationshipInHtmlTable,ye as ResultSortedTableInHtmlTable,ve as ResultTableInHtmlTable,we as SliceInHtmlTable,be as SortedTableInHtmlTable,Ie as SortedTablePaginator,Me as StoreInspector,pe as TableInHtmlTable,fe as ValuesInHtmlTable};
|
|
1
|
+
import e from"react";import{useRowIds as t,useTableCellIds as l,useRowCount as a,useSortedRowIds as n,useValueIds as o,ValueView as r,useIndexesOrIndexesById as i,useSliceRowIds as s,useRelationshipsOrRelationshipsById as d,useResultRowIds as m,useResultTableCellIds as h,useResultRowCount as c,useResultSortedRowIds as u,useCell as g,useSetCellCallback as p,useStoreOrStoreById as b,useValue as f,useSetValueCallback as w,useRemoteRowId as y,CellView as k,ResultCellView as v}from"./ui-react";const C=e=>typeof e,x=C(""),I=C(!0),N=C(0),z="Value",T="currentTarget",M="value",$=isFinite,S=e=>null==e,{PureComponent:F,Fragment:R,createElement:q,useCallback:E,useLayoutEffect:P,useRef:O,useState:V}=e,j=(e,...t)=>S(e)?{}:e(...t),A=(e,t)=>e.map(t),B=Object,D=(e=[])=>B.fromEntries(e),L=(e,t)=>A(B.entries(e),(([e,l])=>t(l,e))),G="M20 80l5-15l40-40l10 10l-40 40l-15 5m5-15l10 10",H='content:url("',J=H+"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' stroke-width='4' stroke='white' fill='none'>",K='</svg>")',Q=H+"data:image/svg+xml,%3csvg viewBox='0 0 680 680' xmlns='http://www.w3.org/2000/svg' style='width:680px%3bheight:680px'%3e %3cpath stroke='white' stroke-width='80' fill='none' d='M340 617a84 241 90 11.01 0zM131 475a94 254 70 10428-124 114 286 70 01-428 124zm0-140a94 254 70 10428-124 114 286 70 01-428 124zm-12-127a94 254 70 00306 38 90 260 90 01-306-38zm221 3a74 241 90 11.01 0z' /%3e %3cpath fill='%23d81b60' d='M131 475a94 254 70 10428-124 114 286 70 01-428 124zm0-140a94 254 70 10428-124 114 286 70 01-428 124z' /%3e %3cpath d='M249 619a94 240 90 00308-128 114 289 70 01-308 128zM119 208a94 254 70 00306 38 90 260 90 01-306-38zm221 3a74 241 90 11.01 0z' /%3e%3c/svg%3e\")",U=A([[20,20,20,60],[20,20,60,20],[20,60,60,20],[60,20,20,60],[30,30,40,40]],(([e,t,l,a])=>J+`<rect x='20' y='20' width='60' height='60' fill='grey'/><rect x='${e}' y='${t}' width='${l}' height='${a}' fill='white'/>`+K)),W=J+"<path d='M20 20l60 60M20 80l60-60' />"+K,X=J+`<path d='${G}' />`+K,Y=J+`<path d='${G}M20 20l60 60' />`+K,Z="*::-webkit-scrollbar";((e,t="")=>{e.join(t)})(L({"*":"all:revert","*::before":"all:revert","*::after":"all:revert",[Z]:"width:0.5rem;height:0.5rem;",[Z+"-track"]:"background:#111",[Z+"-thumb"]:"background:#999;border:1px solid #111",[Z+"-thumb:hover"]:"background:#fff",[Z+"-corner"]:"background:#111",img:"width:1rem;height:1rem;background:#111;border:0;vertical-align:text-bottom",">img":"padding:0.25rem;bottom:0;right:0;position:fixed;"+Q,...D(A(["bottom:0;left:0","top:0;right:0"],((e,t)=>[`>img[data-position='${t}']`,e]))),main:"display:flex;flex-direction:column;background:#111d;color:#fff;position:fixed;",...D(A(["bottom:0;left:0;width:35vw;height:100vh","top:0;right:0;width:100vw;height:30vh","bottom:0;left:0;width:100vw;height:30vh","top:0;right:0;width:35vw;height:100vh","top:0;right:0;width:100vw;height:100vh"],((e,t)=>[`main[data-position='${t}']`,e]))),header:"display:flex;padding:0.25rem;background:#000;align-items:center","header>img:nth-of-type(1)":Q,"header>img:nth-of-type(6)":W,...D(A(U,((e,t)=>[`header>img[data-id='${t}']`,e]))),"header>span":"flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-left:0.25rem",article:"padding:0.25rem 0.25rem 0.25rem 0.5rem;overflow:auto;flex:1",details:"margin-left:0.75rem;width:fit-content;","details img":"display:none","details[open]>summary img":"display:unset;background:none;margin-left:0.25rem","details[open]>summary img.edit":X,"details[open]>summary img.done":Y,summary:"margin-left:-0.75rem;line-height:1.25rem;user-select:none;width:fit-content",table:"border-collapse:collapse;table-layout:fixed;margin-bottom:0.5rem","table input":"background:#111;color:unset;padding:0 0.25rem;border:0;font-size:unset;vertical-align:top;margin:0",'table input[type="number"]':"width:4rem","table tbody button":"font-size:0;background:#fff;border-radius:50%;margin:0 0.125rem 0 0;width:0.85rem;color:#111","table button:first-letter":"font-size:0.75rem",thead:"background:#222","th:nth-of-type(1)":"min-width:2rem;","th.sorted":"background:#000","table caption":"text-align:left;white-space:nowrap;line-height:1.25rem",button:"width:1.5rem;border:none;background:none;color:#fff;padding:0","button[disabled]":"color:#777","button.next":"margin-right:0.5rem","th,td":"overflow:hidden;text-overflow:ellipsis;padding:0.25rem 0.5rem;max-width:12rem;white-space:nowrap;border-width:1px 0;border-style:solid;border-color:#777;text-align:left","span.warn":"margin:0.25rem;color:#d81b60"},((e,t)=>e?`& ${t}{${e}}`:"")));const _=(e,t,l,a)=>e==x?t:e==N?l:a,{useCallback:ee,useMemo:te,useState:le}=e,ae="editable",ne=(e,t)=>A(l(e,t),(t=>e+"."+t)),oe=(e,t,l)=>{const a=ee(e,t);return l?a:void 0},re=(...e)=>te((()=>e),e),ie=(e,t)=>te((()=>({store:e,tableId:t})),[e,t]),se=(e,t)=>te((()=>({queries:e,queryId:t})),[e,t]),de=(e,t=!1,l,a=0,n,o,r,i)=>{const[[s,d,m],h]=le([e,t,a]),c=ee((e=>{h(e),i?.(e)}),[i]),u=oe((e=>c([e,e==s&&!d,m])),[c,s,d,m],l),g=ee((e=>c([s,d,e])),[c,s,d]),p=!0===r?Ie:r;return[[s,d,m],u,te((()=>!1===r?null:q(p,{offset:m,limit:n,total:o,onChange:g})),[r,p,m,n,o,g])]},me=(e,t,l)=>te((()=>{const a=t??e;return D(L(Array.isArray(a)?D(A(a,(e=>[e,e]))):a,((e,t)=>{return[t,{label:t,component:l,...(a=e,C(a)==x?{label:e}:e)}];var a})))}),[t,l,e]),he=({className:e,headerRow:t,idColumn:l,params:[a,n,o,r,i,s]})=>q("table",{className:e},s?q("caption",null,s):null,!1===t?null:q("thead",null,q("tr",null,!1===l?null:q(ce,{sort:r??[],label:"Id",onClick:i}),L(a,(({label:e},t)=>q(ce,{key:t,cellId:t,label:e,sort:r??[],onClick:i}))))),q("tbody",null,A(o,(e=>q("tr",{key:e},!1===l?null:q("th",null,e),L(a,(({component:t,getComponentProps:l},a)=>q("td",{key:a},q(t,{...j(l,e,a),...n,rowId:e,cellId:a}))))))))),ce=({cellId:e,sort:[t,l],label:a=e??"",onClick:n})=>q("th",{onClick:oe((()=>n?.(e)),[n,e],n),className:S(l)||t!=e?void 0:`sorted ${l?"de":"a"}scending`},S(l)||t!=e?null:(l?"↓":"↑")+" ",a),ue=({localRowId:t,params:[l,a,n,o,r,i,s]})=>{const d=y(r,t,i);return q("tr",null,!1===l?null:q(e.Fragment,null,q("th",null,t),q("th",null,d)),L(a,(({component:e,getComponentProps:l},a)=>{const[r,i]=a.split(".",2),m=r===n?t:r===o?d:null;return S(m)?null:q("td",{key:a},q(e,{...j(l,m,i),store:s,tableId:r,rowId:m,cellId:i}))})))},ge=({thing:e,onThingChange:t,className:l,hasSchema:a,showType:n=!0})=>{const[o,r]=le(),[i,s]=le(),[d,m]=le(),[h,c]=le(),[u,g]=le();i!==e&&(r((e=>{const t=C(e);return(e=>e==x||e==I)(t)||t==N&&$(e)?t:void 0})(e)),s(e),m(e+""),c(Number(e)||0),g(!!e));const p=ee(((e,l)=>{l(e),s(e),t(e)}),[t]),b=ee((()=>{if(!a?.()){const e=_(o,N,I,x),l=_(e,d,h,u);r(e),s(l),t(l)}}),[a,t,d,h,u,o]);return q("div",{className:l},n?q("button",{className:o,onClick:b},o):null,_(o,q("input",{key:o,value:d,onChange:ee((e=>p(e[T][M]+"",m)),[p])}),q("input",{key:o,type:"number",value:h,onChange:ee((e=>p(Number(e[T][M]||0),c)),[p])}),q("input",{key:o,type:"checkbox",checked:u,onChange:ee((e=>p(!!e[T].checked,g)),[p])})))},pe=({tableId:e,store:a,editable:n,customCells:o,...r})=>q(he,{...r,params:re(me(l(e,a),o,n?Ce:k),ie(a,e),t(e,a))}),be=({tableId:e,cellId:t,descending:o,offset:r,limit:i,store:s,editable:d,sortOnClick:m,paginator:h=!1,onChange:c,customCells:u,...g})=>{const[p,b,f]=de(t,o,m,r,i,a(e,s),h,c);return q(he,{...g,params:re(me(l(e,s),u,d?Ce:k),ie(s,e),n(e,...p,i,s),p,b,f)})},fe=({store:e,editable:t=!1,valueComponent:l=(t?xe:r),getValueComponentProps:a,className:n,headerRow:i,idColumn:s})=>q("table",{className:n},!1===i?null:q("thead",null,q("tr",null,!1===s?null:q("th",null,"Id"),q("th",null,z))),q("tbody",null,A(o(e),(t=>q("tr",{key:t},!1===s?null:q("th",null,t),q("td",null,q(l,{...j(a,t),valueId:t,store:e}))))))),we=({indexId:e,sliceId:t,indexes:a,editable:n,customCells:o,...r})=>{const[d,m,h]=((e,t)=>[e,e?.getStore(),e?.getTableId(t)])(i(a),e);return q(he,{...r,params:re(me(l(h,m),o,n?Ce:k),ie(m,h),s(e,t,d))})},ye=({relationshipId:l,relationships:a,editable:n,customCells:o,className:r,headerRow:i,idColumn:s=!0})=>{const[m,h,c,u]=((e,t)=>[e,e?.getStore(),e?.getLocalTableId(t),e?.getRemoteTableId(t)])(d(a),l),g=me([...ne(c,h),...ne(u,h)],o,n?Ce:k),p=re(s,g,c,u,l,m,h);return q("table",{className:r},!1===i?null:q("thead",null,q("tr",null,!1===s?null:q(e.Fragment,null,q("th",null,c,".Id"),q("th",null,u,".Id")),L(g,(({label:e},t)=>q("th",{key:t},e))))),q("tbody",null,A(t(c,h),(e=>q(ue,{key:e,localRowId:e,params:p})))))},ke=({queryId:e,queries:t,customCells:l,...a})=>q(he,{...a,params:re(me(h(e,t),l,v),se(t,e),m(e,t))}),ve=({queryId:e,cellId:t,descending:l,offset:a,limit:n,queries:o,sortOnClick:r,paginator:i=!1,customCells:s,onChange:d,...m})=>{const[g,p,b]=de(t,l,r,a,n,c(e,o),i,d);return q(he,{...m,params:re(me(h(e,o),s,v),se(o,e),u(e,...g,n,o),g,p,b)})},Ce=({tableId:e,rowId:t,cellId:l,store:a,className:n,showType:o})=>q(ge,{thing:g(e,t,l,a),onThingChange:p(e,t,l,(e=>e),[],a),className:n??ae+"Cell",showType:o,hasSchema:b(a)?.hasTablesSchema}),xe=({valueId:e,store:t,className:l,showType:a})=>q(ge,{thing:f(e,t),onThingChange:w(e,(e=>e),[],t),className:l??ae+z,showType:a,hasSchema:b(t)?.hasValuesSchema}),Ie=({onChange:t,total:l,offset:a=0,limit:n=l,singular:o="row",plural:r=o+"s"})=>{(a>l||a<0)&&(a=0,t(0));const i=oe((()=>t(a-n)),[t,a,n],a>0),s=oe((()=>t(a+n)),[t,a,n],a+n<l);return q(e.Fragment,null,l>n&&q(e.Fragment,null,q("button",{className:"previous",disabled:0==a,onClick:i},"←"),q("button",{className:"next",disabled:a+n>=l,onClick:s},"→"),a+1," to ",Math.min(l,a+n)," of "),l," ",1!=l?r:o)};class Ne extends F{constructor(e){super(e),this.componentDidCatch=(e,t)=>console.error(e,t.componentStack),this.state={e:0}}static{this.getDerivedStateFromError=()=>({e:1})}render(){return this.state.e?q("span",{className:"warn"},"Inspector error: please see console for details."):this.props.children}}const ze=e=>new Map(e);ze(),ze();const Te=e=>null;export{Ce as EditableCellView,xe as EditableValueView,ye as RelationshipInHtmlTable,ve as ResultSortedTableInHtmlTable,ke as ResultTableInHtmlTable,we as SliceInHtmlTable,be as SortedTableInHtmlTable,Ie as SortedTablePaginator,Te as StoreInspector,pe as TableInHtmlTable,fe as ValuesInHtmlTable};
|
package/lib/ui-react-dom.js.gz
CHANGED
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var t,e;t=this,e=function(t){"use strict";const e=t=>typeof t,a=
|
|
1
|
+
var t,e;t=this,e=function(t){"use strict";const e=t=>typeof t,a="",s=e(a),o=(t,e)=>t instanceof e,n=t=>null==t,r=(t,e,a)=>n(t)?a?.():e(t),i=t=>e(t)==s,c=t=>t.length,d=Object,y=d.keys,u=d.freeze,f=t=>(t=>o(t,d)&&t.constructor==d)(t)&&0==(t=>c(y(t)))(t),h=t=>JSON.stringify(t,((t,e)=>o(e,Map)?d.fromEntries([...e]):e)),l=JSON.parse,p="/store",v=t=>new Map(t),w=(t,e)=>t?.get(e),g=(t,e,a)=>{return n(a)?(s=t,o=e,s?.delete(o),t):t?.set(e,a);var s,o},m=(t,e,a)=>{var s,o;return s=t,o=e,s?.has(o)||g(t,e,a()),w(t,e)},P=v(),S=v(),A="message";t.createPartyKitPersister=(t,e,s,o)=>{const{host:d,room:y}=e.partySocketOptions,{storeProtocol:v="https",storePath:L=p,messagePrefix:C=a}={...i(s)?{storeProtocol:s}:s},T=v+"://"+d+"/parties/"+(e.name??"main")+"/"+y+L,b=async t=>await(await fetch(T,{...t?{method:"PUT",body:h(t)}:{},mode:"cors",cache:"no-store"})).json();return((t,e,a,s,o,i,c=[])=>{let d,y,h,l=0,p=0;m(P,c,(()=>0)),m(S,c,(()=>[]));const v=async t=>(2!=l&&(l=1,await A.schedule((async()=>{await t(),l=0}))),A),A={load:async(a,s)=>await v((async()=>{try{t.setContent(await e())}catch{t.setContent([a,s])}})),startAutoLoad:async(a={},o={})=>(A.stopAutoLoad(),await A.load(a,o),p=1,h=s((async(a,s)=>{if(s){const e=s();await v((async()=>t.setTransactionChanges(e)))}else await v((async()=>{try{t.setContent(a?.()??await e())}catch(t){i?.(t)}}))})),A),stopAutoLoad:()=>(p&&(o(h),h=void 0,p=0),A),save:async e=>(1!=l&&(l=2,await A.schedule((async()=>{try{await a(t.getContent,e)}catch(t){i?.(t)}l=0}))),A),startAutoSave:async()=>(await A.stopAutoSave().save(),d=t.addDidFinishTransactionListener(((t,e)=>{const[a,s]=e();f(a)&&f(s)||A.save((()=>[a,s]))})),A),stopAutoSave:()=>(r(d,t.delListener),A),schedule:async(...t)=>(((t,...e)=>{t.push(...e)})(w(S,c),...t),await(async()=>{if(!w(P,c)){for(g(P,c,1);!n((t=w(S,c),y=t.shift()));)try{await y()}catch(t){i?.(t)}g(P,c,0)}var t})(),A),getStore:()=>t,destroy:()=>A.stopAutoLoad().stopAutoSave(),getStats:()=>({})};return u(A)})(t,(async()=>await b()),(async(t,a)=>{var s,o;a?e.send((s=C,o=a(),s+"s"+(i(o)?o:h(o)))):await b(t())}),(t=>{const a=e=>r(((t,e,a)=>{const s=c(t);return((t,e)=>t.startsWith(e))(e,t)?[e[s],l((o=e,n=s+1,o.slice(n,void 0)))]:void 0;var o,n})(C,e.data),(([e,a])=>{"s"==e&&t(void 0,(()=>a))}));return e.addEventListener(A,a),a}),(t=>{e.removeEventListener(A,t)}),o)}},"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).TinyBasePersisterPartyKitClient={});
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var t
|
|
1
|
+
var e,t;e=this,t=function(e){"use strict";const t=e=>typeof e,a="",s=t(a),n="t",r=(e,t)=>e.startsWith(t),i=Promise,o=e=>null==e,c=(e,t,a)=>o(e)?a?.():t(e),l=(e,t,a)=>e.slice(t,a),u=e=>e.length,f=(e,t)=>e.map(t),h=(e,...t)=>e.push(...t),y=Object,p=(e=[])=>y.fromEntries(e),g=(e,t)=>f(y.entries(e),(([e,a])=>t(a,e))),d=(e,t,a)=>(((e,t)=>!o(((e,t)=>c(e,(e=>e[t])))(e,t)))(e,t)||(e[t]=a()),e[t]),w=e=>JSON.stringify(e,((e,t)=>t instanceof Map?y.fromEntries([...t]):t)),S=JSON.parse,P=(e,a,n)=>e+a+(t(n)==s?n:w(n)),b=(e,t,a)=>{const s=u(e);return r(t,e)?[t[s],(a?S:String)(l(t,s+1))]:void 0},m=(e,t)=>((e,t)=>e?.forEach(t))(e,((e,a)=>t(a,e))),T="hasStore",v=p(f(["Origin","Methods","Headers"],(e=>["Access-Control-Allow-"+e,"*"]))),x=async e=>await e.party.storage.get((e.config.storagePrefix??a)+T),D=async(e,t,s,c)=>{const l=e.party.storage,f=e.config.storagePrefix??a,y=[l.put(f+T,1)],p=[];g(t[0],((t,a)=>o(t)?!s&&e.canDelTable(a,c)&&((e,...t)=>e.unshift(...t))(p,R(f,n,a)):e.canSetTable(a,s,c)&&g(t,((t,r)=>o(t)?!s&&e.canDelRow(a,r,c)&&h(p,R(f,n,a,r)):e.canSetRow(a,r,s,c)&&g(t,((t,i)=>o(t)?!s&&e.canDelCell(a,r,i,c)&&h(y,l.delete(R(f,n,a,r,i))):e.canSetCell(a,r,i,t,s,c)&&h(y,l.put(R(f,n,a,r,i),t)))))))),g(t[1],((t,a)=>o(t)?!s&&e.canDelValue(a,c)&&h(y,l.delete(f+"v"+a)):e.canSetValue(a,t,s,c)&&h(y,l.put(f+"v"+a,t)))),0!=u(p)&&m(await l.list(),(e=>p.every((t=>!r(e,t)||h(y,l.delete(e))&&0)))),await(async e=>i.all(e))(y)},R=(e,t,...a)=>P(e,t,l(w(a),1,-1)),C=async(e,t,a=null)=>new Response(a,{status:t,headers:e.config.responseHeaders??v});e.TinyBasePartyKitServer=class{constructor(e){this.party=e,this.config={}}async onRequest(e){const t=this.config.storePath??"/store";if(new URL(e.url).pathname.endsWith(t)){const t=await x(this),s=await e.text();return"PUT"==e.method?t?C(this,205):(await D(this,S(s),!0,e),C(this,201)):C(this,200,t?w(await(async e=>{const t={},s={},r=e.config.storagePrefix??a;return m(await e.party.storage.list(),((e,a)=>c(b(r,e),(([e,r])=>{if(e==n){const[e,s,n]=S("["+r+"]");d(d(t,e,p),s,p)[n]=a}else"v"==e&&(s[r]=a)})))),[t,s]})(this)):a)}return C(this,404)}async onMessage(e,t){const s=this.config.messagePrefix??a;await c(b(s,e,1),(async([e,a])=>{"s"==e&&await x(this)&&(await D(this,a,!1,t),this.party.broadcast(P(s,"s",a)))}))}canSetTable(e,t,a){return!0}canDelTable(e,t){return!0}canSetRow(e,t,a,s){return!0}canDelRow(e,t,a){return!0}canSetCell(e,t,a,s,n,r){return!0}canDelCell(e,t,a,s){return!0}canSetValue(e,t,a,s){return!0}canDelValue(e,t){return!0}}},"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TinyBasePersisterPartyKitServer={});
|
|
Binary file
|