couchset 0.2.7 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/README.md +284 -153
  2. package/dist/connection/connection.d.ts +68 -0
  3. package/dist/connection/connection.js +485 -0
  4. package/dist/connection/connection.js.map +1 -0
  5. package/dist/connection/env.d.ts +2 -0
  6. package/dist/connection/env.js +16 -0
  7. package/dist/connection/env.js.map +1 -0
  8. package/dist/connection/index.d.ts +3 -0
  9. package/dist/connection/index.js +25 -0
  10. package/dist/connection/index.js.map +1 -0
  11. package/dist/connection/types.d.ts +25 -0
  12. package/dist/connection/types.js +3 -0
  13. package/dist/connection/types.js.map +1 -0
  14. package/dist/database.d.ts +9 -0
  15. package/dist/database.js +196 -0
  16. package/dist/database.js.map +1 -0
  17. package/dist/index.d.ts +18 -6
  18. package/dist/index.js +53 -8
  19. package/dist/index.js.map +1 -1
  20. package/dist/legacy/connection.d.ts +2 -0
  21. package/dist/legacy/connection.js +24 -0
  22. package/dist/legacy/connection.js.map +1 -0
  23. package/dist/legacy/index.d.ts +10 -0
  24. package/dist/legacy/index.js +93 -0
  25. package/dist/legacy/index.js.map +1 -0
  26. package/dist/legacy/model.d.ts +55 -0
  27. package/dist/legacy/model.js +282 -0
  28. package/dist/legacy/model.js.map +1 -0
  29. package/dist/legacy/pagination/index.d.ts +1 -0
  30. package/dist/legacy/pagination/index.js +18 -0
  31. package/dist/legacy/pagination/index.js.map +1 -0
  32. package/dist/legacy/pagination/pagination.d.ts +12 -0
  33. package/dist/legacy/pagination/pagination.js +85 -0
  34. package/dist/legacy/pagination/pagination.js.map +1 -0
  35. package/dist/legacy/search/customQuery.d.ts +13 -0
  36. package/dist/legacy/search/customQuery.js +73 -0
  37. package/dist/legacy/search/customQuery.js.map +1 -0
  38. package/dist/legacy/search/index.d.ts +1 -0
  39. package/dist/legacy/search/index.js +18 -0
  40. package/dist/legacy/search/index.js.map +1 -0
  41. package/dist/model/default-scope.d.ts +10 -0
  42. package/dist/model/default-scope.js +47 -0
  43. package/dist/model/default-scope.js.map +1 -0
  44. package/dist/model/hydrated-document.d.ts +30 -0
  45. package/dist/model/hydrated-document.js +118 -0
  46. package/dist/model/hydrated-document.js.map +1 -0
  47. package/dist/model/include.d.ts +33 -0
  48. package/dist/model/include.js +250 -0
  49. package/dist/model/include.js.map +1 -0
  50. package/dist/model/index.d.ts +137 -51
  51. package/dist/model/index.js +519 -174
  52. package/dist/model/index.js.map +1 -1
  53. package/dist/model/indexes.d.ts +16 -0
  54. package/dist/model/indexes.js +155 -0
  55. package/dist/model/indexes.js.map +1 -0
  56. package/dist/model/keyspace.d.ts +9 -0
  57. package/dist/model/keyspace.js +28 -0
  58. package/dist/model/keyspace.js.map +1 -0
  59. package/dist/model/read-helpers.d.ts +36 -0
  60. package/dist/model/read-helpers.js +275 -0
  61. package/dist/model/read-helpers.js.map +1 -0
  62. package/dist/model/safe-query.d.ts +23 -0
  63. package/dist/model/safe-query.js +138 -0
  64. package/dist/model/safe-query.js.map +1 -0
  65. package/dist/model/ttl.d.ts +9 -0
  66. package/dist/model/ttl.js +73 -0
  67. package/dist/model/ttl.js.map +1 -0
  68. package/dist/model/validation.d.ts +5 -0
  69. package/dist/model/validation.js +104 -0
  70. package/dist/model/validation.js.map +1 -0
  71. package/dist/model/write-helpers.d.ts +31 -0
  72. package/dist/model/write-helpers.js +220 -0
  73. package/dist/model/write-helpers.js.map +1 -0
  74. package/dist/pagination/index.d.ts +1 -0
  75. package/dist/pagination/index.js +1 -0
  76. package/dist/pagination/index.js.map +1 -1
  77. package/dist/pagination/pagination.d.ts +1 -8
  78. package/dist/pagination/pagination.js +16 -29
  79. package/dist/pagination/pagination.js.map +1 -1
  80. package/dist/pagination/safe-pagination.d.ts +15 -0
  81. package/dist/pagination/safe-pagination.js +221 -0
  82. package/dist/pagination/safe-pagination.js.map +1 -0
  83. package/dist/pagination/types.d.ts +11 -0
  84. package/dist/pagination/types.js +3 -0
  85. package/dist/pagination/types.js.map +1 -0
  86. package/dist/search/customQuery.d.ts +10 -3
  87. package/dist/search/customQuery.js +17 -18
  88. package/dist/search/customQuery.js.map +1 -1
  89. package/dist/shared/common.model.js +2 -2
  90. package/dist/shared/common.model.js.map +1 -1
  91. package/dist/timeseries/index.d.ts +1 -0
  92. package/dist/timeseries/index.js +18 -0
  93. package/dist/timeseries/index.js.map +1 -0
  94. package/dist/timeseries/time-series-model.d.ts +60 -0
  95. package/dist/timeseries/time-series-model.js +267 -0
  96. package/dist/timeseries/time-series-model.js.map +1 -0
  97. package/dist/utils/awaitTo.d.ts +1 -1
  98. package/dist/utils/awaitTo.js +1 -1
  99. package/dist/utils/awaitTo.js.map +1 -1
  100. package/docs/beta-migration.md +175 -0
  101. package/legacy/index.js +1 -0
  102. package/legacy/package.json +4 -0
  103. package/next/index.js +1 -0
  104. package/next/package.json +4 -0
  105. package/package.json +13 -8
  106. package/dist/connection.d.ts +0 -42
  107. package/dist/connection.js +0 -156
  108. package/dist/connection.js.map +0 -1
package/README.md CHANGED
@@ -1,236 +1,367 @@
1
-
2
1
  <p align="center">
3
- <h1 align="center"> CouchSet - Couchbase ORM & Automatic GraphQL API generator (Resolver/Queries)</h1>
2
+ <h1 align="center">CouchSet</h1>
4
3
  </p>
5
4
 
6
-
7
5
  <div align="center">
8
-
9
- <div style="display: flex;justify-content:center;">
10
-
11
-
12
- <img alt="NPM" src="https://img.shields.io/npm/dt/couchset.svg"></img>
13
-
14
-
15
-
6
+ <img alt="NPM" src="https://img.shields.io/npm/dt/couchset.svg"></img>
7
+ <br />
8
+ <img width="500px" src="./docs/couchset.png"></img>
16
9
  </div>
17
10
 
18
- <img width="500px" src="./docs/couchset.png"></img>
19
- </div>
20
-
21
-
22
- CouchSet is a Couchbase ORM & Automatic GraphQL API code generator (Resolver/Queries) tool
11
+ CouchSet is a Couchbase model layer for TypeScript and Node.js. The default `couchset` entrypoint keeps the legacy API for safe upgrades; the modern API is available from `couchset/next`.
23
12
 
24
13
  - [Install](#install)
14
+ - [Legacy Default](#legacy-default)
15
+ - [Modern API](#modern-api)
16
+ - [Connection Lifecycle](#connection-lifecycle)
17
+ - [Models](#models)
18
+ - [Reads](#reads)
19
+ - [Writes](#writes)
20
+ - [Queries](#queries)
21
+ - [Gradual Migration](#gradual-migration)
22
+ - [Migration Notes](./docs/beta-migration.md)
25
23
  - [License](#license)
26
24
 
27
- ## 1. Install
25
+ ## Install
26
+
28
27
  ```bash
29
28
  npm i couchset --save
30
29
  ```
31
30
 
32
- ## 2. Start couchset
31
+ ## Legacy Default
32
+
33
+ Existing projects can keep importing from `couchset` and continue using the old model methods while gradually migrating.
34
+
33
35
  ```ts
34
- import { couchset } from 'couchset';
36
+ import {couchset, Model} from 'couchset';
35
37
 
36
- const started = await couchset({
37
- connectionString: 'couchbase://localhost',
38
- username: 'admin',
39
- password: '123456',
40
- bucketName: 'stq'
41
- })
38
+ await couchset({
39
+ connectionString: process.env.COUCHBASE_URL || 'couchbase://localhost',
40
+ username: process.env.COUCHBASE_USERNAME || 'admin',
41
+ password: process.env.COUCHBASE_PASSWORD || '1234',
42
+ bucketName: process.env.COUCHBASE_BUCKET || 'dev',
43
+ });
44
+
45
+ const users = new Model('User', {schema: {createdAt: 'date'}});
46
+
47
+ const created = await users.create({
48
+ userId: 'ceddy',
49
+ email: 'ceddy@example.com',
50
+ });
51
+
52
+ const found = await users.findById(created.id);
53
+ await users.updateById(created.id, {...found, email: 'new@example.com'});
54
+ await users.delete(created.id);
42
55
  ```
43
56
 
44
- ## 3. Create a Model and start using it
57
+ ## Modern API
58
+
59
+ New code can opt into the modern API with `couchset/next`.
45
60
 
46
61
  ```ts
47
- import { Model } from 'couchset';
62
+ import {couchset, Model} from 'couchset/next';
63
+
64
+ type User = {
65
+ userId: string;
66
+ email?: string;
67
+ };
68
+
69
+ const users = new Model('User', {
70
+ schema: {
71
+ createdAt: 'date',
72
+ updatedAt: 'date',
73
+ },
74
+ indexes: [
75
+ {
76
+ name: 'idx_user_userId',
77
+ fields: ['userId'],
78
+ },
79
+ ],
80
+ });
48
81
 
49
- const userModel = new Model('User');
82
+ await couchset({
83
+ connectionString: process.env.COUCHBASE_URL || 'couchbase://localhost',
84
+ username: process.env.COUCHBASE_USERNAME || 'admin',
85
+ password: process.env.COUCHBASE_PASSWORD || '1234',
86
+ bucketName: process.env.COUCHBASE_BUCKET || 'dev',
87
+ });
50
88
 
89
+ await couchset.ready();
51
90
 
52
- // Create document
53
- const created = await userModel.create({
54
- username: 'ceddy',
55
- password: 'love couchbase',
91
+ const created = await users.insert<User>({
92
+ userId: 'ceddy',
93
+ email: 'ceddy@example.com',
56
94
  });
57
95
 
58
- // Find document
59
- const foundData = await userModel.findById(created.id);
96
+ const found = await users.getById<User>(created.id);
60
97
 
61
- // update document
62
- const updatedData = await userModel.updateById(created.id, { ...created, someValue: 'x' });
98
+ const patched = await users.patchById<User>(created.id, {
99
+ $set: {email: 'new@example.com'},
100
+ });
63
101
 
64
- // delete
65
- const deletedData = await userModel.delete(created.id);
102
+ const page = await users.page<User>({
103
+ where: {userId: {$eq: 'ceddy'}},
104
+ limit: 25,
105
+ page: 0,
106
+ });
66
107
 
108
+ await users.deleteById(created.id, {hard: true});
67
109
  ```
68
110
 
69
- ## 4. Pagination
111
+ ## Connection Lifecycle
112
+
113
+ Models can be declared before connecting. Model operations wait for the shared connection before binding to the Couchbase bucket and collection.
70
114
 
71
- All models come with a method for automatic pagination
72
115
  ```ts
73
- const paginationData = await userModel.pagination({
74
- select: ["id", "email", "phone","fullname"],
75
- where: {
76
- userId: { $eq: "ceddy" },
77
- $or: [{ userId: { $eq: "ceddy" } }, { phone: 10 }],
78
- },
79
- limit: 100,
80
- page: 0,
116
+ import {couchset, health, ping, ready, shutdown} from 'couchset/next';
117
+
118
+ await couchset({
119
+ connectionString: 'couchbase://localhost',
120
+ username: 'admin',
121
+ password: '1234',
122
+ bucketName: 'dev',
123
+ autoReconnect: true,
124
+ reconnectIntervalMs: 5000,
81
125
  });
126
+
127
+ await ready();
128
+ await ping();
129
+ console.log(health());
130
+
131
+ await shutdown();
82
132
  ```
83
133
 
84
- which translates to this query
134
+ Reconnect is enabled by default. Environment flags:
135
+
136
+ - `COUCHSET_RECONNECT`: use `false`, `0`, or `no` to disable reconnect.
137
+ - `COUCHSET_RECONNECT_INTERVAL_MS`: reconnect and health-check interval in milliseconds. Default is `5000`.
138
+
139
+ The modern entrypoint also exports app starter helpers that read Couchbase credentials from env:
85
140
 
86
- ```sql
87
- SELECT * FROM `stq` WHERE _type="User" AND userId="ceddy" AND (userId="ceddy" OR phone=10) ORDER BY createdAt DESC LIMIT 100 OFFSET 0
141
+ ```ts
142
+ import {startCouchbase, startCouchbaseServerless} from 'couchset/next';
143
+
144
+ await startCouchbase();
145
+ await startCouchbaseServerless();
88
146
  ```
89
147
 
148
+ The starters read `COUCHBASE_URL`, `COUCHBASE_BUCKET`, `COUCHBASE_USERNAME`, `COUCHBASE_PASSWORD`, and `COUCHBASE_PROXY`. You can pass any `CouchsetArgs` field as an override.
90
149
 
91
- Pagination results
150
+ ## Models
92
151
 
93
- ```js
94
- [
95
- {
96
- id: '209d3143-09b7-4b3d-bf7d-f0ccd3f98922',
97
- updatedAt: 2021-01-26T01:51:43.218Z,
98
- createdAt: 2021-01-26T01:51:43.210Z,
99
- _type: 'User',
100
- userId: 'ceddy',
101
- password: '...',
102
- someValue: 'x'
103
- },
104
- {
105
- id: '1392e4f6-ae1e-4e01-b7d5-103bdd0e843f',
106
- updatedAt: 2021-01-26T01:51:29.591Z,
107
- createdAt: 2021-01-26T01:51:29.583Z,
108
- _type: 'User',
109
- userId: 'ceddy',
110
- password: '...',
111
- someValue: 'x'
112
- }
113
- ]
152
+ ```ts
153
+ const auditEvents = new Model('AuditEvent', {
154
+ scope: 'app',
155
+ collection: 'events',
156
+ softDelete: true,
157
+ defaultWhere: {tenantId: {$eq: 'tenant-1'}},
158
+ dateFields: ['profile.createdAt'],
159
+ validateCreate: (doc) => doc,
160
+ validateReplace: (doc) => doc,
161
+ parse: (doc) => doc,
162
+ });
114
163
  ```
115
164
 
165
+ Useful model helpers:
116
166
 
117
- ## 5. Custom queries & Query builder
118
- Query builder is inspired from node-ottoman, for more examples, please see https://ottomanjs.com/guides/query-builder.html#query-builder
167
+ ```ts
168
+ users.bucket(); // `dev`
169
+ users.keyspace(); // `dev` or default:`dev`.`scope`.`collection`
170
+ users.from('u'); // `dev` AS u
171
+ ```
172
+
173
+ ## Reads
119
174
 
120
175
  ```ts
121
- import { Query } from 'couchset';
176
+ await users.getById<User>('user::1');
177
+ await users.findByIdWithMeta<User>('user::1');
178
+
179
+ await users.findMany<User>({
180
+ select: ['id', 'userId', 'email'],
181
+ where: {userId: {$eq: 'ceddy'}},
182
+ orderBy: {createdAt: 'DESC'},
183
+ limit: 10,
184
+ });
122
185
 
123
- const params = {
124
- select: [
125
- {
126
- $count: {
127
- $field: {
128
- name: 'type',
129
- },
130
- as: 'odm',
131
- },
132
- },
133
- ],
134
- let: [
135
- { key: 'amount_val', value: 10 },
136
- { key: 'size_val', value: 20 },
137
- ],
138
- where: {
139
- $or: [{ price: { $gt: 'amount_val', $isNotNull: true } }, { auto: { $gt: 10 } }, { amount: 10 }],
140
- $and: [
141
- { price2: { $gt: 1.99, $isNotNull: true } },
142
- { $or: [{ price3: { $gt: 1.99, $isNotNull: true } }, { id: '20' }] },
143
- ],
144
- $any: {
145
- $expr: [{ $in: { search_expr: 'search', target_expr: 'address' } }],
146
- $satisfied: { address: '10' },
147
- },
148
- $in: { search_expr: 'search', target_expr: ['address'] },
149
- },
150
- groupBy: [{ expr: 'type', as: 'sch' }],
151
- letting: [
152
- { key: 'amount_v2', value: 10 },
153
- { key: 'size_v2', value: 20 },
154
- ],
155
- having: { type: { $like: '%hotel%' } },
156
- orderBy: { type: 'DESC' },
157
- limit: 10,
158
- offset: 1,
159
- use: ['airlineR_8093', 'airlineR_8094'],
160
- };
186
+ await users.findOne<User>({where: {email: {$eq: 'ceddy@example.com'}}});
187
+ await users.exists({where: {userId: {$eq: 'ceddy'}}});
188
+ await users.count({where: {userId: {$eq: 'ceddy'}}});
161
189
 
162
- const query = new Query(params, 'travel-sample').build();
163
- console.log(query);
190
+ const result = await users.page<User>({
191
+ where: {userId: {$eq: 'ceddy'}},
192
+ limit: 10,
193
+ page: 0,
194
+ });
164
195
 
196
+ result.items;
197
+ result.hasNext;
198
+ result.pageInfo.nextPage;
165
199
  ```
166
200
 
167
- which translates to
201
+ Hydrated documents:
202
+
203
+ ```ts
204
+ const doc = await users.findDocById<User & {id: string}>('user::1');
168
205
 
169
- ```sql
170
- SELECT COUNT(type) AS odm FROM travel-sample USE KEYS ["airlineR_8093","airlineR_8094"] LET amount_val=10,size_val=20 WHERE ((price>amount_val AND price IS NOT NULL) OR auto>10 OR amount=10) AND ((price2>1.99 AND price2 IS NOT NULL) AND ((price3>1.99 AND price3 IS NOT NULL) OR id="20")) AND ANY search IN address SATISFIES address="10" END AND search IN ["address"] GROUP BY type AS sch LETTING amount_v2=10,size_v2=20 HAVING type LIKE "%hotel%" ORDER BY type DESC LIMIT 10 OFFSET 1
206
+ doc.email = 'updated@example.com';
207
+ await doc.save();
208
+ await doc.patch({$set: {verified: true}});
209
+ await doc.reload();
210
+ await doc.delete({hard: true});
171
211
  ```
172
212
 
213
+ Soft delete scopes:
173
214
 
215
+ ```ts
216
+ await users.softDeleteById<User>('user::1');
217
+ await users.restoreById<User>('user::1');
218
+
219
+ await users.withDeleted().findMany<User>();
220
+ await users.onlyDeleted().findMany<User>();
221
+ await users.withoutDefaultWhere().findMany<User>();
222
+ ```
174
223
 
175
- ### Running custom query on cluster
224
+ ## Writes
176
225
 
177
226
  ```ts
178
- import { QueryCluster } from 'couchset';
227
+ await users.insert<User>({id: 'user::1', userId: 'ceddy'});
228
+ await users.upsert<User>({id: 'user::1', userId: 'ceddy'});
229
+ await users.replaceById<User>('user::1', {userId: 'ceddy', email: 'new@example.com'});
230
+ await users.patchById<User>('user::1', {
231
+ $set: {email: 'new@example.com'},
232
+ $inc: {loginCount: 1},
233
+ $unset: ['temporaryCode'],
234
+ });
235
+ await users.incrementById<User>('user::1', 'loginCount', 1);
236
+ await users.deleteById('user::1', {hard: true});
237
+ ```
179
238
 
180
- const queryresults = await QueryCluster(queryBuilder);
181
- // queryresults = { rows: object[], meta: any}
239
+ TTL helpers:
182
240
 
241
+ ```ts
242
+ await users.insert<User>({id: 'user::1', userId: 'ceddy'}, {ttl: '2h'});
243
+ await users.upsert<User>({id: 'user::2', userId: 'ceddy'}, {ttlSeconds: 300});
183
244
  ```
184
245
 
185
- ## 6. Model Automation
246
+ ## Queries
186
247
 
187
- This is how we automate it to generate code with all methods,schema, queries
248
+ Modern query helpers pass SDK parameters correctly and throw on failures by default.
188
249
 
189
250
  ```ts
190
- const automaticUser = userModel.automate();
251
+ const rows = await users.queryRows<User>(
252
+ `SELECT u.* FROM ${users.from('u')} WHERE u.userId=$userId LIMIT $limit`,
253
+ {userId: 'ceddy', limit: 10}
254
+ );
255
+
256
+ const first = await users.queryOne<User>(
257
+ `SELECT u.* FROM ${users.from('u')} WHERE u.email=$email LIMIT 1`,
258
+ {email: 'ceddy@example.com'}
259
+ );
260
+
261
+ const page = await users.queryPage<User>(
262
+ `SELECT u.* FROM ${users.from('u')} WHERE u.userId=$userId LIMIT $limit`,
263
+ {userId: 'ceddy', limit: 10}
264
+ );
191
265
  ```
192
266
 
193
- After automating the model, `automaticUser` will come with Server-side Resolver functions, and client queries, mutations, subscriptions, like below
267
+ Model read helpers also throw by default. Use `throwOnError: false` only when an empty fallback is intentional.
194
268
 
269
+ ```ts
270
+ const rows = await users.findMany<User>({
271
+ where: {userId: {$eq: 'ceddy'}},
272
+ throwOnError: false,
273
+ });
274
+ ```
275
+
276
+ ## Indexes
195
277
 
196
278
  ```ts
197
- // Get all automatic generated resolvers and queries/fragments,mutations,subscriptions
198
- const {
199
- resolver: UserResolver, // Server resolver for building GraphQL
200
- modelKeys: UserSelectors, // for any custom queries or exporting
201
- client, // client queries,mutations,subscriptions
202
- } = automaticUser;
279
+ const users = new Model('User', {
280
+ indexes: [
281
+ {
282
+ name: 'idx_user_email',
283
+ fields: ['email'],
284
+ where: {deleted: {$isNotValued: true}},
285
+ },
286
+ ],
287
+ });
203
288
 
289
+ await users.ensureIndexes();
290
+ await couchset.ensureIndexes();
204
291
  ```
205
292
 
206
- ## 7. Write to filesystem
207
- TODO
293
+ ## Includes
208
294
 
295
+ ```ts
296
+ const posts = new Model('Post');
297
+
298
+ const rows = await posts.findMany({
299
+ where: {published: {$eq: true}},
300
+ include: [
301
+ {
302
+ as: 'author',
303
+ model: users,
304
+ key: 'authorId',
305
+ type: 'leftJoin',
306
+ },
307
+ ],
308
+ });
309
+ ```
209
310
 
311
+ ## Time Series
210
312
 
313
+ ```ts
314
+ import {TimeSeriesModel} from 'couchset/next';
211
315
 
212
- <br/>
213
- <br/>
214
- <br/>
316
+ const metrics = new TimeSeriesModel('Metric', {
317
+ keyField: 'deviceId',
318
+ timeField: 'timestamp',
319
+ values: [{field: 'temperature'}],
320
+ interval: '1m',
321
+ });
215
322
 
216
- #### Contributors needed
217
- - Create automatic pagination
218
- - Create Schema and validation/population ✅
219
- - Create static methods for models like `save`, `update`, `findMany` e.t.c ✅
220
- - Automated indexes (only couchbase enterprise) ✅
221
- - Geospatial queries ✅
222
- - FTS queries ✅
323
+ await metrics.appendChunk('device-1', [
324
+ {deviceId: 'device-1', timestamp: Date.now(), temperature: 21.5},
325
+ ]);
326
+ ```
223
327
 
328
+ ## Gradual Migration
224
329
 
330
+ Use `couchset` for old code and `couchset/next` for new code. Both model APIs share the same connection singleton, reconnect loop, and health state, so you can migrate one model or file at a time without opening a second Couchbase cluster connection.
225
331
 
332
+ ```ts
333
+ import {couchset, Model} from 'couchset';
334
+ import {Model as NextModel} from 'couchset/next';
226
335
 
227
- <div align="center">
228
- <img height="300px" src="./docs/couch.png"></img>
229
- </div>
336
+ await couchset(args);
230
337
 
231
- <p align="center">
232
- <h1 align="center"> Algo Inc </h1>
233
- </p>
338
+ const legacyUsers = new Model('User');
339
+ const nextUsers = new NextModel('User');
340
+ ```
341
+
342
+ `couchset/legacy` remains available as an explicit alias for the default legacy API.
343
+
344
+ Modern replacements:
345
+
346
+ | Old method | Modern method |
347
+ | --- | --- |
348
+ | `create()` | `insert()` or `upsert()` |
349
+ | `findById()` | `getById()` |
350
+ | `updateById()` / `save()` | `replaceById()` or `patchById()` |
351
+ | `delete()` | `deleteById()` |
352
+ | `pagination()` | `findMany()` or `page()` |
353
+ | `customQuery()` | `queryRows()`, `queryOne()`, or `queryPage()` |
354
+
355
+ ## Local Tests
356
+
357
+ ```bash
358
+ npm run build
359
+ npm test
360
+ npm run test:serverless
361
+ ```
362
+
363
+ Set `COUCHBASE_URL`, `COUCHBASE_BUCKET`, `COUCHBASE_USERNAME`, and `COUCHBASE_PASSWORD` to point the integration tests at a local Couchbase instance.
364
+
365
+ ## License
234
366
 
235
- ## License
236
- Couchset is [MIT licensed](./LICENSE).
367
+ CouchSet is [MIT licensed](./LICENSE).
@@ -0,0 +1,68 @@
1
+ import type { Bucket, Cluster, Collection } from 'couchbase';
2
+ import { ConnectionHealth, ConnectionState, CouchsetArgs } from './types';
3
+ /**
4
+ * CouchbaseConnection class
5
+ * Only one CouchbaseConnection can exist that's why it's a singleton
6
+ */
7
+ export declare class CouchbaseConnection implements CouchsetArgs {
8
+ private static _instance;
9
+ bucket: Bucket;
10
+ cluster: Cluster;
11
+ private connectionPromise?;
12
+ private connectionSettings?;
13
+ private reconnectPromise?;
14
+ private reconnectReject?;
15
+ private reconnectTimer?;
16
+ private healthTimer?;
17
+ private connectionState;
18
+ private autoReconnectEnabled;
19
+ private reconnectDelayMs;
20
+ private manuallyClosed;
21
+ private lastConnectionError?;
22
+ connectionString: string;
23
+ bucketName: string;
24
+ username: string;
25
+ password: string;
26
+ static get Instance(): CouchbaseConnection;
27
+ private constructor();
28
+ private configureReconnect;
29
+ private normalizeArgs;
30
+ private sameSettings;
31
+ private assignSettings;
32
+ private settingsError;
33
+ private connectionOptions;
34
+ private clearReconnectTimer;
35
+ private clearHealthTimer;
36
+ private scheduleTimer;
37
+ private rawPing;
38
+ private openCluster;
39
+ private scheduleHealthCheck;
40
+ private connectWithSettings;
41
+ private startReconnect;
42
+ /**
43
+ * start
44
+ */
45
+ init: (args: CouchsetArgs) => Promise<CouchbaseConnection>;
46
+ /**
47
+ * start serverless start
48
+ */
49
+ initServerless: (args: CouchsetArgs) => Promise<CouchbaseConnection>;
50
+ /**
51
+ * getCollection
52
+ */
53
+ getCollection: (scopeName?: string, collectionName?: string) => Collection;
54
+ getCluster: () => Cluster;
55
+ getBucket: () => string;
56
+ isConnected: () => boolean;
57
+ ready: () => Promise<CouchbaseConnection>;
58
+ ping: () => Promise<any>;
59
+ state: () => ConnectionState;
60
+ health: () => ConnectionHealth;
61
+ shouldReconnect: (error: unknown) => boolean;
62
+ markDisconnected: (error?: unknown) => void;
63
+ /**
64
+ * shutdown cluster
65
+ */
66
+ shutdown: () => Promise<void>;
67
+ }
68
+ export default CouchbaseConnection;