mem-fs-editor 10.0.2 → 11.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/README.md CHANGED
@@ -104,7 +104,7 @@ Copy the `from` file and, if it is not a binary file, parse its content as an [e
104
104
 
105
105
  You can optionally pass a `templateOptions` object. `mem-fs-editor` automatically setup the filename option so you can easily use partials.
106
106
 
107
- You can also optionally pass a `copyOptions` object (see [copy() documentation for more details](#copyfrom-to-options)).
107
+ You can also optionally pass a `copyOptions` object (see [copy() documentation for more details](#copyfrom-to-options-context-templateoptions-)).
108
108
 
109
109
  Templates syntax looks like this:
110
110
 
@@ -139,14 +139,17 @@ Move/rename a file from the `from` path to the `to` path.
139
139
 
140
140
  Returns `true` if a file exists. Returns `false` if the file is not found or deleted.
141
141
 
142
- ### `#commit([filters,] [stream,] callback)`
142
+ ### `#commit([options,] [...transforms])`
143
143
 
144
- Persist every changes made to files in the mem-fs store to disk.
144
+ Pass stored files through a pipeline and persist every changes made to files in the mem-fs store to disk.
145
145
 
146
- If provided, `filters` is an array of TransformStream to be applied on a stream of vinyl files (like gulp plugins).
147
- If provided, `stream` is a stream of vinyl files.
146
+ If provided, `options` is the pipeline options.
147
+ By default only modified files are passed through the pipeline.
148
+ Pass a custom filter `options.filter` to customize files passed through the pipeline.
149
+ If provided, `...transforms` is a vararg of TransformStream to be applied on a stream of vinyl files (like gulp plugins).
150
+ `commitTransform` is appended to `transforms` and persists modified files to disk, non modified files are passed through.
148
151
 
149
- `callback` is called once the files are updated on disk.
152
+ returns promise that is resolved once the pipeline is finished.
150
153
 
151
154
  ### `#dump([cwd,] [filter])`
152
155
 
@@ -1,2 +1,2 @@
1
- import type { MemFsEditor, MemFsEditorFile } from '../index.js';
2
- export default function commitFileAsync<EditorFile extends MemFsEditorFile>(this: MemFsEditor<EditorFile>, file: EditorFile): Promise<void>;
1
+ import type { MemFsEditorFile } from '../index.js';
2
+ export default function commitFileAsync<EditorFile extends MemFsEditorFile>(file: EditorFile): Promise<void>;
@@ -1,6 +1,6 @@
1
1
  import fs from 'fs/promises';
2
2
  import path from 'path';
3
- import { clearFileState, isFileStateModified, isFileStateDeleted, setCommittedFile } from '../state.js';
3
+ import { clearFileState, isFileStateModified, isFileStateDeleted, setCommittedFile, isFileNew } from '../state.js';
4
4
  async function write(file) {
5
5
  if (!file.contents) {
6
6
  throw new Error(`${file.path} cannot write an empty file`);
@@ -34,15 +34,11 @@ async function remove(file) {
34
34
  await remove(file.path, { recursive: true });
35
35
  }
36
36
  export default async function commitFileAsync(file) {
37
- const existingFile = this.store.get(file.path);
38
- if (!existingFile || existingFile !== file) {
39
- this.store.add(file);
40
- }
41
37
  if (isFileStateModified(file)) {
42
38
  setCommittedFile(file);
43
39
  await write(file);
44
40
  }
45
- else if (isFileStateDeleted(file)) {
41
+ else if (isFileStateDeleted(file) && !isFileNew(file)) {
46
42
  setCommittedFile(file);
47
43
  await remove(file);
48
44
  }
@@ -1,6 +1,4 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- import { PipelineSource } from 'stream';
1
+ import { type FileTransform, type PipelineOptions } from 'mem-fs';
3
2
  import type { MemFsEditor, MemFsEditorFile } from '../index.js';
4
- declare function commit<EditorFile extends MemFsEditorFile>(this: MemFsEditor<EditorFile>, stream?: PipelineSource<any>): any;
5
- declare function commit<EditorFile extends MemFsEditorFile>(this: MemFsEditor<EditorFile>, filters?: any[], stream?: PipelineSource<any>): any;
3
+ declare function commit<EditorFile extends MemFsEditorFile>(this: MemFsEditor<EditorFile>, options?: PipelineOptions<EditorFile> | FileTransform<EditorFile>, ...transforms: FileTransform<EditorFile>[]): Promise<void>;
6
4
  export default commit;
@@ -1,15 +1,11 @@
1
- import { promisify } from 'util';
2
- import { pipeline as _pipeline } from 'stream';
3
- const pipeline = promisify(_pipeline);
4
- import { createPendingFilesPassthrough, createCommitTransform } from '../transform.js';
1
+ import { isFileTransform } from 'mem-fs';
2
+ import { createCommitTransform } from '../transform.js';
5
3
  import { isFilePending } from '../state.js';
6
- function commit(filters, stream) {
7
- if (!Array.isArray(filters)) {
8
- stream = filters;
9
- filters = [];
4
+ async function commit(options, ...transforms) {
5
+ if (isFileTransform(options)) {
6
+ transforms = [options, ...transforms];
7
+ options = undefined;
10
8
  }
11
- stream = stream ?? this.store.stream({ filter: (file) => isFilePending(file) });
12
- filters = filters ?? [];
13
- return pipeline(stream, createPendingFilesPassthrough(), ...filters, createCommitTransform(this));
9
+ await this.store.pipeline({ filter: isFilePending, ...options }, ...transforms, createCommitTransform());
14
10
  }
15
11
  export default commit;
@@ -0,0 +1,8 @@
1
+ import type { MemFsEditor, MemFsEditorFile } from '../index.js';
2
+ import { type PipelineOptions as MemFsPipelineOptions, type FileTransform as MemFsFileTransform } from 'mem-fs';
3
+ export type PipelineOptions<EditorFile extends MemFsEditorFile> = MemFsPipelineOptions<EditorFile> & {
4
+ pendingFiles?: boolean;
5
+ };
6
+ export type FileTransform<EditorFile extends MemFsEditorFile> = MemFsFileTransform<EditorFile>;
7
+ declare function pipeline<EditorFile extends MemFsEditorFile>(this: MemFsEditor<EditorFile>, options?: PipelineOptions<EditorFile> | FileTransform<EditorFile>, ...transforms: FileTransform<EditorFile>[]): Promise<void>;
8
+ export default pipeline;
@@ -0,0 +1,27 @@
1
+ import { isFileTransform, } from 'mem-fs';
2
+ import { isFilePending } from '../state.js';
3
+ async function pipeline(options, ...transforms) {
4
+ let storeOptions = { filter: isFilePending };
5
+ if (isFileTransform(options)) {
6
+ transforms = [options, ...transforms];
7
+ storeOptions = { filter: isFilePending };
8
+ }
9
+ else if (options) {
10
+ const { pendingFiles = true, ...pipelineOptions } = options;
11
+ if (pipelineOptions.filter) {
12
+ const optionsfilter = pipelineOptions.filter;
13
+ if (pendingFiles) {
14
+ pipelineOptions.filter = (file) => optionsfilter(file) && isFilePending(file);
15
+ }
16
+ else {
17
+ pipelineOptions.filter = optionsfilter;
18
+ }
19
+ }
20
+ else {
21
+ pipelineOptions.filter = pendingFiles ? isFilePending : undefined;
22
+ }
23
+ storeOptions = pipelineOptions;
24
+ }
25
+ await this.store.pipeline(storeOptions, ...transforms);
26
+ }
27
+ export default pipeline;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  import type { Store } from 'mem-fs';
3
3
  import type Vinyl from 'vinyl';
4
+ export type { PipelineOptions, FileTransform } from 'mem-fs';
4
5
  import read from './actions/read.js';
5
6
  import readJSON from './actions/read-json.js';
6
7
  import exists from './actions/exists.js';
@@ -16,7 +17,6 @@ import { copyAsync, _copySingleAsync } from './actions/copy-async.js';
16
17
  import copyTplAsync from './actions/copy-tpl-async.js';
17
18
  import move from './actions/move.js';
18
19
  import commit from './actions/commit.js';
19
- import commitFileAsync from './actions/commit-file-async.js';
20
20
  import dump from './actions/dump.js';
21
21
  export type { AppendOptions } from './actions/append.js';
22
22
  export type { CopyOptions } from './actions/copy.js';
@@ -58,7 +58,6 @@ export interface MemFsEditor<EditorFile extends MemFsEditorFile = VinylMemFsEdit
58
58
  copyTplAsync: typeof copyTplAsync;
59
59
  move: typeof move;
60
60
  commit: typeof commit<EditorFile>;
61
- commitFileAsync: typeof commitFileAsync<EditorFile>;
62
61
  dump: typeof dump<EditorFile>;
63
62
  }
64
63
  export declare function create(store: any): MemFsEditor<VinylMemFsEditorFile>;
package/dist/index.js CHANGED
@@ -13,8 +13,8 @@ import { copyAsync, _copySingleAsync } from './actions/copy-async.js';
13
13
  import copyTplAsync from './actions/copy-tpl-async.js';
14
14
  import move from './actions/move.js';
15
15
  import commit from './actions/commit.js';
16
- import commitFileAsync from './actions/commit-file-async.js';
17
16
  import dump from './actions/dump.js';
17
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
18
18
  export class MemFsEditor {
19
19
  store;
20
20
  constructor(store) {
@@ -39,7 +39,6 @@ MemFsEditor.prototype._copySingleAsync = _copySingleAsync;
39
39
  MemFsEditor.prototype.copyTplAsync = copyTplAsync;
40
40
  MemFsEditor.prototype.move = move;
41
41
  MemFsEditor.prototype.commit = commit;
42
- MemFsEditor.prototype.commitFileAsync = commitFileAsync;
43
42
  MemFsEditor.prototype.dump = dump;
44
43
  export function create(store) {
45
44
  return new MemFsEditor(store);
@@ -1,7 +1,4 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
- /// <reference types="node" resolution-mode="require"/>
3
- import { Transform, TransformCallback } from 'stream';
4
- import type { MemFsEditor, MemFsEditorFile } from './index.js';
5
- export declare function createTransform<EditorFile extends MemFsEditorFile = MemFsEditorFile>(transform: (file: EditorFile, encoding: BufferEncoding, cb: TransformCallback) => void): Transform;
6
- export declare const createPendingFilesPassthrough: () => Transform;
7
- export declare const createCommitTransform: <EditorFile extends MemFsEditorFile = MemFsEditorFile>(memFsEditor: MemFsEditor<EditorFile>) => Transform;
2
+ import { Duplex } from 'stream';
3
+ import type { MemFsEditorFile } from './index.js';
4
+ export declare const createCommitTransform: <EditorFile extends MemFsEditorFile = MemFsEditorFile>() => Duplex;
package/dist/transform.js CHANGED
@@ -1,20 +1,8 @@
1
- import { Transform } from 'stream';
2
- import { isFilePending } from './state.js';
3
- export function createTransform(transform) {
4
- return new Transform({
5
- objectMode: true,
6
- transform(...args) {
7
- transform.apply(this, args);
8
- },
9
- });
10
- }
11
- export const createPendingFilesPassthrough = () => createTransform((file, _enc, cb) => {
12
- // Don't process deleted file who haven't been commited yet.
13
- cb(undefined, isFilePending(file) ? file : undefined);
14
- });
15
- export const createCommitTransform = (memFsEditor) => createTransform((file, _enc, cb) => {
16
- memFsEditor
17
- .commitFileAsync(file)
18
- .then(() => cb())
19
- .catch((error) => cb(error));
1
+ import { Duplex } from 'stream';
2
+ import commitFileAsync from './actions/commit-file-async.js';
3
+ export const createCommitTransform = () => Duplex.from(async function* (generator) {
4
+ for await (const file of generator) {
5
+ await commitFileAsync(file);
6
+ yield file;
7
+ }
20
8
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mem-fs-editor",
3
- "version": "10.0.2",
3
+ "version": "11.0.0",
4
4
  "description": "File edition helpers working on top of mem-fs",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -33,34 +33,40 @@
33
33
  "dist"
34
34
  ],
35
35
  "dependencies": {
36
- "@types/ejs": "^3.1.2",
37
- "binaryextensions": "^4.16.0",
36
+ "@types/ejs": "^3.1.3",
37
+ "@types/node": "^18.18.5",
38
+ "binaryextensions": "^4.18.0",
38
39
  "commondir": "^1.0.1",
39
40
  "deep-extend": "^0.6.0",
40
41
  "ejs": "^3.1.9",
41
- "globby": "^13.1.4",
42
+ "globby": "^13.2.2",
42
43
  "isbinaryfile": "^5.0.0",
43
- "mem-fs": "^3.0.0",
44
- "minimatch": "^9.0.0",
44
+ "minimatch": "^9.0.3",
45
45
  "multimatch": "^6.0.0",
46
46
  "normalize-path": "^3.0.0",
47
- "textextensions": "^5.13.0",
47
+ "textextensions": "^5.16.0",
48
48
  "vinyl": "^3.0.0"
49
49
  },
50
+ "peerDependencies": {
51
+ "mem-fs": "^4.0.0"
52
+ },
50
53
  "devDependencies": {
51
- "coveralls": "^3.0.3",
54
+ "@typescript-eslint/eslint-plugin": "^6.7.5",
55
+ "@typescript-eslint/parser": "^6.7.5",
56
+ "@vitest/coverage-v8": "^0.34.6",
57
+ "coveralls": "^3.1.1",
52
58
  "escape-regexp": "0.0.1",
53
- "eslint": "^8.5.0",
54
- "eslint-config-prettier": "^8.3.0",
59
+ "eslint": "^8.51.0",
60
+ "eslint-config-prettier": "^9.0.0",
55
61
  "eslint-config-xo": "^0.43.1",
56
- "eslint-plugin-prettier": "^4.0.0",
57
- "mem-fs": "^3.0.0",
58
- "prettier": "^2.5.1",
59
- "sinon": "^15.0.1",
60
- "typescript": "^5.0.4",
61
- "vitest": "^0.30.1"
62
+ "eslint-plugin-prettier": "^5.0.1",
63
+ "prettier": "^3.0.3",
64
+ "prettier-plugin-packagejson": "^2.4.6",
65
+ "sinon": "^16.1.0",
66
+ "typescript": "^5.2.2",
67
+ "vitest": "^0.34.6"
62
68
  },
63
69
  "engines": {
64
- "node": ">=16.13.0"
70
+ "node": ">=18.0.0"
65
71
  }
66
72
  }