couchset 0.4.1 → 0.5.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/README.md +177 -2
- package/dist/database.d.ts +6 -0
- package/dist/database.js +51 -2
- package/dist/database.js.map +1 -1
- package/dist/eventing.d.ts +179 -0
- package/dist/eventing.js +822 -0
- package/dist/eventing.js.map +1 -0
- package/dist/model/include.d.ts +36 -3
- package/dist/model/include.js +154 -49
- package/dist/model/include.js.map +1 -1
- package/dist/model/index.d.ts +4 -1
- package/dist/model/index.js +8 -1
- package/dist/model/index.js.map +1 -1
- package/dist/model/read-helpers.d.ts +6 -2
- package/dist/model/read-helpers.js +96 -23
- package/dist/model/read-helpers.js.map +1 -1
- package/dist/model/read-types.d.ts +51 -0
- package/dist/model/read-types.js +3 -0
- package/dist/model/read-types.js.map +1 -0
- package/dist/model/safe-query.d.ts +3 -0
- package/dist/model/safe-query.js +22 -2
- package/dist/model/safe-query.js.map +1 -1
- package/dist/next.d.ts +20 -2
- package/dist/next.js +26 -1
- package/dist/next.js.map +1 -1
- package/dist/next.types.js +149 -1
- package/dist/next.types.js.map +1 -1
- package/dist/pagination/pagination.js +3 -1
- package/dist/pagination/pagination.js.map +1 -1
- package/dist/pagination/types.d.ts +2 -0
- package/dist/pagination/types.js.map +1 -1
- package/dist/search/customQuery.d.ts +2 -0
- package/dist/search/customQuery.js +4 -1
- package/dist/search/customQuery.js.map +1 -1
- package/docs/beta-migration.md +1 -1
- package/docs/document-modeling.md +5 -1
- package/docs/joins-and-consistency.md +228 -0
- package/docs/next-primitives.md +37 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -10,15 +10,17 @@
|
|
|
10
10
|
|
|
11
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`.
|
|
12
12
|
|
|
13
|
-
The additive client-owned primitives—typed definitions, explicit provisioning, transaction-bound models, CAS helpers,
|
|
13
|
+
The additive client-owned primitives—typed definitions, explicit provisioning, transaction-bound models, CAS helpers, safe index plans, and Eventing—are summarized below. Their complete operational guide is [Next primitives](./docs/next-primitives.md).
|
|
14
14
|
|
|
15
15
|
- [Install](#install)
|
|
16
16
|
- [Legacy Default](#legacy-default)
|
|
17
17
|
- [Modern API](#modern-api)
|
|
18
|
+
- [Modern Client Primitives](#modern-client-primitives)
|
|
18
19
|
- [Next primitives](./docs/next-primitives.md)
|
|
19
20
|
- [Connection Lifecycle](#connection-lifecycle)
|
|
20
21
|
- [Models](#models)
|
|
21
22
|
- [Reads](#reads)
|
|
23
|
+
- [Typed Joins and Read Consistency](#typed-joins-and-read-consistency)
|
|
22
24
|
- [Document Modeling](./docs/document-modeling.md)
|
|
23
25
|
- [Writes](#writes)
|
|
24
26
|
- [Queries](#queries)
|
|
@@ -113,6 +115,88 @@ const page = await users.page<User>({
|
|
|
113
115
|
await users.deleteById(created.id, {hard: true});
|
|
114
116
|
```
|
|
115
117
|
|
|
118
|
+
## Modern Client Primitives
|
|
119
|
+
|
|
120
|
+
`couchset/next` also offers a client-owned API for typed manifests, explicit administrative work, safe operational plans, and Eventing. These are deliberately separate from the singleton `Model` API above.
|
|
121
|
+
|
|
122
|
+
### Declarative models
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import {createCouchsetClient, defineModel} from 'couchset/next';
|
|
126
|
+
|
|
127
|
+
const sessions = defineModel({name: 'Session', scope: 'auth', collection: 'sessions'});
|
|
128
|
+
const db = createCouchsetClient({bucketName: 'app', models: [sessions]});
|
|
129
|
+
const sessionModel = db.model(sessions); // registers and binds; no DDL
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Read the [full client and model-definition guide](./docs/next-primitives.md#couchset-next-primitives).
|
|
133
|
+
|
|
134
|
+
### Provisioning and dynamic models
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
await db.ensureCollections(); // creates only missing scopes and collections
|
|
138
|
+
await db.ensureIndexes(); // create-only index DDL
|
|
139
|
+
|
|
140
|
+
const reports = await db.registerModel(reportDefinition, {provision: {collections: true}});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Read about [provisioning and dynamic models](./docs/next-primitives.md#provisioning-and-dynamic-models).
|
|
144
|
+
|
|
145
|
+
### Transactions and CAS
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
await db.transaction(async (tx) => {
|
|
149
|
+
await tx.model(sessions).insert({id: 'session::1', userId: 'user::1'});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const outcome = await sessionModel.consumeOnce('session::1', knownCas);
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Read the [transaction and CAS safety notes](./docs/next-primitives.md#transactions-and-cas).
|
|
156
|
+
|
|
157
|
+
### Safe index plans
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
const plan = await db.planIndexes(); // inspect missing, matching, and drifted indexes
|
|
161
|
+
await db.applyIndexPlan(plan); // creates safe replacements and waits for them
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Read about [index drift and opt-in cleanup](./docs/next-primitives.md#index-drift).
|
|
165
|
+
|
|
166
|
+
### Eventing functions
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
import {defineEventingFunction} from 'couchset/next';
|
|
170
|
+
|
|
171
|
+
const auditOrders = defineEventingFunction({
|
|
172
|
+
name: 'audit_orders',
|
|
173
|
+
code: 'function OnUpdate(doc, meta) { log(meta.id); }',
|
|
174
|
+
sourceKeyspace: {bucket: 'app', scope: 'sales', collection: 'orders'},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const eventing = db.eventing({
|
|
178
|
+
namespace: 'billing',
|
|
179
|
+
metadataKeyspace: {bucket: 'app', scope: 'eventing', collection: 'billing_metadata'},
|
|
180
|
+
definitions: [auditOrders],
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
await eventing.apply();
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Read the [Eventing lifecycle and safety guide](./docs/next-primitives.md#eventing-functions).
|
|
187
|
+
|
|
188
|
+
### Test fixtures
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
import {createCouchsetTestFixture} from 'couchset/next';
|
|
192
|
+
|
|
193
|
+
const {model, cleanup} = await createCouchsetTestFixture(db, {name: 'Invoice'});
|
|
194
|
+
// use model in the test
|
|
195
|
+
await cleanup();
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Read about [isolated CouchSet test fixtures](./docs/next-primitives.md#tests).
|
|
199
|
+
|
|
116
200
|
## Connection Lifecycle
|
|
117
201
|
|
|
118
202
|
Models can be declared before connecting. Model operations wait for the shared connection before binding to the Couchbase bucket and collection.
|
|
@@ -150,7 +234,15 @@ await startCouchbase();
|
|
|
150
234
|
await startCouchbaseServerless();
|
|
151
235
|
```
|
|
152
236
|
|
|
153
|
-
The starters
|
|
237
|
+
The starters accept one PostgreSQL-style `DB_URL` in place of the four connection settings. It takes precedence over `COUCHBASE_URL`, `COUCHBASE_BUCKET`, `COUCHBASE_USERNAME`, and `COUCHBASE_PASSWORD`; explicit `startCouchbase({...})` options still take precedence over either environment form.
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
DB_URL=couchbase://user:password@localhost/bucket
|
|
241
|
+
DB_URL=couchbase://user:password@localhost:11210/bucket
|
|
242
|
+
DB_URL=couchbases://user:password@cb.example.com/bucket
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Use `couchbases://` for TLS. Percent-encode reserved characters in usernames, passwords, and bucket names (for example, `p%40ss` for `p@ss`). `COUCHBASE_PROXY` remains available as a separate optional setting.
|
|
154
246
|
|
|
155
247
|
## Models
|
|
156
248
|
|
|
@@ -230,6 +322,89 @@ await users.onlyDeleted().findMany<User>();
|
|
|
230
322
|
await users.withoutDefaultWhere().findMany<User>();
|
|
231
323
|
```
|
|
232
324
|
|
|
325
|
+
## Typed Joins and Read Consistency
|
|
326
|
+
|
|
327
|
+
Client-bound models infer root and related fields. Using the client-owned `db`
|
|
328
|
+
above, join profiles to battles by arbitrary fields:
|
|
329
|
+
|
|
330
|
+
```ts
|
|
331
|
+
import {dateCodec, defineModel, joinField} from 'couchset/next';
|
|
332
|
+
import {QueryScanConsistency} from 'couchbase';
|
|
333
|
+
|
|
334
|
+
const battles = db.model(defineModel<{
|
|
335
|
+
createdByUserId: string;
|
|
336
|
+
startsAt: Date;
|
|
337
|
+
}>({name: 'Battle', scope: 'app', collection: 'battles', codecs: {startsAt: dateCodec}}));
|
|
338
|
+
|
|
339
|
+
const profiles = db.model(defineModel<{
|
|
340
|
+
ownerUserId: string;
|
|
341
|
+
displayName: string;
|
|
342
|
+
birthday: Date;
|
|
343
|
+
}>({name: 'Profile', scope: 'app', collection: 'profiles', codecs: {birthday: dateCodec}}));
|
|
344
|
+
|
|
345
|
+
const joined = await battles.page({
|
|
346
|
+
sourceAlias: 'battle',
|
|
347
|
+
include: [{
|
|
348
|
+
as: 'creator',
|
|
349
|
+
model: profiles,
|
|
350
|
+
type: 'leftJoin',
|
|
351
|
+
on: {
|
|
352
|
+
left: joinField('creator.ownerUserId'),
|
|
353
|
+
op: '$eq',
|
|
354
|
+
right: joinField('battle.createdByUserId'),
|
|
355
|
+
},
|
|
356
|
+
}],
|
|
357
|
+
limit: 20,
|
|
358
|
+
queryOptions: {scanConsistency: QueryScanConsistency.RequestPlus},
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
joined.items[0]?.startsAt; // Date | undefined
|
|
362
|
+
joined.items[0]?.creator?.birthday; // Date | undefined; related codec applied
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
Provision the collections and appropriate indexes explicitly before querying.
|
|
366
|
+
`joinField()` denotes a field reference; an ordinary string is a bound value.
|
|
367
|
+
Use `$and` / `$or` to combine predicates. Existing `key` / `keys` includes still
|
|
368
|
+
use `ON KEYS`.
|
|
369
|
+
|
|
370
|
+
Use NEST for arrays, and select just the fields needed:
|
|
371
|
+
|
|
372
|
+
```ts
|
|
373
|
+
const summaries = await battles.findMany({
|
|
374
|
+
select: ['startsAt'],
|
|
375
|
+
include: [{
|
|
376
|
+
as: 'creators',
|
|
377
|
+
model: profiles,
|
|
378
|
+
type: 'leftNest',
|
|
379
|
+
on: {left: joinField('creators.ownerUserId'), op: '$eq', right: joinField('doc.createdByUserId')},
|
|
380
|
+
select: ['displayName', 'birthday'],
|
|
381
|
+
}],
|
|
382
|
+
});
|
|
383
|
+
// {startsAt: Date; creators: {displayName: string; birthday: Date}[]}[]
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
LEFT JOIN may omit its related property; LEFT NEST returns `[]` when unmatched.
|
|
387
|
+
JOIN preserves one row per match, including repeated root IDs. Choose an alias
|
|
388
|
+
that does not overwrite a root field. NEST does not promise source-key ordering.
|
|
389
|
+
|
|
390
|
+
For read-your-writes, pass tokens from successful SDK mutations:
|
|
391
|
+
|
|
392
|
+
```ts
|
|
393
|
+
import {MutationState, MutationToken} from 'couchbase';
|
|
394
|
+
|
|
395
|
+
async function readAfterWrites(tokens: MutationToken[]) {
|
|
396
|
+
return battles.findMany({
|
|
397
|
+
queryOptions: {consistentWith: new MutationState(...tokens)},
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
// Call with SDK mutationResult.token values, not whole mutation results.
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
`request_plus` and `consistentWith` are alternatives; neither is a multi-document
|
|
404
|
+
transaction. Defaults are unchanged when no consistency option is supplied.
|
|
405
|
+
See [joined reads and consistency](./docs/joins-and-consistency.md) for predicates,
|
|
406
|
+
projection limits, codecs, compatibility changes, and live validation results.
|
|
407
|
+
|
|
233
408
|
## Writes
|
|
234
409
|
|
|
235
410
|
```ts
|
package/dist/database.d.ts
CHANGED
|
@@ -3,6 +3,12 @@ export type CouchbaseStarterLogger = ((...args: any[]) => void) | false;
|
|
|
3
3
|
export interface StartCouchbaseOptions extends Partial<CouchsetArgs> {
|
|
4
4
|
logger?: CouchbaseStarterLogger;
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Convert a PostgreSQL-style DB_URL into Couchbase SDK connection settings.
|
|
8
|
+
* The bucket lives in the URL path; it is not part of Couchbase's connection
|
|
9
|
+
* string, which contains only the scheme, host, optional port, and options.
|
|
10
|
+
*/
|
|
11
|
+
export declare const parseDatabaseUrl: (value: string) => Pick<CouchsetArgs, "bucketName" | "connectionString" | "password" | "username">;
|
|
6
12
|
export declare const getConnectionOptions: (overrides?: Partial<CouchsetArgs>) => CouchsetArgs;
|
|
7
13
|
export declare const connectionOptions: CouchsetArgs;
|
|
8
14
|
export declare const startCouchbase: (options?: StartCouchbaseOptions) => Promise<boolean>;
|
package/dist/database.js
CHANGED
|
@@ -86,13 +86,61 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
86
86
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
87
87
|
};
|
|
88
88
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
89
|
-
exports.startCouchbaseServerless = exports.startCouchbase = exports.connectionOptions = exports.getConnectionOptions = void 0;
|
|
89
|
+
exports.startCouchbaseServerless = exports.startCouchbase = exports.connectionOptions = exports.getConnectionOptions = exports.parseDatabaseUrl = void 0;
|
|
90
90
|
var connection_1 = __importDefault(require("./connection"));
|
|
91
91
|
var envValue = function (key, fallback) {
|
|
92
92
|
if (fallback === void 0) { fallback = ''; }
|
|
93
93
|
var value = typeof process !== 'undefined' && process.env ? process.env[key] : undefined;
|
|
94
94
|
return value === undefined ? fallback : value;
|
|
95
95
|
};
|
|
96
|
+
var databaseUrlError = function (reason) {
|
|
97
|
+
return new Error("DB_URL must use couchbase:// or couchbases://user:password@host/bucket: ".concat(reason));
|
|
98
|
+
};
|
|
99
|
+
var decodeDatabaseUrlComponent = function (value, label) {
|
|
100
|
+
try {
|
|
101
|
+
return decodeURIComponent(value);
|
|
102
|
+
}
|
|
103
|
+
catch (_error) {
|
|
104
|
+
throw databaseUrlError("".concat(label, " contains invalid percent-encoding"));
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* Convert a PostgreSQL-style DB_URL into Couchbase SDK connection settings.
|
|
109
|
+
* The bucket lives in the URL path; it is not part of Couchbase's connection
|
|
110
|
+
* string, which contains only the scheme, host, optional port, and options.
|
|
111
|
+
*/
|
|
112
|
+
var parseDatabaseUrl = function (value) {
|
|
113
|
+
var url;
|
|
114
|
+
try {
|
|
115
|
+
url = new URL(value);
|
|
116
|
+
}
|
|
117
|
+
catch (_error) {
|
|
118
|
+
throw databaseUrlError('the value is not a valid URL');
|
|
119
|
+
}
|
|
120
|
+
if (url.protocol !== 'couchbase:' && url.protocol !== 'couchbases:') {
|
|
121
|
+
throw databaseUrlError("unsupported protocol ".concat(url.protocol || '(missing)'));
|
|
122
|
+
}
|
|
123
|
+
if (!url.hostname) {
|
|
124
|
+
throw databaseUrlError('a host is required');
|
|
125
|
+
}
|
|
126
|
+
if (!url.username || !url.password) {
|
|
127
|
+
throw databaseUrlError('a username and password are required');
|
|
128
|
+
}
|
|
129
|
+
if (url.hash) {
|
|
130
|
+
throw databaseUrlError('fragments are not supported');
|
|
131
|
+
}
|
|
132
|
+
var bucketName = decodeDatabaseUrlComponent(url.pathname.replace(/^\//, ''), 'the bucket name');
|
|
133
|
+
if (!bucketName || bucketName.indexOf('/') !== -1) {
|
|
134
|
+
throw databaseUrlError('the path must contain exactly one bucket name');
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
bucketName: bucketName,
|
|
138
|
+
connectionString: "".concat(url.protocol, "//").concat(url.host).concat(url.search),
|
|
139
|
+
password: decodeDatabaseUrlComponent(url.password, 'the password'),
|
|
140
|
+
username: decodeDatabaseUrlComponent(url.username, 'the username'),
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
exports.parseDatabaseUrl = parseDatabaseUrl;
|
|
96
144
|
var maskPassword = function (password) {
|
|
97
145
|
return password ? 'xxxxxx' : 'empty';
|
|
98
146
|
};
|
|
@@ -104,6 +152,7 @@ var splitStartOptions = function (options) {
|
|
|
104
152
|
var getConnectionOptions = function (overrides) {
|
|
105
153
|
if (overrides === void 0) { overrides = {}; }
|
|
106
154
|
var proxy = envValue('COUCHBASE_PROXY');
|
|
155
|
+
var databaseUrl = envValue('DB_URL');
|
|
107
156
|
var options = {
|
|
108
157
|
bucketName: envValue('COUCHBASE_BUCKET', 'dev'),
|
|
109
158
|
connectionString: envValue('COUCHBASE_URL', 'couchbase://localhost'),
|
|
@@ -113,7 +162,7 @@ var getConnectionOptions = function (overrides) {
|
|
|
113
162
|
if (proxy) {
|
|
114
163
|
options.proxy = proxy;
|
|
115
164
|
}
|
|
116
|
-
return __assign(__assign({}, options), overrides);
|
|
165
|
+
return __assign(__assign(__assign({}, options), (databaseUrl ? (0, exports.parseDatabaseUrl)(databaseUrl) : {})), overrides);
|
|
117
166
|
};
|
|
118
167
|
exports.getConnectionOptions = getConnectionOptions;
|
|
119
168
|
exports.connectionOptions = (0, exports.getConnectionOptions)();
|
package/dist/database.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"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","sourcesContent":["import CouchbaseConnection, {CouchsetArgs} from './connection';\n\nexport type CouchbaseStarterLogger = ((...args: any[]) => void) | false;\n\nexport interface StartCouchbaseOptions extends Partial<CouchsetArgs> {\n logger?: CouchbaseStarterLogger;\n}\n\nconst envValue = (key: string, fallback = ''): string => {\n const value = typeof process !== 'undefined' && process.env ? process.env[key] : undefined;\n\n return value === undefined ? fallback : value;\n};\n\nconst maskPassword = (password: string): string => {\n return password ? 'xxxxxx' : 'empty';\n};\n\nconst splitStartOptions = (options: StartCouchbaseOptions = {}) => {\n const {logger, ...connectionOverrides} = options;\n\n return {connectionOverrides, logger};\n};\n\nexport const getConnectionOptions = (overrides: Partial<CouchsetArgs> = {}): CouchsetArgs => {\n const proxy = envValue('COUCHBASE_PROXY');\n const options: CouchsetArgs = {\n bucketName: envValue('COUCHBASE_BUCKET', 'dev'),\n connectionString: envValue('COUCHBASE_URL', 'couchbase://localhost'),\n password: envValue('COUCHBASE_PASSWORD', '1234'),\n username: envValue('COUCHBASE_USERNAME', 'admin'),\n };\n\n if (proxy) {\n options.proxy = proxy;\n }\n\n return {\n ...options,\n ...overrides,\n };\n};\n\nexport const connectionOptions: CouchsetArgs = getConnectionOptions();\n\nconst refreshConnectionOptions = (overrides: Partial<CouchsetArgs> = {}): CouchsetArgs => {\n const nextOptions = getConnectionOptions(overrides);\n\n Object.keys(connectionOptions).forEach((key) => {\n delete (connectionOptions as any)[key];\n });\n Object.assign(connectionOptions, nextOptions);\n\n return connectionOptions;\n};\n\nconst logConnectionStart = (\n options: CouchsetArgs,\n logger: CouchbaseStarterLogger | undefined,\n mode: string\n): void => {\n if (logger === false) {\n return;\n }\n\n const log = logger || console.log;\n\n log(\n 'Couchbase',\n 'starting',\n mode,\n JSON.stringify({\n bucket: options.bucketName,\n host: options.connectionString,\n password: maskPassword(options.password),\n username: options.username,\n })\n );\n};\n\nconst logConnectionStarted = (\n options: CouchsetArgs,\n logger: CouchbaseStarterLogger | undefined,\n mode: string\n): void => {\n if (logger === false) {\n return;\n }\n\n const log = logger || console.log;\n\n log(\n 'Couchbase',\n 'started',\n mode,\n JSON.stringify({bucket: options.bucketName, host: options.connectionString})\n );\n};\n\nexport const startCouchbase = async (options: StartCouchbaseOptions = {}): Promise<boolean> => {\n const {connectionOverrides, logger} = splitStartOptions(options);\n const resolvedOptions = refreshConnectionOptions(connectionOverrides);\n\n logConnectionStart(resolvedOptions, logger, 'standard');\n await CouchbaseConnection.Instance.init(resolvedOptions);\n logConnectionStarted(resolvedOptions, logger, 'standard');\n\n return true;\n};\n\nexport const startCouchbaseServerless = async (\n options: StartCouchbaseOptions = {}\n): Promise<boolean> => {\n const {connectionOverrides, logger} = splitStartOptions(options);\n const resolvedOptions = refreshConnectionOptions(connectionOverrides);\n\n logConnectionStart(resolvedOptions, logger, 'serverless');\n await CouchbaseConnection.Instance.initServerless(resolvedOptions);\n logConnectionStarted(resolvedOptions, logger, 'serverless');\n\n return true;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"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","sourcesContent":["import CouchbaseConnection, {CouchsetArgs} from './connection';\n\nexport type CouchbaseStarterLogger = ((...args: any[]) => void) | false;\n\nexport interface StartCouchbaseOptions extends Partial<CouchsetArgs> {\n logger?: CouchbaseStarterLogger;\n}\n\nconst envValue = (key: string, fallback = ''): string => {\n const value = typeof process !== 'undefined' && process.env ? process.env[key] : undefined;\n\n return value === undefined ? fallback : value;\n};\n\nconst databaseUrlError = (reason: string): Error =>\n new Error(`DB_URL must use couchbase:// or couchbases://user:password@host/bucket: ${reason}`);\n\nconst decodeDatabaseUrlComponent = (value: string, label: string): string => {\n try {\n return decodeURIComponent(value);\n } catch (_error) {\n throw databaseUrlError(`${label} contains invalid percent-encoding`);\n }\n};\n\n/**\n * Convert a PostgreSQL-style DB_URL into Couchbase SDK connection settings.\n * The bucket lives in the URL path; it is not part of Couchbase's connection\n * string, which contains only the scheme, host, optional port, and options.\n */\nexport const parseDatabaseUrl = (\n value: string\n): Pick<CouchsetArgs, 'bucketName' | 'connectionString' | 'password' | 'username'> => {\n let url: URL;\n\n try {\n url = new URL(value);\n } catch (_error) {\n throw databaseUrlError('the value is not a valid URL');\n }\n\n if (url.protocol !== 'couchbase:' && url.protocol !== 'couchbases:') {\n throw databaseUrlError(`unsupported protocol ${url.protocol || '(missing)'}`);\n }\n if (!url.hostname) {\n throw databaseUrlError('a host is required');\n }\n if (!url.username || !url.password) {\n throw databaseUrlError('a username and password are required');\n }\n if (url.hash) {\n throw databaseUrlError('fragments are not supported');\n }\n\n const bucketName = decodeDatabaseUrlComponent(\n url.pathname.replace(/^\\//, ''),\n 'the bucket name'\n );\n if (!bucketName || bucketName.indexOf('/') !== -1) {\n throw databaseUrlError('the path must contain exactly one bucket name');\n }\n\n return {\n bucketName,\n connectionString: `${url.protocol}//${url.host}${url.search}`,\n password: decodeDatabaseUrlComponent(url.password, 'the password'),\n username: decodeDatabaseUrlComponent(url.username, 'the username'),\n };\n};\n\nconst maskPassword = (password: string): string => {\n return password ? 'xxxxxx' : 'empty';\n};\n\nconst splitStartOptions = (options: StartCouchbaseOptions = {}) => {\n const {logger, ...connectionOverrides} = options;\n\n return {connectionOverrides, logger};\n};\n\nexport const getConnectionOptions = (overrides: Partial<CouchsetArgs> = {}): CouchsetArgs => {\n const proxy = envValue('COUCHBASE_PROXY');\n const databaseUrl = envValue('DB_URL');\n const options: CouchsetArgs = {\n bucketName: envValue('COUCHBASE_BUCKET', 'dev'),\n connectionString: envValue('COUCHBASE_URL', 'couchbase://localhost'),\n password: envValue('COUCHBASE_PASSWORD', '1234'),\n username: envValue('COUCHBASE_USERNAME', 'admin'),\n };\n\n if (proxy) {\n options.proxy = proxy;\n }\n\n return {\n ...options,\n ...(databaseUrl ? parseDatabaseUrl(databaseUrl) : {}),\n ...overrides,\n };\n};\n\nexport const connectionOptions: CouchsetArgs = getConnectionOptions();\n\nconst refreshConnectionOptions = (overrides: Partial<CouchsetArgs> = {}): CouchsetArgs => {\n const nextOptions = getConnectionOptions(overrides);\n\n Object.keys(connectionOptions).forEach((key) => {\n delete (connectionOptions as any)[key];\n });\n Object.assign(connectionOptions, nextOptions);\n\n return connectionOptions;\n};\n\nconst logConnectionStart = (\n options: CouchsetArgs,\n logger: CouchbaseStarterLogger | undefined,\n mode: string\n): void => {\n if (logger === false) {\n return;\n }\n\n const log = logger || console.log;\n\n log(\n 'Couchbase',\n 'starting',\n mode,\n JSON.stringify({\n bucket: options.bucketName,\n host: options.connectionString,\n password: maskPassword(options.password),\n username: options.username,\n })\n );\n};\n\nconst logConnectionStarted = (\n options: CouchsetArgs,\n logger: CouchbaseStarterLogger | undefined,\n mode: string\n): void => {\n if (logger === false) {\n return;\n }\n\n const log = logger || console.log;\n\n log(\n 'Couchbase',\n 'started',\n mode,\n JSON.stringify({bucket: options.bucketName, host: options.connectionString})\n );\n};\n\nexport const startCouchbase = async (options: StartCouchbaseOptions = {}): Promise<boolean> => {\n const {connectionOverrides, logger} = splitStartOptions(options);\n const resolvedOptions = refreshConnectionOptions(connectionOverrides);\n\n logConnectionStart(resolvedOptions, logger, 'standard');\n await CouchbaseConnection.Instance.init(resolvedOptions);\n logConnectionStarted(resolvedOptions, logger, 'standard');\n\n return true;\n};\n\nexport const startCouchbaseServerless = async (\n options: StartCouchbaseOptions = {}\n): Promise<boolean> => {\n const {connectionOverrides, logger} = splitStartOptions(options);\n const resolvedOptions = refreshConnectionOptions(connectionOverrides);\n\n logConnectionStart(resolvedOptions, logger, 'serverless');\n await CouchbaseConnection.Instance.initServerless(resolvedOptions);\n logConnectionStarted(resolvedOptions, logger, 'serverless');\n\n return true;\n};\n"]}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import type { EventingFunction, EventingFunctionManager, EventingFunctionSettings, EventingFunctionState } from 'couchbase';
|
|
2
|
+
/** A Couchbase bucket/scope/collection used by an Eventing function. */
|
|
3
|
+
export interface EventingKeyspace {
|
|
4
|
+
bucket: string;
|
|
5
|
+
scope?: string;
|
|
6
|
+
collection?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A declarative Eventing handler. `name` is logical: CouchSet derives the
|
|
10
|
+
* physical Couchbase name from the Eventing namespace.
|
|
11
|
+
*/
|
|
12
|
+
export interface EventingDefinition {
|
|
13
|
+
name: string;
|
|
14
|
+
code: string;
|
|
15
|
+
sourceKeyspace: EventingKeyspace;
|
|
16
|
+
enforceSchema?: boolean;
|
|
17
|
+
bucketBindings?: EventingFunction['bucketBindings'];
|
|
18
|
+
urlBindings?: EventingFunction['urlBindings'];
|
|
19
|
+
constantBindings?: EventingFunction['constantBindings'];
|
|
20
|
+
settings?: Partial<EventingFunctionSettings>;
|
|
21
|
+
}
|
|
22
|
+
export type EventingFunctionDefinition = EventingDefinition;
|
|
23
|
+
/**
|
|
24
|
+
* The metadata collection is used only by Couchbase Eventing for checkpoints
|
|
25
|
+
* and timers. CouchSet never opens it as an application collection or writes
|
|
26
|
+
* documents to it.
|
|
27
|
+
*/
|
|
28
|
+
export interface EventingOptions {
|
|
29
|
+
/** Required ownership boundary for physical Couchbase function names. */
|
|
30
|
+
namespace: string;
|
|
31
|
+
/** A dedicated collection reserved for Couchbase Eventing metadata. */
|
|
32
|
+
metadataKeyspace: EventingKeyspace;
|
|
33
|
+
/** Definitions registered when the control plane is constructed. */
|
|
34
|
+
definitions?: EventingDefinition[];
|
|
35
|
+
/** Alias for definitions, useful for manifest-shaped configuration. */
|
|
36
|
+
functions?: EventingDefinition[];
|
|
37
|
+
/** Explicit SDK manager injection, primarily for tests or owned clusters. */
|
|
38
|
+
manager?: EventingFunctionManagerLike;
|
|
39
|
+
/** Maximum time to wait for Couchbase Eventing lifecycle convergence. */
|
|
40
|
+
lifecycleTimeoutMs?: number;
|
|
41
|
+
/** Delay between lifecycle status checks. Defaults to 250ms. */
|
|
42
|
+
lifecyclePollIntervalMs?: number;
|
|
43
|
+
}
|
|
44
|
+
export interface EventingApplyOptions {
|
|
45
|
+
/**
|
|
46
|
+
* Permit source or metadata keyspace changes. Couchbase must undeploy first,
|
|
47
|
+
* which erases the function's timers and checkpoints.
|
|
48
|
+
*/
|
|
49
|
+
allowRecreate?: boolean;
|
|
50
|
+
}
|
|
51
|
+
export type EventingOutcomeAction = 'created' | 'updated' | 'resumed' | 'unchanged' | 'pruned' | 'paused' | 'removed' | 'requires-recreate';
|
|
52
|
+
export interface EventingOutcome {
|
|
53
|
+
action: EventingOutcomeAction;
|
|
54
|
+
/** Lifecycle operations performed for this function, in order. */
|
|
55
|
+
actions: EventingOutcomeAction[];
|
|
56
|
+
name: string;
|
|
57
|
+
physicalName: string;
|
|
58
|
+
/** Present whenever undeploying can erase Eventing timers/checkpoints. */
|
|
59
|
+
timerStateLost?: boolean;
|
|
60
|
+
message?: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Each status array contains the matching outcome, so callers can inspect a
|
|
64
|
+
* report directly without parsing text. An update can also be in `paused` and
|
|
65
|
+
* `resumed`, because that is the safe lifecycle used to perform the update.
|
|
66
|
+
*/
|
|
67
|
+
export interface EventingReport {
|
|
68
|
+
outcomes: EventingOutcome[];
|
|
69
|
+
created: EventingOutcome[];
|
|
70
|
+
updated: EventingOutcome[];
|
|
71
|
+
resumed: EventingOutcome[];
|
|
72
|
+
unchanged: EventingOutcome[];
|
|
73
|
+
pruned: EventingOutcome[];
|
|
74
|
+
paused: EventingOutcome[];
|
|
75
|
+
removed: EventingOutcome[];
|
|
76
|
+
requiresRecreate: EventingOutcome[];
|
|
77
|
+
}
|
|
78
|
+
/** The portion of SDK 4.7's EventingFunctionManager used by CouchSet. */
|
|
79
|
+
export interface EventingFunctionManagerLike {
|
|
80
|
+
upsertFunction(functionDefinition: EventingFunction): Promise<void>;
|
|
81
|
+
dropFunction(name: string): Promise<void>;
|
|
82
|
+
getAllFunctions(): Promise<EventingFunction[]>;
|
|
83
|
+
deployFunction(name: string): Promise<void>;
|
|
84
|
+
undeployFunction(name: string): Promise<void>;
|
|
85
|
+
pauseFunction(name: string): Promise<void>;
|
|
86
|
+
resumeFunction(name: string): Promise<void>;
|
|
87
|
+
functionsStatus(): Promise<{
|
|
88
|
+
functions: EventingFunctionState[];
|
|
89
|
+
}>;
|
|
90
|
+
}
|
|
91
|
+
/** A minimal client shape that lets Eventing acquire the connected SDK cluster. */
|
|
92
|
+
export interface EventingClient {
|
|
93
|
+
ready(): Promise<any>;
|
|
94
|
+
getConnection(): {
|
|
95
|
+
cluster: {
|
|
96
|
+
eventingFunctions?: () => EventingFunctionManager;
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Declarative Eventing reconciler backed by the SDK 4.7 EventingFunctionManager.
|
|
102
|
+
* It only manages names starting with its namespace prefix.
|
|
103
|
+
*/
|
|
104
|
+
export declare class Eventing {
|
|
105
|
+
private readonly definitionsByName;
|
|
106
|
+
private readonly eventingMetadataKeyspace;
|
|
107
|
+
private readonly lifecyclePollIntervalMs;
|
|
108
|
+
private readonly lifecycleTimeoutMs;
|
|
109
|
+
private readonly prefix;
|
|
110
|
+
private readonly client?;
|
|
111
|
+
private readonly explicitManager?;
|
|
112
|
+
constructor(client: EventingClient | undefined, options: EventingOptions);
|
|
113
|
+
/** Logical namespace that owns this controller's physical functions. */
|
|
114
|
+
get namespace(): string;
|
|
115
|
+
/** A copy of registered, code-only declarations. This performs no I/O. */
|
|
116
|
+
definitions(): EventingDefinition[];
|
|
117
|
+
/** Converts a logical declaration name into its Couchbase function name. */
|
|
118
|
+
physicalName(name: string): string;
|
|
119
|
+
/** Registers or replaces an in-memory manifest declaration without I/O. */
|
|
120
|
+
register(definition: EventingDefinition): EventingDefinition;
|
|
121
|
+
/** Alias for register(), matching the declaration-oriented API vocabulary. */
|
|
122
|
+
define(definition: EventingDefinition): EventingDefinition;
|
|
123
|
+
apply(options?: EventingApplyOptions): Promise<EventingReport>;
|
|
124
|
+
apply(definition: EventingDefinition, options?: EventingApplyOptions): Promise<EventingReport>;
|
|
125
|
+
/** Temporarily disables one namespace-owned Eventing function. */
|
|
126
|
+
pause(name: string): Promise<EventingReport>;
|
|
127
|
+
/**
|
|
128
|
+
* Intentionally undeploys then deletes one namespace-owned function.
|
|
129
|
+
* Undeployment erases Couchbase Eventing timers and checkpoints.
|
|
130
|
+
*/
|
|
131
|
+
remove(name: string): Promise<EventingReport>;
|
|
132
|
+
private reconcile;
|
|
133
|
+
private prune;
|
|
134
|
+
private matches;
|
|
135
|
+
private sdkDefinition;
|
|
136
|
+
private metadataKeyspace;
|
|
137
|
+
private manager;
|
|
138
|
+
private states;
|
|
139
|
+
/**
|
|
140
|
+
* Management requests acknowledge receipt, not necessarily completion. Do
|
|
141
|
+
* not issue the next incompatible Eventing operation until status confirms
|
|
142
|
+
* that Couchbase has converged.
|
|
143
|
+
*/
|
|
144
|
+
private waitForLifecycle;
|
|
145
|
+
/**
|
|
146
|
+
* Couchbase Server may turn a paused function into an undeployed function
|
|
147
|
+
* when upsert persists new code/settings/bindings. Inspect that post-upsert
|
|
148
|
+
* state rather than assuming resume is legal; deploy is the compatible
|
|
149
|
+
* activation operation in that case.
|
|
150
|
+
*/
|
|
151
|
+
private activateAfterUpsert;
|
|
152
|
+
/**
|
|
153
|
+
* A live function with no status row is unknown, not safely undeployed.
|
|
154
|
+
* Poll for a positive row; a known transitional row remains an immediate
|
|
155
|
+
* blocker so callers do not race an operator's in-progress lifecycle call.
|
|
156
|
+
*/
|
|
157
|
+
private stableLifecycle;
|
|
158
|
+
/** Waits for a stable state caused by this controller's own upsert call. */
|
|
159
|
+
private waitForStableLifecycle;
|
|
160
|
+
private record;
|
|
161
|
+
private outcome;
|
|
162
|
+
private owns;
|
|
163
|
+
private logicalName;
|
|
164
|
+
private assertDefinition;
|
|
165
|
+
private assertLogicalName;
|
|
166
|
+
private assertStable;
|
|
167
|
+
private isDefinition;
|
|
168
|
+
private positiveNumber;
|
|
169
|
+
private nonNegativeNumber;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Construct an Eventing control plane from a CouchSet client. The client is
|
|
173
|
+
* used only to obtain the SDK EventingFunctionManager after `ready()`.
|
|
174
|
+
*/
|
|
175
|
+
export declare const createEventing: (client: EventingClient, options: EventingOptions) => Eventing;
|
|
176
|
+
/** Construct an Eventing control plane around an application-owned SDK manager. */
|
|
177
|
+
export declare const createEventingWithManager: (options: EventingOptions) => Eventing;
|
|
178
|
+
/** A small helper that makes Eventing definitions read as manifest declarations. */
|
|
179
|
+
export declare const defineEventingFunction: (definition: EventingDefinition) => EventingDefinition;
|