@adobe/helix-google-support 3.3.4 → 4.0.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 CHANGED
@@ -1,3 +1,22 @@
1
+ # [4.0.0](https://github.com/adobe/helix-google-support/compare/v3.3.5...v4.0.0) (2025-09-23)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * stop finding item author-friendly after 1000 hits ([#513](https://github.com/adobe/helix-google-support/issues/513)) ([d21c9c5](https://github.com/adobe/helix-google-support/commit/d21c9c57025f9289c52e30ec24d14515f0e0af6e))
7
+
8
+
9
+ ### BREAKING CHANGES
10
+
11
+ * flat hierarchies no longer support author-friendly search
12
+
13
+ ## [3.3.5](https://github.com/adobe/helix-google-support/compare/v3.3.4...v3.3.5) (2025-09-16)
14
+
15
+
16
+ ### Bug Fixes
17
+
18
+ * decrease log level for not found ([#512](https://github.com/adobe/helix-google-support/issues/512)) ([691b0b6](https://github.com/adobe/helix-google-support/commit/691b0b681f4af82ec9d5cc51e5133186c44cec34))
19
+
1
20
  ## [3.3.4](https://github.com/adobe/helix-google-support/compare/v3.3.3...v3.3.4) (2025-09-08)
2
21
 
3
22
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/helix-google-support",
3
- "version": "3.3.4",
3
+ "version": "4.0.0",
4
4
  "description": "Helix Google Support",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -8,7 +8,7 @@
8
8
  ".": "./src/index.js"
9
9
  },
10
10
  "scripts": {
11
- "test": "c8 mocha",
11
+ "test": "c8 mocha --spec=test/**/*.test.js",
12
12
  "lint": "eslint .",
13
13
  "semantic-release": "semantic-release",
14
14
  "semantic-release-dry": "semantic-release --dry-run --branches $CI_BRANCH",
@@ -40,12 +40,13 @@
40
40
  "lru-cache": "^11.0.2"
41
41
  },
42
42
  "devDependencies": {
43
- "@adobe/eslint-config-helix": "3.0.9",
43
+ "@adobe/eslint-config-helix": "3.0.10",
44
44
  "@adobe/helix-shared-tokencache": "1.5.0",
45
45
  "@eslint/config-helpers": "0.3.1",
46
46
  "@semantic-release/changelog": "6.0.3",
47
47
  "@semantic-release/git": "10.0.1",
48
48
  "c8": "10.1.3",
49
+ "dotenv": "17.2.2",
49
50
  "eslint": "9.4.0",
50
51
  "eslint-plugin-header": "3.1.1",
51
52
  "eslint-plugin-import": "2.32.0",
@@ -186,29 +186,23 @@ export class GoogleClient {
186
186
  }
187
187
 
188
188
  /**
189
- * @param {string} parentId
190
- * @param {string[]} pathSegments
191
- * @param {string} parentPath
192
- * @param {string} [type] optional file mimetype
193
- * @returns {Promise<DriveItemInfo[]>|null}
189
+ * Get a child item given its base name and extension in an author
190
+ * friendly way.
191
+ *
192
+ * @param {String} parentId parent id
193
+ * @param {String} basename base name
194
+ * @param {String} ext extension
195
+ * @param {String} type mime type of the child
196
+ * @returns {Object} containing item and whether more than 1000 items were found
194
197
  */
195
- async getUncachedItemsFromSegments(parentId, pathSegments, parentPath, type) {
198
+ async #fuzzyGetChild(parentId, basename, ext, type) {
196
199
  const { log, drive, googleApiOpts } = this;
197
- const name = pathSegments.shift();
198
- const [baseName, ext] = splitByExtension(name);
199
- const sanitizedName = sanitizeName(baseName);
200
-
200
+ const sanitizedName = sanitizeName(basename);
201
201
  const items = [];
202
- let mimeTypeFilter;
203
- // filter for folder if path continues
204
- if (pathSegments.length) {
205
- mimeTypeFilter = 'and mimeType = \'application/vnd.google-apps.folder\'';
206
- } else {
207
- mimeTypeFilter = type
208
- ? `and mimeType = '${type}'`
209
- : 'and mimeType != \'application/vnd.google-apps.folder\'';
210
- }
211
202
 
203
+ const mimeTypeFilter = type
204
+ ? `and mimeType = '${type}'`
205
+ : 'and mimeType != \'application/vnd.google-apps.folder\'';
212
206
  const params = {
213
207
  q: [
214
208
  `'${parentId}' in parents`,
@@ -221,37 +215,29 @@ export class GoogleClient {
221
215
  pageSize: 1000,
222
216
  };
223
217
 
224
- do {
225
- // eslint-disable-next-line no-await-in-loop
226
- const { data } = await drive.files.list(params, googleApiOpts);
227
- if (data.nextPageToken) {
228
- params.pageToken = data.nextPageToken;
229
- } else {
230
- params.pageToken = null;
218
+ const { data } = await drive.files.list(params, googleApiOpts);
219
+ log.debug(`fetched ${data.files.length} items below ${parentId}`);
220
+
221
+ // find fuzzy match
222
+ data.files.forEach((item) => {
223
+ const [itemName, itemExt] = splitByExtension(item.name);
224
+ // remember extension
225
+ // eslint-disable-next-line no-param-reassign
226
+ item.extension = itemExt;
227
+ /* c8 ignore next 4 */
228
+ if (ext && ext !== itemExt) {
229
+ // only match extension if given via relPath
230
+ return;
231
231
  }
232
- log.debug(`fetched ${data.files.length} items below ${parentId}. nextPageToken=${params.pageToken ? '****' : 'null'}`);
233
-
234
- // find fuzzy match
235
- data.files.forEach((item) => {
236
- const [itemName, itemExt] = splitByExtension(item.name);
237
- // remember extension
238
- // eslint-disable-next-line no-param-reassign
239
- item.extension = itemExt;
240
- /* c8 ignore next 4 */
241
- if (ext && ext !== itemExt) {
242
- // only match extension if given via relPath
243
- return;
244
- }
245
- const sanitizedItemName = sanitizeName(itemName);
246
- if (sanitizedItemName !== sanitizedName) {
247
- return;
248
- }
249
- // compute edit distance
250
- // eslint-disable-next-line no-param-reassign
251
- item.fuzzyDistance = editDistance(baseName, itemName);
252
- items.push(item);
253
- });
254
- } while (params.pageToken);
232
+ const sanitizedItemName = sanitizeName(itemName);
233
+ if (sanitizedItemName !== sanitizedName) {
234
+ return;
235
+ }
236
+ // compute edit distance
237
+ // eslint-disable-next-line no-param-reassign
238
+ item.fuzzyDistance = editDistance(basename, itemName);
239
+ items.push(item);
240
+ });
255
241
 
256
242
  // sort items by edit distance first and 2nd by item name
257
243
  items.sort((i0, i1) => {
@@ -264,7 +250,69 @@ export class GoogleClient {
264
250
  });
265
251
 
266
252
  const [item] = items;
253
+ return {
254
+ item,
255
+ tooManyResults: !!data.nextPageToken,
256
+ };
257
+ }
258
+
259
+ /**
260
+ * Gets a child directly by looking for its name in a parent folder.
261
+ *
262
+ * @param {String} parentId parent Id
263
+ * @param {String} name child name
264
+ * @param {String} type child mime type
265
+ * @returns {Object} item or null
266
+ */
267
+ async #getChild(parentId, name, type) {
268
+ const { drive, googleApiOpts } = this;
269
+
270
+ const mimeTypeFilter = type
271
+ ? `and mimeType = '${type}'`
272
+ : 'and mimeType != \'application/vnd.google-apps.folder\'';
273
+ const params = {
274
+ q: [
275
+ `'${parentId}' in parents`,
276
+ `and name = '${name}'`,
277
+ 'and trashed=false',
278
+ mimeTypeFilter,
279
+ ].join(' '),
280
+ fields: 'files(id, name, mimeType, modifiedTime, size)',
281
+ includeItemsFromAllDrives: true,
282
+ supportsAllDrives: true,
283
+ pageSize: 1,
284
+ };
285
+
286
+ const { data } = await drive.files.list(params, googleApiOpts);
287
+ if (data.files.length !== 1) {
288
+ return null;
289
+ }
290
+ const [item] = data.files;
291
+ const [, itemExt] = splitByExtension(item.name);
292
+ item.extension = itemExt;
293
+ return item;
294
+ }
267
295
 
296
+ /**
297
+ * @param {string} parentId
298
+ * @param {string[]} pathSegments
299
+ * @param {string} parentPath
300
+ * @param {string} [type] optional file mimetype
301
+ * @returns {Promise<DriveItemInfo[]>|null}
302
+ */
303
+ async getUncachedItemsFromSegments(parentId, pathSegments, parentPath, type) {
304
+ const name = pathSegments.shift();
305
+ const [basename, ext] = splitByExtension(name);
306
+ const sanitizedName = sanitizeName(basename);
307
+ const childType = pathSegments.length
308
+ ? 'application/vnd.google-apps.folder'
309
+ : type;
310
+
311
+ const ret = await this.#fuzzyGetChild(parentId, basename, ext, childType);
312
+ let { item } = ret;
313
+ if (!item && ret.tooManyResults) {
314
+ item = await this.#getChild(parentId, name, childType);
315
+ }
268
316
  if (!item) {
269
317
  return null;
270
318
  }
@@ -409,7 +457,7 @@ export class GoogleClient {
409
457
  } catch (e) {
410
458
  const err = processError(e);
411
459
  if (err.response && err.response.status === 404) {
412
- log.info(`unable to get items for ${fileId}. Not found`);
460
+ log.debug(`unable to get items for ${fileId}. Not found`);
413
461
  return [];
414
462
  }
415
463
  log.warn(`unable to get items for ${fileId}. ${err}`);