@_linked/server 2.7.4 → 2.8.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,5 +1,62 @@
1
1
  # @\_linked/server
2
2
 
3
+ ## 2.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#63](https://github.com/linked-fw/server/pull/63) [`10a61bb`](https://github.com/linked-fw/server/commit/10a61bb7bcd2d85c24abc108ce86ac7bdfa51472) Thanks [@flyon](https://github.com/flyon)! - `LocalFileStore` suffixes only on a real collision, and `listFiles` returns keys you can use.
8
+
9
+ **`preventDuplicates` now means what its name says.** The random `_ab12cd` suffix
10
+ was applied to _every_ save, without ever checking whether the name was taken —
11
+ so a caller never got back the key it asked for. A content-hashed bundle handed
12
+ over as `main-hwqwrAvA.css` landed as `main-hwqwrAvA_x9k2ml.css`, and the name
13
+ baked into the HTML no longer resolved. `@_linked/cli` publishes app assets with
14
+ a bare two-argument `saveFile`, so it hit exactly this.
15
+
16
+ The store now checks first and suffixes only when the name is occupied,
17
+ re-checking the suffixed name in turn. **The never-clobber guarantee is
18
+ unchanged** — a taken name still gets a fresh key, and an explicit
19
+ `preventDuplicates: false` still overwrites in place. What changes is that a free
20
+ name is left alone, which is what `S3FileStore` has always done: the two
21
+ implementations of `IFileStore` now read the flag the same way.
22
+
23
+ Minor rather than patch because stored keys change shape: a first save that used
24
+ to produce `report_312acb.pdf` now produces `report.pdf`. Anything that recorded
25
+ a returned `storedPath` keeps working; anything that _assumed_ every key carries
26
+ a suffix should re-read `storedPath`, which has always been the supported way to
27
+ learn the key.
28
+
29
+ **`listFiles` is usable for the first time.** It returned keys joined onto
30
+ `basePath` (`data/uploads/x.txt`) while every other method on the store resolves
31
+ its argument _against_ `basePath` — so feeding a result straight back into
32
+ `getFile` looked for `data/uploads/data/uploads/x.txt` and found nothing. Keys
33
+ are now relative to the base folder, matching `S3FileStore`, which strips its
34
+ bucket prefix before returning.
35
+
36
+ Two more bugs went with it: the recursive branch called `listFiles(prefix)`,
37
+ which re-read `basePath` and found the same directory again — unbounded
38
+ recursion as soon as the store held a single folder — and the `prefix` argument
39
+ was accepted and then ignored entirely. Subdirectories are now walked properly
40
+ and `prefix` filters the returned keys.
41
+
42
+ ## 2.7.5
43
+
44
+ ### Patch Changes
45
+
46
+ - [#61](https://github.com/linked-fw/server/pull/61) [`fd8a5ec`](https://github.com/linked-fw/server/commit/fd8a5ec14f14a91e03ced486582a3ffd698e0967) Thanks [@flyon](https://github.com/flyon)! - `LocalFileStore` no longer extends `Shape`.
47
+
48
+ It used nothing from `Shape`: no `this.id`, no `this.uri`, no `nodeShape`, no
49
+ Shape statics, no property decorators, and no caller anywhere treats it as a
50
+ Shape. The only inherited behaviour was `super({id})` writing an id nothing read.
51
+
52
+ Stores and datasets stopped being Shapes deliberately in core `0e8c86e`
53
+ ("datasets are not shapes"), and `Shape`'s instantiation guard is currently
54
+ deferred naming this class as the reason it had to be. This removes one of the
55
+ last obstacles to re-enabling that guard.
56
+
57
+ No API change: the constructor still accepts both the `string` and `{id}` forms,
58
+ and the class still implements `IFileStore` in full.
59
+
3
60
  ## 2.7.4
4
61
 
5
62
  ### Patch Changes
@@ -1,5 +1,4 @@
1
1
  import { FileStat, IFileStore, SaveFileOptions } from '@_linked/core/interfaces/IFileStore';
2
- import { Shape } from '@_linked/core/shapes/Shape';
3
2
  /**
4
3
  * What `saveFile` stored, and where.
5
4
  *
@@ -14,9 +13,27 @@ export interface SavedFileLocation {
14
13
  /** The public URL, the same string `saveFile` returns. */
15
14
  publicURL: string;
16
15
  }
17
- export declare class LocalFileStore extends Shape implements IFileStore {
16
+ /**
17
+ * A file store is not a Shape.
18
+ *
19
+ * This class used to `extends Shape`, but used nothing from it: no `this.id`, no
20
+ * `this.uri`, no `nodeShape`, no Shape statics, no property decorators, and no
21
+ * caller that treated it as a Shape. The only inherited behaviour was `super({id})`
22
+ * writing an id that nothing ever read.
23
+ *
24
+ * Datasets and stores stopped being Shapes deliberately (core `0e8c86e`,
25
+ * "datasets are not shapes"), and `Shape`'s instantiation guard is currently
26
+ * DEFERRED naming this very class as the reason. Dropping the inheritance removes
27
+ * one of the last obstacles to re-enabling it.
28
+ */
29
+ export declare class LocalFileStore implements IFileStore {
18
30
  private readonly basePath;
19
31
  readonly accessURL: string;
32
+ /**
33
+ * `n` names the store. It was previously also accepted as `{id}` because that is
34
+ * `Shape`'s constructor signature; both forms are still taken so existing callers
35
+ * keep working, but neither is stored as a node id any more.
36
+ */
20
37
  constructor(n: string | {
21
38
  id: string;
22
39
  }, basePath?: string);
@@ -39,11 +56,19 @@ export declare class LocalFileStore extends Shape implements IFileStore {
39
56
  */
40
57
  getFile(filePath: string): Promise<Buffer | null>;
41
58
  /**
42
- * List all files in the local filesystem, relative to the base upload folder
43
- * @param recursive Whether or not to search all subdirectories recursively
44
- * @returns A promise that resolves to a list of file paths, relative to the base upload folder
45
- * @todo Think about taking an options parameter instead of positional args
46
- * @todo Take a path parameter to list files in a subdirectory
59
+ * List every file in the store, recursively.
60
+ *
61
+ * @param prefix Only return keys starting with this string. Matched against
62
+ * the returned (relative) key, so `listFiles('images/')` selects the
63
+ * `images` folder and `listFiles('main-')` selects by file name.
64
+ * @returns Keys relative to the base folder, exactly as `getFile`,
65
+ * `fileExists`, `deleteFile` and `statFile` expect them.
66
+ *
67
+ * The keys are relative on purpose: every other method on this store resolves
68
+ * its argument *against* `basePath`, so returning `data/uploads/x.txt` here
69
+ * meant a caller who fed the result straight back into `getFile` looked for
70
+ * `data/uploads/data/uploads/x.txt`. It also matches `S3FileStore`, which
71
+ * strips the bucket prefix before returning.
47
72
  */
48
73
  listFiles(prefix?: string): Promise<string[]>;
49
74
  /**
@@ -87,10 +112,11 @@ export declare class LocalFileStore extends Shape implements IFileStore {
87
112
  * take. That is what `storedPath` is: hand it straight back to any of them.
88
113
  *
89
114
  * The key equals the `filePath` given verbatim — case included — as long as
90
- * the name needs no sanitising, already has an extension, and
91
- * `preventDuplicates` is `false`. With `preventDuplicates` left unspecified
92
- * (this store's default, kept for upload callers) a random suffix is added,
93
- * and `storedPath` is the only place that name is reported.
115
+ * the name needs no sanitising and already has an extension. With
116
+ * `preventDuplicates` left unspecified (this store's default, kept for upload
117
+ * callers) that still holds for a name nothing else occupies; only a name
118
+ * already taken gains a random suffix, and `storedPath` is the only place
119
+ * that name is reported.
94
120
  */
95
121
  saveFileWithPath(filePath: string, fileContent: Buffer, options?: SaveFileOptions | string, preventDuplicates?: boolean): Promise<SavedFileLocation>;
96
122
  /**
@@ -1,20 +1,30 @@
1
1
  import { relativeFileSystemUploadPath } from '@_linked/server-utils/utils/Upload';
2
2
  import { publicUploadPath } from '@_linked/server-utils/utils/ServerPaths';
3
3
  import { normalizeSaveFileOptions, } from '@_linked/core/interfaces/IFileStore';
4
- import { Shape } from '@_linked/core/shapes/Shape';
5
4
  import { createHash } from 'node:crypto';
6
5
  import * as fsSync from 'node:fs';
7
6
  import fs from 'node:fs/promises';
8
7
  import path from 'node:path';
9
- export class LocalFileStore extends Shape {
8
+ /**
9
+ * A file store is not a Shape.
10
+ *
11
+ * This class used to `extends Shape`, but used nothing from it: no `this.id`, no
12
+ * `this.uri`, no `nodeShape`, no Shape statics, no property decorators, and no
13
+ * caller that treated it as a Shape. The only inherited behaviour was `super({id})`
14
+ * writing an id that nothing ever read.
15
+ *
16
+ * Datasets and stores stopped being Shapes deliberately (core `0e8c86e`,
17
+ * "datasets are not shapes"), and `Shape`'s instantiation guard is currently
18
+ * DEFERRED naming this very class as the reason. Dropping the inheritance removes
19
+ * one of the last obstacles to re-enabling it.
20
+ */
21
+ export class LocalFileStore {
22
+ /**
23
+ * `n` names the store. It was previously also accepted as `{id}` because that is
24
+ * `Shape`'s constructor signature; both forms are still taken so existing callers
25
+ * keep working, but neither is stored as a node id any more.
26
+ */
10
27
  constructor(n, basePath = relativeFileSystemUploadPath) {
11
- if (typeof n === 'string') {
12
- const uri = `${process.env.DATA_ROOT}/local-filestore/${n}`;
13
- super({ id: uri });
14
- }
15
- else {
16
- super(n);
17
- }
18
28
  this.accessURL = process.env.SITE_ROOT;
19
29
  this.basePath = basePath;
20
30
  }
@@ -49,33 +59,44 @@ export class LocalFileStore extends Shape {
49
59
  return fs.readFile(fileToGet).catch(() => null);
50
60
  }
51
61
  /**
52
- * List all files in the local filesystem, relative to the base upload folder
53
- * @param recursive Whether or not to search all subdirectories recursively
54
- * @returns A promise that resolves to a list of file paths, relative to the base upload folder
55
- * @todo Think about taking an options parameter instead of positional args
56
- * @todo Take a path parameter to list files in a subdirectory
62
+ * List every file in the store, recursively.
63
+ *
64
+ * @param prefix Only return keys starting with this string. Matched against
65
+ * the returned (relative) key, so `listFiles('images/')` selects the
66
+ * `images` folder and `listFiles('main-')` selects by file name.
67
+ * @returns Keys relative to the base folder, exactly as `getFile`,
68
+ * `fileExists`, `deleteFile` and `statFile` expect them.
69
+ *
70
+ * The keys are relative on purpose: every other method on this store resolves
71
+ * its argument *against* `basePath`, so returning `data/uploads/x.txt` here
72
+ * meant a caller who fed the result straight back into `getFile` looked for
73
+ * `data/uploads/data/uploads/x.txt`. It also matches `S3FileStore`, which
74
+ * strips the bucket prefix before returning.
57
75
  */
58
76
  async listFiles(prefix) {
59
- let files = await fs.readdir(this.basePath);
60
- // if (recursive) {
61
- const allFiles = await Promise.all(files.map((file) => {
62
- const filePath = path.join(this.basePath, file);
63
- return fs
64
- .stat(filePath)
65
- .then((stat) => {
66
- if (stat.isDirectory()) {
67
- return this.listFiles(prefix).then((files) => files.map((file) => path.join(filePath, file)));
68
- }
69
- else {
70
- return [filePath];
71
- }
72
- })
73
- .catch((err) => {
77
+ const walk = async (relativeDir) => {
78
+ const absoluteDir = path.join(this.basePath, relativeDir);
79
+ let entries;
80
+ try {
81
+ entries = await fs.readdir(absoluteDir, { withFileTypes: true });
82
+ }
83
+ catch (err) {
74
84
  console.warn('Error during listFiles', err);
75
85
  return [];
76
- });
77
- }));
78
- return allFiles.flat();
86
+ }
87
+ const nested = await Promise.all(entries.map((entry) => {
88
+ // path.join('', 'x') === 'x', so the top level stays unprefixed
89
+ const key = path.join(relativeDir, entry.name);
90
+ // recurse into the subdirectory itself. This used to call
91
+ // listFiles(prefix), which re-read basePath and so found the same
92
+ // directory again -- unbounded recursion as soon as the store held
93
+ // one folder.
94
+ return entry.isDirectory() ? walk(key) : Promise.resolve([key]);
95
+ }));
96
+ return nested.flat();
97
+ };
98
+ const keys = await walk('');
99
+ return prefix ? keys.filter((key) => key.startsWith(prefix)) : keys;
79
100
  }
80
101
  /**
81
102
  * Work out the key a save will use, and the URL that key is served under.
@@ -95,7 +116,7 @@ export class LocalFileStore extends Shape {
95
116
  * Characters that are not safe in a file name are still replaced, exactly as
96
117
  * `getUploadTarget` does it — only the case is left alone.
97
118
  */
98
- resolveTarget(filePath, mimeType, suffixDuplicates) {
119
+ async resolveTarget(filePath, mimeType, suffixDuplicates) {
99
120
  // alphanumerics, dot, underscore, dash and the path separator survive; a
100
121
  // run of anything else becomes one dash. Case is deliberately preserved.
101
122
  //
@@ -114,12 +135,33 @@ export class LocalFileStore extends Shape {
114
135
  }
115
136
  const ext = sanitisedName.split('.').pop();
116
137
  const withoutExt = sanitisedName.substring(0, sanitisedName.length - (ext.length + 1));
117
- // 6 character random string to avoid clobbering an existing file,
118
- // e.g. report.pdf -> report_312acb.pdf
119
- const randomStringSuffix = suffixDuplicates
120
- ? '_' + Math.random().toString(36).substring(2, 8)
121
- : '';
122
- const storedPath = withoutExt + randomStringSuffix + '.' + ext;
138
+ // A 6 character random string avoids clobbering an existing file,
139
+ // e.g. report.pdf -> report_312acb.pdf.
140
+ //
141
+ // It is only applied when the name is actually taken. This used to be
142
+ // unconditional, which did prevent duplicates but also meant a caller never
143
+ // got back the key it asked for: a content-hashed bundle handed over as
144
+ // `main-hwqwrAvA.css` landed as `main-hwqwrAvA_x9k2ml.css`, so the name
145
+ // baked into the HTML no longer resolved. Checking first keeps the
146
+ // never-clobber guarantee -- a taken name still gets a suffix, and the
147
+ // suffixed name is itself re-checked -- while leaving free names alone.
148
+ // `S3FileStore` has always worked this way, so the two implementations of
149
+ // IFileStore now read the flag the same.
150
+ let storedPath = withoutExt + '.' + ext;
151
+ if (suffixDuplicates) {
152
+ // 36^6 is ~2 billion, so a second collision is already vanishingly
153
+ // unlikely; the cap turns a pathological case into a clear error rather
154
+ // than a spin.
155
+ const maxAttempts = 10;
156
+ let attempt = 0;
157
+ while (await this.fileExists(storedPath)) {
158
+ if (attempt++ >= maxAttempts) {
159
+ throw new Error(`Could not find a free name for '${filePath}' after ${maxAttempts} attempts`);
160
+ }
161
+ storedPath =
162
+ withoutExt + '_' + Math.random().toString(36).substring(2, 8) + '.' + ext;
163
+ }
164
+ }
123
165
  return {
124
166
  storedPath,
125
167
  publicURL: this.accessURL + publicUploadPath + '/' + storedPath,
@@ -150,19 +192,20 @@ export class LocalFileStore extends Shape {
150
192
  * take. That is what `storedPath` is: hand it straight back to any of them.
151
193
  *
152
194
  * The key equals the `filePath` given verbatim — case included — as long as
153
- * the name needs no sanitising, already has an extension, and
154
- * `preventDuplicates` is `false`. With `preventDuplicates` left unspecified
155
- * (this store's default, kept for upload callers) a random suffix is added,
156
- * and `storedPath` is the only place that name is reported.
195
+ * the name needs no sanitising and already has an extension. With
196
+ * `preventDuplicates` left unspecified (this store's default, kept for upload
197
+ * callers) that still holds for a name nothing else occupies; only a name
198
+ * already taken gains a random suffix, and `storedPath` is the only place
199
+ * that name is reported.
157
200
  */
158
201
  async saveFileWithPath(filePath, fileContent, options, preventDuplicates) {
159
202
  var _a;
160
203
  const normalized = normalizeSaveFileOptions(options, preventDuplicates);
161
204
  // Core reports an unspecified preventDuplicates as undefined, leaving the
162
- // default to each store. This one has always appended a random suffix, so
163
- // only an explicit `false` turns that off.
205
+ // default to each store. This one protects an existing file, so only an
206
+ // explicit `false` allows an overwrite.
164
207
  const suffixDuplicates = (_a = normalized.preventDuplicates) !== null && _a !== void 0 ? _a : true;
165
- const target = this.resolveTarget(filePath, normalized.mimeType, suffixDuplicates);
208
+ const target = await this.resolveTarget(filePath, normalized.mimeType, suffixDuplicates);
166
209
  // resolved against basePath, exactly like every read method does, so what
167
210
  // is written here can be read back by the same key
168
211
  const targetFilePath = path.join(this.basePath, target.storedPath);
@@ -1 +1 @@
1
- {"version":3,"file":"LocalFileStore.js","sourceRoot":"","sources":["../../../../src/shapes/filestores/LocalFileStore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LocalFileStore.js","sourceRoot":"","sources":["../../../../src/shapes/filestores/LocalFileStore.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "type": "git",
11
11
  "url": "git+https://github.com/linked-fw/server.git"
12
12
  },
13
- "version": "2.7.4",
13
+ "version": "2.8.0",
14
14
  "packageManager": "npm@11.19.1",
15
15
  "linkedPackage": true,
16
16
  "type": "module",