couchset 0.3.0 → 0.4.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/CHANGELOG.md ADDED
@@ -0,0 +1,41 @@
1
+ # Changelog
2
+
3
+ ## 0.3.0 - 2026-05-18
4
+
5
+ ### Compatibility
6
+
7
+ - Kept the default `couchset` entrypoint on the legacy API so existing projects can upgrade without rewriting model imports.
8
+ - Kept `couchset/legacy` as an explicit legacy alias.
9
+ - Added `couchset/next` for the modern API.
10
+ - Shared one Couchbase connection singleton across legacy and modern models, allowing both APIs to run side by side during gradual migrations.
11
+
12
+ ### Modern API
13
+
14
+ - Added strict modern model helpers: `insert`, `upsert`, `getById`, `replaceById`, `patchById`, `deleteById`, `findMany`, `findOne`, `page`, `exists`, and `count`.
15
+ - Removed old model method names from the modern model surface so the new API can evolve independently.
16
+ - Added hydrated document helpers for reload/save/patch/delete workflows.
17
+ - Added soft-delete/default-scope helpers, TTL helpers, validation/parse hooks, scoped collection support, include helpers, and declarative index helpers.
18
+ - Added safe SQL++ query helpers with named/positional parameters: `queryRows`, `queryOne`, and `queryPage`.
19
+ - Added safer keyspace helpers: `Model.bucket()` and `Model.from(alias?)`.
20
+
21
+ ### Connection Lifecycle
22
+
23
+ - Added lazy model binding so models can be constructed before `couchset()` connects.
24
+ - Added lifecycle helpers: `ready`, `ping`, `health`, `shutdown`, and `ensureIndexes`.
25
+ - Added reconnect support that is enabled by default, with `COUCHSET_RECONNECT` and `COUCHSET_RECONNECT_INTERVAL_MS` environment controls.
26
+ - Added retry/rebind behavior for reconnectable operation failures.
27
+
28
+ ### Starters
29
+
30
+ - Added modern env-based starter helpers on `couchset/next`: `getConnectionOptions`, `connectionOptions`, `startCouchbase`, and `startCouchbaseServerless`.
31
+ - Starter helpers read `COUCHBASE_URL`, `COUCHBASE_BUCKET`, `COUCHBASE_USERNAME`, `COUCHBASE_PASSWORD`, and `COUCHBASE_PROXY`.
32
+
33
+ ### Documentation
34
+
35
+ - Updated the README for the legacy-default and modern-next import paths.
36
+ - Added beta migration notes for running legacy and modern models together.
37
+
38
+ ### Maintenance
39
+
40
+ - Cleared high and critical `npm audit` findings.
41
+ - Updated the publish workflow to the two-job version bump and npm publish flow.
package/README.md CHANGED
@@ -10,16 +10,21 @@
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, and safe index plans—are documented in [Next primitives](./docs/next-primitives.md).
14
+
13
15
  - [Install](#install)
14
16
  - [Legacy Default](#legacy-default)
15
17
  - [Modern API](#modern-api)
18
+ - [Next primitives](./docs/next-primitives.md)
16
19
  - [Connection Lifecycle](#connection-lifecycle)
17
20
  - [Models](#models)
18
21
  - [Reads](#reads)
22
+ - [Document Modeling](./docs/document-modeling.md)
19
23
  - [Writes](#writes)
20
24
  - [Queries](#queries)
21
25
  - [Gradual Migration](#gradual-migration)
22
26
  - [Migration Notes](./docs/beta-migration.md)
27
+ - [Changelog](./CHANGELOG.md)
23
28
  - [License](#license)
24
29
 
25
30
  ## Install
@@ -170,6 +175,10 @@ users.keyspace(); // `dev` or default:`dev`.`scope`.`collection`
170
175
  users.from('u'); // `dev` AS u
171
176
  ```
172
177
 
178
+ For large objects, keep list metadata and heavy payloads in separate models.
179
+ See [Document Modeling](./docs/document-modeling.md) for the recommended read
180
+ shape.
181
+
173
182
  ## Reads
174
183
 
175
184
  ```ts
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
36
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
37
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -1 +1 @@
1
- {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/connection/connection.ts"],"names":[],"mappings":"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","sourcesContent":["import type {Bucket, Cluster, Collection} from 'couchbase';\nimport * as couchbase from 'couchbase';\n\nimport {envFlag, envNumber} from './env';\nimport {ConnectionHealth, ConnectionSettings, ConnectionState, CouchsetArgs} from './types';\n\n/**\n * CouchbaseConnection class\n * Only one CouchbaseConnection can exist that's why it's a singleton\n */\nexport class CouchbaseConnection implements CouchsetArgs {\n private static _instance: CouchbaseConnection;\n\n bucket: Bucket = null;\n cluster: Cluster = null;\n private connectionPromise?: Promise<CouchbaseConnection>;\n private connectionSettings?: ConnectionSettings;\n private reconnectPromise?: Promise<CouchbaseConnection>;\n private reconnectReject?: (error: Error) => void;\n private reconnectTimer?: ReturnType<typeof setTimeout>;\n private healthTimer?: ReturnType<typeof setTimeout>;\n private connectionState: ConnectionState = 'idle';\n private autoReconnectEnabled = true;\n private reconnectDelayMs = 5000;\n private manuallyClosed = false;\n private lastConnectionError?: any;\n\n // Args\n connectionString: string = null;\n bucketName: string = null;\n username: string = null;\n password: string = null;\n\n public static get Instance(): CouchbaseConnection {\n return this._instance || (this._instance = new this());\n }\n\n private constructor() {}\n\n private configureReconnect(args: CouchsetArgs): void {\n this.autoReconnectEnabled =\n typeof args.autoReconnect === 'boolean'\n ? args.autoReconnect\n : envFlag(process.env.COUCHSET_RECONNECT, true);\n this.reconnectDelayMs =\n typeof args.reconnectIntervalMs === 'number' && args.reconnectIntervalMs > 0\n ? args.reconnectIntervalMs\n : envNumber(process.env.COUCHSET_RECONNECT_INTERVAL_MS, 5000);\n }\n\n private normalizeArgs(args: CouchsetArgs): ConnectionSettings {\n const {connectionString, password, username, bucketName = 'default', proxy} = args;\n\n return {\n bucketName,\n connectionString,\n password,\n proxy,\n username,\n };\n }\n\n private sameSettings(next: ConnectionSettings): boolean {\n const current = this.connectionSettings;\n\n return (\n !!current &&\n current.connectionString === next.connectionString &&\n current.bucketName === next.bucketName &&\n current.username === next.username &&\n current.password === next.password &&\n current.proxy === next.proxy\n );\n }\n\n private assignSettings(settings: ConnectionSettings): void {\n this.connectionString = settings.connectionString;\n this.bucketName = settings.bucketName;\n this.username = settings.username;\n this.password = settings.password;\n this.connectionSettings = settings;\n }\n\n private settingsError(): Error {\n return new Error(\n 'couchset is already connected with different settings; call couchset({...args, force: true}) to reconnect'\n );\n }\n\n private connectionOptions(settings: ConnectionSettings): any {\n const options: any = {\n password: settings.password,\n username: settings.username,\n };\n\n if (settings.proxy) {\n options.proxy = settings.proxy;\n }\n\n return options;\n }\n\n private clearReconnectTimer(): void {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n }\n }\n\n private clearHealthTimer(): void {\n if (this.healthTimer) {\n clearTimeout(this.healthTimer);\n this.healthTimer = undefined;\n }\n }\n\n private scheduleTimer(callback: () => void, unref = true): ReturnType<typeof setTimeout> {\n const timer = setTimeout(callback, this.reconnectDelayMs);\n\n if (unref && typeof (timer as any).unref === 'function') {\n (timer as any).unref();\n }\n\n return timer;\n }\n\n private rawPing = async (): Promise<any> => {\n if (!this.cluster) {\n throw new Error('couchset is not connected; call couchset(args) first');\n }\n\n if (typeof (this.cluster as any).ping === 'function') {\n return (this.cluster as any).ping();\n }\n\n return this.cluster.query('SELECT 1');\n };\n\n private openCluster = (settings: ConnectionSettings): Promise<Cluster> => {\n return couchbase.connect(settings.connectionString, this.connectionOptions(settings));\n };\n\n private scheduleHealthCheck(): void {\n this.clearHealthTimer();\n\n if (!this.autoReconnectEnabled || this.manuallyClosed) {\n return;\n }\n\n this.healthTimer = this.scheduleTimer(async () => {\n try {\n await this.rawPing();\n this.scheduleHealthCheck();\n } catch (error) {\n this.markDisconnected(error);\n }\n });\n }\n\n private connectWithSettings = async (\n settings: ConnectionSettings\n ): Promise<CouchbaseConnection> => {\n const cluster = await this.openCluster(settings);\n\n if (this.manuallyClosed) {\n if (cluster && typeof (cluster as any).close === 'function') {\n await (cluster as any).close();\n }\n throw new Error('couchset reconnect stopped');\n }\n\n this.cluster = cluster as any;\n this.bucket = this.cluster.bucket(settings.bucketName);\n this.connectionState = 'connected';\n this.lastConnectionError = undefined;\n this.scheduleHealthCheck();\n\n return this;\n };\n\n private startReconnect = (): Promise<CouchbaseConnection> => {\n if (this.reconnectPromise) {\n return this.reconnectPromise;\n }\n\n if (!this.autoReconnectEnabled || !this.connectionSettings || this.manuallyClosed) {\n return Promise.reject(\n new Error('couchset reconnect is disabled or no connection settings are available')\n );\n }\n\n this.connectionState = 'reconnecting';\n\n this.reconnectPromise = new Promise<CouchbaseConnection>((resolve, reject) => {\n this.reconnectReject = reject;\n\n const attempt = async () => {\n if (this.manuallyClosed || !this.connectionSettings) {\n reject(new Error('couchset reconnect stopped'));\n return;\n }\n\n try {\n const connection = await this.connectWithSettings(this.connectionSettings);\n this.reconnectPromise = undefined;\n this.reconnectReject = undefined;\n this.clearReconnectTimer();\n resolve(connection);\n } catch (error) {\n this.lastConnectionError = error;\n this.connectionState = 'reconnecting';\n this.reconnectTimer = this.scheduleTimer(attempt, false);\n }\n };\n\n attempt();\n });\n\n return this.reconnectPromise;\n };\n\n /**\n * start\n */\n public init = async (args: CouchsetArgs): Promise<CouchbaseConnection> => {\n const settings = this.normalizeArgs(args);\n this.configureReconnect(args);\n\n if (this.connectionPromise && this.sameSettings(settings)) {\n return this.connectionPromise;\n }\n\n if (this.reconnectPromise && this.sameSettings(settings)) {\n return this.reconnectPromise;\n }\n\n if (this.isConnected() && this.sameSettings(settings)) {\n return this;\n }\n\n if (\n (this.isConnected() || this.connectionPromise || this.reconnectPromise) &&\n !args.force\n ) {\n throw this.settingsError();\n }\n\n if (args.force && this.connectionPromise) {\n await this.connectionPromise.catch(() => undefined);\n }\n\n if (args.force) {\n await this.shutdown();\n this.configureReconnect(args);\n }\n\n this.manuallyClosed = false;\n this.clearReconnectTimer();\n this.clearHealthTimer();\n this.assignSettings(settings);\n this.connectionState = 'connecting';\n this.connectionPromise = this.connectWithSettings(settings)\n .then((connection) => {\n this.connectionPromise = undefined;\n\n return connection;\n })\n .catch((error) => {\n this.connectionPromise = undefined;\n this.connectionSettings = undefined;\n this.connectionState = 'idle';\n this.lastConnectionError = error;\n throw error;\n });\n\n return this.connectionPromise;\n };\n\n /**\n * start serverless start\n */\n public initServerless = async (args: CouchsetArgs): Promise<CouchbaseConnection> => {\n return this.init(args);\n };\n\n /**\n * getCollection\n */\n public getCollection = (scopeName?: string, collectionName?: string): Collection => {\n if (scopeName || collectionName) {\n return this.bucket\n .scope(scopeName || '_default')\n .collection(collectionName || '_default');\n }\n\n return this.bucket.defaultCollection();\n };\n\n public getCluster = (): Cluster => {\n return this.cluster;\n };\n\n public getBucket = (): string => {\n return this.bucketName;\n };\n\n public isConnected = (): boolean => {\n return !!this.cluster && !!this.bucket;\n };\n\n public ready = async (): Promise<CouchbaseConnection> => {\n if (this.isConnected()) {\n return this;\n }\n\n if (this.connectionPromise) {\n return this.connectionPromise;\n }\n\n if (this.reconnectPromise) {\n return this.reconnectPromise;\n }\n\n if (this.autoReconnectEnabled && this.connectionSettings && !this.manuallyClosed) {\n return this.startReconnect();\n }\n\n throw new Error('couchset is not connected; call couchset(args) first');\n };\n\n public ping = async (): Promise<any> => {\n await this.ready();\n\n try {\n return await this.rawPing();\n } catch (error) {\n this.markDisconnected(error);\n throw error;\n }\n };\n\n public state = (): ConnectionState => {\n return this.connectionState;\n };\n\n public health = (): ConnectionHealth => {\n return {\n autoReconnect: this.autoReconnectEnabled,\n bucketName: this.bucketName,\n lastError: this.lastConnectionError,\n reconnectIntervalMs: this.reconnectDelayMs,\n state: this.connectionState,\n };\n };\n\n public shouldReconnect = (error: unknown): boolean => {\n if (!this.autoReconnectEnabled || this.manuallyClosed) {\n return false;\n }\n\n const caught = error as any;\n const name = String(caught?.name || caught?.constructor?.name || '');\n const message = String(caught?.message || '');\n const text = `${name} ${message}`.toLowerCase();\n\n return [\n 'timeout',\n 'network',\n 'connect',\n 'closed',\n 'disconnect',\n 'unavailable',\n 'socket',\n 'econnrefused',\n 'etimedout',\n 'temporary failure',\n ].some((value) => text.includes(value));\n };\n\n public markDisconnected = (error?: unknown): void => {\n if (!this.connectionSettings || this.manuallyClosed) {\n return;\n }\n\n const cluster = this.cluster;\n\n this.lastConnectionError = error;\n this.connectionPromise = undefined;\n this.cluster = null;\n this.bucket = null;\n this.clearHealthTimer();\n\n if (cluster && typeof (cluster as any).close === 'function') {\n (cluster as any).close().catch(() => undefined);\n }\n\n if (this.autoReconnectEnabled) {\n this.connectionState = 'reconnecting';\n this.startReconnect().catch(() => undefined);\n return;\n }\n\n this.connectionState = 'idle';\n };\n\n /**\n * shutdown cluster\n */\n public shutdown = async (): Promise<void> => {\n const cluster = this.cluster;\n\n this.manuallyClosed = true;\n this.clearReconnectTimer();\n this.clearHealthTimer();\n if (this.reconnectReject) {\n this.reconnectReject(new Error('couchset reconnect stopped'));\n }\n this.reconnectPromise = undefined;\n this.reconnectReject = undefined;\n this.connectionPromise = undefined;\n this.connectionSettings = undefined;\n this.cluster = null;\n this.bucket = null;\n this.connectionString = null;\n this.bucketName = null;\n this.username = null;\n this.password = null;\n this.connectionState = 'closed';\n this.lastConnectionError = undefined;\n\n if (cluster && typeof (cluster as any).close === 'function') {\n await (cluster as any).close();\n }\n };\n}\n\nexport default CouchbaseConnection;\n"]}
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/connection/connection.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,mDAAuC;AAEvC,6BAAyC;AAGzC;;;GAGG;AACH;IA2BI;QAAA,iBAAwB;QAxBxB,WAAM,GAAW,IAAI,CAAC;QACtB,YAAO,GAAY,IAAI,CAAC;QAOhB,oBAAe,GAAoB,MAAM,CAAC;QAC1C,yBAAoB,GAAG,IAAI,CAAC;QAC5B,qBAAgB,GAAG,IAAI,CAAC;QACxB,mBAAc,GAAG,KAAK,CAAC;QAG/B,OAAO;QACP,qBAAgB,GAAW,IAAI,CAAC;QAChC,eAAU,GAAW,IAAI,CAAC;QAC1B,aAAQ,GAAW,IAAI,CAAC;QACxB,aAAQ,GAAW,IAAI,CAAC;QA+FhB,YAAO,GAAG;;gBACd,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;oBAChB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;gBAC5E,CAAC;gBAED,IAAI,OAAQ,IAAI,CAAC,OAAe,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;oBACnD,sBAAQ,IAAI,CAAC,OAAe,CAAC,IAAI,EAAE,EAAC;gBACxC,CAAC;gBAED,sBAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,EAAC;;aACzC,CAAC;QAEM,gBAAW,GAAG,UAAC,QAA4B;YAC/C,OAAO,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,EAAE,KAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC1F,CAAC,CAAC;QAmBM,wBAAmB,GAAG,UAC1B,QAA4B;;;;4BAEZ,qBAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAA;;wBAA1C,OAAO,GAAG,SAAgC;6BAE5C,IAAI,CAAC,cAAc,EAAnB,wBAAmB;6BACf,CAAA,OAAO,IAAI,OAAQ,OAAe,CAAC,KAAK,KAAK,UAAU,CAAA,EAAvD,wBAAuD;wBACvD,qBAAO,OAAe,CAAC,KAAK,EAAE,EAAA;;wBAA9B,SAA8B,CAAC;;4BAEnC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;;wBAGlD,IAAI,CAAC,OAAO,GAAG,OAAc,CAAC;wBAC9B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;wBACvD,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC;wBACnC,IAAI,CAAC,mBAAmB,GAAG,SAAS,CAAC;wBACrC,IAAI,CAAC,mBAAmB,EAAE,CAAC;wBAE3B,sBAAO,IAAI,EAAC;;;aACf,CAAC;QAEM,mBAAc,GAAG;YACrB,IAAI,KAAI,CAAC,gBAAgB,EAAE,CAAC;gBACxB,OAAO,KAAI,CAAC,gBAAgB,CAAC;YACjC,CAAC;YAED,IAAI,CAAC,KAAI,CAAC,oBAAoB,IAAI,CAAC,KAAI,CAAC,kBAAkB,IAAI,KAAI,CAAC,cAAc,EAAE,CAAC;gBAChF,OAAO,OAAO,CAAC,MAAM,CACjB,IAAI,KAAK,CAAC,wEAAwE,CAAC,CACtF,CAAC;YACN,CAAC;YAED,KAAI,CAAC,eAAe,GAAG,cAAc,CAAC;YAEtC,KAAI,CAAC,gBAAgB,GAAG,IAAI,OAAO,CAAsB,UAAC,OAAO,EAAE,MAAM;gBACrE,KAAI,CAAC,eAAe,GAAG,MAAM,CAAC;gBAE9B,IAAM,OAAO,GAAG;;;;;gCACZ,IAAI,IAAI,CAAC,cAAc,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;oCAClD,MAAM,CAAC,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC,CAAC;oCAChD,sBAAO;gCACX,CAAC;;;;gCAGsB,qBAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAA;;gCAApE,UAAU,GAAG,SAAuD;gCAC1E,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;gCAClC,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;gCACjC,IAAI,CAAC,mBAAmB,EAAE,CAAC;gCAC3B,OAAO,CAAC,UAAU,CAAC,CAAC;;;;gCAEpB,IAAI,CAAC,mBAAmB,GAAG,OAAK,CAAC;gCACjC,IAAI,CAAC,eAAe,GAAG,cAAc,CAAC;gCACtC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;;;;;qBAEhE,CAAC;gBAEF,OAAO,EAAE,CAAC;YACd,CAAC,CAAC,CAAC;YAEH,OAAO,KAAI,CAAC,gBAAgB,CAAC;QACjC,CAAC,CAAC;QAEF;;WAEG;QACI,SAAI,GAAG,UAAO,IAAkB;;;;;;wBAC7B,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;wBAC1C,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;wBAE9B,IAAI,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;4BACxD,sBAAO,IAAI,CAAC,iBAAiB,EAAC;wBAClC,CAAC;wBAED,IAAI,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;4BACvD,sBAAO,IAAI,CAAC,gBAAgB,EAAC;wBACjC,CAAC;wBAED,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;4BACpD,sBAAO,IAAI,EAAC;wBAChB,CAAC;wBAED,IACI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,gBAAgB,CAAC;4BACvE,CAAC,IAAI,CAAC,KAAK,EACb,CAAC;4BACC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;wBAC/B,CAAC;6BAEG,CAAA,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,iBAAiB,CAAA,EAApC,wBAAoC;wBACpC,qBAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,cAAM,OAAA,SAAS,EAAT,CAAS,CAAC,EAAA;;wBAAnD,SAAmD,CAAC;;;6BAGpD,IAAI,CAAC,KAAK,EAAV,wBAAU;wBACV,qBAAM,IAAI,CAAC,QAAQ,EAAE,EAAA;;wBAArB,SAAqB,CAAC;wBACtB,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;;;wBAGlC,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;wBAC5B,IAAI,CAAC,mBAAmB,EAAE,CAAC;wBAC3B,IAAI,CAAC,gBAAgB,EAAE,CAAC;wBACxB,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;wBAC9B,IAAI,CAAC,eAAe,GAAG,YAAY,CAAC;wBACpC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC;6BACtD,IAAI,CAAC,UAAC,UAAU;4BACb,KAAI,CAAC,iBAAiB,GAAG,SAAS,CAAC;4BAEnC,OAAO,UAAU,CAAC;wBACtB,CAAC,CAAC;6BACD,KAAK,CAAC,UAAC,KAAK;4BACT,KAAI,CAAC,iBAAiB,GAAG,SAAS,CAAC;4BACnC,KAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;4BACpC,KAAI,CAAC,eAAe,GAAG,MAAM,CAAC;4BAC9B,KAAI,CAAC,mBAAmB,GAAG,KAAK,CAAC;4BACjC,MAAM,KAAK,CAAC;wBAChB,CAAC,CAAC,CAAC;wBAEP,sBAAO,IAAI,CAAC,iBAAiB,EAAC;;;aACjC,CAAC;QAEF;;WAEG;QACI,mBAAc,GAAG,UAAO,IAAkB;;gBAC7C,sBAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAC;;aAC1B,CAAC;QAEF;;WAEG;QACI,kBAAa,GAAG,UAAC,SAAkB,EAAE,cAAuB;YAC/D,IAAI,SAAS,IAAI,cAAc,EAAE,CAAC;gBAC9B,OAAO,KAAI,CAAC,MAAM;qBACb,KAAK,CAAC,SAAS,IAAI,UAAU,CAAC;qBAC9B,UAAU,CAAC,cAAc,IAAI,UAAU,CAAC,CAAC;YAClD,CAAC;YAED,OAAO,KAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC3C,CAAC,CAAC;QAEK,eAAU,GAAG;YAChB,OAAO,KAAI,CAAC,OAAO,CAAC;QACxB,CAAC,CAAC;QAEK,cAAS,GAAG;YACf,OAAO,KAAI,CAAC,UAAU,CAAC;QAC3B,CAAC,CAAC;QAEK,gBAAW,GAAG;YACjB,OAAO,CAAC,CAAC,KAAI,CAAC,OAAO,IAAI,CAAC,CAAC,KAAI,CAAC,MAAM,CAAC;QAC3C,CAAC,CAAC;QAEK,UAAK,GAAG;;gBACX,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;oBACrB,sBAAO,IAAI,EAAC;gBAChB,CAAC;gBAED,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBACzB,sBAAO,IAAI,CAAC,iBAAiB,EAAC;gBAClC,CAAC;gBAED,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;oBACxB,sBAAO,IAAI,CAAC,gBAAgB,EAAC;gBACjC,CAAC;gBAED,IAAI,IAAI,CAAC,oBAAoB,IAAI,IAAI,CAAC,kBAAkB,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;oBAC/E,sBAAO,IAAI,CAAC,cAAc,EAAE,EAAC;gBACjC,CAAC;gBAED,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;;aAC3E,CAAC;QAEK,SAAI,GAAG;;;;4BACV,qBAAM,IAAI,CAAC,KAAK,EAAE,EAAA;;wBAAlB,SAAkB,CAAC;;;;wBAGR,qBAAM,IAAI,CAAC,OAAO,EAAE,EAAA;4BAA3B,sBAAO,SAAoB,EAAC;;;wBAE5B,IAAI,CAAC,gBAAgB,CAAC,OAAK,CAAC,CAAC;wBAC7B,MAAM,OAAK,CAAC;;;;aAEnB,CAAC;QAEK,UAAK,GAAG;YACX,OAAO,KAAI,CAAC,eAAe,CAAC;QAChC,CAAC,CAAC;QAEK,WAAM,GAAG;YACZ,OAAO;gBACH,aAAa,EAAE,KAAI,CAAC,oBAAoB;gBACxC,UAAU,EAAE,KAAI,CAAC,UAAU;gBAC3B,SAAS,EAAE,KAAI,CAAC,mBAAmB;gBACnC,mBAAmB,EAAE,KAAI,CAAC,gBAAgB;gBAC1C,KAAK,EAAE,KAAI,CAAC,eAAe;aAC9B,CAAC;QACN,CAAC,CAAC;QAEK,oBAAe,GAAG,UAAC,KAAc;;YACpC,IAAI,CAAC,KAAI,CAAC,oBAAoB,IAAI,KAAI,CAAC,cAAc,EAAE,CAAC;gBACpD,OAAO,KAAK,CAAC;YACjB,CAAC;YAED,IAAM,MAAM,GAAG,KAAY,CAAC;YAC5B,IAAM,IAAI,GAAG,MAAM,CAAC,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,MAAI,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,WAAW,0CAAE,IAAI,CAAA,IAAI,EAAE,CAAC,CAAC;YACrE,IAAM,OAAO,GAAG,MAAM,CAAC,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,OAAO,KAAI,EAAE,CAAC,CAAC;YAC9C,IAAM,IAAI,GAAG,UAAG,IAAI,cAAI,OAAO,CAAE,CAAC,WAAW,EAAE,CAAC;YAEhD,OAAO;gBACH,SAAS;gBACT,SAAS;gBACT,SAAS;gBACT,QAAQ;gBACR,YAAY;gBACZ,aAAa;gBACb,QAAQ;gBACR,cAAc;gBACd,WAAW;gBACX,mBAAmB;aACtB,CAAC,IAAI,CAAC,UAAC,KAAK,IAAK,OAAA,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAApB,CAAoB,CAAC,CAAC;QAC5C,CAAC,CAAC;QAEK,qBAAgB,GAAG,UAAC,KAAe;YACtC,IAAI,CAAC,KAAI,CAAC,kBAAkB,IAAI,KAAI,CAAC,cAAc,EAAE,CAAC;gBAClD,OAAO;YACX,CAAC;YAED,IAAM,OAAO,GAAG,KAAI,CAAC,OAAO,CAAC;YAE7B,KAAI,CAAC,mBAAmB,GAAG,KAAK,CAAC;YACjC,KAAI,CAAC,iBAAiB,GAAG,SAAS,CAAC;YACnC,KAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,KAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,KAAI,CAAC,gBAAgB,EAAE,CAAC;YAExB,IAAI,OAAO,IAAI,OAAQ,OAAe,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;gBACzD,OAAe,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,cAAM,OAAA,SAAS,EAAT,CAAS,CAAC,CAAC;YACpD,CAAC;YAED,IAAI,KAAI,CAAC,oBAAoB,EAAE,CAAC;gBAC5B,KAAI,CAAC,eAAe,GAAG,cAAc,CAAC;gBACtC,KAAI,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,cAAM,OAAA,SAAS,EAAT,CAAS,CAAC,CAAC;gBAC7C,OAAO;YACX,CAAC;YAED,KAAI,CAAC,eAAe,GAAG,MAAM,CAAC;QAClC,CAAC,CAAC;QAEF;;WAEG;QACI,aAAQ,GAAG;;;;;wBACR,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;wBAE7B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;wBAC3B,IAAI,CAAC,mBAAmB,EAAE,CAAC;wBAC3B,IAAI,CAAC,gBAAgB,EAAE,CAAC;wBACxB,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;4BACvB,IAAI,CAAC,eAAe,CAAC,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC,CAAC;wBAClE,CAAC;wBACD,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;wBAClC,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;wBACjC,IAAI,CAAC,iBAAiB,GAAG,SAAS,CAAC;wBACnC,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;wBACpC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;wBACpB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;wBACnB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;wBAC7B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;wBACvB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;wBACrB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;wBACrB,IAAI,CAAC,eAAe,GAAG,QAAQ,CAAC;wBAChC,IAAI,CAAC,mBAAmB,GAAG,SAAS,CAAC;6BAEjC,CAAA,OAAO,IAAI,OAAQ,OAAe,CAAC,KAAK,KAAK,UAAU,CAAA,EAAvD,wBAAuD;wBACvD,qBAAO,OAAe,CAAC,KAAK,EAAE,EAAA;;wBAA9B,SAA8B,CAAC;;;;;aAEtC,CAAC;IA5YqB,CAAC;IAJxB,sBAAkB,+BAAQ;aAA1B;YACI,OAAO,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;;;OAAA;IAIO,gDAAkB,GAA1B,UAA2B,IAAkB;QACzC,IAAI,CAAC,oBAAoB;YACrB,OAAO,IAAI,CAAC,aAAa,KAAK,SAAS;gBACnC,CAAC,CAAC,IAAI,CAAC,aAAa;gBACpB,CAAC,CAAC,IAAA,aAAO,EAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;QACxD,IAAI,CAAC,gBAAgB;YACjB,OAAO,IAAI,CAAC,mBAAmB,KAAK,QAAQ,IAAI,IAAI,CAAC,mBAAmB,GAAG,CAAC;gBACxE,CAAC,CAAC,IAAI,CAAC,mBAAmB;gBAC1B,CAAC,CAAC,IAAA,eAAS,EAAC,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,IAAI,CAAC,CAAC;IAC1E,CAAC;IAEO,2CAAa,GAArB,UAAsB,IAAkB;QAC7B,IAAA,gBAAgB,GAAuD,IAAI,iBAA3D,EAAE,QAAQ,GAA6C,IAAI,SAAjD,EAAE,QAAQ,GAAmC,IAAI,SAAvC,EAAE,KAAiC,IAAI,WAAf,EAAtB,UAAU,mBAAG,SAAS,KAAA,EAAE,KAAK,GAAI,IAAI,MAAR,CAAS;QAEnF,OAAO;YACH,UAAU,YAAA;YACV,gBAAgB,kBAAA;YAChB,QAAQ,UAAA;YACR,KAAK,OAAA;YACL,QAAQ,UAAA;SACX,CAAC;IACN,CAAC;IAEO,0CAAY,GAApB,UAAqB,IAAwB;QACzC,IAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC;QAExC,OAAO,CACH,CAAC,CAAC,OAAO;YACT,OAAO,CAAC,gBAAgB,KAAK,IAAI,CAAC,gBAAgB;YAClD,OAAO,CAAC,UAAU,KAAK,IAAI,CAAC,UAAU;YACtC,OAAO,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ;YAClC,OAAO,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ;YAClC,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAC/B,CAAC;IACN,CAAC;IAEO,4CAAc,GAAtB,UAAuB,QAA4B;QAC/C,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC,gBAAgB,CAAC;QAClD,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC;QACtC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;QAClC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;QAClC,IAAI,CAAC,kBAAkB,GAAG,QAAQ,CAAC;IACvC,CAAC;IAEO,2CAAa,GAArB;QACI,OAAO,IAAI,KAAK,CACZ,2GAA2G,CAC9G,CAAC;IACN,CAAC;IAEO,+CAAiB,GAAzB,UAA0B,QAA4B;QAClD,IAAM,OAAO,GAAQ;YACjB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;SAC9B,CAAC;QAEF,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;QACnC,CAAC;QAED,OAAO,OAAO,CAAC;IACnB,CAAC;IAEO,iDAAmB,GAA3B;QACI,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAClC,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QACpC,CAAC;IACL,CAAC;IAEO,8CAAgB,GAAxB;QACI,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC/B,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;QACjC,CAAC;IACL,CAAC;IAEO,2CAAa,GAArB,UAAsB,QAAoB,EAAE,KAAY;QAAZ,sBAAA,EAAA,YAAY;QACpD,IAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAE1D,IAAI,KAAK,IAAI,OAAQ,KAAa,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;YACrD,KAAa,CAAC,KAAK,EAAE,CAAC;QAC3B,CAAC;QAED,OAAO,KAAK,CAAC;IACjB,CAAC;IAkBO,iDAAmB,GAA3B;QAAA,iBAeC;QAdG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAExB,IAAI,CAAC,IAAI,CAAC,oBAAoB,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACpD,OAAO;QACX,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC;;;;;;wBAE9B,qBAAM,IAAI,CAAC,OAAO,EAAE,EAAA;;wBAApB,SAAoB,CAAC;wBACrB,IAAI,CAAC,mBAAmB,EAAE,CAAC;;;;wBAE3B,IAAI,CAAC,gBAAgB,CAAC,OAAK,CAAC,CAAC;;;;;aAEpC,CAAC,CAAC;IACP,CAAC;IAqRL,0BAAC;AAAD,CAAC,AAxaD,IAwaC;AAxaY,kDAAmB;AA0ahC,kBAAe,mBAAmB,CAAC","sourcesContent":["import type {Bucket, Cluster, Collection} from 'couchbase';\nimport * as couchbase from 'couchbase';\n\nimport {envFlag, envNumber} from './env';\nimport {ConnectionHealth, ConnectionSettings, ConnectionState, CouchsetArgs} from './types';\n\n/**\n * CouchbaseConnection class\n * Only one CouchbaseConnection can exist that's why it's a singleton\n */\nexport class CouchbaseConnection implements CouchsetArgs {\n private static _instance: CouchbaseConnection;\n\n bucket: Bucket = null;\n cluster: Cluster = null;\n private connectionPromise?: Promise<CouchbaseConnection>;\n private connectionSettings?: ConnectionSettings;\n private reconnectPromise?: Promise<CouchbaseConnection>;\n private reconnectReject?: (error: Error) => void;\n private reconnectTimer?: ReturnType<typeof setTimeout>;\n private healthTimer?: ReturnType<typeof setTimeout>;\n private connectionState: ConnectionState = 'idle';\n private autoReconnectEnabled = true;\n private reconnectDelayMs = 5000;\n private manuallyClosed = false;\n private lastConnectionError?: any;\n\n // Args\n connectionString: string = null;\n bucketName: string = null;\n username: string = null;\n password: string = null;\n\n public static get Instance(): CouchbaseConnection {\n return this._instance || (this._instance = new this());\n }\n\n private constructor() {}\n\n private configureReconnect(args: CouchsetArgs): void {\n this.autoReconnectEnabled =\n typeof args.autoReconnect === 'boolean'\n ? args.autoReconnect\n : envFlag(process.env.COUCHSET_RECONNECT, true);\n this.reconnectDelayMs =\n typeof args.reconnectIntervalMs === 'number' && args.reconnectIntervalMs > 0\n ? args.reconnectIntervalMs\n : envNumber(process.env.COUCHSET_RECONNECT_INTERVAL_MS, 5000);\n }\n\n private normalizeArgs(args: CouchsetArgs): ConnectionSettings {\n const {connectionString, password, username, bucketName = 'default', proxy} = args;\n\n return {\n bucketName,\n connectionString,\n password,\n proxy,\n username,\n };\n }\n\n private sameSettings(next: ConnectionSettings): boolean {\n const current = this.connectionSettings;\n\n return (\n !!current &&\n current.connectionString === next.connectionString &&\n current.bucketName === next.bucketName &&\n current.username === next.username &&\n current.password === next.password &&\n current.proxy === next.proxy\n );\n }\n\n private assignSettings(settings: ConnectionSettings): void {\n this.connectionString = settings.connectionString;\n this.bucketName = settings.bucketName;\n this.username = settings.username;\n this.password = settings.password;\n this.connectionSettings = settings;\n }\n\n private settingsError(): Error {\n return new Error(\n 'couchset is already connected with different settings; call couchset({...args, force: true}) to reconnect'\n );\n }\n\n private connectionOptions(settings: ConnectionSettings): any {\n const options: any = {\n password: settings.password,\n username: settings.username,\n };\n\n if (settings.proxy) {\n options.proxy = settings.proxy;\n }\n\n return options;\n }\n\n private clearReconnectTimer(): void {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n }\n }\n\n private clearHealthTimer(): void {\n if (this.healthTimer) {\n clearTimeout(this.healthTimer);\n this.healthTimer = undefined;\n }\n }\n\n private scheduleTimer(callback: () => void, unref = true): ReturnType<typeof setTimeout> {\n const timer = setTimeout(callback, this.reconnectDelayMs);\n\n if (unref && typeof (timer as any).unref === 'function') {\n (timer as any).unref();\n }\n\n return timer;\n }\n\n private rawPing = async (): Promise<any> => {\n if (!this.cluster) {\n throw new Error('couchset is not connected; call couchset(args) first');\n }\n\n if (typeof (this.cluster as any).ping === 'function') {\n return (this.cluster as any).ping();\n }\n\n return this.cluster.query('SELECT 1');\n };\n\n private openCluster = (settings: ConnectionSettings): Promise<Cluster> => {\n return couchbase.connect(settings.connectionString, this.connectionOptions(settings));\n };\n\n private scheduleHealthCheck(): void {\n this.clearHealthTimer();\n\n if (!this.autoReconnectEnabled || this.manuallyClosed) {\n return;\n }\n\n this.healthTimer = this.scheduleTimer(async () => {\n try {\n await this.rawPing();\n this.scheduleHealthCheck();\n } catch (error) {\n this.markDisconnected(error);\n }\n });\n }\n\n private connectWithSettings = async (\n settings: ConnectionSettings\n ): Promise<CouchbaseConnection> => {\n const cluster = await this.openCluster(settings);\n\n if (this.manuallyClosed) {\n if (cluster && typeof (cluster as any).close === 'function') {\n await (cluster as any).close();\n }\n throw new Error('couchset reconnect stopped');\n }\n\n this.cluster = cluster as any;\n this.bucket = this.cluster.bucket(settings.bucketName);\n this.connectionState = 'connected';\n this.lastConnectionError = undefined;\n this.scheduleHealthCheck();\n\n return this;\n };\n\n private startReconnect = (): Promise<CouchbaseConnection> => {\n if (this.reconnectPromise) {\n return this.reconnectPromise;\n }\n\n if (!this.autoReconnectEnabled || !this.connectionSettings || this.manuallyClosed) {\n return Promise.reject(\n new Error('couchset reconnect is disabled or no connection settings are available')\n );\n }\n\n this.connectionState = 'reconnecting';\n\n this.reconnectPromise = new Promise<CouchbaseConnection>((resolve, reject) => {\n this.reconnectReject = reject;\n\n const attempt = async () => {\n if (this.manuallyClosed || !this.connectionSettings) {\n reject(new Error('couchset reconnect stopped'));\n return;\n }\n\n try {\n const connection = await this.connectWithSettings(this.connectionSettings);\n this.reconnectPromise = undefined;\n this.reconnectReject = undefined;\n this.clearReconnectTimer();\n resolve(connection);\n } catch (error) {\n this.lastConnectionError = error;\n this.connectionState = 'reconnecting';\n this.reconnectTimer = this.scheduleTimer(attempt, false);\n }\n };\n\n attempt();\n });\n\n return this.reconnectPromise;\n };\n\n /**\n * start\n */\n public init = async (args: CouchsetArgs): Promise<CouchbaseConnection> => {\n const settings = this.normalizeArgs(args);\n this.configureReconnect(args);\n\n if (this.connectionPromise && this.sameSettings(settings)) {\n return this.connectionPromise;\n }\n\n if (this.reconnectPromise && this.sameSettings(settings)) {\n return this.reconnectPromise;\n }\n\n if (this.isConnected() && this.sameSettings(settings)) {\n return this;\n }\n\n if (\n (this.isConnected() || this.connectionPromise || this.reconnectPromise) &&\n !args.force\n ) {\n throw this.settingsError();\n }\n\n if (args.force && this.connectionPromise) {\n await this.connectionPromise.catch(() => undefined);\n }\n\n if (args.force) {\n await this.shutdown();\n this.configureReconnect(args);\n }\n\n this.manuallyClosed = false;\n this.clearReconnectTimer();\n this.clearHealthTimer();\n this.assignSettings(settings);\n this.connectionState = 'connecting';\n this.connectionPromise = this.connectWithSettings(settings)\n .then((connection) => {\n this.connectionPromise = undefined;\n\n return connection;\n })\n .catch((error) => {\n this.connectionPromise = undefined;\n this.connectionSettings = undefined;\n this.connectionState = 'idle';\n this.lastConnectionError = error;\n throw error;\n });\n\n return this.connectionPromise;\n };\n\n /**\n * start serverless start\n */\n public initServerless = async (args: CouchsetArgs): Promise<CouchbaseConnection> => {\n return this.init(args);\n };\n\n /**\n * getCollection\n */\n public getCollection = (scopeName?: string, collectionName?: string): Collection => {\n if (scopeName || collectionName) {\n return this.bucket\n .scope(scopeName || '_default')\n .collection(collectionName || '_default');\n }\n\n return this.bucket.defaultCollection();\n };\n\n public getCluster = (): Cluster => {\n return this.cluster;\n };\n\n public getBucket = (): string => {\n return this.bucketName;\n };\n\n public isConnected = (): boolean => {\n return !!this.cluster && !!this.bucket;\n };\n\n public ready = async (): Promise<CouchbaseConnection> => {\n if (this.isConnected()) {\n return this;\n }\n\n if (this.connectionPromise) {\n return this.connectionPromise;\n }\n\n if (this.reconnectPromise) {\n return this.reconnectPromise;\n }\n\n if (this.autoReconnectEnabled && this.connectionSettings && !this.manuallyClosed) {\n return this.startReconnect();\n }\n\n throw new Error('couchset is not connected; call couchset(args) first');\n };\n\n public ping = async (): Promise<any> => {\n await this.ready();\n\n try {\n return await this.rawPing();\n } catch (error) {\n this.markDisconnected(error);\n throw error;\n }\n };\n\n public state = (): ConnectionState => {\n return this.connectionState;\n };\n\n public health = (): ConnectionHealth => {\n return {\n autoReconnect: this.autoReconnectEnabled,\n bucketName: this.bucketName,\n lastError: this.lastConnectionError,\n reconnectIntervalMs: this.reconnectDelayMs,\n state: this.connectionState,\n };\n };\n\n public shouldReconnect = (error: unknown): boolean => {\n if (!this.autoReconnectEnabled || this.manuallyClosed) {\n return false;\n }\n\n const caught = error as any;\n const name = String(caught?.name || caught?.constructor?.name || '');\n const message = String(caught?.message || '');\n const text = `${name} ${message}`.toLowerCase();\n\n return [\n 'timeout',\n 'network',\n 'connect',\n 'closed',\n 'disconnect',\n 'unavailable',\n 'socket',\n 'econnrefused',\n 'etimedout',\n 'temporary failure',\n ].some((value) => text.includes(value));\n };\n\n public markDisconnected = (error?: unknown): void => {\n if (!this.connectionSettings || this.manuallyClosed) {\n return;\n }\n\n const cluster = this.cluster;\n\n this.lastConnectionError = error;\n this.connectionPromise = undefined;\n this.cluster = null;\n this.bucket = null;\n this.clearHealthTimer();\n\n if (cluster && typeof (cluster as any).close === 'function') {\n (cluster as any).close().catch(() => undefined);\n }\n\n if (this.autoReconnectEnabled) {\n this.connectionState = 'reconnecting';\n this.startReconnect().catch(() => undefined);\n return;\n }\n\n this.connectionState = 'idle';\n };\n\n /**\n * shutdown cluster\n */\n public shutdown = async (): Promise<void> => {\n const cluster = this.cluster;\n\n this.manuallyClosed = true;\n this.clearReconnectTimer();\n this.clearHealthTimer();\n if (this.reconnectReject) {\n this.reconnectReject(new Error('couchset reconnect stopped'));\n }\n this.reconnectPromise = undefined;\n this.reconnectReject = undefined;\n this.connectionPromise = undefined;\n this.connectionSettings = undefined;\n this.cluster = null;\n this.bucket = null;\n this.connectionString = null;\n this.bucketName = null;\n this.username = null;\n this.password = null;\n this.connectionState = 'closed';\n this.lastConnectionError = undefined;\n\n if (cluster && typeof (cluster as any).close === 'function') {\n await (cluster as any).close();\n }\n };\n}\n\nexport default CouchbaseConnection;\n"]}
package/dist/index.d.ts CHANGED
@@ -8,6 +8,8 @@ export * from './search';
8
8
  export * from './pagination';
9
9
  export * from './shared';
10
10
  export * from './timeseries';
11
+ /** Additive client-owned APIs exposed by couchset/next (and this modern entrypoint). */
12
+ export * from './next';
11
13
  export declare const ensureIndexes: (options?: EnsureIndexOptions) => Promise<string[]>;
12
14
  export declare const ready: () => Promise<CouchbaseConnection>;
13
15
  export declare const ping: () => Promise<any>;
package/dist/index.js CHANGED
@@ -64,6 +64,8 @@ __exportStar(require("./search"), exports);
64
64
  __exportStar(require("./pagination"), exports);
65
65
  __exportStar(require("./shared"), exports);
66
66
  __exportStar(require("./timeseries"), exports);
67
+ /** Additive client-owned APIs exposed by couchset/next (and this modern entrypoint). */
68
+ __exportStar(require("./next"), exports);
67
69
  var ensureIndexes = function (options) { return __awaiter(void 0, void 0, void 0, function () {
68
70
  return __generator(this, function (_a) {
69
71
  return [2 /*return*/, model_1.Model.ensureIndexes(options)];
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4DAAiF;AACjF,iCAAkD;AAElD,0CAAwB;AACxB,+CAA6B;AAC7B,6CAA2B;AAC3B,0CAAwB;AACxB,2CAAyB;AACzB,+CAA6B;AAC7B,2CAAyB;AACzB,+CAA6B;AAEtB,IAAM,aAAa,GAAG,UAAO,OAA4B;;QAC5D,sBAAO,aAAK,CAAC,aAAa,CAAC,OAAO,CAAC,EAAC;;KACvC,CAAC;AAFW,QAAA,aAAa,iBAExB;AAEK,IAAM,KAAK,GAAG;;QACjB,sBAAO,oBAAmB,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAC;;KAC/C,CAAC;AAFW,QAAA,KAAK,SAEhB;AAEK,IAAM,IAAI,GAAG;;QAChB,sBAAO,oBAAmB,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAC;;KAC9C,CAAC;AAFW,QAAA,IAAI,QAEf;AAEK,IAAM,MAAM,GAAG;IAClB,OAAO,oBAAmB,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;AACjD,CAAC,CAAC;AAFW,QAAA,MAAM,UAEjB;AAEK,IAAM,QAAQ,GAAG;;QACpB,sBAAO,oBAAmB,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAC;;KAClD,CAAC;AAFW,QAAA,QAAQ,YAEnB;AAWF;;;GAGG;AACH,IAAM,aAAa,GAAG,UAAO,IAAkB;;;;;gBACrC,KAAK,GAAG,oBAAmB,CAAC,QAAQ,CAAC;gBAC3C,qBAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAA;;gBAAtB,SAAsB,CAAC;gBACvB,sBAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAC;;;KAChC,CAAC;AAEW,QAAA,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE;IACjD,aAAa,uBAAA;IACb,MAAM,gBAAA;IACN,IAAI,cAAA;IACJ,KAAK,eAAA;IACL,QAAQ,kBAAA;CACX,CAAoB,CAAC;AAEtB;;;GAGG;AACI,IAAM,kBAAkB,GAAG,UAAO,IAAkB;;;;;gBACjD,KAAK,GAAG,oBAAmB,CAAC,QAAQ,CAAC;gBAC3C,qBAAM,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,EAAA;;gBAAhC,SAAgC,CAAC;gBACjC,sBAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAC;;;KAChC,CAAC;AAJW,QAAA,kBAAkB,sBAI7B;AAEF,kBAAe,gBAAQ,CAAC","sourcesContent":["import CouchbaseConnection, {ConnectionHealth, CouchsetArgs} from './connection';\nimport {EnsureIndexOptions, Model} from './model';\n\nexport * from './model';\nexport * from './connection';\nexport * from './database';\nexport * from './query';\nexport * from './search';\nexport * from './pagination';\nexport * from './shared';\nexport * from './timeseries';\n\nexport const ensureIndexes = async (options?: EnsureIndexOptions): Promise<string[]> => {\n return Model.ensureIndexes(options);\n};\n\nexport const ready = async (): Promise<CouchbaseConnection> => {\n return CouchbaseConnection.Instance.ready();\n};\n\nexport const ping = async (): Promise<any> => {\n return CouchbaseConnection.Instance.ping();\n};\n\nexport const health = (): ConnectionHealth => {\n return CouchbaseConnection.Instance.health();\n};\n\nexport const shutdown = async (): Promise<void> => {\n return CouchbaseConnection.Instance.shutdown();\n};\n\nexport interface CouchsetStarter {\n (args: CouchsetArgs): Promise<boolean>;\n ensureIndexes: typeof ensureIndexes;\n health: typeof health;\n ping: typeof ping;\n ready: typeof ready;\n shutdown: typeof shutdown;\n}\n\n/**\n * Main function to start CouchSet\n * @param @interface CouchsetArgs\n */\nconst startCouchset = async (args: CouchsetArgs): Promise<boolean> => {\n const couch = CouchbaseConnection.Instance;\n await couch.init(args);\n return Promise.resolve(true);\n};\n\nexport const couchset = Object.assign(startCouchset, {\n ensureIndexes,\n health,\n ping,\n ready,\n shutdown,\n}) as CouchsetStarter;\n\n/**\n * Main function to start CouchSet\n * @param @interface CouchsetArgs\n */\nexport const couchsetServerless = async (args: CouchsetArgs): Promise<boolean> => {\n const couch = CouchbaseConnection.Instance;\n await couch.initServerless(args);\n return Promise.resolve(true);\n};\n\nexport default couchset;\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4DAAiF;AACjF,iCAAkD;AAElD,0CAAwB;AACxB,+CAA6B;AAC7B,6CAA2B;AAC3B,0CAAwB;AACxB,2CAAyB;AACzB,+CAA6B;AAC7B,2CAAyB;AACzB,+CAA6B;AAC7B,wFAAwF;AACxF,yCAAuB;AAEhB,IAAM,aAAa,GAAG,UAAO,OAA4B;;QAC5D,sBAAO,aAAK,CAAC,aAAa,CAAC,OAAO,CAAC,EAAC;;KACvC,CAAC;AAFW,QAAA,aAAa,iBAExB;AAEK,IAAM,KAAK,GAAG;;QACjB,sBAAO,oBAAmB,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAC;;KAC/C,CAAC;AAFW,QAAA,KAAK,SAEhB;AAEK,IAAM,IAAI,GAAG;;QAChB,sBAAO,oBAAmB,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAC;;KAC9C,CAAC;AAFW,QAAA,IAAI,QAEf;AAEK,IAAM,MAAM,GAAG;IAClB,OAAO,oBAAmB,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;AACjD,CAAC,CAAC;AAFW,QAAA,MAAM,UAEjB;AAEK,IAAM,QAAQ,GAAG;;QACpB,sBAAO,oBAAmB,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAC;;KAClD,CAAC;AAFW,QAAA,QAAQ,YAEnB;AAWF;;;GAGG;AACH,IAAM,aAAa,GAAG,UAAO,IAAkB;;;;;gBACrC,KAAK,GAAG,oBAAmB,CAAC,QAAQ,CAAC;gBAC3C,qBAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAA;;gBAAtB,SAAsB,CAAC;gBACvB,sBAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAC;;;KAChC,CAAC;AAEW,QAAA,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE;IACjD,aAAa,uBAAA;IACb,MAAM,gBAAA;IACN,IAAI,cAAA;IACJ,KAAK,eAAA;IACL,QAAQ,kBAAA;CACX,CAAoB,CAAC;AAEtB;;;GAGG;AACI,IAAM,kBAAkB,GAAG,UAAO,IAAkB;;;;;gBACjD,KAAK,GAAG,oBAAmB,CAAC,QAAQ,CAAC;gBAC3C,qBAAM,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,EAAA;;gBAAhC,SAAgC,CAAC;gBACjC,sBAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAC;;;KAChC,CAAC;AAJW,QAAA,kBAAkB,sBAI7B;AAEF,kBAAe,gBAAQ,CAAC","sourcesContent":["import CouchbaseConnection, {ConnectionHealth, CouchsetArgs} from './connection';\nimport {EnsureIndexOptions, Model} from './model';\n\nexport * from './model';\nexport * from './connection';\nexport * from './database';\nexport * from './query';\nexport * from './search';\nexport * from './pagination';\nexport * from './shared';\nexport * from './timeseries';\n/** Additive client-owned APIs exposed by couchset/next (and this modern entrypoint). */\nexport * from './next';\n\nexport const ensureIndexes = async (options?: EnsureIndexOptions): Promise<string[]> => {\n return Model.ensureIndexes(options);\n};\n\nexport const ready = async (): Promise<CouchbaseConnection> => {\n return CouchbaseConnection.Instance.ready();\n};\n\nexport const ping = async (): Promise<any> => {\n return CouchbaseConnection.Instance.ping();\n};\n\nexport const health = (): ConnectionHealth => {\n return CouchbaseConnection.Instance.health();\n};\n\nexport const shutdown = async (): Promise<void> => {\n return CouchbaseConnection.Instance.shutdown();\n};\n\nexport interface CouchsetStarter {\n (args: CouchsetArgs): Promise<boolean>;\n ensureIndexes: typeof ensureIndexes;\n health: typeof health;\n ping: typeof ping;\n ready: typeof ready;\n shutdown: typeof shutdown;\n}\n\n/**\n * Main function to start CouchSet\n * @param @interface CouchsetArgs\n */\nconst startCouchset = async (args: CouchsetArgs): Promise<boolean> => {\n const couch = CouchbaseConnection.Instance;\n await couch.init(args);\n return Promise.resolve(true);\n};\n\nexport const couchset = Object.assign(startCouchset, {\n ensureIndexes,\n health,\n ping,\n ready,\n shutdown,\n}) as CouchsetStarter;\n\n/**\n * Main function to start CouchSet\n * @param @interface CouchsetArgs\n */\nexport const couchsetServerless = async (args: CouchsetArgs): Promise<boolean> => {\n const couch = CouchbaseConnection.Instance;\n await couch.initServerless(args);\n return Promise.resolve(true);\n};\n\nexport default couchset;\n"]}
@@ -1,4 +1,4 @@
1
- import type { Collection, GetOptions, MutateInOptions, RemoveOptions, ReplaceOptions } from 'couchbase';
1
+ import type { Collection, Cluster, GetOptions, MutateInOptions, RemoveOptions, ReplaceOptions } from 'couchbase';
2
2
  import { SchemaTypes } from '../utils';
3
3
  import type { ModelPageResult, ModelReadArgs } from './read-helpers';
4
4
  import type { QueryPageOptions, QueryPageResult, QueryParameters, SafeQueryOptions } from './safe-query';
@@ -6,6 +6,23 @@ import type { FindByIdWithMetaResult, InsertWriteOptions, PatchByIdArgs, UpsertW
6
6
  import { Hydrated } from './hydrated-document';
7
7
  import { EnsureIndexOptions, ModelIndexDefinition } from './indexes';
8
8
  import type { ParseHook, ValidationHook } from './validation';
9
+ /** A small connection surface used by client-bound models. */
10
+ export interface ModelConnection {
11
+ bucket?: any;
12
+ bucketName?: string;
13
+ cluster: Cluster;
14
+ getBucket(): string;
15
+ getCollection(scopeName?: string, collectionName?: string): Collection;
16
+ isConnected(): boolean;
17
+ ready(): Promise<any>;
18
+ shouldReconnect(error: any): boolean;
19
+ markDisconnected(error: any): void;
20
+ }
21
+ /** Converts a field between the application's value and Couchbase JSON. */
22
+ export interface FieldCodec<T = any, TDatabase = any> {
23
+ toDatabase(value: T): TDatabase;
24
+ fromDatabase(value: TDatabase): T;
25
+ }
9
26
  export type { ModelPageResult, ModelReadArgs } from './read-helpers';
10
27
  export type { QueryLogger, QueryPageOptions, QueryPageResult, QueryParameters, SafeQueryOptions, } from './safe-query';
11
28
  export type { FindByIdWithMetaResult, PatchByIdArgs } from './write-helpers';
@@ -38,8 +55,20 @@ export interface ModalOptions {
38
55
  validateReplace?: ValidationHook;
39
56
  parse?: ParseHook;
40
57
  dateFields?: string[];
58
+ /**
59
+ * Explicit field transforms. A field cannot also be a dateFields/schema date
60
+ * transform, since that makes the parse order ambiguous.
61
+ */
62
+ codecs?: Record<string, FieldCodec<any, any>>;
41
63
  indexes?: ModelIndexDefinition[];
42
64
  }
65
+ export type ConsumeOnceResult = {
66
+ status: 'consumed';
67
+ } | {
68
+ status: 'missing';
69
+ } | {
70
+ status: 'conflict';
71
+ };
43
72
  export declare class Model {
44
73
  private static registeredModels;
45
74
  collection: Collection;
@@ -54,9 +83,11 @@ export declare class Model {
54
83
  private validateReplaceHook?;
55
84
  private parseHook?;
56
85
  private dateFields?;
86
+ private codecs;
87
+ private readonly connection?;
57
88
  private indexes;
58
89
  schema: Record<string, SchemaTypes>;
59
- constructor(name: string, options?: ModalOptions);
90
+ constructor(name: string, options?: ModalOptions, connection?: ModelConnection);
60
91
  /**
61
92
  * Ensure indexes for every constructed model with index declarations.
62
93
  */
@@ -147,6 +178,8 @@ export declare class Model {
147
178
  * Insert a new document and fail if the id already exists.
148
179
  */
149
180
  insert<T>(data: T, options?: InsertWriteOptions): Promise<T & AutoModelFields>;
181
+ /** @internal Prepare a transaction insert without issuing a normal SDK write. */
182
+ prepareInsert<T>(data: T): Promise<T & AutoModelFields>;
150
183
  /**
151
184
  * Explicit insert-or-replace write.
152
185
  */
@@ -159,10 +192,26 @@ export declare class Model {
159
192
  * Find a document with SDK metadata.
160
193
  */
161
194
  findByIdWithMeta<T>(id: string, options?: GetOptions): Promise<FindByIdWithMetaResult<T>>;
195
+ /** Ergonomic alias for findByIdWithMeta, intended for CAS workflows. */
196
+ getWithCas<T>(id: string, options?: GetOptions): Promise<FindByIdWithMetaResult<T>>;
162
197
  /**
163
198
  * Explicit full-document replace.
164
199
  */
165
200
  replaceById<T>(id: string, data: T, options?: UpdateOptions): Promise<T & AutoModelFields>;
201
+ /** @internal Prepare a transaction replace without issuing a normal SDK write. */
202
+ prepareReplace<T>(id: string, data: T, options?: UpdateOptions): Promise<T & AutoModelFields>;
203
+ /**
204
+ * Replace only when the supplied CAS still describes the current document.
205
+ * CouchSet deliberately performs one SDK operation and never re-reads/retries
206
+ * with a new CAS, because doing so would defeat the caller's concurrency check.
207
+ */
208
+ replaceIfCas<T>(id: string, data: T, cas: any, options?: UpdateOptions): Promise<T & AutoModelFields>;
209
+ /**
210
+ * Remove a one-time document with exactly the CAS supplied by the caller.
211
+ * Missing and CAS-mismatch cases are normal outcomes; transport and ambiguous
212
+ * failures are rethrown so callers never mistake an unknown commit for success.
213
+ */
214
+ consumeOnce(id: string, cas: any): Promise<ConsumeOnceResult>;
166
215
  /**
167
216
  * Partial document mutation using common patch operators.
168
217
  */
@@ -185,5 +234,10 @@ export declare class Model {
185
234
  id: string;
186
235
  }>(data: T & AutoModelFields): Hydrated<T>;
187
236
  parse<T>(data: T): T;
237
+ /** @internal Used by the typed client before a document reaches the SDK. */
238
+ serialize<T>(data: T): T;
239
+ /** @internal Used by patch helpers and transaction-bound models. */
240
+ serializeField(path: string, value: any): any;
241
+ private deserialize;
188
242
  }
189
243
  export default Model;
@@ -109,10 +109,11 @@ var hydrated_document_1 = require("./hydrated-document");
109
109
  var indexes_1 = require("./indexes");
110
110
  var validation_1 = require("./validation");
111
111
  var Model = /** @class */ (function () {
112
- function Model(name, options) {
112
+ function Model(name, options, connection) {
113
113
  this.scope = '_default';
114
114
  this.defaultWhereMode = 'default';
115
115
  this.softDelete = false;
116
+ this.codecs = {};
116
117
  this.indexes = [];
117
118
  this.schema = {
118
119
  createdAt: 'date',
@@ -120,6 +121,7 @@ var Model = /** @class */ (function () {
120
121
  };
121
122
  // this.collection = CouchbaseConnection.Instance.getCollection();
122
123
  this.collectionName = name;
124
+ this.connection = connection;
123
125
  if (options) {
124
126
  var hasScope = Object.prototype.hasOwnProperty.call(options, 'scope');
125
127
  var hasCollection = Object.prototype.hasOwnProperty.call(options, 'collection');
@@ -134,10 +136,20 @@ var Model = /** @class */ (function () {
134
136
  this.validateReplaceHook = options.validateReplace;
135
137
  this.parseHook = options.parse;
136
138
  this.dateFields = options.dateFields;
139
+ this.codecs = options.codecs || {};
140
+ var dateFields_1 = new Set(options.dateFields || []);
141
+ Object.keys(this.codecs).forEach(function (field) {
142
+ var _a;
143
+ if (dateFields_1.has(field) || ((_a = options.schema) === null || _a === void 0 ? void 0 : _a[field]) === 'date') {
144
+ throw new Error("codec for ".concat(field, " conflicts with dateFields or schema date; use one transform"));
145
+ }
146
+ });
137
147
  this.indexes = options.indexes || [];
138
148
  this.schema = __assign(__assign(__assign({}, ((options && options.schema) || {})), (0, validation_1.schemaFromDateFields)(options.dateFields)), { createdAt: 'date', updatedAt: 'date' });
139
149
  }
140
- if (this.indexes.length) {
150
+ // Legacy models participate in the singleton registry. Client-bound
151
+ // models are registered only by their owning CouchsetClient.
152
+ if (this.indexes.length && !this.connection) {
141
153
  Model.registeredModels.push(this);
142
154
  }
143
155
  }
@@ -212,9 +224,9 @@ var Model = /** @class */ (function () {
212
224
  */
213
225
  Model.prototype.fresh = function () {
214
226
  // if couchbase connection has been init
215
- if (connection_1.default.Instance.isConnected()) {
227
+ if (this.couchbaseConnection().isConnected()) {
216
228
  var target = this.collectionTarget();
217
- this.collection = connection_1.default.Instance.getCollection(target.scopeName, target.collectionName);
229
+ this.collection = this.couchbaseConnection().getCollection(target.scopeName, target.collectionName);
218
230
  }
219
231
  };
220
232
  Model.prototype.prepare = function () {
@@ -270,8 +282,7 @@ var Model = /** @class */ (function () {
270
282
  * getCollection
271
283
  */
272
284
  Model.prototype.getBucketName = function () {
273
- var _a;
274
- var bucketName = (_a = connection_1.default.Instance) === null || _a === void 0 ? void 0 : _a.getBucket();
285
+ var bucketName = this.couchbaseConnection().getBucket();
275
286
  if (!bucketName) {
276
287
  throw new Error('couchset is not connected; call couchset(args) first');
277
288
  }
@@ -281,7 +292,7 @@ var Model = /** @class */ (function () {
281
292
  * getCollection
282
293
  */
283
294
  Model.prototype.couchbaseConnection = function () {
284
- return connection_1.default.Instance;
295
+ return this.connection || connection_1.default.Instance;
285
296
  };
286
297
  /** Get this collection
287
298
  * getCollection
@@ -328,12 +339,15 @@ var Model = /** @class */ (function () {
328
339
  collectionName: this.collectionName,
329
340
  scope: this.scope,
330
341
  parse: function (data) { return _this.parse(data); },
342
+ serialize: function (data) { return _this.serialize(data); },
343
+ serializeField: function (path, value) { return _this.serializeField(path, value); },
331
344
  validateCreate: this.validateCreateHook,
332
345
  validateReplace: this.validateReplaceHook,
333
346
  };
334
347
  };
335
348
  Model.prototype.cloneWithDefaultWhereMode = function (mode) {
336
349
  var options = {
350
+ codecs: this.codecs,
337
351
  dateFields: this.dateFields,
338
352
  defaultWhere: this.defaultWhere,
339
353
  parse: this.parseHook,
@@ -348,7 +362,7 @@ var Model = /** @class */ (function () {
348
362
  if (this.collectionTargetName) {
349
363
  options.collection = this.collectionTargetName;
350
364
  }
351
- var model = new Model(this.collectionName, options);
365
+ var model = new Model(this.collectionName, options, this.connection);
352
366
  model.defaultWhereMode = mode;
353
367
  return model;
354
368
  };
@@ -514,6 +528,10 @@ var Model = /** @class */ (function () {
514
528
  });
515
529
  });
516
530
  };
531
+ /** @internal Prepare a transaction insert without issuing a normal SDK write. */
532
+ Model.prototype.prepareInsert = function (data) {
533
+ return (0, write_helpers_1.prepareInsertDocument)(this.writeContext(), data);
534
+ };
517
535
  /**
518
536
  * Explicit insert-or-replace write.
519
537
  */
@@ -567,6 +585,14 @@ var Model = /** @class */ (function () {
567
585
  });
568
586
  });
569
587
  };
588
+ /** Ergonomic alias for findByIdWithMeta, intended for CAS workflows. */
589
+ Model.prototype.getWithCas = function (id, options) {
590
+ return __awaiter(this, void 0, void 0, function () {
591
+ return __generator(this, function (_a) {
592
+ return [2 /*return*/, this.findByIdWithMeta(id, options)];
593
+ });
594
+ });
595
+ };
570
596
  /**
571
597
  * Explicit full-document replace.
572
598
  */
@@ -580,6 +606,58 @@ var Model = /** @class */ (function () {
580
606
  });
581
607
  });
582
608
  };
609
+ /** @internal Prepare a transaction replace without issuing a normal SDK write. */
610
+ Model.prototype.prepareReplace = function (id, data, options) {
611
+ return (0, write_helpers_1.prepareReplacementDocument)(this.writeContext(), id, data, options);
612
+ };
613
+ /**
614
+ * Replace only when the supplied CAS still describes the current document.
615
+ * CouchSet deliberately performs one SDK operation and never re-reads/retries
616
+ * with a new CAS, because doing so would defeat the caller's concurrency check.
617
+ */
618
+ Model.prototype.replaceIfCas = function (id, data, cas, options) {
619
+ return __awaiter(this, void 0, void 0, function () {
620
+ return __generator(this, function (_a) {
621
+ return [2 /*return*/, this.replaceById(id, data, __assign(__assign({}, (options || {})), { cas: cas }))];
622
+ });
623
+ });
624
+ };
625
+ /**
626
+ * Remove a one-time document with exactly the CAS supplied by the caller.
627
+ * Missing and CAS-mismatch cases are normal outcomes; transport and ambiguous
628
+ * failures are rethrown so callers never mistake an unknown commit for success.
629
+ */
630
+ Model.prototype.consumeOnce = function (id, cas) {
631
+ return __awaiter(this, void 0, void 0, function () {
632
+ var error_2, name_1, message;
633
+ return __generator(this, function (_a) {
634
+ switch (_a.label) {
635
+ case 0: return [4 /*yield*/, this.prepare()];
636
+ case 1:
637
+ _a.sent();
638
+ _a.label = 2;
639
+ case 2:
640
+ _a.trys.push([2, 4, , 5]);
641
+ return [4 /*yield*/, this.collection.remove(id, { cas: cas })];
642
+ case 3:
643
+ _a.sent();
644
+ return [2 /*return*/, { status: 'consumed' }];
645
+ case 4:
646
+ error_2 = _a.sent();
647
+ name_1 = (error_2 === null || error_2 === void 0 ? void 0 : error_2.name) || '';
648
+ message = (error_2 === null || error_2 === void 0 ? void 0 : error_2.message) || '';
649
+ if (/DocumentNotFound|not found/i.test("".concat(name_1, " ").concat(message))) {
650
+ return [2 /*return*/, { status: 'missing' }];
651
+ }
652
+ if (/CasMismatch|cas mismatch/i.test("".concat(name_1, " ").concat(message))) {
653
+ return [2 /*return*/, { status: 'conflict' }];
654
+ }
655
+ throw error_2;
656
+ case 5: return [2 /*return*/];
657
+ }
658
+ });
659
+ });
660
+ };
583
661
  /**
584
662
  * Partial document mutation using common patch operators.
585
663
  */
@@ -673,13 +751,64 @@ var Model = /** @class */ (function () {
673
751
  return (0, hydrated_document_1.hydrate)(this, this.parse(data));
674
752
  };
675
753
  Model.prototype.parse = function (data) {
676
- var parsed = (0, utils_1.parseSchema)(this.schema, data);
754
+ var decoded = this.deserialize(data);
755
+ var parsed = (0, utils_1.parseSchema)(this.schema, decoded);
677
756
  var parsedDates = (0, validation_1.parseDateFields)(parsed, this.dateFields);
678
757
  return this.parseHook ? this.parseHook(parsedDates) : parsedDates;
679
758
  };
759
+ /** @internal Used by the typed client before a document reaches the SDK. */
760
+ Model.prototype.serialize = function (data) {
761
+ var _this = this;
762
+ var result = __assign({}, data);
763
+ Object.keys(this.codecs).forEach(function (path) {
764
+ var current = getPath(result, path);
765
+ if (current !== undefined) {
766
+ setPath(result, path, _this.codecs[path].toDatabase(current));
767
+ }
768
+ });
769
+ return result;
770
+ };
771
+ /** @internal Used by patch helpers and transaction-bound models. */
772
+ Model.prototype.serializeField = function (path, value) {
773
+ return this.codecs[path] ? this.codecs[path].toDatabase(value) : value;
774
+ };
775
+ Model.prototype.deserialize = function (data) {
776
+ var _this = this;
777
+ var result = __assign({}, data);
778
+ Object.keys(this.codecs).forEach(function (path) {
779
+ var current = getPath(result, path);
780
+ if (current !== undefined) {
781
+ setPath(result, path, _this.codecs[path].fromDatabase(current));
782
+ }
783
+ });
784
+ return result;
785
+ };
680
786
  Model.registeredModels = [];
681
787
  return Model;
682
788
  }());
683
789
  exports.Model = Model;
790
+ var getPath = function (data, path) {
791
+ return path.split('.').reduce(function (value, key) { return (value == null ? undefined : value[key]); }, data);
792
+ };
793
+ var setPath = function (data, path, value) {
794
+ var parts = path.split('.');
795
+ var key = parts.pop();
796
+ var target = parts.reduce(function (current, part) {
797
+ var existing = current[part];
798
+ if (Array.isArray(existing)) {
799
+ current[part] = existing.slice();
800
+ }
801
+ else if (existing && typeof existing === 'object') {
802
+ // serialize/parse start with a shallow root copy. Clone every branch
803
+ // we traverse so dotted codecs never mutate caller or SDK content.
804
+ current[part] = __assign({}, existing);
805
+ }
806
+ else {
807
+ current[part] = {};
808
+ }
809
+ return current[part];
810
+ }, data);
811
+ target[key] = value;
812
+ };
684
813
  exports.default = Model;
685
814
  //# sourceMappingURL=index.js.map