@proteinjs/db-driver-spanner 1.10.20 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/test/index.d.ts +1 -0
- package/dist/test/index.d.ts.map +1 -1
- package/dist/test/index.js +1 -0
- package/dist/test/index.js.map +1 -1
- package/dist/test/util/SpannerEmulatorProvisioner.d.ts +31 -0
- package/dist/test/util/SpannerEmulatorProvisioner.d.ts.map +1 -0
- package/dist/test/util/SpannerEmulatorProvisioner.js +128 -0
- package/dist/test/util/SpannerEmulatorProvisioner.js.map +1 -0
- package/package.json +8 -8
- package/test/index.ts +1 -0
- package/test/util/SpannerEmulatorProvisioner.ts +68 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [1.11.0](https://github.com/proteinjs/db/compare/@proteinjs/db-driver-spanner@1.10.21...@proteinjs/db-driver-spanner@1.11.0) (2026-07-23)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **spanner:** SpannerEmulatorProvisioner — shared test-harness emulator provisioning ([b9e634a](https://github.com/proteinjs/db/commit/b9e634ab74580a66e589ce277985aca21e13a518))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
## [1.10.20](https://github.com/proteinjs/db/compare/@proteinjs/db-driver-spanner@1.10.19...@proteinjs/db-driver-spanner@1.10.20) (2026-07-21)
|
|
7
18
|
|
|
8
19
|
|
package/dist/test/index.d.ts
CHANGED
package/dist/test/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../test/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../test/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,mCAAmC,CAAC"}
|
package/dist/test/index.js
CHANGED
|
@@ -15,4 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./util/getDropTestTable"), exports);
|
|
18
|
+
__exportStar(require("./util/SpannerEmulatorProvisioner"), exports);
|
|
18
19
|
//# sourceMappingURL=index.js.map
|
package/dist/test/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../test/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0DAAwC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../test/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0DAAwC;AACxC,oEAAkD"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared test-harness provisioning for the Spanner emulator.
|
|
3
|
+
*
|
|
4
|
+
* The emulator holds instances IN MEMORY — any container restart (Docker updates, host reboots,
|
|
5
|
+
* fresh CI service containers) silently wipes them, and every suite then fast-fails with a
|
|
6
|
+
* cryptic gRPC "Instance not found" until someone re-provisions by hand. Harnesses call
|
|
7
|
+
* `ensureProvisioned` in beforeAll; it is idempotent (ALREADY_EXISTS answers are success) and
|
|
8
|
+
* gated on `SPANNER_EMULATOR_HOST`, so it can never touch real GCP.
|
|
9
|
+
*
|
|
10
|
+
* Provisioning uses the ADMIN API over gRPC on the SAME address the suites' data client uses —
|
|
11
|
+
* no second endpoint to derive or configure, any docker port mapping works (the emulator's REST
|
|
12
|
+
* port doesn't even need publishing), and it shares the data client's exact fate: if the address
|
|
13
|
+
* is wrong, no suite could pass anyway.
|
|
14
|
+
*
|
|
15
|
+
* @internal This class is intended to be used only in tests. Do not use it in production code.
|
|
16
|
+
*/
|
|
17
|
+
export declare class SpannerEmulatorProvisioner {
|
|
18
|
+
/** Kept until release(): closing right after the create-operations races their trailing LRO
|
|
19
|
+
* callbacks into an unhandled "client has already been closed" that fails the suite. */
|
|
20
|
+
private static client;
|
|
21
|
+
/** Ensure the instance + database exist on the emulator. No-op without SPANNER_EMULATOR_HOST. */
|
|
22
|
+
static ensureProvisioned(config: {
|
|
23
|
+
projectId: string;
|
|
24
|
+
instanceName: string;
|
|
25
|
+
databaseName: string;
|
|
26
|
+
}): Promise<void>;
|
|
27
|
+
/** Close the admin client — call from afterAll so jest's event loop can drain. */
|
|
28
|
+
static release(): void;
|
|
29
|
+
private static swallowAlreadyExists;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=SpannerEmulatorProvisioner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SpannerEmulatorProvisioner.d.ts","sourceRoot":"","sources":["../../../test/util/SpannerEmulatorProvisioner.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,0BAA0B;IACrC;6FACyF;IACzF,OAAO,CAAC,MAAM,CAAC,MAAM,CAAsB;IAE3C,iGAAiG;WACpF,iBAAiB,CAAC,MAAM,EAAE;QACrC,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBjB,kFAAkF;IAClF,MAAM,CAAC,OAAO,IAAI,IAAI;IAQtB,OAAO,CAAC,MAAM,CAAC,oBAAoB;CAKpC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
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;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.SpannerEmulatorProvisioner = void 0;
|
|
40
|
+
var spanner_1 = require("@google-cloud/spanner");
|
|
41
|
+
/**
|
|
42
|
+
* Shared test-harness provisioning for the Spanner emulator.
|
|
43
|
+
*
|
|
44
|
+
* The emulator holds instances IN MEMORY — any container restart (Docker updates, host reboots,
|
|
45
|
+
* fresh CI service containers) silently wipes them, and every suite then fast-fails with a
|
|
46
|
+
* cryptic gRPC "Instance not found" until someone re-provisions by hand. Harnesses call
|
|
47
|
+
* `ensureProvisioned` in beforeAll; it is idempotent (ALREADY_EXISTS answers are success) and
|
|
48
|
+
* gated on `SPANNER_EMULATOR_HOST`, so it can never touch real GCP.
|
|
49
|
+
*
|
|
50
|
+
* Provisioning uses the ADMIN API over gRPC on the SAME address the suites' data client uses —
|
|
51
|
+
* no second endpoint to derive or configure, any docker port mapping works (the emulator's REST
|
|
52
|
+
* port doesn't even need publishing), and it shares the data client's exact fate: if the address
|
|
53
|
+
* is wrong, no suite could pass anyway.
|
|
54
|
+
*
|
|
55
|
+
* @internal This class is intended to be used only in tests. Do not use it in production code.
|
|
56
|
+
*/
|
|
57
|
+
var SpannerEmulatorProvisioner = /** @class */ (function () {
|
|
58
|
+
function SpannerEmulatorProvisioner() {
|
|
59
|
+
}
|
|
60
|
+
/** Ensure the instance + database exist on the emulator. No-op without SPANNER_EMULATOR_HOST. */
|
|
61
|
+
SpannerEmulatorProvisioner.ensureProvisioned = function (config) {
|
|
62
|
+
var _a;
|
|
63
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
64
|
+
var spanner, instance, _b, operation, error_1, _c, operation, error_2;
|
|
65
|
+
return __generator(this, function (_d) {
|
|
66
|
+
switch (_d.label) {
|
|
67
|
+
case 0:
|
|
68
|
+
if (!process.env.SPANNER_EMULATOR_HOST) {
|
|
69
|
+
return [2 /*return*/];
|
|
70
|
+
}
|
|
71
|
+
spanner = (_a = SpannerEmulatorProvisioner.client) !== null && _a !== void 0 ? _a : new spanner_1.Spanner({ projectId: config.projectId });
|
|
72
|
+
SpannerEmulatorProvisioner.client = spanner;
|
|
73
|
+
instance = spanner.instance(config.instanceName);
|
|
74
|
+
_d.label = 1;
|
|
75
|
+
case 1:
|
|
76
|
+
_d.trys.push([1, 4, , 5]);
|
|
77
|
+
return [4 /*yield*/, instance.create({
|
|
78
|
+
config: 'emulator-config',
|
|
79
|
+
displayName: "".concat(config.instanceName, " (test)"),
|
|
80
|
+
nodes: 1,
|
|
81
|
+
})];
|
|
82
|
+
case 2:
|
|
83
|
+
_b = _d.sent(), operation = _b[1];
|
|
84
|
+
return [4 /*yield*/, operation.promise()];
|
|
85
|
+
case 3:
|
|
86
|
+
_d.sent();
|
|
87
|
+
return [3 /*break*/, 5];
|
|
88
|
+
case 4:
|
|
89
|
+
error_1 = _d.sent();
|
|
90
|
+
SpannerEmulatorProvisioner.swallowAlreadyExists(error_1);
|
|
91
|
+
return [3 /*break*/, 5];
|
|
92
|
+
case 5:
|
|
93
|
+
_d.trys.push([5, 8, , 9]);
|
|
94
|
+
return [4 /*yield*/, instance.createDatabase(config.databaseName)];
|
|
95
|
+
case 6:
|
|
96
|
+
_c = _d.sent(), operation = _c[1];
|
|
97
|
+
return [4 /*yield*/, operation.promise()];
|
|
98
|
+
case 7:
|
|
99
|
+
_d.sent();
|
|
100
|
+
return [3 /*break*/, 9];
|
|
101
|
+
case 8:
|
|
102
|
+
error_2 = _d.sent();
|
|
103
|
+
SpannerEmulatorProvisioner.swallowAlreadyExists(error_2);
|
|
104
|
+
return [3 /*break*/, 9];
|
|
105
|
+
case 9: return [2 /*return*/];
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
/** Close the admin client — call from afterAll so jest's event loop can drain. */
|
|
111
|
+
SpannerEmulatorProvisioner.release = function () {
|
|
112
|
+
var _a;
|
|
113
|
+
try {
|
|
114
|
+
(_a = SpannerEmulatorProvisioner.client) === null || _a === void 0 ? void 0 : _a.close();
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
SpannerEmulatorProvisioner.client = undefined;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
SpannerEmulatorProvisioner.swallowAlreadyExists = function (error) {
|
|
121
|
+
if (error.code !== 6 /* gRPC ALREADY_EXISTS */) {
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
return SpannerEmulatorProvisioner;
|
|
126
|
+
}());
|
|
127
|
+
exports.SpannerEmulatorProvisioner = SpannerEmulatorProvisioner;
|
|
128
|
+
//# sourceMappingURL=SpannerEmulatorProvisioner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SpannerEmulatorProvisioner.js","sourceRoot":"","sources":["../../../test/util/SpannerEmulatorProvisioner.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iDAAgD;AAEhD;;;;;;;;;;;;;;;GAeG;AACH;IAAA;IAiDA,CAAC;IA5CC,iGAAiG;IACpF,4CAAiB,GAA9B,UAA+B,MAI9B;;;;;;;wBACC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE;4BACtC,sBAAO;yBACR;wBACK,OAAO,GAAG,MAAA,0BAA0B,CAAC,MAAM,mCAAI,IAAI,iBAAO,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;wBAClG,0BAA0B,CAAC,MAAM,GAAG,OAAO,CAAC;wBACtC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;;;;wBAE/B,qBAAM,QAAQ,CAAC,MAAM,CAAC;gCAC1C,MAAM,EAAE,iBAAiB;gCACzB,WAAW,EAAE,UAAG,MAAM,CAAC,YAAY,YAAS;gCAC5C,KAAK,EAAE,CAAC;6BACT,CAAC,EAAA;;wBAJI,KAAgB,SAIpB,EAJO,SAAS,QAAA;wBAKlB,qBAAM,SAAS,CAAC,OAAO,EAAE,EAAA;;wBAAzB,SAAyB,CAAC;;;;wBAE1B,0BAA0B,CAAC,oBAAoB,CAAC,OAAK,CAAC,CAAC;;;;wBAGjC,qBAAM,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,YAAY,CAAC,EAAA;;wBAAlE,KAAgB,SAAkD,EAA/D,SAAS,QAAA;wBAClB,qBAAM,SAAS,CAAC,OAAO,EAAE,EAAA;;wBAAzB,SAAyB,CAAC;;;;wBAE1B,0BAA0B,CAAC,oBAAoB,CAAC,OAAK,CAAC,CAAC;;;;;;KAE1D;IAED,kFAAkF;IAC3E,kCAAO,GAAd;;QACE,IAAI;YACF,MAAA,0BAA0B,CAAC,MAAM,0CAAE,KAAK,EAAE,CAAC;SAC5C;gBAAS;YACR,0BAA0B,CAAC,MAAM,GAAG,SAAS,CAAC;SAC/C;IACH,CAAC;IAEc,+CAAoB,GAAnC,UAAoC,KAAc;QAChD,IAAK,KAA2B,CAAC,IAAI,KAAK,CAAC,CAAC,yBAAyB,EAAE;YACrE,MAAM,KAAK,CAAC;SACb;IACH,CAAC;IACH,iCAAC;AAAD,CAAC,AAjDD,IAiDC;AAjDY,gEAA0B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@proteinjs/db-driver-spanner",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"main": "./dist/generated/index.js",
|
|
5
5
|
"types": "./dist/generated/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -42,16 +42,16 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@google-cloud/spanner": "7.5.0",
|
|
45
|
-
"@proteinjs/db": "^1.22.
|
|
46
|
-
"@proteinjs/db-query": "^1.4.
|
|
47
|
-
"@proteinjs/db-spanner-common": "^1.1.
|
|
48
|
-
"@proteinjs/db-transaction-context": "^0.2.
|
|
49
|
-
"@proteinjs/logger": "^1.0.
|
|
45
|
+
"@proteinjs/db": "^1.22.2",
|
|
46
|
+
"@proteinjs/db-query": "^1.4.9",
|
|
47
|
+
"@proteinjs/db-spanner-common": "^1.1.35",
|
|
48
|
+
"@proteinjs/db-transaction-context": "^0.2.34",
|
|
49
|
+
"@proteinjs/logger": "^1.0.20",
|
|
50
50
|
"@proteinjs/reflection": "^1.1.11",
|
|
51
51
|
"@proteinjs/util": "^1.6.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@proteinjs/reflection-build": "^1.4.
|
|
54
|
+
"@proteinjs/reflection-build": "^1.4.8",
|
|
55
55
|
"@types/jest": "29.5.5",
|
|
56
56
|
"@types/node": "14.0.27",
|
|
57
57
|
"@typescript-eslint/eslint-plugin": "7.8.0",
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"ts-jest": "29.1.1",
|
|
64
64
|
"typescript": "5.2.2"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "fd394c848fa43ee594de4c84c827a607cddca3db"
|
|
67
67
|
}
|
package/test/index.ts
CHANGED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Spanner } from '@google-cloud/spanner';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared test-harness provisioning for the Spanner emulator.
|
|
5
|
+
*
|
|
6
|
+
* The emulator holds instances IN MEMORY — any container restart (Docker updates, host reboots,
|
|
7
|
+
* fresh CI service containers) silently wipes them, and every suite then fast-fails with a
|
|
8
|
+
* cryptic gRPC "Instance not found" until someone re-provisions by hand. Harnesses call
|
|
9
|
+
* `ensureProvisioned` in beforeAll; it is idempotent (ALREADY_EXISTS answers are success) and
|
|
10
|
+
* gated on `SPANNER_EMULATOR_HOST`, so it can never touch real GCP.
|
|
11
|
+
*
|
|
12
|
+
* Provisioning uses the ADMIN API over gRPC on the SAME address the suites' data client uses —
|
|
13
|
+
* no second endpoint to derive or configure, any docker port mapping works (the emulator's REST
|
|
14
|
+
* port doesn't even need publishing), and it shares the data client's exact fate: if the address
|
|
15
|
+
* is wrong, no suite could pass anyway.
|
|
16
|
+
*
|
|
17
|
+
* @internal This class is intended to be used only in tests. Do not use it in production code.
|
|
18
|
+
*/
|
|
19
|
+
export class SpannerEmulatorProvisioner {
|
|
20
|
+
/** Kept until release(): closing right after the create-operations races their trailing LRO
|
|
21
|
+
* callbacks into an unhandled "client has already been closed" that fails the suite. */
|
|
22
|
+
private static client: Spanner | undefined;
|
|
23
|
+
|
|
24
|
+
/** Ensure the instance + database exist on the emulator. No-op without SPANNER_EMULATOR_HOST. */
|
|
25
|
+
static async ensureProvisioned(config: {
|
|
26
|
+
projectId: string;
|
|
27
|
+
instanceName: string;
|
|
28
|
+
databaseName: string;
|
|
29
|
+
}): Promise<void> {
|
|
30
|
+
if (!process.env.SPANNER_EMULATOR_HOST) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const spanner = SpannerEmulatorProvisioner.client ?? new Spanner({ projectId: config.projectId });
|
|
34
|
+
SpannerEmulatorProvisioner.client = spanner;
|
|
35
|
+
const instance = spanner.instance(config.instanceName);
|
|
36
|
+
try {
|
|
37
|
+
const [, operation] = await instance.create({
|
|
38
|
+
config: 'emulator-config',
|
|
39
|
+
displayName: `${config.instanceName} (test)`,
|
|
40
|
+
nodes: 1,
|
|
41
|
+
});
|
|
42
|
+
await operation.promise();
|
|
43
|
+
} catch (error) {
|
|
44
|
+
SpannerEmulatorProvisioner.swallowAlreadyExists(error);
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const [, operation] = await instance.createDatabase(config.databaseName);
|
|
48
|
+
await operation.promise();
|
|
49
|
+
} catch (error) {
|
|
50
|
+
SpannerEmulatorProvisioner.swallowAlreadyExists(error);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Close the admin client — call from afterAll so jest's event loop can drain. */
|
|
55
|
+
static release(): void {
|
|
56
|
+
try {
|
|
57
|
+
SpannerEmulatorProvisioner.client?.close();
|
|
58
|
+
} finally {
|
|
59
|
+
SpannerEmulatorProvisioner.client = undefined;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private static swallowAlreadyExists(error: unknown): void {
|
|
64
|
+
if ((error as { code?: number }).code !== 6 /* gRPC ALREADY_EXISTS */) {
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|