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/dist/next.js ADDED
@@ -0,0 +1,1190 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
24
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ var __values = (this && this.__values) || function(o) {
50
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
51
+ if (m) return m.call(o);
52
+ if (o && typeof o.length === "number") return {
53
+ next: function () {
54
+ if (o && i >= o.length) o = void 0;
55
+ return { value: o && o[i++], done: !o };
56
+ }
57
+ };
58
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
59
+ };
60
+ var __read = (this && this.__read) || function (o, n) {
61
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
62
+ if (!m) return o;
63
+ var i = m.call(o), r, ar = [], e;
64
+ try {
65
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
66
+ }
67
+ catch (error) { e = { error: error }; }
68
+ finally {
69
+ try {
70
+ if (r && !r.done && (m = i["return"])) m.call(i);
71
+ }
72
+ finally { if (e) throw e.error; }
73
+ }
74
+ return ar;
75
+ };
76
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
77
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
78
+ if (ar || !(i in from)) {
79
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
80
+ ar[i] = from[i];
81
+ }
82
+ }
83
+ return to.concat(ar || Array.prototype.slice.call(from));
84
+ };
85
+ var __importDefault = (this && this.__importDefault) || function (mod) {
86
+ return (mod && mod.__esModule) ? mod : { "default": mod };
87
+ };
88
+ Object.defineProperty(exports, "__esModule", { value: true });
89
+ exports.createCouchsetClient = exports.createCouchsetTestFixture = exports.CouchsetTransaction = exports.TransactionModel = exports.CouchsetClient = exports.defineModel = exports.dateCodec = void 0;
90
+ var couchbase_1 = __importDefault(require("./couchbase"));
91
+ var model_1 = require("./model");
92
+ var indexes_1 = require("./model/indexes");
93
+ var keyspace_1 = require("./model/keyspace");
94
+ var builders_1 = require("./query/helpers/builders");
95
+ var uuid_1 = require("./uuid");
96
+ /** A JSON-friendly Date codec for models declared with defineModel. */
97
+ exports.dateCodec = {
98
+ fromDatabase: function (value) { return new Date(value); },
99
+ toDatabase: function (value) { return value.toISOString(); },
100
+ };
101
+ var defineModel = function (definition) {
102
+ if (!definition || !definition.name) {
103
+ throw new Error('defineModel requires a non-empty name');
104
+ }
105
+ return __assign({}, definition);
106
+ };
107
+ exports.defineModel = defineModel;
108
+ var defaultSettings = function (options) { return ({
109
+ bucketName: options.bucketName || 'default',
110
+ connectionString: options.connectionString || 'couchbase://localhost',
111
+ password: options.password || '',
112
+ username: options.username || '',
113
+ proxy: options.proxy,
114
+ }); };
115
+ var errorText = function (error) { return "".concat((error === null || error === void 0 ? void 0 : error.name) || '', " ").concat((error === null || error === void 0 ? void 0 : error.message) || error || ''); };
116
+ var isAlreadyExists = function (error) {
117
+ return /already exists|exists|ScopeExists|CollectionExists/i.test(errorText(error));
118
+ };
119
+ var isNotFound = function (error) { return /not found|not exist/i.test(errorText(error)); };
120
+ var provisionError = function (operation, target, error) {
121
+ var message = errorText(error);
122
+ var privilege = /access|permission|authoriz|privilege|forbidden/i.test(message)
123
+ ? ' This operation requires Couchbase Manage Scopes privileges on the bucket.'
124
+ : '';
125
+ var wrapped = new Error("CouchSet could not ".concat(operation, " ").concat(target, ".").concat(privilege, " ").concat(message).trim());
126
+ wrapped.cause = error;
127
+ return wrapped;
128
+ };
129
+ var delay = function (milliseconds) {
130
+ return new Promise(function (resolve) { return setTimeout(resolve, milliseconds); });
131
+ };
132
+ var DirectConnection = /** @class */ (function () {
133
+ function DirectConnection(settings, dependencies) {
134
+ this.settings = settings;
135
+ this.dependencies = dependencies;
136
+ this.cluster = dependencies.cluster;
137
+ this.bucket = dependencies.bucket;
138
+ if (this.cluster && !this.bucket) {
139
+ this.bucket = this.cluster.bucket(settings.bucketName);
140
+ }
141
+ }
142
+ DirectConnection.prototype.getBucket = function () {
143
+ return this.settings.bucketName;
144
+ };
145
+ DirectConnection.prototype.getCollection = function (scopeName, collectionName) {
146
+ if (!this.bucket) {
147
+ throw new Error('CouchSet client is not connected; call client.ready() first');
148
+ }
149
+ if (!scopeName && !collectionName) {
150
+ return this.bucket.defaultCollection();
151
+ }
152
+ return this.bucket.scope(scopeName || '_default').collection(collectionName || '_default');
153
+ };
154
+ DirectConnection.prototype.isConnected = function () {
155
+ return !!this.cluster && !!this.bucket;
156
+ };
157
+ DirectConnection.prototype.ready = function () {
158
+ return __awaiter(this, void 0, void 0, function () {
159
+ var connect, _a;
160
+ return __generator(this, function (_b) {
161
+ switch (_b.label) {
162
+ case 0:
163
+ if (this.isConnected()) {
164
+ return [2 /*return*/, this];
165
+ }
166
+ if (!this.connectPromise) {
167
+ connect = this.dependencies.connect ||
168
+ (function (settings) {
169
+ return couchbase_1.default.connect(settings.connectionString, {
170
+ password: settings.password,
171
+ proxy: settings.proxy,
172
+ username: settings.username,
173
+ });
174
+ });
175
+ this.connectPromise = connect(this.settings);
176
+ }
177
+ _a = this;
178
+ return [4 /*yield*/, this.connectPromise];
179
+ case 1:
180
+ _a.cluster = _b.sent();
181
+ this.bucket = this.cluster.bucket(this.settings.bucketName);
182
+ return [2 /*return*/, this];
183
+ }
184
+ });
185
+ });
186
+ };
187
+ DirectConnection.prototype.shouldReconnect = function () {
188
+ return false;
189
+ };
190
+ DirectConnection.prototype.markDisconnected = function () {
191
+ // A client-owned connection never retries an arbitrary write operation.
192
+ };
193
+ DirectConnection.prototype.shutdown = function () {
194
+ return __awaiter(this, void 0, void 0, function () {
195
+ return __generator(this, function (_a) {
196
+ switch (_a.label) {
197
+ case 0:
198
+ if (!(this.cluster && typeof this.cluster.close === 'function')) return [3 /*break*/, 2];
199
+ return [4 /*yield*/, this.cluster.close()];
200
+ case 1:
201
+ _a.sent();
202
+ _a.label = 2;
203
+ case 2:
204
+ this.cluster = undefined;
205
+ this.bucket = undefined;
206
+ return [2 /*return*/];
207
+ }
208
+ });
209
+ });
210
+ };
211
+ return DirectConnection;
212
+ }());
213
+ /**
214
+ * A client owns its model-definition registry and connection. It intentionally
215
+ * does not alter the legacy singleton or register models globally.
216
+ */
217
+ var CouchsetClient = /** @class */ (function () {
218
+ function CouchsetClient(options) {
219
+ if (options === void 0) { options = {}; }
220
+ var _this = this;
221
+ this.registered = new Map();
222
+ this.settings = defaultSettings(options);
223
+ var dependencies = options.dependencies || {};
224
+ if (dependencies.connection) {
225
+ var bucketName = dependencies.connection.getBucket();
226
+ if (!bucketName) {
227
+ throw new Error('Injected CouchSet connections must expose a bucket name');
228
+ }
229
+ if (options.bucketName && options.bucketName !== bucketName) {
230
+ throw new Error("Injected CouchSet connection targets ".concat(bucketName, ", not requested bucket ").concat(options.bucketName));
231
+ }
232
+ this.settings.bucketName = bucketName;
233
+ }
234
+ else if (dependencies.bucket) {
235
+ var bucketName = dependencies.bucket.name;
236
+ if (options.bucketName && options.bucketName !== bucketName) {
237
+ throw new Error("Injected Couchbase bucket targets ".concat(bucketName, ", not requested bucket ").concat(options.bucketName));
238
+ }
239
+ this.settings.bucketName = bucketName;
240
+ }
241
+ else if (dependencies.cluster && !options.bucketName) {
242
+ throw new Error('bucketName is required when injecting a Couchbase cluster');
243
+ }
244
+ this.connection =
245
+ dependencies.connection || new DirectConnection(this.settings, dependencies);
246
+ (options.models || []).forEach(function (definition) { return _this.model(definition); });
247
+ }
248
+ CouchsetClient.prototype.ready = function () {
249
+ return __awaiter(this, void 0, void 0, function () {
250
+ return __generator(this, function (_a) {
251
+ switch (_a.label) {
252
+ case 0: return [4 /*yield*/, this.connection.ready()];
253
+ case 1:
254
+ _a.sent();
255
+ return [2 /*return*/, this];
256
+ }
257
+ });
258
+ });
259
+ };
260
+ CouchsetClient.prototype.shutdown = function () {
261
+ return __awaiter(this, void 0, void 0, function () {
262
+ var shutdown;
263
+ return __generator(this, function (_a) {
264
+ switch (_a.label) {
265
+ case 0:
266
+ shutdown = this.connection.shutdown;
267
+ if (!(typeof shutdown === 'function')) return [3 /*break*/, 2];
268
+ return [4 /*yield*/, shutdown.call(this.connection)];
269
+ case 1:
270
+ _a.sent();
271
+ _a.label = 2;
272
+ case 2: return [2 /*return*/];
273
+ }
274
+ });
275
+ });
276
+ };
277
+ CouchsetClient.prototype.definitions = function () {
278
+ return Array.from(this.registered.values()).map(function (_a) {
279
+ var definition = _a.definition;
280
+ return definition;
281
+ });
282
+ };
283
+ /** Bind and register a definition without provisioning or index DDL. */
284
+ CouchsetClient.prototype.model = function (definition) {
285
+ var identity = modelIdentity(definition);
286
+ var existing = this.registered.get(identity);
287
+ if (existing) {
288
+ assertSameDefinition(existing.definition, definition);
289
+ return existing.model;
290
+ }
291
+ var model = new model_1.Model(definition.name, definition, this.connection);
292
+ this.registered.set(identity, { definition: definition, model: model });
293
+ return model;
294
+ };
295
+ /**
296
+ * Async registration for dynamic models. DDL is performed only when the
297
+ * caller explicitly opts into provision; ordinary model() is side-effect-free.
298
+ */
299
+ CouchsetClient.prototype.registerModel = function (definition_1) {
300
+ return __awaiter(this, arguments, void 0, function (definition, options) {
301
+ var model, requested, config;
302
+ if (options === void 0) { options = {}; }
303
+ return __generator(this, function (_a) {
304
+ switch (_a.label) {
305
+ case 0:
306
+ model = this.model(definition);
307
+ requested = options.provision;
308
+ if (!requested) return [3 /*break*/, 2];
309
+ config = typeof requested === 'boolean' ? { collections: true, indexes: true } : requested;
310
+ return [4 /*yield*/, this.provision({
311
+ collections: config.collections !== false,
312
+ indexes: config.indexes !== false,
313
+ models: [definition],
314
+ timeoutMs: options.timeoutMs,
315
+ waitForIndexes: config.waitForIndexes,
316
+ })];
317
+ case 1:
318
+ _a.sent();
319
+ _a.label = 2;
320
+ case 2: return [2 /*return*/, model];
321
+ }
322
+ });
323
+ });
324
+ };
325
+ /** Create only missing scopes/collections. Existing resources are never altered. */
326
+ CouchsetClient.prototype.ensureCollections = function () {
327
+ return __awaiter(this, arguments, void 0, function (options) {
328
+ var targets, manager, manifest, error_1, result, _loop_1, this_1, targets_1, targets_1_1, target, e_1_1;
329
+ var e_1, _a;
330
+ if (options === void 0) { options = {}; }
331
+ return __generator(this, function (_b) {
332
+ switch (_b.label) {
333
+ case 0: return [4 /*yield*/, this.ready()];
334
+ case 1:
335
+ _b.sent();
336
+ targets = this.targets(options.models);
337
+ manager = this.connection.bucket.collections();
338
+ _b.label = 2;
339
+ case 2:
340
+ _b.trys.push([2, 4, , 5]);
341
+ return [4 /*yield*/, manager.getAllScopes()];
342
+ case 3:
343
+ manifest = _b.sent();
344
+ return [3 /*break*/, 5];
345
+ case 4:
346
+ error_1 = _b.sent();
347
+ throw provisionError('read the scope manifest for', this.settings.bucketName, error_1);
348
+ case 5:
349
+ result = [];
350
+ _loop_1 = function (target) {
351
+ var defaultTarget, scope, createdScope, error_2, exists, createdCollection, error_3;
352
+ return __generator(this, function (_c) {
353
+ switch (_c.label) {
354
+ case 0:
355
+ defaultTarget = target.scope === '_default' && target.collection === '_default';
356
+ if (defaultTarget) {
357
+ result.push(__assign(__assign({}, target), { createdScope: false, createdCollection: false }));
358
+ return [2 /*return*/, "continue"];
359
+ }
360
+ scope = findScope(manifest, target.scope);
361
+ createdScope = false;
362
+ if (!(!scope && target.scope !== '_default')) return [3 /*break*/, 6];
363
+ _c.label = 1;
364
+ case 1:
365
+ _c.trys.push([1, 3, , 4]);
366
+ return [4 /*yield*/, manager.createScope(target.scope)];
367
+ case 2:
368
+ _c.sent();
369
+ createdScope = true;
370
+ return [3 /*break*/, 4];
371
+ case 3:
372
+ error_2 = _c.sent();
373
+ if (!isAlreadyExists(error_2)) {
374
+ throw provisionError('create scope', target.scope, error_2);
375
+ }
376
+ return [3 /*break*/, 4];
377
+ case 4: return [4 /*yield*/, this_1.waitForCollectionManifest(target.scope, undefined, options)];
378
+ case 5:
379
+ manifest = _c.sent();
380
+ scope = findScope(manifest, target.scope);
381
+ _c.label = 6;
382
+ case 6:
383
+ if (!scope) {
384
+ throw new Error("CouchSet could not find scope ".concat(target.scope, " after provisioning"));
385
+ }
386
+ exists = (scope.collections || []).some(function (item) { return item.name === target.collection; });
387
+ createdCollection = false;
388
+ if (!!exists) return [3 /*break*/, 10];
389
+ _c.label = 7;
390
+ case 7:
391
+ _c.trys.push([7, 9, , 10]);
392
+ return [4 /*yield*/, manager.createCollection(target.collection, target.scope, target.settings || {})];
393
+ case 8:
394
+ _c.sent();
395
+ createdCollection = true;
396
+ return [3 /*break*/, 10];
397
+ case 9:
398
+ error_3 = _c.sent();
399
+ if (!isAlreadyExists(error_3)) {
400
+ throw provisionError('create collection', "".concat(target.scope, ".").concat(target.collection), error_3);
401
+ }
402
+ return [3 /*break*/, 10];
403
+ case 10: return [4 /*yield*/, this_1.waitForCollectionManifest(target.scope, target.collection, options)];
404
+ case 11:
405
+ _c.sent();
406
+ result.push(__assign(__assign({}, target), { createdScope: createdScope, createdCollection: createdCollection }));
407
+ return [2 /*return*/];
408
+ }
409
+ });
410
+ };
411
+ this_1 = this;
412
+ _b.label = 6;
413
+ case 6:
414
+ _b.trys.push([6, 11, 12, 13]);
415
+ targets_1 = __values(targets), targets_1_1 = targets_1.next();
416
+ _b.label = 7;
417
+ case 7:
418
+ if (!!targets_1_1.done) return [3 /*break*/, 10];
419
+ target = targets_1_1.value;
420
+ return [5 /*yield**/, _loop_1(target)];
421
+ case 8:
422
+ _b.sent();
423
+ _b.label = 9;
424
+ case 9:
425
+ targets_1_1 = targets_1.next();
426
+ return [3 /*break*/, 7];
427
+ case 10: return [3 /*break*/, 13];
428
+ case 11:
429
+ e_1_1 = _b.sent();
430
+ e_1 = { error: e_1_1 };
431
+ return [3 /*break*/, 13];
432
+ case 12:
433
+ try {
434
+ if (targets_1_1 && !targets_1_1.done && (_a = targets_1.return)) _a.call(targets_1);
435
+ }
436
+ finally { if (e_1) throw e_1.error; }
437
+ return [7 /*endfinally*/];
438
+ case 13: return [2 /*return*/, result];
439
+ }
440
+ });
441
+ });
442
+ };
443
+ /** Explicit bootstrap: provisioning occurs before index creation. */
444
+ CouchsetClient.prototype.provision = function () {
445
+ return __awaiter(this, arguments, void 0, function (options) {
446
+ var definitions, collections, _a, indexes, _b;
447
+ if (options === void 0) { options = {}; }
448
+ return __generator(this, function (_c) {
449
+ switch (_c.label) {
450
+ case 0:
451
+ definitions = options.models || this.definitions();
452
+ if (!(options.collections === false)) return [3 /*break*/, 1];
453
+ _a = [];
454
+ return [3 /*break*/, 3];
455
+ case 1: return [4 /*yield*/, this.ensureCollections(__assign(__assign({}, options), { models: definitions }))];
456
+ case 2:
457
+ _a = _c.sent();
458
+ _c.label = 3;
459
+ case 3:
460
+ collections = _a;
461
+ if (!options.indexes) return [3 /*break*/, 5];
462
+ return [4 /*yield*/, this.ensureIndexes({
463
+ models: definitions,
464
+ waitForIndexes: options.waitForIndexes,
465
+ timeoutMs: options.timeoutMs,
466
+ })];
467
+ case 4:
468
+ _b = _c.sent();
469
+ return [3 /*break*/, 6];
470
+ case 5:
471
+ _b = [];
472
+ _c.label = 6;
473
+ case 6:
474
+ indexes = _b;
475
+ return [2 /*return*/, { collections: collections, indexes: indexes }];
476
+ }
477
+ });
478
+ });
479
+ };
480
+ /** Normal ensureIndexes stays create-only. It never checks, drops, or changes an existing index. */
481
+ CouchsetClient.prototype.ensureIndexes = function () {
482
+ return __awaiter(this, arguments, void 0, function (options) {
483
+ var definitions, queries, indexes, _loop_2, this_2, definitions_1, definitions_1_1, definition, e_2_1;
484
+ var e_2, _a;
485
+ if (options === void 0) { options = {}; }
486
+ return __generator(this, function (_b) {
487
+ switch (_b.label) {
488
+ case 0: return [4 /*yield*/, this.ready()];
489
+ case 1:
490
+ _b.sent();
491
+ definitions = options.models || this.definitions();
492
+ queries = [];
493
+ indexes = [];
494
+ _loop_2 = function (definition) {
495
+ var model, statements;
496
+ return __generator(this, function (_c) {
497
+ switch (_c.label) {
498
+ case 0:
499
+ model = this_2.model(definition);
500
+ return [4 /*yield*/, model.ensureIndexes({ deferred: options.deferred })];
501
+ case 1:
502
+ statements = _c.sent();
503
+ queries.push.apply(queries, __spreadArray([], __read(statements), false));
504
+ indexes.push.apply(indexes, __spreadArray([], __read((definition.indexes || []).map(function (index) { return ({
505
+ name: index.name,
506
+ target: definitionTarget(definition),
507
+ }); })), false));
508
+ return [2 /*return*/];
509
+ }
510
+ });
511
+ };
512
+ this_2 = this;
513
+ _b.label = 2;
514
+ case 2:
515
+ _b.trys.push([2, 7, 8, 9]);
516
+ definitions_1 = __values(definitions), definitions_1_1 = definitions_1.next();
517
+ _b.label = 3;
518
+ case 3:
519
+ if (!!definitions_1_1.done) return [3 /*break*/, 6];
520
+ definition = definitions_1_1.value;
521
+ return [5 /*yield**/, _loop_2(definition)];
522
+ case 4:
523
+ _b.sent();
524
+ _b.label = 5;
525
+ case 5:
526
+ definitions_1_1 = definitions_1.next();
527
+ return [3 /*break*/, 3];
528
+ case 6: return [3 /*break*/, 9];
529
+ case 7:
530
+ e_2_1 = _b.sent();
531
+ e_2 = { error: e_2_1 };
532
+ return [3 /*break*/, 9];
533
+ case 8:
534
+ try {
535
+ if (definitions_1_1 && !definitions_1_1.done && (_a = definitions_1.return)) _a.call(definitions_1);
536
+ }
537
+ finally { if (e_2) throw e_2.error; }
538
+ return [7 /*endfinally*/];
539
+ case 9:
540
+ if (!(options.waitForIndexes && indexes.length)) return [3 /*break*/, 11];
541
+ return [4 /*yield*/, this.waitForIndexes(indexes, options.timeoutMs)];
542
+ case 10:
543
+ _b.sent();
544
+ _b.label = 11;
545
+ case 11: return [2 /*return*/, queries];
546
+ }
547
+ });
548
+ });
549
+ };
550
+ /** Report missing, matching, and drifted indexes; this method has no DDL side effects. */
551
+ CouchsetClient.prototype.planIndexes = function () {
552
+ return __awaiter(this, arguments, void 0, function (options) {
553
+ var rows, items, _loop_3, this_3, _a, _b, definition;
554
+ var e_3, _c;
555
+ if (options === void 0) { options = {}; }
556
+ return __generator(this, function (_d) {
557
+ switch (_d.label) {
558
+ case 0: return [4 /*yield*/, this.ready()];
559
+ case 1:
560
+ _d.sent();
561
+ return [4 /*yield*/, this.indexCatalog()];
562
+ case 2:
563
+ rows = _d.sent();
564
+ items = [];
565
+ _loop_3 = function (definition) {
566
+ var e_4, _e;
567
+ var keyspace = this_3.keyspace(definition);
568
+ var target = definitionTarget(definition);
569
+ var _loop_4 = function (index) {
570
+ var matchingRows = rows.filter(function (row) { return indexRowMatchesTarget(row, definition); });
571
+ var desired = matchingRows.find(function (row) { return row.name === index.name; });
572
+ var replacementName = versionedIndexName(index.name, index);
573
+ var replacement = matchingRows.find(function (row) { return row.name === replacementName; });
574
+ // A previous safe rollout may have dropped the old logical name
575
+ // while retaining this deterministic replacement physical name.
576
+ if (replacement && indexMatches(replacement, index)) {
577
+ items.push({
578
+ createAs: replacementName,
579
+ definition: index,
580
+ keyspace: keyspace,
581
+ status: 'matching',
582
+ target: target,
583
+ });
584
+ return "continue";
585
+ }
586
+ if (desired && indexMatches(desired, index)) {
587
+ items.push({
588
+ createAs: index.name,
589
+ definition: index,
590
+ keyspace: keyspace,
591
+ status: 'matching',
592
+ target: target,
593
+ });
594
+ return "continue";
595
+ }
596
+ // `replaces` explicitly asks for a new physical index, even if
597
+ // the predecessor happens to have equivalent keys.
598
+ var predecessorName = index.replaces || index.name;
599
+ var predecessor = matchingRows.find(function (row) { return row.name === predecessorName; });
600
+ if (!predecessor) {
601
+ items.push({
602
+ createAs: index.name,
603
+ definition: index,
604
+ keyspace: keyspace,
605
+ status: 'create',
606
+ target: target,
607
+ });
608
+ return "continue";
609
+ }
610
+ var createAs = index.replaces ? index.name : replacementName;
611
+ items.push({
612
+ createAs: createAs,
613
+ definition: index,
614
+ keyspace: keyspace,
615
+ reason: 'Declared keys, predicate, or primary mode differs from the live index.',
616
+ replaces: predecessor.name,
617
+ status: 'replace',
618
+ target: target,
619
+ });
620
+ };
621
+ try {
622
+ for (var _f = (e_4 = void 0, __values(definition.indexes || [])), _g = _f.next(); !_g.done; _g = _f.next()) {
623
+ var index = _g.value;
624
+ _loop_4(index);
625
+ }
626
+ }
627
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
628
+ finally {
629
+ try {
630
+ if (_g && !_g.done && (_e = _f.return)) _e.call(_f);
631
+ }
632
+ finally { if (e_4) throw e_4.error; }
633
+ }
634
+ };
635
+ this_3 = this;
636
+ try {
637
+ for (_a = __values(options.models || this.definitions()), _b = _a.next(); !_b.done; _b = _a.next()) {
638
+ definition = _b.value;
639
+ _loop_3(definition);
640
+ }
641
+ }
642
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
643
+ finally {
644
+ try {
645
+ if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
646
+ }
647
+ finally { if (e_3) throw e_3.error; }
648
+ }
649
+ return [2 /*return*/, { items: items }];
650
+ }
651
+ });
652
+ });
653
+ };
654
+ /**
655
+ * Apply a reviewed plan by creating versioned replacements and waiting for
656
+ * them. Dropping old indexes is deliberately an explicit second opt-in.
657
+ */
658
+ CouchsetClient.prototype.applyIndexPlan = function (plan_1) {
659
+ return __awaiter(this, arguments, void 0, function (plan, options) {
660
+ var applied, replacements, _a, _b, item, definition, query, e_5_1, _c, _d, item, e_6_1;
661
+ var e_5, _e, e_6, _f;
662
+ if (options === void 0) { options = {}; }
663
+ return __generator(this, function (_g) {
664
+ switch (_g.label) {
665
+ case 0: return [4 /*yield*/, this.ready()];
666
+ case 1:
667
+ _g.sent();
668
+ applied = [];
669
+ replacements = [];
670
+ _g.label = 2;
671
+ case 2:
672
+ _g.trys.push([2, 7, 8, 9]);
673
+ _a = __values(plan.items), _b = _a.next();
674
+ _g.label = 3;
675
+ case 3:
676
+ if (!!_b.done) return [3 /*break*/, 6];
677
+ item = _b.value;
678
+ if (item.status === 'matching') {
679
+ return [3 /*break*/, 5];
680
+ }
681
+ definition = __assign(__assign({}, item.definition), { name: item.createAs });
682
+ query = (0, indexes_1.buildIndexQuery)(item.keyspace, definition);
683
+ return [4 /*yield*/, this.connection.cluster.query(query)];
684
+ case 4:
685
+ _g.sent();
686
+ applied.push(query);
687
+ replacements.push({ name: item.createAs, target: item.target });
688
+ _g.label = 5;
689
+ case 5:
690
+ _b = _a.next();
691
+ return [3 /*break*/, 3];
692
+ case 6: return [3 /*break*/, 9];
693
+ case 7:
694
+ e_5_1 = _g.sent();
695
+ e_5 = { error: e_5_1 };
696
+ return [3 /*break*/, 9];
697
+ case 8:
698
+ try {
699
+ if (_b && !_b.done && (_e = _a.return)) _e.call(_a);
700
+ }
701
+ finally { if (e_5) throw e_5.error; }
702
+ return [7 /*endfinally*/];
703
+ case 9:
704
+ if (!replacements.length) return [3 /*break*/, 11];
705
+ return [4 /*yield*/, this.waitForIndexes(replacements, options.timeoutMs)];
706
+ case 10:
707
+ _g.sent();
708
+ _g.label = 11;
709
+ case 11:
710
+ if (!options.dropReplaced) return [3 /*break*/, 19];
711
+ _g.label = 12;
712
+ case 12:
713
+ _g.trys.push([12, 17, 18, 19]);
714
+ _c = __values(plan.items), _d = _c.next();
715
+ _g.label = 13;
716
+ case 13:
717
+ if (!!_d.done) return [3 /*break*/, 16];
718
+ item = _d.value;
719
+ if (!(item.status === 'replace' && item.replaces)) return [3 /*break*/, 15];
720
+ return [4 /*yield*/, this.connection.cluster.query("DROP INDEX ".concat(item.keyspace, ".").concat((0, keyspace_1.escapeIdentifier)(item.replaces)))];
721
+ case 14:
722
+ _g.sent();
723
+ _g.label = 15;
724
+ case 15:
725
+ _d = _c.next();
726
+ return [3 /*break*/, 13];
727
+ case 16: return [3 /*break*/, 19];
728
+ case 17:
729
+ e_6_1 = _g.sent();
730
+ e_6 = { error: e_6_1 };
731
+ return [3 /*break*/, 19];
732
+ case 18:
733
+ try {
734
+ if (_d && !_d.done && (_f = _c.return)) _f.call(_c);
735
+ }
736
+ finally { if (e_6) throw e_6.error; }
737
+ return [7 /*endfinally*/];
738
+ case 19: return [2 /*return*/, applied];
739
+ }
740
+ });
741
+ });
742
+ };
743
+ /**
744
+ * Run the callback through Couchbase's transaction retry loop. The callback
745
+ * may execute more than once; do not perform external side effects inside it.
746
+ * A commit-ambiguous error is rethrown and must be resolved by the caller via
747
+ * an idempotency key/outbox, never by blindly retrying a side effect.
748
+ */
749
+ CouchsetClient.prototype.transaction = function (callback) {
750
+ return __awaiter(this, void 0, void 0, function () {
751
+ var result;
752
+ var _this = this;
753
+ return __generator(this, function (_a) {
754
+ switch (_a.label) {
755
+ case 0: return [4 /*yield*/, this.ready()];
756
+ case 1:
757
+ _a.sent();
758
+ return [4 /*yield*/, this.connection.cluster.transactions().run(function (attempt) { return __awaiter(_this, void 0, void 0, function () {
759
+ return __generator(this, function (_a) {
760
+ switch (_a.label) {
761
+ case 0: return [4 /*yield*/, callback(new CouchsetTransaction(this, attempt))];
762
+ case 1:
763
+ result = _a.sent();
764
+ return [2 /*return*/];
765
+ }
766
+ });
767
+ }); })];
768
+ case 2:
769
+ _a.sent();
770
+ return [2 /*return*/, result];
771
+ }
772
+ });
773
+ });
774
+ };
775
+ CouchsetClient.prototype.keyspace = function (definition) {
776
+ var target = definitionTarget(definition);
777
+ return (0, keyspace_1.keyspaceIdentifier)({
778
+ bucketName: this.settings.bucketName,
779
+ collectionName: target.collection,
780
+ scopeName: target.scope,
781
+ });
782
+ };
783
+ CouchsetClient.prototype.getConnection = function () {
784
+ return this.connection;
785
+ };
786
+ CouchsetClient.prototype.targets = function (definitions) {
787
+ var e_7, _a;
788
+ var targets = new Map();
789
+ try {
790
+ for (var _b = __values(definitions || this.definitions()), _c = _b.next(); !_c.done; _c = _b.next()) {
791
+ var definition = _c.value;
792
+ var target = definitionTarget(definition);
793
+ var identity = "".concat(target.scope, ".").concat(target.collection);
794
+ var existing = targets.get(identity);
795
+ var settings = definition.collectionSettings;
796
+ if (existing &&
797
+ JSON.stringify(existing.settings || {}) !== JSON.stringify(settings || {})) {
798
+ throw new Error("Conflicting collection settings declared for ".concat(identity, "; CouchSet will not alter an existing collection"));
799
+ }
800
+ targets.set(identity, __assign(__assign({}, target), { settings: settings }));
801
+ }
802
+ }
803
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
804
+ finally {
805
+ try {
806
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
807
+ }
808
+ finally { if (e_7) throw e_7.error; }
809
+ }
810
+ return Array.from(targets.values());
811
+ };
812
+ CouchsetClient.prototype.waitForCollectionManifest = function (scopeName, collectionName, options) {
813
+ return __awaiter(this, void 0, void 0, function () {
814
+ var manager, timeout, poll, deadline, manifest, scope, error_4;
815
+ return __generator(this, function (_a) {
816
+ switch (_a.label) {
817
+ case 0:
818
+ manager = this.connection.bucket.collections();
819
+ timeout = options.timeoutMs || 30000;
820
+ poll = options.pollIntervalMs || 100;
821
+ deadline = Date.now() + timeout;
822
+ _a.label = 1;
823
+ case 1:
824
+ if (!(Date.now() <= deadline)) return [3 /*break*/, 7];
825
+ _a.label = 2;
826
+ case 2:
827
+ _a.trys.push([2, 4, , 5]);
828
+ return [4 /*yield*/, manager.getAllScopes()];
829
+ case 3:
830
+ manifest = _a.sent();
831
+ scope = findScope(manifest, scopeName);
832
+ if (scope &&
833
+ (!collectionName ||
834
+ (scope.collections || []).some(function (item) { return item.name === collectionName; }))) {
835
+ return [2 /*return*/, manifest];
836
+ }
837
+ return [3 /*break*/, 5];
838
+ case 4:
839
+ error_4 = _a.sent();
840
+ if (!isNotFound(error_4)) {
841
+ throw provisionError('wait for collection metadata', "".concat(scopeName, ".").concat(collectionName || ''), error_4);
842
+ }
843
+ return [3 /*break*/, 5];
844
+ case 5: return [4 /*yield*/, delay(poll)];
845
+ case 6:
846
+ _a.sent();
847
+ return [3 /*break*/, 1];
848
+ case 7: throw new Error("Timed out waiting for Couchbase collection ".concat(scopeName, ".").concat(collectionName || '', " to appear in the manifest"));
849
+ }
850
+ });
851
+ });
852
+ };
853
+ CouchsetClient.prototype.waitForIndexes = function (indexes_2) {
854
+ return __awaiter(this, arguments, void 0, function (indexes, timeoutMs) {
855
+ var deadline, _loop_5, this_4, state_1;
856
+ if (timeoutMs === void 0) { timeoutMs = 30000; }
857
+ return __generator(this, function (_a) {
858
+ switch (_a.label) {
859
+ case 0:
860
+ deadline = Date.now() + timeoutMs;
861
+ _loop_5 = function () {
862
+ var rows;
863
+ return __generator(this, function (_b) {
864
+ switch (_b.label) {
865
+ case 0: return [4 /*yield*/, this_4.indexCatalog()];
866
+ case 1:
867
+ rows = _b.sent();
868
+ if (indexes.every(function (index) {
869
+ return rows.some(function (row) {
870
+ return row.name === index.name &&
871
+ String(row.state).toLowerCase() === 'online' &&
872
+ indexRowMatchesCollection(row, index.target);
873
+ });
874
+ })) {
875
+ return [2 /*return*/, { value: void 0 }];
876
+ }
877
+ return [4 /*yield*/, delay(100)];
878
+ case 2:
879
+ _b.sent();
880
+ return [2 /*return*/];
881
+ }
882
+ });
883
+ };
884
+ this_4 = this;
885
+ _a.label = 1;
886
+ case 1:
887
+ if (!(Date.now() <= deadline)) return [3 /*break*/, 3];
888
+ return [5 /*yield**/, _loop_5()];
889
+ case 2:
890
+ state_1 = _a.sent();
891
+ if (typeof state_1 === "object")
892
+ return [2 /*return*/, state_1.value];
893
+ return [3 /*break*/, 1];
894
+ case 3: throw new Error("Timed out waiting for Couchbase indexes to become online: ".concat(indexes
895
+ .map(function (index) { return index.name; })
896
+ .join(', ')));
897
+ }
898
+ });
899
+ });
900
+ };
901
+ CouchsetClient.prototype.indexCatalog = function () {
902
+ return __awaiter(this, void 0, void 0, function () {
903
+ var result;
904
+ return __generator(this, function (_a) {
905
+ switch (_a.label) {
906
+ case 0: return [4 /*yield*/, this.connection.cluster.query('SELECT name, bucket_id, keyspace_id, scope_id, collection_id, index_key, condition, is_primary, state FROM system:indexes WHERE bucket_id = $bucket OR keyspace_id = $bucket', { parameters: { bucket: this.settings.bucketName } })];
907
+ case 1:
908
+ result = _a.sent();
909
+ return [2 /*return*/, result.rows || []];
910
+ }
911
+ });
912
+ });
913
+ };
914
+ return CouchsetClient;
915
+ }());
916
+ exports.CouchsetClient = CouchsetClient;
917
+ /** A model bound strictly to a Couchbase transaction attempt. */
918
+ var TransactionModel = /** @class */ (function () {
919
+ function TransactionModel(model, attempt) {
920
+ this.model = model;
921
+ this.attempt = attempt;
922
+ }
923
+ TransactionModel.prototype.get = function (id) {
924
+ return __awaiter(this, void 0, void 0, function () {
925
+ var document_1, error_5;
926
+ return __generator(this, function (_a) {
927
+ switch (_a.label) {
928
+ case 0:
929
+ _a.trys.push([0, 2, , 3]);
930
+ return [4 /*yield*/, this.attempt.get(this.model.getCollection(), id)];
931
+ case 1:
932
+ document_1 = _a.sent();
933
+ return [2 /*return*/, { content: this.model.parse(document_1.content), document: document_1 }];
934
+ case 2:
935
+ error_5 = _a.sent();
936
+ if (isNotFound(error_5)) {
937
+ return [2 /*return*/, null];
938
+ }
939
+ throw error_5;
940
+ case 3: return [2 /*return*/];
941
+ }
942
+ });
943
+ });
944
+ };
945
+ TransactionModel.prototype.getById = function (id) {
946
+ return this.get(id);
947
+ };
948
+ TransactionModel.prototype.insert = function (id, data) {
949
+ return __awaiter(this, void 0, void 0, function () {
950
+ var stored, document;
951
+ return __generator(this, function (_a) {
952
+ switch (_a.label) {
953
+ case 0: return [4 /*yield*/, this.model.prepareInsert(__assign(__assign({}, data), { id: id }))];
954
+ case 1:
955
+ stored = _a.sent();
956
+ return [4 /*yield*/, this.attempt.insert(this.model.getCollection(), id, stored)];
957
+ case 2:
958
+ document = _a.sent();
959
+ return [2 /*return*/, {
960
+ content: this.model.parse(document.content || stored),
961
+ document: document,
962
+ }];
963
+ }
964
+ });
965
+ });
966
+ };
967
+ /** Replace requires the prior transactional read, as required by the SDK. */
968
+ TransactionModel.prototype.replace = function (document, data) {
969
+ return __awaiter(this, void 0, void 0, function () {
970
+ var stored, replacement;
971
+ return __generator(this, function (_a) {
972
+ switch (_a.label) {
973
+ case 0: return [4 /*yield*/, this.model.prepareReplace(document.content.id, data)];
974
+ case 1:
975
+ stored = _a.sent();
976
+ return [4 /*yield*/, this.attempt.replace(document.document, stored)];
977
+ case 2:
978
+ replacement = _a.sent();
979
+ return [2 /*return*/, {
980
+ content: this.model.parse(replacement.content || stored),
981
+ document: replacement,
982
+ }];
983
+ }
984
+ });
985
+ });
986
+ };
987
+ TransactionModel.prototype.replaceById = function (id, data) {
988
+ return __awaiter(this, void 0, void 0, function () {
989
+ var current;
990
+ return __generator(this, function (_a) {
991
+ switch (_a.label) {
992
+ case 0: return [4 /*yield*/, this.get(id)];
993
+ case 1:
994
+ current = _a.sent();
995
+ if (!current) {
996
+ throw new Error("Cannot replace missing transaction document ".concat(id));
997
+ }
998
+ return [2 /*return*/, this.replace(current, data)];
999
+ }
1000
+ });
1001
+ });
1002
+ };
1003
+ TransactionModel.prototype.remove = function (document) {
1004
+ return __awaiter(this, void 0, void 0, function () {
1005
+ return __generator(this, function (_a) {
1006
+ switch (_a.label) {
1007
+ case 0: return [4 /*yield*/, this.attempt.remove(document.document)];
1008
+ case 1:
1009
+ _a.sent();
1010
+ return [2 /*return*/];
1011
+ }
1012
+ });
1013
+ });
1014
+ };
1015
+ TransactionModel.prototype.query = function (statement, options) {
1016
+ return this.attempt.query(statement, options);
1017
+ };
1018
+ return TransactionModel;
1019
+ }());
1020
+ exports.TransactionModel = TransactionModel;
1021
+ var CouchsetTransaction = /** @class */ (function () {
1022
+ function CouchsetTransaction(client, attempt) {
1023
+ this.client = client;
1024
+ this.attempt = attempt;
1025
+ }
1026
+ CouchsetTransaction.prototype.model = function (definition) {
1027
+ return new TransactionModel(this.client.model(definition), this.attempt);
1028
+ };
1029
+ CouchsetTransaction.prototype.query = function (statement, options) {
1030
+ return this.attempt.query(statement, options);
1031
+ };
1032
+ return CouchsetTransaction;
1033
+ }());
1034
+ exports.CouchsetTransaction = CouchsetTransaction;
1035
+ /**
1036
+ * Creates a short-lived scoped fixture and a cleanup function. The caller must
1037
+ * invoke cleanup in after/afterEach; no normal client operation ever drops data.
1038
+ */
1039
+ var createCouchsetTestFixture = function (client, definition) { return __awaiter(void 0, void 0, void 0, function () {
1040
+ var suffix, fixtureScope, generatedScope, scoped, model;
1041
+ return __generator(this, function (_a) {
1042
+ switch (_a.label) {
1043
+ case 0:
1044
+ suffix = (0, uuid_1.generateUUID)().replace(/-/g, '').slice(0, 12);
1045
+ fixtureScope = definition.scope || "couchset_test_".concat(suffix);
1046
+ generatedScope = fixtureScope !== definition.scope;
1047
+ scoped = (0, exports.defineModel)(__assign(__assign({}, definition), { collection: definition.collection || "fixture_".concat(suffix), scope: fixtureScope }));
1048
+ return [4 /*yield*/, client.registerModel(scoped, { provision: { collections: true } })];
1049
+ case 1:
1050
+ model = _a.sent();
1051
+ return [2 /*return*/, {
1052
+ definition: scoped,
1053
+ model: model,
1054
+ cleanup: function () { return __awaiter(void 0, void 0, void 0, function () {
1055
+ var target, manager, error_6, error_7;
1056
+ return __generator(this, function (_a) {
1057
+ switch (_a.label) {
1058
+ case 0:
1059
+ target = definitionTarget(scoped);
1060
+ manager = client.getConnection().bucket.collections();
1061
+ _a.label = 1;
1062
+ case 1:
1063
+ _a.trys.push([1, 3, , 4]);
1064
+ return [4 /*yield*/, manager.dropCollection(target.collection, target.scope)];
1065
+ case 2:
1066
+ _a.sent();
1067
+ return [3 /*break*/, 4];
1068
+ case 3:
1069
+ error_6 = _a.sent();
1070
+ if (!isNotFound(error_6)) {
1071
+ throw provisionError('drop fixture collection', "".concat(target.scope, ".").concat(target.collection), error_6);
1072
+ }
1073
+ return [3 /*break*/, 4];
1074
+ case 4:
1075
+ if (!generatedScope) return [3 /*break*/, 8];
1076
+ _a.label = 5;
1077
+ case 5:
1078
+ _a.trys.push([5, 7, , 8]);
1079
+ return [4 /*yield*/, manager.dropScope(target.scope)];
1080
+ case 6:
1081
+ _a.sent();
1082
+ return [3 /*break*/, 8];
1083
+ case 7:
1084
+ error_7 = _a.sent();
1085
+ if (!isNotFound(error_7)) {
1086
+ throw provisionError('drop fixture scope', target.scope, error_7);
1087
+ }
1088
+ return [3 /*break*/, 8];
1089
+ case 8: return [2 /*return*/];
1090
+ }
1091
+ });
1092
+ }); },
1093
+ }];
1094
+ }
1095
+ });
1096
+ }); };
1097
+ exports.createCouchsetTestFixture = createCouchsetTestFixture;
1098
+ var createCouchsetClient = function (options) {
1099
+ if (options === void 0) { options = {}; }
1100
+ return new CouchsetClient(options);
1101
+ };
1102
+ exports.createCouchsetClient = createCouchsetClient;
1103
+ var definitionTarget = function (definition) { return ({
1104
+ collection: Object.prototype.hasOwnProperty.call(definition, 'collection')
1105
+ ? definition.collection || '_default'
1106
+ : '_default',
1107
+ scope: Object.prototype.hasOwnProperty.call(definition, 'scope')
1108
+ ? definition.scope || '_default'
1109
+ : '_default',
1110
+ }); };
1111
+ var modelIdentity = function (definition) {
1112
+ var target = definitionTarget(definition);
1113
+ return "".concat(target.scope, ".").concat(target.collection, ".").concat(definition.name);
1114
+ };
1115
+ var assertSameDefinition = function (left, right) {
1116
+ if (!sameValue(left, right)) {
1117
+ throw new Error("Model ".concat(modelIdentity(left), " is already registered with a different definition; create a separate client or use a new model name"));
1118
+ }
1119
+ };
1120
+ var sameValue = function (left, right) {
1121
+ if (left === right) {
1122
+ return true;
1123
+ }
1124
+ if (!left || !right || typeof left !== 'object' || typeof right !== 'object') {
1125
+ return false;
1126
+ }
1127
+ if (left instanceof Date || right instanceof Date) {
1128
+ return left instanceof Date && right instanceof Date && left.getTime() === right.getTime();
1129
+ }
1130
+ if (Array.isArray(left) || Array.isArray(right)) {
1131
+ return (Array.isArray(left) &&
1132
+ Array.isArray(right) &&
1133
+ left.length === right.length &&
1134
+ left.every(function (item, index) { return sameValue(item, right[index]); }));
1135
+ }
1136
+ var leftKeys = Object.keys(left).sort();
1137
+ var rightKeys = Object.keys(right).sort();
1138
+ return (leftKeys.length === rightKeys.length &&
1139
+ leftKeys.every(function (key, index) { return key === rightKeys[index] && sameValue(left[key], right[key]); }));
1140
+ };
1141
+ var findScope = function (scopes, name) { return scopes.find(function (scope) { return scope.name === name; }); };
1142
+ var normalize = function (value) {
1143
+ return JSON.stringify(value || '')
1144
+ .replace(/[\s`()"']/g, '')
1145
+ .toLowerCase();
1146
+ };
1147
+ var indexMatches = function (row, definition) {
1148
+ if (!!row.is_primary !== !!definition.primary) {
1149
+ return false;
1150
+ }
1151
+ if (definition.primary) {
1152
+ return true;
1153
+ }
1154
+ var expectedKeys = (definition.fields || []).map(function (field) {
1155
+ if (typeof field === 'string') {
1156
+ return field;
1157
+ }
1158
+ var key = Object.keys(field)[0];
1159
+ return "".concat(key, " ").concat(field[key]);
1160
+ });
1161
+ return (normalize(row.index_key) === normalize(expectedKeys) &&
1162
+ normalize(row.condition) === normalize(indexCondition(definition)));
1163
+ };
1164
+ /** Match Couchbase's catalogued SQL++ condition against the same SQL++ we declare. */
1165
+ var indexCondition = function (definition) {
1166
+ return (0, builders_1.buildWhereExpr)(definition.where).replace(/^\s*WHERE\s+/i, '');
1167
+ };
1168
+ var indexRowMatchesTarget = function (row, definition) {
1169
+ return indexRowMatchesCollection(row, definitionTarget(definition));
1170
+ };
1171
+ var indexRowMatchesCollection = function (row, target) {
1172
+ // On current Couchbase Server, scoped collection indexes expose the
1173
+ // collection in keyspace_id and omit collection_id. Older/default targets
1174
+ // may use keyspace_id for the bucket, so prefer collection_id when present.
1175
+ var collection = row.collection_id || (row.scope_id ? row.keyspace_id : undefined);
1176
+ return ((!row.scope_id || row.scope_id === target.scope) &&
1177
+ (!collection || collection === target.collection));
1178
+ };
1179
+ var versionedIndexName = function (name, definition) {
1180
+ var fingerprint = JSON.stringify({
1181
+ fields: definition.fields,
1182
+ primary: definition.primary,
1183
+ where: definition.where,
1184
+ })
1185
+ .split('')
1186
+ .reduce(function (hash, character) { return (hash * 31 + character.charCodeAt(0)) >>> 0; }, 7)
1187
+ .toString(36);
1188
+ return "".concat(name, "_v").concat(fingerprint);
1189
+ };
1190
+ //# sourceMappingURL=next.js.map