@eik/core 2.1.83 → 2.2.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 CHANGED
@@ -1,37 +1,16 @@
1
- ## [2.1.83](https://github.com/eik-lib/core/compare/v2.1.82...v2.1.83) (2026-08-19)
1
+ ## [2.2.1](https://github.com/eik-lib/core/compare/v2.2.0...v2.2.1) (2026-08-20)
2
2
 
3
3
 
4
4
  ### Bug Fixes
5
5
 
6
- * reduce MAX_CONCURRENT_WRITES from 16 to 8 ([#642](https://github.com/eik-lib/core/issues/642)) ([8ab90c6](https://github.com/eik-lib/core/commit/8ab90c62123ac0d2001d8e0dff5ae4d21a194531))
6
+ * **deps:** update eik packages ([#644](https://github.com/eik-lib/core/issues/644)) ([b94cddb](https://github.com/eik-lib/core/commit/b94cddb8aef95066769212a48ac51f0da86bac4f))
7
7
 
8
- ## [2.1.82](https://github.com/eik-lib/core/compare/v2.1.81...v2.1.82) (2026-08-19)
8
+ # [2.2.0](https://github.com/eik-lib/core/compare/v2.1.83...v2.2.0) (2026-08-20)
9
9
 
10
10
 
11
- ### Bug Fixes
12
-
13
- * reclassify GCS 412 errors in writeJSONWithOptions rather than via stream re-emission ([#641](https://github.com/eik-lib/core/issues/641)) ([5094866](https://github.com/eik-lib/core/commit/5094866a9f47cfd75a3252e3b9d160df6bfc442b))
14
-
15
- ## [2.1.81](https://github.com/eik-lib/core/compare/v2.1.80...v2.1.81) (2026-08-19)
16
-
17
-
18
- ### Bug Fixes
19
-
20
- * **deps:** update eik packages to v2.1.0 ([#640](https://github.com/eik-lib/core/issues/640)) ([4ee2d69](https://github.com/eik-lib/core/commit/4ee2d69491e287f5a719973c3b20cf11f9c327ad))
21
-
22
- ## [2.1.80](https://github.com/eik-lib/core/compare/v2.1.79...v2.1.80) (2026-08-19)
23
-
24
-
25
- ### Bug Fixes
26
-
27
- * **deps:** update eik packages ([#639](https://github.com/eik-lib/core/issues/639)) ([4e0aa6c](https://github.com/eik-lib/core/commit/4e0aa6caf9630a79af03dd2889392d60cf8b276f))
28
-
29
- ## [2.1.79](https://github.com/eik-lib/core/compare/v2.1.78...v2.1.79) (2026-08-19)
30
-
31
-
32
- ### Bug Fixes
11
+ ### Features
33
12
 
34
- * use atomic sink writes to prevent concurrent upload races ([#638](https://github.com/eik-lib/core/issues/638)) ([cf29a68](https://github.com/eik-lib/core/commit/cf29a6838622360f8c80bc83c86d07536d580f33)), closes [#1](https://github.com/eik-lib/core/issues/1) [#2](https://github.com/eik-lib/core/issues/2) [#3](https://github.com/eik-lib/core/issues/3) [#6](https://github.com/eik-lib/core/issues/6)
13
+ * revert to pre-atomic-write implementation ([#643](https://github.com/eik-lib/core/issues/643)) ([add3724](https://github.com/eik-lib/core/commit/add3724d2150ae24e8fe212648f9cefb30cdbe1b)), closes [#1](https://github.com/eik-lib/core/issues/1) [#2](https://github.com/eik-lib/core/issues/2) [#3](https://github.com/eik-lib/core/issues/3) [#6](https://github.com/eik-lib/core/issues/6)
35
14
 
36
15
  ## [2.1.78](https://github.com/eik-lib/core/compare/v2.1.77...v2.1.78) (2026-08-17)
37
16
 
@@ -8,7 +8,7 @@ import {
8
8
  createFilePathToAlias,
9
9
  createFilePathToAliasOrigin,
10
10
  } from "../utils/path-builders-fs.js";
11
- import { decodeUriComponent, writeJSONWithOptions } from "../utils/utils.js";
11
+ import { decodeUriComponent, writeJSON } from "../utils/utils.js";
12
12
  import { createURIToAlias } from "../utils/path-builders-uri.js";
13
13
  import MultipartParser from "../multipart/parser.js";
14
14
  import HttpIncoming from "../classes/http-incoming.js";
@@ -109,18 +109,8 @@ const AliasPut = class AliasPut {
109
109
  );
110
110
 
111
111
  try {
112
- await writeJSONWithOptions(
113
- this._sink,
114
- path,
115
- alias,
116
- "application/json",
117
- { ifNotExists: true },
118
- );
112
+ await writeJSON(this._sink, path, alias, "application/json");
119
113
  } catch (error) {
120
- const err = /** @type {any} */ (error);
121
- if (err.code === "ALREADY_EXISTS") {
122
- throw new HttpError.Conflict();
123
- }
124
114
  this._log.error(
125
115
  `alias:put - Failed writing alias to sink - Pathname: ${path}`,
126
116
  );
@@ -20,8 +20,7 @@ import {
20
20
  decodeUriComponent,
21
21
  streamCollector,
22
22
  writeJSON,
23
- writeJSONWithOptions,
24
- readJSONWithGeneration,
23
+ readJSON,
25
24
  } from "../utils/utils.js";
26
25
 
27
26
  /**
@@ -173,7 +172,7 @@ const MapPut = class MapPut {
173
172
 
174
173
  /**
175
174
  * @param {any} incoming
176
- * @returns {Promise<{ versions: InstanceType<typeof Versions>, generation: string }>}
175
+ * @returns {Promise<InstanceType<typeof Versions>>}
177
176
  */
178
177
  async _readVersions(incoming) {
179
178
  const path = createFilePathToVersion(incoming);
@@ -187,65 +186,30 @@ const MapPut = class MapPut {
187
186
  this._log.info(
188
187
  `map:put - Version meta file did not exist in sink - Create new - Pathname: ${path}`,
189
188
  );
190
- return { versions: new Versions(incoming), generation: "" };
189
+ return new Versions(incoming);
191
190
  }
192
191
 
193
192
  // File exists. Any failure here must propagate rather than be
194
193
  // swallowed — silently falling back to an empty Versions object
195
194
  // would cause _writeVersions to overwrite the index and erase the
196
195
  // entire version history.
197
- const { data, generation } = await readJSONWithGeneration(this._sink, path);
196
+ const obj = await readJSON(this._sink, path);
198
197
  this._log.info(
199
198
  `map:put - Successfully read version meta file from sink - Pathname: ${path}`,
200
199
  );
201
- return { versions: new Versions(data), generation };
200
+ return new Versions(obj);
202
201
  }
203
202
 
204
203
  /**
205
- * Writes versions.json with compare-and-swap semantics when a generation
206
- * token is available. On conflict the read-modify-write cycle is retried.
207
- *
208
204
  * @param {any} incoming
209
- * @param {InstanceType<typeof Versions>} versions
210
- * @param {string} generation
211
- * @param {string} pVersion
212
- * @param {string} integrity
205
+ * @param {any} versions
213
206
  */
214
- async _writeVersions(incoming, versions, generation, pVersion, integrity) {
207
+ async _writeVersions(incoming, versions) {
215
208
  const path = createFilePathToVersion(incoming);
216
- const maxRetries = 3;
217
- /** @type {{ ifGenerationMatch?: string | number }} */
218
- let options = generation ? { ifGenerationMatch: generation } : {};
219
- let currentVersions = versions;
220
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
221
- try {
222
- await writeJSONWithOptions(
223
- this._sink,
224
- path,
225
- currentVersions,
226
- "application/json",
227
- options,
228
- );
229
- this._log.info(
230
- `map:put - Successfully wrote version meta file to sink - Pathname: ${path}`,
231
- );
232
- return;
233
- } catch (error) {
234
- const err = /** @type {any} */ (error);
235
- if (err.code === "CONFLICT" && attempt < maxRetries) {
236
- this._log.info(
237
- `map:put - versions.json conflict on attempt ${attempt + 1}, retrying`,
238
- );
239
- const { versions: fresh, generation: newGen } =
240
- await this._readVersions(incoming);
241
- fresh.setVersion(pVersion, integrity);
242
- currentVersions = fresh;
243
- options = newGen ? { ifGenerationMatch: newGen } : {};
244
- continue;
245
- }
246
- throw error;
247
- }
248
- }
209
+ await writeJSON(this._sink, path, versions, "application/json");
210
+ this._log.info(
211
+ `map:put - Successfully wrote version meta file to sink - Pathname: ${path}`,
212
+ );
249
213
  }
250
214
 
251
215
  /**
@@ -294,13 +258,11 @@ const MapPut = class MapPut {
294
258
  org,
295
259
  });
296
260
 
297
- const { versions, generation } = await this._readVersions(incoming).catch(
298
- () => {
299
- const e = new HttpError.BadGateway();
300
- end({ labels: { success: false, status: e.status, type: "map" } });
301
- throw e;
302
- },
303
- );
261
+ const versions = await this._readVersions(incoming).catch(() => {
262
+ const e = new HttpError.BadGateway();
263
+ end({ labels: { success: false, status: e.status, type: "map" } });
264
+ throw e;
265
+ });
304
266
 
305
267
  if (!versions.check(pVersion)) {
306
268
  this._log.info(
@@ -315,13 +277,7 @@ const MapPut = class MapPut {
315
277
  versions.setVersion(pVersion, integrity);
316
278
 
317
279
  try {
318
- await this._writeVersions(
319
- incoming,
320
- versions,
321
- generation,
322
- pVersion,
323
- integrity,
324
- );
280
+ await this._writeVersions(incoming, versions);
325
281
  // eslint-disable-next-line no-unused-vars
326
282
  } catch (error) {
327
283
  const e = new HttpError.BadGateway();
@@ -13,8 +13,7 @@ import {
13
13
  import {
14
14
  decodeUriComponent,
15
15
  writeJSON,
16
- writeJSONWithOptions,
17
- readJSONWithGeneration,
16
+ readJSON,
18
17
  readEikJson,
19
18
  } from "../utils/utils.js";
20
19
  import { createURIPathToPkgLog } from "../utils/path-builders-uri.js";
@@ -130,12 +129,11 @@ const PkgPut = class PkgPut {
130
129
  type: incoming.type,
131
130
  };
132
131
  const eikJsonPath = createFilePathToEikJson(incoming);
133
- const buffer = await writeJSONWithOptions(
132
+ const buffer = await writeJSON(
134
133
  this._sink,
135
134
  eikJsonPath,
136
135
  content,
137
136
  "application/json",
138
- { ifNotExists: true },
139
137
  );
140
138
  this._log.info(
141
139
  `pkg:put - Successfully wrote eik.json to sink - Pathname: ${eikJsonPath}`,
@@ -157,7 +155,7 @@ const PkgPut = class PkgPut {
157
155
 
158
156
  /**
159
157
  * @param {any} incoming
160
- * @returns {Promise<{ versions: InstanceType<typeof Versions>, generation: string }>}
158
+ * @returns {Promise<InstanceType<typeof Versions>>}
161
159
  */
162
160
  async _readVersions(incoming) {
163
161
  const path = createFilePathToVersion(incoming);
@@ -171,18 +169,18 @@ const PkgPut = class PkgPut {
171
169
  this._log.info(
172
170
  `pkg:put - Version meta file did not exist in sink - Create new - Pathname: ${path}`,
173
171
  );
174
- return { versions: new Versions(incoming), generation: "" };
172
+ return new Versions(incoming);
175
173
  }
176
174
 
177
175
  // File exists. Any failure here (GCS error, corrupt JSON, network
178
176
  // timeout) must propagate rather than be swallowed — silently falling
179
177
  // back to an empty Versions object would cause _writeVersions to
180
178
  // overwrite the index and erase the entire version history.
181
- const { data, generation } = await readJSONWithGeneration(this._sink, path);
179
+ const obj = await readJSON(this._sink, path);
182
180
  this._log.info(
183
181
  `pkg:put - Successfully read version meta file from sink - Pathname: ${path}`,
184
182
  );
185
- return { versions: new Versions(data), generation };
183
+ return new Versions(obj);
186
184
  }
187
185
 
188
186
  /**
@@ -207,50 +205,15 @@ const PkgPut = class PkgPut {
207
205
  }
208
206
 
209
207
  /**
210
- * Writes versions.json with compare-and-swap semantics when a generation
211
- * token is available. On conflict the read-modify-write cycle is retried.
212
- *
213
208
  * @param {any} incoming
214
- * @param {InstanceType<typeof Versions>} versions
215
- * @param {string} generation
216
- * @param {string} pVersion
217
- * @param {string} integrity
209
+ * @param {any} versions
218
210
  */
219
- async _writeVersions(incoming, versions, generation, pVersion, integrity) {
211
+ async _writeVersions(incoming, versions) {
220
212
  const path = createFilePathToVersion(incoming);
221
- const maxRetries = 3;
222
- /** @type {{ ifGenerationMatch?: string | number }} */
223
- let options = generation ? { ifGenerationMatch: generation } : {};
224
- let currentVersions = versions;
225
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
226
- try {
227
- await writeJSONWithOptions(
228
- this._sink,
229
- path,
230
- currentVersions,
231
- "application/json",
232
- options,
233
- );
234
- this._log.info(
235
- `pkg:put - Successfully wrote version meta file to sink - Pathname: ${path}`,
236
- );
237
- return;
238
- } catch (error) {
239
- const err = /** @type {any} */ (error);
240
- if (err.code === "CONFLICT" && attempt < maxRetries) {
241
- this._log.info(
242
- `pkg:put - versions.json conflict on attempt ${attempt + 1}, retrying`,
243
- );
244
- const { versions: fresh, generation: newGen } =
245
- await this._readVersions(incoming);
246
- fresh.setVersion(pVersion, integrity);
247
- currentVersions = fresh;
248
- options = newGen ? { ifGenerationMatch: newGen } : {};
249
- continue;
250
- }
251
- throw error;
252
- }
253
- }
213
+ await writeJSON(this._sink, path, versions, "application/json");
214
+ this._log.info(
215
+ `pkg:put - Successfully wrote version meta file to sink - Pathname: ${path}`,
216
+ );
254
217
  }
255
218
 
256
219
  /**
@@ -312,13 +275,11 @@ const PkgPut = class PkgPut {
312
275
  throw e;
313
276
  }
314
277
 
315
- const { versions, generation } = await this._readVersions(incoming).catch(
316
- () => {
317
- const e = new HttpError.BadGateway();
318
- end({ labels: { success: false, status: e.status, type } });
319
- throw e;
320
- },
321
- );
278
+ const versions = await this._readVersions(incoming).catch(() => {
279
+ const e = new HttpError.BadGateway();
280
+ end({ labels: { success: false, status: e.status, type } });
281
+ throw e;
282
+ });
322
283
 
323
284
  const { pkg, eikJson } = await this._parser(incoming);
324
285
 
@@ -327,15 +288,8 @@ const PkgPut = class PkgPut {
327
288
  let eikJsonAsset;
328
289
  try {
329
290
  eikJsonAsset = await this._writeEikJson(incoming, eikJson);
291
+ // eslint-disable-next-line no-unused-vars
330
292
  } catch (error) {
331
- const err = /** @type {any} */ (error);
332
- if (err.code === "ALREADY_EXISTS") {
333
- // Another replica committed this version while this upload was in
334
- // flight. Treat it as a conflict identical to the early existence check.
335
- const e = new HttpError.Conflict();
336
- end({ labels: { success: false, status: e.status, type } });
337
- throw e;
338
- }
339
293
  const e = new HttpError.BadGateway();
340
294
  end({ labels: { success: false, status: e.status, type } });
341
295
  throw e;
@@ -355,14 +309,10 @@ const PkgPut = class PkgPut {
355
309
  throw e;
356
310
  }
357
311
 
312
+ versions.setVersion(pVersion, pkg.integrity);
313
+
358
314
  try {
359
- await this._writeVersions(
360
- incoming,
361
- versions,
362
- generation,
363
- pVersion,
364
- pkg.integrity,
365
- );
315
+ await this._writeVersions(incoming, versions);
366
316
  // eslint-disable-next-line no-unused-vars
367
317
  } catch (error) {
368
318
  const e = new HttpError.BadGateway();
@@ -162,9 +162,7 @@ const MultipartParser = class MultipartParser {
162
162
  // Without a cap, a tar with thousands of files would open an equal
163
163
  // number of concurrent GCS resumable uploads or filesystem write
164
164
  // streams, exhausting the connection pool or file descriptor limit.
165
- // 8 keeps the peak concurrent GCS API calls below the default
166
- // EventEmitter maxListeners threshold of 10.
167
- const MAX_CONCURRENT_WRITES = 8;
165
+ const MAX_CONCURRENT_WRITES = 16;
168
166
  let runningWrites = 0;
169
167
  /** @type {import("tar").ReadEntry[]} */
170
168
  const pendingEntries = [];
@@ -107,109 +107,9 @@ const decodeUriComponent = (value) => {
107
107
  return decodeURIComponent(value);
108
108
  };
109
109
 
110
- /**
111
- * Like readJSON but also returns the generation token from the ReadFile,
112
- * which can be passed back to writeJSONWithOptions as ifGenerationMatch
113
- * for compare-and-swap semantics.
114
- *
115
- * @param {any} sink
116
- * @param {string} path
117
- * @returns {Promise<{ data: any, generation: string }>}
118
- */
119
- const readJSONWithGeneration = (sink, path) =>
120
- // eslint-disable-next-line no-async-promise-executor
121
- new Promise(async (resolve, reject) => {
122
- try {
123
- /** @type {any[]} */
124
- const buffer = [];
125
- const from = await sink.read(path);
126
-
127
- const to = new Writable({
128
- objectMode: false,
129
- write(chunk, encoding, callback) {
130
- buffer.push(chunk);
131
- callback();
132
- },
133
- });
134
-
135
- pipeline(from.stream, to, (error) => {
136
- if (error) return reject(error);
137
- const str = Buffer.concat(buffer).toString("utf8");
138
- try {
139
- const obj = JSON.parse(str);
140
- return resolve({ data: obj, generation: from.generation ?? "" });
141
- } catch (err) {
142
- return reject(err);
143
- }
144
- });
145
- } catch (error) {
146
- reject(error);
147
- }
148
- });
149
-
150
- /**
151
- * Like writeJSON but accepts sink write options (e.g. { ifNotExists, ifGenerationMatch })
152
- * for atomic conditional writes.
153
- *
154
- * @param {any} sink
155
- * @param {string} path
156
- * @param {any} obj
157
- * @param {string} contentType
158
- * @param {{ ifNotExists?: boolean, ifGenerationMatch?: string | number }} [options]
159
- */
160
- const writeJSONWithOptions = (sink, path, obj, contentType, options = {}) =>
161
- // eslint-disable-next-line no-async-promise-executor
162
- new Promise(async (resolve, reject) => {
163
- try {
164
- const buffer = Buffer.from(JSON.stringify(obj));
165
-
166
- const from = new Readable({
167
- objectMode: false,
168
- read() {
169
- this.push(buffer);
170
- this.push(null);
171
- },
172
- });
173
-
174
- const to = await sink.write(path, contentType, options);
175
-
176
- pipeline(from, to, (error) => {
177
- if (error) {
178
- // GCS returns HTTP 412 Precondition Failed when a conditional
179
- // write constraint was not met. Reclassify using the options
180
- // that triggered the condition so callers receive a meaningful
181
- // error code rather than the raw HTTP status.
182
- const err = /** @type {any} */ (error);
183
- if (err.code === 412) {
184
- if (options.ifNotExists) {
185
- return reject(
186
- Object.assign(new Error(`File already exists: ${path}`), {
187
- code: "ALREADY_EXISTS",
188
- }),
189
- );
190
- }
191
- if (options.ifGenerationMatch !== undefined) {
192
- return reject(
193
- Object.assign(new Error(`Generation mismatch: ${path}`), {
194
- code: "CONFLICT",
195
- }),
196
- );
197
- }
198
- }
199
- return reject(error);
200
- }
201
- return resolve(buffer);
202
- });
203
- } catch (error) {
204
- reject(error);
205
- }
206
- });
207
-
208
110
  export {
209
111
  readJSON,
210
- readJSONWithGeneration,
211
112
  writeJSON,
212
- writeJSONWithOptions,
213
113
  streamCollector,
214
114
  etagFromFsStat,
215
115
  decodeUriComponent,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eik/core",
3
- "version": "2.1.83",
3
+ "version": "2.2.1",
4
4
  "description": "Core server package",
5
5
  "main": "lib/main.js",
6
6
  "types": "./types/main.d.ts",
@@ -31,8 +31,8 @@
31
31
  "dependencies": {
32
32
  "@eik/common": "5.2.0",
33
33
  "@eik/sink": "1.2.7",
34
- "@eik/sink-file-system": "2.1.0",
35
- "@eik/sink-memory": "2.1.0",
34
+ "@eik/sink-file-system": "2.2.0",
35
+ "@eik/sink-memory": "2.2.1",
36
36
  "@metrics/client": "2.5.5",
37
37
  "abslog": "2.4.4",
38
38
  "busboy": "1.6.0",
@@ -42,23 +42,14 @@ declare const MapPut: {
42
42
  }): Promise<string>;
43
43
  /**
44
44
  * @param {any} incoming
45
- * @returns {Promise<{ versions: InstanceType<typeof Versions>, generation: string }>}
45
+ * @returns {Promise<InstanceType<typeof Versions>>}
46
46
  */
47
- _readVersions(incoming: any): Promise<{
48
- versions: InstanceType<typeof Versions>;
49
- generation: string;
50
- }>;
47
+ _readVersions(incoming: any): Promise<InstanceType<typeof Versions>>;
51
48
  /**
52
- * Writes versions.json with compare-and-swap semantics when a generation
53
- * token is available. On conflict the read-modify-write cycle is retried.
54
- *
55
49
  * @param {any} incoming
56
- * @param {InstanceType<typeof Versions>} versions
57
- * @param {string} generation
58
- * @param {string} pVersion
59
- * @param {string} integrity
50
+ * @param {any} versions
60
51
  */
61
- _writeVersions(incoming: any, versions: InstanceType<typeof Versions>, generation: string, pVersion: string, integrity: string): Promise<void>;
52
+ _writeVersions(incoming: any, versions: any): Promise<void>;
62
53
  /**
63
54
  * @param {any} req
64
55
  * @param {any} user
@@ -82,27 +82,18 @@ declare const PkgPut: {
82
82
  _writeEikJson(incoming: any, capturedEikJson: Record<string, any> | null): Promise<InstanceType<typeof Asset>>;
83
83
  /**
84
84
  * @param {any} incoming
85
- * @returns {Promise<{ versions: InstanceType<typeof Versions>, generation: string }>}
85
+ * @returns {Promise<InstanceType<typeof Versions>>}
86
86
  */
87
- _readVersions(incoming: any): Promise<{
88
- versions: InstanceType<typeof Versions>;
89
- generation: string;
90
- }>;
87
+ _readVersions(incoming: any): Promise<InstanceType<typeof Versions>>;
91
88
  /**
92
89
  * @param {any} incoming
93
90
  */
94
91
  _readVersion(incoming: any): Promise<boolean>;
95
92
  /**
96
- * Writes versions.json with compare-and-swap semantics when a generation
97
- * token is available. On conflict the read-modify-write cycle is retried.
98
- *
99
93
  * @param {any} incoming
100
- * @param {InstanceType<typeof Versions>} versions
101
- * @param {string} generation
102
- * @param {string} pVersion
103
- * @param {string} integrity
94
+ * @param {any} versions
104
95
  */
105
- _writeVersions(incoming: any, versions: InstanceType<typeof Versions>, generation: string, pVersion: string, integrity: string): Promise<void>;
96
+ _writeVersions(incoming: any, versions: any): Promise<void>;
106
97
  /**
107
98
  * @param {any} req
108
99
  * @param {any} user
@@ -3,19 +3,6 @@
3
3
  * @param {string} path
4
4
  */
5
5
  export function readJSON(sink: any, path: string): Promise<any>;
6
- /**
7
- * Like readJSON but also returns the generation token from the ReadFile,
8
- * which can be passed back to writeJSONWithOptions as ifGenerationMatch
9
- * for compare-and-swap semantics.
10
- *
11
- * @param {any} sink
12
- * @param {string} path
13
- * @returns {Promise<{ data: any, generation: string }>}
14
- */
15
- export function readJSONWithGeneration(sink: any, path: string): Promise<{
16
- data: any;
17
- generation: string;
18
- }>;
19
6
  /**
20
7
  * @param {any} sink
21
8
  * @param {string} path
@@ -23,20 +10,6 @@ export function readJSONWithGeneration(sink: any, path: string): Promise<{
23
10
  * @param {string} contentType
24
11
  */
25
12
  export function writeJSON(sink: any, path: string, obj: any, contentType: string): Promise<any>;
26
- /**
27
- * Like writeJSON but accepts sink write options (e.g. { ifNotExists, ifGenerationMatch })
28
- * for atomic conditional writes.
29
- *
30
- * @param {any} sink
31
- * @param {string} path
32
- * @param {any} obj
33
- * @param {string} contentType
34
- * @param {{ ifNotExists?: boolean, ifGenerationMatch?: string | number }} [options]
35
- */
36
- export function writeJSONWithOptions(sink: any, path: string, obj: any, contentType: string, options?: {
37
- ifNotExists?: boolean;
38
- ifGenerationMatch?: string | number;
39
- }): Promise<any>;
40
13
  /**
41
14
  * @param {any} from
42
15
  */