tinybase 9.5.0 → 9.6.0-beta.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.
- package/@types/omni/index.d.ts +4 -0
- package/@types/omni/with-schemas/index.d.ts +4 -0
- package/@types/persisters/index.d.ts +8 -1
- package/@types/persisters/persister-better-sqlite3/index.d.ts +178 -0
- package/@types/persisters/persister-better-sqlite3/with-schemas/index.d.ts +202 -0
- package/@types/persisters/persister-capacitor-sqlite/index.d.ts +181 -0
- package/@types/persisters/persister-capacitor-sqlite/with-schemas/index.d.ts +205 -0
- package/@types/persisters/persister-indexed-db/index.d.ts +17 -9
- package/@types/persisters/persister-indexed-db/with-schemas/index.d.ts +18 -10
- package/@types/persisters/persister-libsql/index.d.ts +27 -0
- package/@types/persisters/persister-libsql/with-schemas/index.d.ts +27 -0
- package/@types/persisters/persister-pg/index.d.ts +197 -0
- package/@types/persisters/persister-pg/with-schemas/index.d.ts +222 -0
- package/@types/persisters/persister-supabase/index.d.ts +201 -0
- package/@types/persisters/persister-supabase/with-schemas/index.d.ts +217 -0
- package/@types/persisters/with-schemas/index.d.ts +8 -1
- package/@types/ui-react-dom/index.d.ts +10 -10
- package/@types/ui-react-dom/with-schemas/index.d.ts +10 -10
- package/@types/ui-react-dom-charts/index.d.ts +7 -7
- package/@types/ui-react-dom-charts/with-schemas/index.d.ts +7 -7
- package/@types/ui-react-inspector/index.d.ts +1 -1
- package/@types/ui-react-inspector/with-schemas/index.d.ts +1 -1
- package/@types/ui-solid-dom/index.d.ts +10 -10
- package/@types/ui-solid-dom/with-schemas/index.d.ts +10 -10
- package/@types/ui-solid-inspector/index.d.ts +1 -1
- package/@types/ui-solid-inspector/with-schemas/index.d.ts +1 -1
- package/@types/ui-svelte-dom/index.d.ts +10 -10
- package/@types/ui-svelte-dom/with-schemas/index.d.ts +10 -10
- package/@types/ui-svelte-inspector/index.d.ts +1 -1
- package/@types/ui-svelte-inspector/with-schemas/index.d.ts +1 -1
- package/agents.md +55 -2
- package/min/omni/index.js +1 -1
- package/min/omni/index.js.gz +0 -0
- package/min/omni/with-schemas/index.js +1 -1
- package/min/omni/with-schemas/index.js.gz +0 -0
- package/min/persisters/index.js +1 -1
- package/min/persisters/index.js.gz +0 -0
- package/min/persisters/persister-better-sqlite3/index.js +1 -0
- package/min/persisters/persister-better-sqlite3/index.js.gz +0 -0
- package/min/persisters/persister-better-sqlite3/with-schemas/index.js +1 -0
- package/min/persisters/persister-better-sqlite3/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-capacitor-sqlite/index.js +1 -0
- package/min/persisters/persister-capacitor-sqlite/index.js.gz +0 -0
- package/min/persisters/persister-capacitor-sqlite/with-schemas/index.js +1 -0
- package/min/persisters/persister-capacitor-sqlite/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-cr-sqlite-wasm/index.js +1 -1
- package/min/persisters/persister-cr-sqlite-wasm/index.js.gz +0 -0
- package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +1 -1
- package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-durable-object-sql-storage/index.js +1 -1
- package/min/persisters/persister-durable-object-sql-storage/index.js.gz +0 -0
- package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js +1 -1
- package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-electric-sql/index.js +1 -1
- package/min/persisters/persister-electric-sql/index.js.gz +0 -0
- package/min/persisters/persister-electric-sql/with-schemas/index.js +1 -1
- package/min/persisters/persister-electric-sql/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-expo-sqlite/index.js +1 -1
- package/min/persisters/persister-expo-sqlite/index.js.gz +0 -0
- package/min/persisters/persister-expo-sqlite/with-schemas/index.js +1 -1
- package/min/persisters/persister-expo-sqlite/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-indexed-db/index.js +1 -1
- package/min/persisters/persister-indexed-db/index.js.gz +0 -0
- package/min/persisters/persister-indexed-db/with-schemas/index.js +1 -1
- package/min/persisters/persister-indexed-db/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-libsql/index.js +1 -1
- package/min/persisters/persister-libsql/index.js.gz +0 -0
- package/min/persisters/persister-libsql/with-schemas/index.js +1 -1
- package/min/persisters/persister-libsql/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-pg/index.js +1 -0
- package/min/persisters/persister-pg/index.js.gz +0 -0
- package/min/persisters/persister-pg/with-schemas/index.js +1 -0
- package/min/persisters/persister-pg/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-pglite/index.js +1 -1
- package/min/persisters/persister-pglite/index.js.gz +0 -0
- package/min/persisters/persister-pglite/with-schemas/index.js +1 -1
- package/min/persisters/persister-pglite/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-postgres/index.js +1 -1
- package/min/persisters/persister-postgres/index.js.gz +0 -0
- package/min/persisters/persister-postgres/with-schemas/index.js +1 -1
- package/min/persisters/persister-postgres/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-powersync/index.js +1 -1
- package/min/persisters/persister-powersync/index.js.gz +0 -0
- package/min/persisters/persister-powersync/with-schemas/index.js +1 -1
- package/min/persisters/persister-powersync/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-react-native-sqlite/index.js +1 -1
- package/min/persisters/persister-react-native-sqlite/index.js.gz +0 -0
- package/min/persisters/persister-react-native-sqlite/with-schemas/index.js +1 -1
- package/min/persisters/persister-react-native-sqlite/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-sqlite-bun/index.js +1 -1
- package/min/persisters/persister-sqlite-bun/index.js.gz +0 -0
- package/min/persisters/persister-sqlite-bun/with-schemas/index.js +1 -1
- package/min/persisters/persister-sqlite-bun/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-sqlite-wasm/index.js +1 -1
- package/min/persisters/persister-sqlite-wasm/index.js.gz +0 -0
- package/min/persisters/persister-sqlite-wasm/with-schemas/index.js +1 -1
- package/min/persisters/persister-sqlite-wasm/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-sqlite3/index.js +1 -1
- package/min/persisters/persister-sqlite3/index.js.gz +0 -0
- package/min/persisters/persister-sqlite3/with-schemas/index.js +1 -1
- package/min/persisters/persister-sqlite3/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-supabase/index.js +1 -0
- package/min/persisters/persister-supabase/index.js.gz +0 -0
- package/min/persisters/persister-supabase/with-schemas/index.js +1 -0
- package/min/persisters/persister-supabase/with-schemas/index.js.gz +0 -0
- package/min/persisters/with-schemas/index.js +1 -1
- package/min/persisters/with-schemas/index.js.gz +0 -0
- package/omni/index.js +269 -34
- package/omni/with-schemas/index.js +269 -34
- package/package.json +164 -4
- package/persisters/index.js +23 -7
- package/persisters/persister-better-sqlite3/index.js +1767 -0
- package/persisters/persister-better-sqlite3/with-schemas/index.js +1767 -0
- package/persisters/persister-capacitor-sqlite/index.js +1769 -0
- package/persisters/persister-capacitor-sqlite/with-schemas/index.js +1769 -0
- package/persisters/persister-cr-sqlite-wasm/index.js +20 -6
- package/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +20 -6
- package/persisters/persister-durable-object-sql-storage/index.js +20 -7
- package/persisters/persister-durable-object-sql-storage/with-schemas/index.js +20 -7
- package/persisters/persister-electric-sql/index.js +20 -6
- package/persisters/persister-electric-sql/with-schemas/index.js +20 -6
- package/persisters/persister-expo-sqlite/index.js +20 -6
- package/persisters/persister-expo-sqlite/with-schemas/index.js +20 -6
- package/persisters/persister-indexed-db/index.js +48 -20
- package/persisters/persister-indexed-db/with-schemas/index.js +48 -20
- package/persisters/persister-libsql/index.js +20 -6
- package/persisters/persister-libsql/with-schemas/index.js +20 -6
- package/persisters/persister-pg/index.js +1905 -0
- package/persisters/persister-pg/with-schemas/index.js +1905 -0
- package/persisters/persister-pglite/index.js +20 -6
- package/persisters/persister-pglite/with-schemas/index.js +20 -6
- package/persisters/persister-postgres/index.js +20 -6
- package/persisters/persister-postgres/with-schemas/index.js +20 -6
- package/persisters/persister-powersync/index.js +27 -10
- package/persisters/persister-powersync/with-schemas/index.js +27 -10
- package/persisters/persister-react-native-sqlite/index.js +20 -6
- package/persisters/persister-react-native-sqlite/with-schemas/index.js +20 -6
- package/persisters/persister-sqlite-bun/index.js +20 -6
- package/persisters/persister-sqlite-bun/with-schemas/index.js +20 -6
- package/persisters/persister-sqlite-wasm/index.js +20 -6
- package/persisters/persister-sqlite-wasm/with-schemas/index.js +20 -6
- package/persisters/persister-sqlite3/index.js +20 -6
- package/persisters/persister-sqlite3/with-schemas/index.js +20 -6
- package/persisters/persister-supabase/index.js +883 -0
- package/persisters/persister-supabase/with-schemas/index.js +883 -0
- package/persisters/with-schemas/index.js +23 -7
- package/readme.md +14 -14
- package/releases.md +163 -66
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The persister-pg module of the TinyBase project lets you save and load Store
|
|
3
|
+
* data to and from a PostgreSQL database, via the `pg` module (in an
|
|
4
|
+
* appropriate environment).
|
|
5
|
+
*
|
|
6
|
+
* Since the `pg` module is the de facto standard PostgreSQL driver for Node.js,
|
|
7
|
+
* this module also works with the many hosted PostgreSQL services that provide
|
|
8
|
+
* a `pg`-compatible driver, such as Neon.
|
|
9
|
+
* @see Database Persistence guide
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
* @module persister-pg
|
|
12
|
+
* @since 9.6.0
|
|
13
|
+
*/
|
|
14
|
+
import type {Client, Pool} from 'pg';
|
|
15
|
+
import type {MergeableStore} from '../../../mergeable-store/with-schemas/index.d.ts';
|
|
16
|
+
import type {
|
|
17
|
+
OptionalSchemas,
|
|
18
|
+
Store,
|
|
19
|
+
} from '../../../store/with-schemas/index.d.ts';
|
|
20
|
+
import type {
|
|
21
|
+
DatabasePersisterConfig,
|
|
22
|
+
DpcJson,
|
|
23
|
+
Persister,
|
|
24
|
+
Persists,
|
|
25
|
+
} from '../../with-schemas/index.d.ts';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The PgPersister interface represents a Persister that lets you save and load
|
|
29
|
+
* Store data to and from a PostgreSQL database, via the `pg` module.
|
|
30
|
+
*
|
|
31
|
+
* You should use the createPgPersister function to create a PgPersister object.
|
|
32
|
+
*
|
|
33
|
+
* It is a minor extension to the Persister interface and simply provides an
|
|
34
|
+
* extra getPg method for accessing a reference to the database connection the
|
|
35
|
+
* Store is being persisted to.
|
|
36
|
+
* @category Persister
|
|
37
|
+
* @since 9.6.0
|
|
38
|
+
*/
|
|
39
|
+
export interface PgPersister<Schemas extends OptionalSchemas> extends Persister<
|
|
40
|
+
Schemas,
|
|
41
|
+
Persists.StoreOrMergeableStore
|
|
42
|
+
> {
|
|
43
|
+
/**
|
|
44
|
+
* The getPg method returns a reference to the database connection the Store
|
|
45
|
+
* is being persisted to.
|
|
46
|
+
* @returns A reference to the `pg` Pool or Client.
|
|
47
|
+
* @example
|
|
48
|
+
* This example creates a Persister object against a newly-created Store and
|
|
49
|
+
* then gets the database connection back out again.
|
|
50
|
+
*
|
|
51
|
+
* ```js
|
|
52
|
+
* import {Pool} from 'pg';
|
|
53
|
+
* import {createStore} from 'tinybase';
|
|
54
|
+
* import {createPgPersister} from 'tinybase/persisters/persister-pg';
|
|
55
|
+
*
|
|
56
|
+
* const pool = new Pool({
|
|
57
|
+
* connectionString: 'postgres://localhost:5432/tinybase',
|
|
58
|
+
* });
|
|
59
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
60
|
+
* const persister = await createPgPersister(store, pool, 'my_tinybase');
|
|
61
|
+
*
|
|
62
|
+
* console.log(persister.getPg() == pool);
|
|
63
|
+
* // -> true
|
|
64
|
+
*
|
|
65
|
+
* await persister.destroy();
|
|
66
|
+
* await pool.end();
|
|
67
|
+
* ```
|
|
68
|
+
* @category Getter
|
|
69
|
+
* @since 9.6.0
|
|
70
|
+
*/
|
|
71
|
+
getPg(): Pool | Client;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The createPgPersister function creates a PgPersister object that can persist
|
|
76
|
+
* the Store to a PostgreSQL database via the `pg` module.
|
|
77
|
+
*
|
|
78
|
+
* This has schema-based typing. The following is a simplified representation:
|
|
79
|
+
*
|
|
80
|
+
* ```ts override
|
|
81
|
+
* createPgPersister<StoreType extends Store>(
|
|
82
|
+
* store: StoreType,
|
|
83
|
+
* pg: Pool | Client,
|
|
84
|
+
* configOrStoreTableName?:
|
|
85
|
+
* | (NoInfer<StoreType> extends MergeableStore
|
|
86
|
+
* ? DpcJson
|
|
87
|
+
* : DatabasePersisterConfig)
|
|
88
|
+
* | string,
|
|
89
|
+
* onSqlCommand?: (sql: string, params?: any[]) => void,
|
|
90
|
+
* onIgnoredError?: (error: any) => void,
|
|
91
|
+
* ): Promise<PgPersister>;
|
|
92
|
+
* ```
|
|
93
|
+
*
|
|
94
|
+
* A PgPersister supports regular Store objects, and can also be used to persist
|
|
95
|
+
* the metadata of a MergeableStore when using the JSON serialization mode, as
|
|
96
|
+
* described below.
|
|
97
|
+
*
|
|
98
|
+
* As well as providing a reference to the Store to persist, you must provide a
|
|
99
|
+
* `pg` parameter which is either a Pool or a Client. If you provide a Pool, one
|
|
100
|
+
* connection is checked out for the lifetime of the Persister (and a second
|
|
101
|
+
* while automatic loading is enabled), since the Persister needs to issue
|
|
102
|
+
* transactions on a stable connection. Make sure your pool is large enough to
|
|
103
|
+
* accommodate that.
|
|
104
|
+
*
|
|
105
|
+
* A database Persister uses one of two modes: either a JSON serialization of
|
|
106
|
+
* the whole Store stored in a single row of a table (the default), or a tabular
|
|
107
|
+
* mapping of Table Ids to database table names and vice-versa).
|
|
108
|
+
*
|
|
109
|
+
* The third argument is a DatabasePersisterConfig object that configures which
|
|
110
|
+
* of those modes to use, and settings for each. If the third argument is simply
|
|
111
|
+
* a string, it is used as the `storeTableName` property of the JSON
|
|
112
|
+
* serialization.
|
|
113
|
+
*
|
|
114
|
+
* See the documentation for the DpcJson and DpcTabular types for more
|
|
115
|
+
* information on how both of those modes can be configured.
|
|
116
|
+
*
|
|
117
|
+
* Note: When using tabular mode, SQL NULL values are loaded as TinyBase null
|
|
118
|
+
* values, making tables dense (every Row has every Cell). See the Database
|
|
119
|
+
* Persistence guide for details.
|
|
120
|
+
*
|
|
121
|
+
* This method is asynchronous because it will await the creation of a dedicated
|
|
122
|
+
* new connection to the database. You will need to `await` a call to this
|
|
123
|
+
* function or handle the return type natively as a Promise.
|
|
124
|
+
* @param store The Store or MergeableStore to persist.
|
|
125
|
+
* @param pg The `pg` Pool or Client that identifies the database connection.
|
|
126
|
+
* @param configOrStoreTableName A DatabasePersisterConfig to configure the
|
|
127
|
+
* persistence mode (or a string to set the `storeTableName` property of the
|
|
128
|
+
* JSON serialization).
|
|
129
|
+
* @param onSqlCommand An optional handler called every time the Persister
|
|
130
|
+
* executes a SQL command or query. This is suitable for logging persistence
|
|
131
|
+
* behavior in a development environment.
|
|
132
|
+
* @param onIgnoredError An optional handler for the errors that the Persister
|
|
133
|
+
* would otherwise ignore when trying to save or load data. This is suitable for
|
|
134
|
+
* debugging persistence issues in a development environment.
|
|
135
|
+
* @returns A reference to the new PgPersister object.
|
|
136
|
+
* @example
|
|
137
|
+
* This example creates a PgPersister object and persists the Store to a local
|
|
138
|
+
* PostgreSQL database as a JSON serialization into the `my_tinybase` table. It
|
|
139
|
+
* makes a change to the database directly and then reloads it back into the
|
|
140
|
+
* Store.
|
|
141
|
+
*
|
|
142
|
+
* ```js
|
|
143
|
+
* import {Pool} from 'pg';
|
|
144
|
+
* import {createStore} from 'tinybase';
|
|
145
|
+
* import {createPgPersister} from 'tinybase/persisters/persister-pg';
|
|
146
|
+
*
|
|
147
|
+
* const pool = new Pool({
|
|
148
|
+
* connectionString: 'postgres://localhost:5432/tinybase',
|
|
149
|
+
* });
|
|
150
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
151
|
+
* const persister = await createPgPersister(store, pool, 'my_tinybase');
|
|
152
|
+
*
|
|
153
|
+
* await persister.save();
|
|
154
|
+
* // Store will be saved to the database.
|
|
155
|
+
*
|
|
156
|
+
* console.log((await pool.query('SELECT * FROM my_tinybase;')).rows);
|
|
157
|
+
* // -> [{_id: '_', store: '[{"pets":{"fido":{"species":"dog"}}},{}]'}]
|
|
158
|
+
*
|
|
159
|
+
* const json = '[{"pets":{"felix":{"species":"cat"}}},{}]';
|
|
160
|
+
* await pool.query('UPDATE my_tinybase SET store = $1 WHERE _id = $2;', [
|
|
161
|
+
* json,
|
|
162
|
+
* '_',
|
|
163
|
+
* ]);
|
|
164
|
+
*
|
|
165
|
+
* await persister.load();
|
|
166
|
+
* console.log(store.getTables());
|
|
167
|
+
* // -> {pets: {felix: {species: 'cat'}}}
|
|
168
|
+
*
|
|
169
|
+
* await persister.destroy();
|
|
170
|
+
* await pool.end();
|
|
171
|
+
* ```
|
|
172
|
+
* @example
|
|
173
|
+
* This example creates a PgPersister object and persists the Store to a local
|
|
174
|
+
* PostgreSQL database with tabular mapping.
|
|
175
|
+
*
|
|
176
|
+
* ```js
|
|
177
|
+
* import {Pool} from 'pg';
|
|
178
|
+
* import {createStore} from 'tinybase';
|
|
179
|
+
* import {createPgPersister} from 'tinybase/persisters/persister-pg';
|
|
180
|
+
*
|
|
181
|
+
* const pool = new Pool({
|
|
182
|
+
* connectionString: 'postgres://localhost:5432/tinybase',
|
|
183
|
+
* });
|
|
184
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
185
|
+
* const persister = await createPgPersister(store, pool, {
|
|
186
|
+
* mode: 'tabular',
|
|
187
|
+
* tables: {load: {pets: 'pets'}, save: {pets: 'pets'}},
|
|
188
|
+
* });
|
|
189
|
+
*
|
|
190
|
+
* await persister.save();
|
|
191
|
+
* console.log((await pool.query('SELECT * FROM pets;')).rows);
|
|
192
|
+
* // -> [{_id: 'fido', species: '"dog"'}]
|
|
193
|
+
* // Note that Cells and Values are JSON-encoded in PostgreSQL databases.
|
|
194
|
+
*
|
|
195
|
+
* await pool.query(
|
|
196
|
+
* `INSERT INTO pets (_id, species) VALUES ('felix', '"cat"')`,
|
|
197
|
+
* );
|
|
198
|
+
* await persister.load();
|
|
199
|
+
* console.log(store.getTables());
|
|
200
|
+
* // -> {pets: {fido: {species: 'dog'}, felix: {species: 'cat'}}}
|
|
201
|
+
*
|
|
202
|
+
* await persister.destroy();
|
|
203
|
+
* await pool.query('DROP TABLE IF EXISTS pets');
|
|
204
|
+
* await pool.end();
|
|
205
|
+
* ```
|
|
206
|
+
* @category Creation
|
|
207
|
+
* @since 9.6.0
|
|
208
|
+
*/
|
|
209
|
+
export function createPgPersister<Schemas extends OptionalSchemas>(
|
|
210
|
+
store: MergeableStore<Schemas>,
|
|
211
|
+
pg: Pool | Client,
|
|
212
|
+
configOrStoreTableName?: DpcJson | string,
|
|
213
|
+
onSqlCommand?: (sql: string, params?: any[]) => void,
|
|
214
|
+
onIgnoredError?: (error: any) => void,
|
|
215
|
+
): Promise<PgPersister<Schemas>>;
|
|
216
|
+
export function createPgPersister<Schemas extends OptionalSchemas>(
|
|
217
|
+
store: Store<Schemas> & {getMergeableContent?: never},
|
|
218
|
+
pg: Pool | Client,
|
|
219
|
+
configOrStoreTableName?: DatabasePersisterConfig<Schemas> | string,
|
|
220
|
+
onSqlCommand?: (sql: string, params?: any[]) => void,
|
|
221
|
+
onIgnoredError?: (error: any) => void,
|
|
222
|
+
): Promise<PgPersister<Schemas>>;
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The persister-supabase module of the TinyBase project lets you save and load
|
|
3
|
+
* Store data to and from a Supabase project, via the `@supabase/supabase-js`
|
|
4
|
+
* module.
|
|
5
|
+
*
|
|
6
|
+
* Unlike the other PostgreSQL Persisters, this one talks to Supabase's REST API
|
|
7
|
+
* rather than to the database directly. That means it works in a browser or
|
|
8
|
+
* edge runtime, that row-level security policies apply to the data it reads and
|
|
9
|
+
* writes, and that changes can arrive over Supabase Realtime instead of
|
|
10
|
+
* polling.
|
|
11
|
+
*
|
|
12
|
+
* It also means that only the JSON serialization mode is available, since the
|
|
13
|
+
* REST API cannot execute the arbitrary SQL that tabular mapping needs.
|
|
14
|
+
*
|
|
15
|
+
* Most importantly, it means this Persister issues no DDL whatsoever, which is
|
|
16
|
+
* a real departure from how the other database Persisters behave. Those create
|
|
17
|
+
* their table when it is missing, add columns as new Cells appear, drop columns
|
|
18
|
+
* and tables that have become empty, and, in PostgreSQL, install the functions
|
|
19
|
+
* and event triggers they need to listen for changes and drop them again when
|
|
20
|
+
* they are destroyed. This one does none of that: it reads and writes a single
|
|
21
|
+
* row of a table you have already set up, and if that table is missing or
|
|
22
|
+
* shaped wrong, it reports the error rather than correcting the schema. Your
|
|
23
|
+
* database structure is yours, and stays exactly as your migrations left it.
|
|
24
|
+
*
|
|
25
|
+
* If you want a Persister that manages its own schema, or you need tabular
|
|
26
|
+
* mode, connect to the database directly with the persister-pg module instead.
|
|
27
|
+
* @see Database Persistence guide
|
|
28
|
+
* @packageDocumentation
|
|
29
|
+
* @module persister-supabase
|
|
30
|
+
* @since 9.6.0
|
|
31
|
+
*/
|
|
32
|
+
import type {SupabaseClient} from '@supabase/supabase-js';
|
|
33
|
+
import type {MergeableStore} from '../../mergeable-store/index.d.ts';
|
|
34
|
+
import type {Store} from '../../store/index.d.ts';
|
|
35
|
+
import type {DpcJson, Persister, Persists} from '../index.d.ts';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The SupabasePersister interface represents a Persister that lets you save and
|
|
39
|
+
* load Store data to and from a Supabase project.
|
|
40
|
+
*
|
|
41
|
+
* You should use the createSupabasePersister function to create a
|
|
42
|
+
* SupabasePersister object.
|
|
43
|
+
*
|
|
44
|
+
* It is a minor extension to the Persister interface and simply provides an
|
|
45
|
+
* extra getSupabase method for accessing a reference to the Supabase client the
|
|
46
|
+
* Store is being persisted with.
|
|
47
|
+
* @category Persister
|
|
48
|
+
* @since 9.6.0
|
|
49
|
+
*/
|
|
50
|
+
export interface SupabasePersister extends Persister<Persists.StoreOrMergeableStore> {
|
|
51
|
+
/**
|
|
52
|
+
* The getSupabase method returns a reference to the Supabase client the Store
|
|
53
|
+
* is being persisted with.
|
|
54
|
+
* @returns A reference to the Supabase client.
|
|
55
|
+
* @example
|
|
56
|
+
* This example creates a Persister object against a newly-created Store and
|
|
57
|
+
* then gets the Supabase client back out again.
|
|
58
|
+
*
|
|
59
|
+
* ```js ignore
|
|
60
|
+
* import {createClient} from '@supabase/supabase-js';
|
|
61
|
+
* import {createStore} from 'tinybase';
|
|
62
|
+
* import {createSupabasePersister} from 'tinybase/persisters/persister-supabase';
|
|
63
|
+
*
|
|
64
|
+
* const supabase = createClient(
|
|
65
|
+
* 'https://my-project.supabase.co',
|
|
66
|
+
* 'anon-key',
|
|
67
|
+
* );
|
|
68
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
69
|
+
* const persister = createSupabasePersister(store, supabase, 'my_tinybase');
|
|
70
|
+
*
|
|
71
|
+
* console.log(persister.getSupabase() == supabase);
|
|
72
|
+
* // -> true
|
|
73
|
+
*
|
|
74
|
+
* await persister.destroy();
|
|
75
|
+
* ```
|
|
76
|
+
* @category Getter
|
|
77
|
+
* @since 9.6.0
|
|
78
|
+
*/
|
|
79
|
+
getSupabase(): SupabaseClient;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The createSupabasePersister function creates a SupabasePersister object that
|
|
84
|
+
* can persist the Store to a Supabase project.
|
|
85
|
+
*
|
|
86
|
+
* A SupabasePersister supports regular Store objects, and can also be used to
|
|
87
|
+
* persist the metadata of a MergeableStore.
|
|
88
|
+
*
|
|
89
|
+
* As well as providing a reference to the Store to persist, you must provide a
|
|
90
|
+
* `supabase` parameter which is the client returned from Supabase's
|
|
91
|
+
* `createClient` function.
|
|
92
|
+
*
|
|
93
|
+
* The Persister stores a JSON serialization of the whole Store in a single row
|
|
94
|
+
* of a table. The third argument is a DpcJson object that configures the table
|
|
95
|
+
* and column names to use, or, if it is simply a string, it is used as the
|
|
96
|
+
* `storeTableName` property.
|
|
97
|
+
*
|
|
98
|
+
* Unlike the other database Persisters, this one will not create or alter any
|
|
99
|
+
* of that structure for you, so you need to set it up yourself with a migration
|
|
100
|
+
* or the Supabase SQL editor before the Persister will work at all. By default
|
|
101
|
+
* it expects a table called `tinybase` with a text primary key called `_id` and
|
|
102
|
+
* a text column called `store`:
|
|
103
|
+
*
|
|
104
|
+
* ```sql ignore
|
|
105
|
+
* CREATE TABLE tinybase (_id text PRIMARY KEY, store text);
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* Row-level security applies to everything the Persister does, so it will read
|
|
109
|
+
* nothing and save nothing until a policy grants access to it. What that policy
|
|
110
|
+
* should be depends on who is allowed to see the Store: the following lets any
|
|
111
|
+
* signed-in user read and write it, which suits a Store that a whole team
|
|
112
|
+
* shares, but a per-user Store wants a policy that compares `auth.uid()` to a
|
|
113
|
+
* column of its own instead.
|
|
114
|
+
*
|
|
115
|
+
* ```sql ignore
|
|
116
|
+
* ALTER TABLE tinybase ENABLE ROW LEVEL SECURITY;
|
|
117
|
+
* CREATE POLICY tinybase_access ON tinybase
|
|
118
|
+
* FOR ALL TO authenticated USING (true) WITH CHECK (true);
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* For the startAutoLoad method to pick up changes made elsewhere, the table
|
|
122
|
+
* must also be published to Supabase Realtime:
|
|
123
|
+
*
|
|
124
|
+
* ```sql ignore
|
|
125
|
+
* ALTER PUBLICATION supabase_realtime ADD TABLE tinybase;
|
|
126
|
+
* ```
|
|
127
|
+
*
|
|
128
|
+
* Note that Realtime checks a client's `SELECT` policy before it will send that
|
|
129
|
+
* client a change, so a Store that loads and saves correctly but never
|
|
130
|
+
* auto-loads is usually a policy problem rather than a publication one.
|
|
131
|
+
*
|
|
132
|
+
* If you cannot enable Realtime, set the `autoLoadIntervalSeconds` property of
|
|
133
|
+
* the DpcJson object, and the Persister will additionally poll the table at
|
|
134
|
+
* that interval. It does not poll unless you provide that property.
|
|
135
|
+
* @param store The Store or MergeableStore to persist.
|
|
136
|
+
* @param supabase The Supabase client that was returned from `createClient`.
|
|
137
|
+
* @param configOrStoreTableName A DpcJson object to configure the table and
|
|
138
|
+
* column names (or a string to set the `storeTableName` property).
|
|
139
|
+
* @param onIgnoredError An optional handler for the errors that the Persister
|
|
140
|
+
* would otherwise ignore when trying to save or load data. This is suitable for
|
|
141
|
+
* debugging persistence issues in a development environment.
|
|
142
|
+
* @returns A reference to the new SupabasePersister object.
|
|
143
|
+
* @example
|
|
144
|
+
* This example creates a SupabasePersister object and persists the Store to a
|
|
145
|
+
* Supabase project as a JSON serialization into the `my_tinybase` table.
|
|
146
|
+
*
|
|
147
|
+
* ```js ignore
|
|
148
|
+
* import {createClient} from '@supabase/supabase-js';
|
|
149
|
+
* import {createStore} from 'tinybase';
|
|
150
|
+
* import {createSupabasePersister} from 'tinybase/persisters/persister-supabase';
|
|
151
|
+
*
|
|
152
|
+
* const supabase = createClient(
|
|
153
|
+
* 'https://my-project.supabase.co',
|
|
154
|
+
* 'anon-key',
|
|
155
|
+
* );
|
|
156
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
157
|
+
* const persister = createSupabasePersister(store, supabase, 'my_tinybase');
|
|
158
|
+
*
|
|
159
|
+
* await persister.save();
|
|
160
|
+
* // Store will be saved to the Supabase table.
|
|
161
|
+
*
|
|
162
|
+
* console.log((await supabase.from('my_tinybase').select('store')).data);
|
|
163
|
+
* // -> [{store: '[{"pets":{"fido":{"species":"dog"}}},{}]'}]
|
|
164
|
+
*
|
|
165
|
+
* await persister.destroy();
|
|
166
|
+
* ```
|
|
167
|
+
* @example
|
|
168
|
+
* This example creates a SupabasePersister object that automatically loads
|
|
169
|
+
* changes made to the table by other clients, over Supabase Realtime.
|
|
170
|
+
*
|
|
171
|
+
* ```js ignore
|
|
172
|
+
* import {createClient} from '@supabase/supabase-js';
|
|
173
|
+
* import {createStore} from 'tinybase';
|
|
174
|
+
* import {createSupabasePersister} from 'tinybase/persisters/persister-supabase';
|
|
175
|
+
*
|
|
176
|
+
* const supabase = createClient(
|
|
177
|
+
* 'https://my-project.supabase.co',
|
|
178
|
+
* 'anon-key',
|
|
179
|
+
* );
|
|
180
|
+
* const store = createStore();
|
|
181
|
+
* const persister = createSupabasePersister(store, supabase, {
|
|
182
|
+
* mode: 'json',
|
|
183
|
+
* storeTableName: 'my_tinybase',
|
|
184
|
+
* });
|
|
185
|
+
*
|
|
186
|
+
* await persister.startAutoLoad();
|
|
187
|
+
* await persister.startAutoSave();
|
|
188
|
+
*
|
|
189
|
+
* // Changes made by other clients now arrive over Realtime.
|
|
190
|
+
*
|
|
191
|
+
* await persister.destroy();
|
|
192
|
+
* ```
|
|
193
|
+
* @category Creation
|
|
194
|
+
* @since 9.6.0
|
|
195
|
+
*/
|
|
196
|
+
export function createSupabasePersister(
|
|
197
|
+
store: Store | MergeableStore,
|
|
198
|
+
supabase: SupabaseClient,
|
|
199
|
+
configOrStoreTableName?: DpcJson | string,
|
|
200
|
+
onIgnoredError?: (error: any) => void,
|
|
201
|
+
): SupabasePersister;
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The persister-supabase module of the TinyBase project lets you save and load
|
|
3
|
+
* Store data to and from a Supabase project, via the `@supabase/supabase-js`
|
|
4
|
+
* module.
|
|
5
|
+
*
|
|
6
|
+
* Unlike the other PostgreSQL Persisters, this one talks to Supabase's REST API
|
|
7
|
+
* rather than to the database directly. That means it works in a browser or
|
|
8
|
+
* edge runtime, that row-level security policies apply to the data it reads and
|
|
9
|
+
* writes, and that changes can arrive over Supabase Realtime instead of
|
|
10
|
+
* polling.
|
|
11
|
+
*
|
|
12
|
+
* It also means that only the JSON serialization mode is available, since the
|
|
13
|
+
* REST API cannot execute the arbitrary SQL that tabular mapping needs.
|
|
14
|
+
*
|
|
15
|
+
* Most importantly, it means this Persister issues no DDL whatsoever, which is
|
|
16
|
+
* a real departure from how the other database Persisters behave. Those create
|
|
17
|
+
* their table when it is missing, add columns as new Cells appear, drop columns
|
|
18
|
+
* and tables that have become empty, and, in PostgreSQL, install the functions
|
|
19
|
+
* and event triggers they need to listen for changes and drop them again when
|
|
20
|
+
* they are destroyed. This one does none of that: it reads and writes a single
|
|
21
|
+
* row of a table you have already set up, and if that table is missing or
|
|
22
|
+
* shaped wrong, it reports the error rather than correcting the schema. Your
|
|
23
|
+
* database structure is yours, and stays exactly as your migrations left it.
|
|
24
|
+
*
|
|
25
|
+
* If you want a Persister that manages its own schema, or you need tabular
|
|
26
|
+
* mode, connect to the database directly with the persister-pg module instead.
|
|
27
|
+
* @see Database Persistence guide
|
|
28
|
+
* @packageDocumentation
|
|
29
|
+
* @module persister-supabase
|
|
30
|
+
* @since 9.6.0
|
|
31
|
+
*/
|
|
32
|
+
import type {SupabaseClient} from '@supabase/supabase-js';
|
|
33
|
+
import type {MergeableStore} from '../../../mergeable-store/with-schemas/index.d.ts';
|
|
34
|
+
import type {
|
|
35
|
+
OptionalSchemas,
|
|
36
|
+
Store,
|
|
37
|
+
} from '../../../store/with-schemas/index.d.ts';
|
|
38
|
+
import type {DpcJson, Persister, Persists} from '../../with-schemas/index.d.ts';
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The SupabasePersister interface represents a Persister that lets you save and
|
|
42
|
+
* load Store data to and from a Supabase project.
|
|
43
|
+
*
|
|
44
|
+
* You should use the createSupabasePersister function to create a
|
|
45
|
+
* SupabasePersister object.
|
|
46
|
+
*
|
|
47
|
+
* It is a minor extension to the Persister interface and simply provides an
|
|
48
|
+
* extra getSupabase method for accessing a reference to the Supabase client the
|
|
49
|
+
* Store is being persisted with.
|
|
50
|
+
* @category Persister
|
|
51
|
+
* @since 9.6.0
|
|
52
|
+
*/
|
|
53
|
+
export interface SupabasePersister<
|
|
54
|
+
Schemas extends OptionalSchemas,
|
|
55
|
+
> extends Persister<Schemas, Persists.StoreOrMergeableStore> {
|
|
56
|
+
/**
|
|
57
|
+
* The getSupabase method returns a reference to the Supabase client the Store
|
|
58
|
+
* is being persisted with.
|
|
59
|
+
* @returns A reference to the Supabase client.
|
|
60
|
+
* @example
|
|
61
|
+
* This example creates a Persister object against a newly-created Store and
|
|
62
|
+
* then gets the Supabase client back out again.
|
|
63
|
+
*
|
|
64
|
+
* ```js ignore
|
|
65
|
+
* import {createClient} from '@supabase/supabase-js';
|
|
66
|
+
* import {createStore} from 'tinybase';
|
|
67
|
+
* import {createSupabasePersister} from 'tinybase/persisters/persister-supabase';
|
|
68
|
+
*
|
|
69
|
+
* const supabase = createClient(
|
|
70
|
+
* 'https://my-project.supabase.co',
|
|
71
|
+
* 'anon-key',
|
|
72
|
+
* );
|
|
73
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
74
|
+
* const persister = createSupabasePersister(store, supabase, 'my_tinybase');
|
|
75
|
+
*
|
|
76
|
+
* console.log(persister.getSupabase() == supabase);
|
|
77
|
+
* // -> true
|
|
78
|
+
*
|
|
79
|
+
* await persister.destroy();
|
|
80
|
+
* ```
|
|
81
|
+
* @category Getter
|
|
82
|
+
* @since 9.6.0
|
|
83
|
+
*/
|
|
84
|
+
getSupabase(): SupabaseClient;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The createSupabasePersister function creates a SupabasePersister object that
|
|
89
|
+
* can persist the Store to a Supabase project.
|
|
90
|
+
*
|
|
91
|
+
* This has schema-based typing. The following is a simplified representation:
|
|
92
|
+
*
|
|
93
|
+
* ```ts override
|
|
94
|
+
* createSupabasePersister(
|
|
95
|
+
* store: Store | MergeableStore,
|
|
96
|
+
* supabase: SupabaseClient,
|
|
97
|
+
* configOrStoreTableName?: DpcJson | string,
|
|
98
|
+
* onIgnoredError?: (error: any) => void,
|
|
99
|
+
* ): SupabasePersister;
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* A SupabasePersister supports regular Store objects, and can also be used to
|
|
103
|
+
* persist the metadata of a MergeableStore.
|
|
104
|
+
*
|
|
105
|
+
* As well as providing a reference to the Store to persist, you must provide a
|
|
106
|
+
* `supabase` parameter which is the client returned from Supabase's
|
|
107
|
+
* `createClient` function.
|
|
108
|
+
*
|
|
109
|
+
* The Persister stores a JSON serialization of the whole Store in a single row
|
|
110
|
+
* of a table. The third argument is a DpcJson object that configures the table
|
|
111
|
+
* and column names to use, or, if it is simply a string, it is used as the
|
|
112
|
+
* `storeTableName` property.
|
|
113
|
+
*
|
|
114
|
+
* Unlike the other database Persisters, this one will not create or alter any
|
|
115
|
+
* of that structure for you, so you need to set it up yourself with a migration
|
|
116
|
+
* or the Supabase SQL editor before the Persister will work at all. By default
|
|
117
|
+
* it expects a table called `tinybase` with a text primary key called `_id` and
|
|
118
|
+
* a text column called `store`:
|
|
119
|
+
*
|
|
120
|
+
* ```sql ignore
|
|
121
|
+
* CREATE TABLE tinybase (_id text PRIMARY KEY, store text);
|
|
122
|
+
* ```
|
|
123
|
+
*
|
|
124
|
+
* Row-level security applies to everything the Persister does, so it will read
|
|
125
|
+
* nothing and save nothing until a policy grants access to it. What that policy
|
|
126
|
+
* should be depends on who is allowed to see the Store: the following lets any
|
|
127
|
+
* signed-in user read and write it, which suits a Store that a whole team
|
|
128
|
+
* shares, but a per-user Store wants a policy that compares `auth.uid()` to a
|
|
129
|
+
* column of its own instead.
|
|
130
|
+
*
|
|
131
|
+
* ```sql ignore
|
|
132
|
+
* ALTER TABLE tinybase ENABLE ROW LEVEL SECURITY;
|
|
133
|
+
* CREATE POLICY tinybase_access ON tinybase
|
|
134
|
+
* FOR ALL TO authenticated USING (true) WITH CHECK (true);
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* For the startAutoLoad method to pick up changes made elsewhere, the table
|
|
138
|
+
* must also be published to Supabase Realtime:
|
|
139
|
+
*
|
|
140
|
+
* ```sql ignore
|
|
141
|
+
* ALTER PUBLICATION supabase_realtime ADD TABLE tinybase;
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* Note that Realtime checks a client's `SELECT` policy before it will send that
|
|
145
|
+
* client a change, so a Store that loads and saves correctly but never
|
|
146
|
+
* auto-loads is usually a policy problem rather than a publication one.
|
|
147
|
+
*
|
|
148
|
+
* If you cannot enable Realtime, set the `autoLoadIntervalSeconds` property of
|
|
149
|
+
* the DpcJson object, and the Persister will additionally poll the table at
|
|
150
|
+
* that interval. It does not poll unless you provide that property.
|
|
151
|
+
* @param store The Store or MergeableStore to persist.
|
|
152
|
+
* @param supabase The Supabase client that was returned from `createClient`.
|
|
153
|
+
* @param configOrStoreTableName A DpcJson object to configure the table and
|
|
154
|
+
* column names (or a string to set the `storeTableName` property).
|
|
155
|
+
* @param onIgnoredError An optional handler for the errors that the Persister
|
|
156
|
+
* would otherwise ignore when trying to save or load data. This is suitable for
|
|
157
|
+
* debugging persistence issues in a development environment.
|
|
158
|
+
* @returns A reference to the new SupabasePersister object.
|
|
159
|
+
* @example
|
|
160
|
+
* This example creates a SupabasePersister object and persists the Store to a
|
|
161
|
+
* Supabase project as a JSON serialization into the `my_tinybase` table.
|
|
162
|
+
*
|
|
163
|
+
* ```js ignore
|
|
164
|
+
* import {createClient} from '@supabase/supabase-js';
|
|
165
|
+
* import {createStore} from 'tinybase';
|
|
166
|
+
* import {createSupabasePersister} from 'tinybase/persisters/persister-supabase';
|
|
167
|
+
*
|
|
168
|
+
* const supabase = createClient(
|
|
169
|
+
* 'https://my-project.supabase.co',
|
|
170
|
+
* 'anon-key',
|
|
171
|
+
* );
|
|
172
|
+
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
|
|
173
|
+
* const persister = createSupabasePersister(store, supabase, 'my_tinybase');
|
|
174
|
+
*
|
|
175
|
+
* await persister.save();
|
|
176
|
+
* // Store will be saved to the Supabase table.
|
|
177
|
+
*
|
|
178
|
+
* console.log((await supabase.from('my_tinybase').select('store')).data);
|
|
179
|
+
* // -> [{store: '[{"pets":{"fido":{"species":"dog"}}},{}]'}]
|
|
180
|
+
*
|
|
181
|
+
* await persister.destroy();
|
|
182
|
+
* ```
|
|
183
|
+
* @example
|
|
184
|
+
* This example creates a SupabasePersister object that automatically loads
|
|
185
|
+
* changes made to the table by other clients, over Supabase Realtime.
|
|
186
|
+
*
|
|
187
|
+
* ```js ignore
|
|
188
|
+
* import {createClient} from '@supabase/supabase-js';
|
|
189
|
+
* import {createStore} from 'tinybase';
|
|
190
|
+
* import {createSupabasePersister} from 'tinybase/persisters/persister-supabase';
|
|
191
|
+
*
|
|
192
|
+
* const supabase = createClient(
|
|
193
|
+
* 'https://my-project.supabase.co',
|
|
194
|
+
* 'anon-key',
|
|
195
|
+
* );
|
|
196
|
+
* const store = createStore();
|
|
197
|
+
* const persister = createSupabasePersister(store, supabase, {
|
|
198
|
+
* mode: 'json',
|
|
199
|
+
* storeTableName: 'my_tinybase',
|
|
200
|
+
* });
|
|
201
|
+
*
|
|
202
|
+
* await persister.startAutoLoad();
|
|
203
|
+
* await persister.startAutoSave();
|
|
204
|
+
*
|
|
205
|
+
* // Changes made by other clients now arrive over Realtime.
|
|
206
|
+
*
|
|
207
|
+
* await persister.destroy();
|
|
208
|
+
* ```
|
|
209
|
+
* @category Creation
|
|
210
|
+
* @since 9.6.0
|
|
211
|
+
*/
|
|
212
|
+
export function createSupabasePersister<Schemas extends OptionalSchemas>(
|
|
213
|
+
store: Store<Schemas> | MergeableStore<Schemas>,
|
|
214
|
+
supabase: SupabaseClient,
|
|
215
|
+
configOrStoreTableName?: DpcJson | string,
|
|
216
|
+
onIgnoredError?: (error: any) => void,
|
|
217
|
+
): SupabasePersister<Schemas>;
|
|
@@ -2110,11 +2110,18 @@ export function createCustomPersister<
|
|
|
2110
2110
|
* ideas on how to build your own Persister type, and as functional examples.
|
|
2111
2111
|
* Examine the implementation of the createSqlite3Persister function as a good
|
|
2112
2112
|
* starting point, for example.
|
|
2113
|
+
*
|
|
2114
|
+
* Your `executeCommand` function is given SQL that uses SQLite's anonymous `?`
|
|
2115
|
+
* placeholders, with the parameters to bind to them in order. SQLite drivers
|
|
2116
|
+
* agree on that form, whereas they vary in how they handle the numbered
|
|
2117
|
+
* placeholders that PostgreSQL requires, so you should not need to rewrite
|
|
2118
|
+
* statements before passing them on.
|
|
2113
2119
|
* @param store The Store to persist.
|
|
2114
2120
|
* @param configOrStoreTableName A DatabasePersisterConfig object, or a string
|
|
2115
2121
|
* that will be used as the name of the Store's table in the database.
|
|
2116
2122
|
* @param executeCommand A function that will execute a command against the
|
|
2117
|
-
* database.
|
|
2123
|
+
* database. It receives SQL with anonymous `?` placeholders, and the parameters
|
|
2124
|
+
* to bind to them in order.
|
|
2118
2125
|
* @param addChangeListener A function that will register a listener for changes
|
|
2119
2126
|
* to the database.
|
|
2120
2127
|
* @param delChangeListener A function that will unregister the listener for
|