@frsource/frs-replace 5.0.3 → 5.1.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
@@ -245,15 +245,15 @@ const result = sync({
245
245
 
246
246
  | Rank | Library | Average latency [ms] | Difference percentage (comparing to best average latency) |
247
247
  | ---- | ----------------------------- | -------------------- | ----------------------------------------------------------------------------- |
248
- | 1 | @frsource/frs-replace (sync) | 0.45 ± 1.04% | +0.00% |
249
- | 2 | replace-in-file (sync) | 0.82 ± 1.22% | +81.91% |
250
- | 3 | @frsource/frs-replace (async) | 1.84 ± 1.29% | +306.10% |
251
- | 4 | replace-in-file (async) | 3.10 ± 1.13% | +585.08% |
248
+ | 1 | @frsource/frs-replace (sync) | 0.48 ± 1.46% | +0.00% |
249
+ | 2 | replace-in-file (sync) | 0.83 ± 1.31% | +72.00% |
250
+ | 3 | @frsource/frs-replace (async) | 1.85 ± 1.44% | +283.71% |
251
+ | 4 | replace-in-file (async) | 3.08 ± 1.25% | +540.18% |
252
252
 
253
253
  ### input & replacement as strings
254
254
 
255
255
  | Rank | Library | Average latency [ms] | Difference percentage (comparing to best average latency) |
256
256
  | ---- | ----------------------------- | -------------------- | ----------------------------------------------------------------------------- |
257
- | 1 | @frsource/frs-replace (sync) | 0.01 ± 0.26% | +0.00% |
258
- | 2 | @frsource/frs-replace (async) | 0.01 ± 0.25% | +12.08% |
259
- | 3 | replaceString | 0.18 ± 0.82% | +2152.96% |
257
+ | 1 | @frsource/frs-replace (sync) | 0.01 ± 0.27% | +0.00% |
258
+ | 2 | @frsource/frs-replace (async) | 0.01 ± 0.27% | +10.72% |
259
+ | 3 | replaceString | 0.18 ± 0.95% | +2136.12% |
package/bin/cli.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import { resolve } from 'path';
3
3
  import yargs from 'yargs/yargs';
4
4
  import { hideBin } from 'yargs/helpers';
5
- import { sync } from '../dist/index.mjs';
5
+ import sync from '../src/sync.mjs';
6
6
 
7
7
  (~process.argv.indexOf('--no-stdin')
8
8
  ? Promise.resolve()
package/package.json CHANGED
@@ -1,19 +1,16 @@
1
1
  {
2
2
  "name": "@frsource/frs-replace",
3
- "version": "5.0.3",
3
+ "version": "5.1.0",
4
4
  "description": "Simple wrapper around javascript replace with CLI usage support!",
5
5
  "bin": {
6
6
  "frs-replace": "./bin/cli.mjs"
7
7
  },
8
8
  "type": "module",
9
- "source": "src/index.ts",
10
9
  "main": "dist/index.mjs",
11
- "types": "dist/index.d.ts",
12
10
  "exports": {
13
- ".": {
14
- "types": "./dist/index.d.ts",
15
- "default": "./dist/index.mjs"
16
- },
11
+ ".": "./src/index.mjs",
12
+ "./sync": "./src/sync.mjs",
13
+ "./async": "./src/async.mjs",
17
14
  "./*": "./*.mjs"
18
15
  },
19
16
  "repository": "https://github.com/FRSOURCE/frs-replace.git",
@@ -26,7 +23,7 @@
26
23
  "homepage": "https://github.com/FRSOURCE/frs-replace#readme",
27
24
  "files": [
28
25
  "bin/cli.mjs",
29
- "dist",
26
+ "src/*.mjs",
30
27
  "package.json"
31
28
  ],
32
29
  "keywords": [
@@ -45,8 +42,7 @@
45
42
  "javascript"
46
43
  ],
47
44
  "scripts": {
48
- "start": "pnpm clean && microbundle watch",
49
- "build": "pnpm clean && microbundle src/index.ts --target node --compress -f modern",
45
+ "typecheck": "tsc --project tsconfig.json",
50
46
  "release": "semantic-release",
51
47
  "release:ci": "pnpm release --yes",
52
48
  "test": "vitest",
@@ -57,12 +53,11 @@
57
53
  "lint": "pnpm eslint && pnpm prettier",
58
54
  "fix": "pnpm eslint --fix && prettier . --write",
59
55
  "bench": "vitest bench",
60
- "test:bench": "TEST_TYPE=bench vitest",
61
- "clean": "rimraf dist"
56
+ "test:bench": "TEST_TYPE=bench vitest"
62
57
  },
63
58
  "devDependencies": {
64
- "@frsource/eslint-config": "1.32.0",
65
- "@frsource/prettier-config": "1.20.0",
59
+ "@frsource/eslint-config": "1.33.0",
60
+ "@frsource/prettier-config": "1.21.0",
66
61
  "@frsource/semantic-release-config": "^1.35.0",
67
62
  "@semantic-release/changelog": "^6.0.3",
68
63
  "@semantic-release/commit-analyzer": "^12.0.0",
@@ -78,11 +73,9 @@
78
73
  "execa": "^9.5.2",
79
74
  "globals": "^15.14.0",
80
75
  "globals-vitest": "^1.6.0",
81
- "microbundle": "^0.15.1",
82
76
  "prettier": "^3.2.5",
83
77
  "replace-in-file": "8.3.0",
84
78
  "replace-string": "4.0.0",
85
- "rimraf": "^5.0.5",
86
79
  "semantic-release": "^23.0.8",
87
80
  "tmp-promise": "3.0.3",
88
81
  "typescript": "^5.4.5",
package/src/async.mjs ADDED
@@ -0,0 +1,132 @@
1
+ import { sep, join, normalize, dirname } from 'path';
2
+ import { readFile, promises as fs } from 'fs';
3
+ import fastGlob from 'fast-glob';
4
+ import { writeError, getReplaceFn } from './utils.mjs';
5
+
6
+ /**
7
+ * @typedef {import("./types.mjs").Strategy} Strategy
8
+ * @typedef {import("./types.mjs").InputStrategyFn} InputStrategyFn
9
+ * @typedef {import("./types.mjs").OutputStrategyFn} OutputStrategyFn
10
+ * @typedef {import("./types.mjs").Args} Args
11
+ * @typedef {import("./types.mjs").FileResult} FileResult
12
+ */
13
+
14
+ /**
15
+ * @param {string} path
16
+ * @param {string} data
17
+ * @param {Parameters<typeof import('fs').writeFileSync>[2]} options
18
+ */
19
+ const write = async (path, data, options) => {
20
+ await fs.mkdir(dirname(path), { recursive: true });
21
+ await fs.writeFile(path, data, options);
22
+ };
23
+
24
+ /** @satisfies {Record<Strategy, InputStrategyFn>} */
25
+ const inputStrategyMap = {
26
+ join: async (results, outputJoinString) => [
27
+ await Promise.all(await results).then((results) => {
28
+ const len = results.length;
29
+ let result = (results[0] && results[0][1]) || '';
30
+ for (let i = 1; i < len; ++i) {
31
+ result += outputJoinString + results[i][1];
32
+ }
33
+ return ['', result];
34
+ }),
35
+ ],
36
+ flatten: async (results) =>
37
+ await Promise.all(
38
+ (await results).map(async (result) => {
39
+ result = await result;
40
+ result[0] = result[0].substring(result[0].lastIndexOf(sep));
41
+ return result;
42
+ }),
43
+ ),
44
+ 'preserve-structure': async (results) => await Promise.all(await results),
45
+ };
46
+
47
+ /** @type {OutputStrategyFn} */
48
+ const multipleFilesOutputStrategy = async (
49
+ results,
50
+ output,
51
+ outputWriteOptions,
52
+ ) =>
53
+ Promise.all(
54
+ (await results).map(async (result) => {
55
+ result[0] = join(output, result[0]);
56
+ await write(result[0], result[1], outputWriteOptions);
57
+ return result;
58
+ }),
59
+ );
60
+
61
+ /** @satisfies {Record<Strategy, OutputStrategyFn>} */
62
+ const outputStrategyMap = {
63
+ join: async (results, output, outputWriteOptions) => {
64
+ const result = (await results)[0];
65
+ await write(output, result[1], outputWriteOptions);
66
+ result[0] = output;
67
+ return [result];
68
+ },
69
+ flatten: multipleFilesOutputStrategy,
70
+ 'preserve-structure': multipleFilesOutputStrategy,
71
+ };
72
+
73
+ /** @param {Args} args */
74
+ export default async ({ strategy = 'join', needle, replacement, ...args }) => {
75
+ /** @type {Parameters<InputStrategyFn>[0]} */
76
+ let inputData;
77
+ const replaceFn = getReplaceFn(needle, replacement);
78
+
79
+ if ('content' in args && args.content !== undefined) {
80
+ inputData = [['', replaceFn(args.content)]];
81
+ } else if ('input' in args && args.input !== undefined) {
82
+ args.inputReadOptions ??= 'utf8';
83
+ /** @type {Promise<FileResult>[]} */
84
+ const replacePromises = [];
85
+
86
+ const fileStream = fastGlob.stream(args.input, args.inputGlobOptions);
87
+ fileStream.on('error', writeError);
88
+ fileStream.on('data', (path) =>
89
+ replacePromises.push(
90
+ new Promise((resolve, reject) =>
91
+ readFile(path, args.inputReadOptions, (error, data) => {
92
+ /* c8 ignore next */
93
+ if (error) return reject(error);
94
+
95
+ resolve([path, replaceFn(data.toString())]);
96
+ }),
97
+ ),
98
+ ),
99
+ );
100
+ inputData = /** @type {Promise<typeof replacePromises>} */ new Promise(
101
+ (resolve) => fileStream.once('end', () => resolve(replacePromises)),
102
+ ).catch(writeError);
103
+ } else {
104
+ writeError('at least one input source must be defined!');
105
+ }
106
+
107
+ if (!inputStrategyMap[strategy])
108
+ writeError(
109
+ 'unsupported strategy used! Possible values are: "join", "preserve-structure" or "flatten"',
110
+ );
111
+
112
+ const outputJoinString =
113
+ ('outputJoinString' in args ? args.outputJoinString : undefined) ?? '\n';
114
+
115
+ let results = await inputStrategyMap[strategy](
116
+ // @ts-expect-error: False positive from TS - this variable is assigned already
117
+ inputData,
118
+ outputJoinString,
119
+ );
120
+
121
+ if ('output' in args && args.output !== undefined) {
122
+ args.outputWriteOptions ??= 'utf8';
123
+
124
+ results = await outputStrategyMap[strategy](
125
+ results,
126
+ normalize(args.output),
127
+ args.outputWriteOptions,
128
+ );
129
+ }
130
+
131
+ return results;
132
+ };
package/src/index.mjs ADDED
@@ -0,0 +1,3 @@
1
+ export * from './types.mjs';
2
+ export { default as sync } from './sync.mjs';
3
+ export { default as async } from './async.mjs';
package/src/sync.mjs ADDED
@@ -0,0 +1,116 @@
1
+ import { sep, join, normalize, dirname } from 'path';
2
+ import { readFileSync, writeFileSync, mkdirSync } from 'fs';
3
+ import fastGlob from 'fast-glob';
4
+ import { writeError, getReplaceFn } from './utils.mjs';
5
+
6
+ /**
7
+ * @typedef {import("./types.mjs").Strategy} Strategy
8
+ * @typedef {import("./types.mjs").InputStrategyFnSync} InputStrategyFnSync
9
+ * @typedef {import("./types.mjs").OutputStrategyFnSync} OutputStrategyFnSync
10
+ * @typedef {import("./types.mjs").Args} Args
11
+ * @typedef {import("./types.mjs").FileResult} FileResult
12
+ */
13
+
14
+ /**
15
+ * @param {string} path
16
+ * @param {string} data
17
+ * @param {Parameters<typeof import('fs').writeFileSync>[2]} options
18
+ */
19
+ const writeSync = (path, data, options) => {
20
+ mkdirSync(dirname(path), { recursive: true });
21
+ writeFileSync(path, data, options);
22
+ };
23
+
24
+ /** @satisfies {Record<Strategy, InputStrategyFnSync>} */
25
+ const inputStrategyMap = {
26
+ join: (results, outputJoinString) => {
27
+ let result = results[0]?.[1] || '';
28
+ for (let i = 1; i < results.length; ++i) {
29
+ result += outputJoinString + results[i][1];
30
+ }
31
+ return [[['', result]]];
32
+ },
33
+ flatten: (results) => {
34
+ for (let i = 0; i < results.length; ++i) {
35
+ const result = results[i][0];
36
+ results[i][0] = result.substring(result.lastIndexOf(sep));
37
+ }
38
+ return [results];
39
+ },
40
+ 'preserve-structure': (...args) => args,
41
+ };
42
+
43
+ /** @type {OutputStrategyFnSync} */
44
+ const multipleFilesOutputStrategy = (results, output, outputWriteOptions) => {
45
+ for (let i = 0; i < results.length; ++i) {
46
+ const result = results[i];
47
+ result[0] = join(output, result[0]);
48
+ writeSync(result[0], result[1], outputWriteOptions);
49
+ }
50
+ return results;
51
+ };
52
+
53
+ /** @satisfies {Record<Strategy, OutputStrategyFnSync>} */
54
+ const outputStrategyMap = {
55
+ join: (results, output, outputWriteOptions) => {
56
+ writeSync(output, results[0][1], outputWriteOptions);
57
+ results[0][0] = output;
58
+ return results;
59
+ },
60
+ flatten: multipleFilesOutputStrategy,
61
+ 'preserve-structure': multipleFilesOutputStrategy,
62
+ };
63
+
64
+ /** @param {Args} args */
65
+ export default ({ strategy = 'join', needle, replacement, ...args }) => {
66
+ /** @type {FileResult[]} */
67
+ let results;
68
+ const replaceFn = getReplaceFn(needle, replacement);
69
+
70
+ if ('content' in args && args.content !== undefined) {
71
+ results = [['', replaceFn(args.content)]];
72
+ } else if ('input' in args && args.input !== undefined) {
73
+ args.inputReadOptions ??= 'utf8';
74
+ results = [];
75
+
76
+ const files = fastGlob.sync(args.input, args.inputGlobOptions);
77
+ const len = files.length;
78
+ for (let i = 0; i < len; ++i) {
79
+ const filePath = files[i];
80
+ results.push([
81
+ filePath,
82
+ replaceFn(readFileSync(filePath, args.inputReadOptions).toString()),
83
+ ]);
84
+ }
85
+ } else {
86
+ writeError(
87
+ "at least one input source must be defined! Use either 'content' or 'input' param.",
88
+ );
89
+ }
90
+
91
+ if (!inputStrategyMap[strategy])
92
+ writeError(
93
+ 'unsupported strategy used! Possible values are: "join", "preserve-structure" or "flatten"',
94
+ );
95
+
96
+ const outputJoinString =
97
+ ('outputJoinString' in args ? args.outputJoinString : undefined) ?? '\n';
98
+
99
+ [results] = inputStrategyMap[strategy](
100
+ // @ts-expect-error: False positive from TS - this variable is assigned already
101
+ results,
102
+ outputJoinString,
103
+ );
104
+
105
+ if ('output' in args && args.output !== undefined) {
106
+ args.outputWriteOptions ??= 'utf8';
107
+
108
+ results = outputStrategyMap[strategy](
109
+ results,
110
+ normalize(args.output),
111
+ args.outputWriteOptions,
112
+ );
113
+ }
114
+
115
+ return results;
116
+ };
package/src/types.mjs ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @typedef {'join' | 'flatten' | 'preserve-structure'} Strategy
3
+ * @typedef {{
4
+ * strategy?: Strategy;
5
+ * needle: string | RegExp;
6
+ * replacement: string
7
+ * }} CommonArgs
8
+ * @typedef {{
9
+ * input: Parameters<typeof import('fast-glob').sync>[0];
10
+ * inputReadOptions?: Parameters<typeof import('fs').readFileSync>[1];
11
+ * inputGlobOptions?: Parameters<typeof import('fast-glob').sync>[1];
12
+ * }
13
+ * | { content: string }
14
+ * } InputArgs
15
+ * @typedef {{
16
+ * output?: string;
17
+ * outputWriteOptions?: Parameters<typeof import('fs').writeFileSync>[2];
18
+ * outputJoinString?: string;
19
+ * }
20
+ * | object
21
+ * } OutputArgs
22
+ * @typedef {CommonArgs & InputArgs & OutputArgs} Args
23
+ * @typedef {[string, string]} FileResult
24
+ * @typedef {(
25
+ * results: FileResult[],
26
+ * outputJoinString: string,
27
+ * ) => [FileResult[]] | [FileResult[], string]
28
+ * } InputStrategyFnSync
29
+ * @typedef {(
30
+ * results: FileResult[],
31
+ * output: string,
32
+ * outputWriteOptions: Parameters<typeof import('fs').writeFileSync>[2],
33
+ * ) => FileResult[]
34
+ * } OutputStrategyFnSync
35
+ * @typedef {(
36
+ * results: Promise<Promise<FileResult>[]> | FileResult[],
37
+ * outputJoinString: string,
38
+ * ) => Promise<FileResult[]> | FileResult[]
39
+ * } InputStrategyFn
40
+ * @typedef {(
41
+ * results: Promise<FileResult[]> | FileResult[],
42
+ * output: string,
43
+ * outputWriteOptions: Parameters<typeof import('fs').writeFileSync>[2],
44
+ * ) => Promise<FileResult[]>
45
+ * } OutputStrategyFn
46
+ */
package/src/utils.mjs ADDED
@@ -0,0 +1,28 @@
1
+ /** @typedef {import("./types.mjs").Args} Args */
2
+
3
+ /** @param {string} msg */
4
+ export const writeError = (msg) => {
5
+ throw new Error(`@frsource/frs-replace :: ${msg}`);
6
+ };
7
+
8
+ /**
9
+ * @param {Args['needle']} needle
10
+ * @param {string} replacement
11
+ */
12
+ export const getReplaceFn = (needle, replacement) =>
13
+ typeof needle === 'string'
14
+ ? /** @param {string} content */ (content) => {
15
+ const needleLen = needle.length;
16
+ let result = '';
17
+ let i;
18
+ let endIndex = 0;
19
+
20
+ while ((i = content.indexOf(needle, endIndex)) !== -1) {
21
+ result += content.slice(endIndex, i) + replacement;
22
+ endIndex = i + needleLen;
23
+ }
24
+
25
+ return result + content.slice(endIndex, content.length);
26
+ }
27
+ : /** @param {string} content */ (content) =>
28
+ content.replace(needle, replacement);
package/dist/async.d.ts DELETED
@@ -1,3 +0,0 @@
1
- import type { Args, FileResult } from './types.js';
2
- declare const _default: ({ strategy, needle, replacement, ...args }: Args) => Promise<FileResult[]>;
3
- export default _default;
package/dist/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from './types.js';
2
- export { default as sync } from './sync.js';
3
- export { default as async } from './async.js';
package/dist/index.mjs DELETED
@@ -1,2 +0,0 @@
1
- import{normalize as t,sep as e,dirname as n,join as r}from"path";import{readFileSync as i,mkdirSync as o,writeFileSync as u,readFile as s,promises as a}from"fs";import l from"fast-glob";function p(t,e){if(null==t)return{};var n={};for(var r in t)if(Object.prototype.hasOwnProperty.call(t,r)){if(e.indexOf(r)>=0)continue;n[r]=t[r]}return n}const c=t=>{throw new Error(`@frsource/frs-replace :: ${t}`)},f=(t,e)=>"string"==typeof t?n=>{const r=t.length;let i,o="",u=0;for(;-1!==(i=n.indexOf(t,u));)o+=n.slice(u,i)+e,u=i+r;return o+n.slice(u,n.length)}:n=>n.replace(t,e),d=["strategy","needle","replacement"],v=(t,e,r)=>{o(n(t),{recursive:!0}),u(t,e,r)},g={join:(t,e)=>{var n;let r=(null==(n=t[0])?void 0:n[1])||"";for(let n=1;n<t.length;++n)r+=e+t[n][1];return[[["",r]]]},flatten:t=>{for(let n=0;n<t.length;++n){const r=t[n][0];t[n][0]=r.substring(r.lastIndexOf(e))}return[t]},"preserve-structure":(...t)=>t},m=(t,e,n)=>{for(let i=0;i<t.length;++i){const o=t[i];o[0]=r(e,o[0]),v(o[0],o[1],n)}return t},w={join:(t,e,n)=>(v(e,t[0][1],n),t[0][0]=e,t),flatten:m,"preserve-structure":m};var O=e=>{var n;let r,{strategy:o="join",needle:u,replacement:s}=e,a=p(e,d);const v=f(u,s);if("content"in a&&void 0!==a.content)r=[["",v(a.content)]];else if("input"in a&&void 0!==a.input){null!=a.inputReadOptions||(a.inputReadOptions="utf8"),r=[];const t=l.sync(a.input,a.inputGlobOptions),e=t.length;for(let n=0;n<e;++n){const e=t[n];r.push([e,v(i(e,a.inputReadOptions).toString())])}}else c("at least one input source must be defined! Use either 'content' or 'input' param.");g[o]||c('unsupported strategy used! Possible values are: "join", "preserve-structure" or "flatten"');const m=null!=(n="outputJoinString"in a?a.outputJoinString:void 0)?n:"\n";return[r]=g[o](r,m),"output"in a&&void 0!==a.output&&(null!=a.outputWriteOptions||(a.outputWriteOptions="utf8"),r=w[o](r,t(a.output),a.outputWriteOptions)),r};const y=["strategy","needle","replacement"],h=async(t,e,r)=>{await a.mkdir(n(t),{recursive:!0}),await a.writeFile(t,e,r)},b={join:async(t,e)=>[await Promise.all(await t).then(t=>{const n=t.length;let r=t[0]&&t[0][1]||"";for(let i=1;i<n;++i)r+=e+t[i][1];return["",r]})],flatten:async t=>await Promise.all((await t).map(async t=>((t=await t)[0]=t[0].substring(t[0].lastIndexOf(e)),t))),"preserve-structure":async t=>await Promise.all(await t)},j=async(t,e,n)=>Promise.all((await t).map(async t=>(t[0]=r(e,t[0]),await h(t[0],t[1],n),t))),P={join:async(t,e,n)=>{const r=(await t)[0];return await h(e,r[1],n),r[0]=e,[r]},flatten:j,"preserve-structure":j};var R=async e=>{var n;let r,{strategy:i="join",needle:o,replacement:u}=e,a=p(e,y);const d=f(o,u);if("content"in a&&void 0!==a.content)r=[["",d(a.content)]];else if("input"in a&&void 0!==a.input){null!=a.inputReadOptions||(a.inputReadOptions="utf8");const t=[],e=l.stream(a.input,a.inputGlobOptions);e.on("error",c),e.on("data",e=>t.push(new Promise((t,n)=>s(e,a.inputReadOptions,(r,i)=>{if(r)return n(r);t([e,d(i.toString())])})))),r=new Promise(n=>e.once("end",()=>n(t))).catch(c)}else c("at least one input source must be defined!");b[i]||c('unsupported strategy used! Possible values are: "join", "preserve-structure" or "flatten"');const v=null!=(n="outputJoinString"in a?a.outputJoinString:void 0)?n:"\n";let g=await b[i](r,v);return"output"in a&&void 0!==a.output&&(null!=a.outputWriteOptions||(a.outputWriteOptions="utf8"),g=await P[i](g,t(a.output),a.outputWriteOptions)),g};export{R as async,O as sync};
2
- //# sourceMappingURL=index.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/utils.ts","../src/sync.ts","../src/async.ts"],"sourcesContent":["import type { Args } from './types.js';\n\nexport const writeError = (msg: string) => {\n throw new Error(`@frsource/frs-replace :: ${msg}`);\n};\n\nexport const getReplaceFn = (needle: Args['needle'], replacement: string) =>\n typeof needle === 'string'\n ? (content: string) => {\n const needleLen = needle.length;\n let result = '';\n let i;\n let endIndex = 0;\n\n while ((i = content.indexOf(needle, endIndex)) !== -1) {\n result += content.slice(endIndex, i) + replacement;\n endIndex = i + needleLen;\n }\n\n return result + content.slice(endIndex, content.length);\n }\n : (content: string) => content.replace(needle, replacement);\n","import { sep, join, normalize, dirname } from 'path';\nimport { readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport fastGlob from 'fast-glob';\nimport { writeError, getReplaceFn } from './utils.js';\nimport type {\n Strategy,\n InputStrategyFnSync,\n OutputStrategyFnSync,\n Args,\n FileResult,\n} from './types.js';\n\nconst writeSync = (\n path: string,\n data: string,\n options: Parameters<typeof writeFileSync>[2],\n) => {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, data, options);\n};\n\nconst inputStrategyMap = {\n join: (results, outputJoinString) => {\n let result = results[0]?.[1] || '';\n for (let i = 1; i < results.length; ++i) {\n result += outputJoinString + results[i][1];\n }\n return [[['', result]]];\n },\n flatten: (results) => {\n for (let i = 0; i < results.length; ++i) {\n const result = results[i][0];\n results[i][0] = result.substring(result.lastIndexOf(sep));\n }\n return [results];\n },\n 'preserve-structure': (...args) => args,\n} satisfies Record<Strategy, InputStrategyFnSync>;\n\nconst multipleFilesOutputStrategy: OutputStrategyFnSync = (\n results,\n output,\n outputWriteOptions,\n) => {\n for (let i = 0; i < results.length; ++i) {\n const result = results[i];\n result[0] = join(output, result[0]);\n writeSync(result[0], result[1], outputWriteOptions);\n }\n return results;\n};\n\nconst outputStrategyMap = {\n join: (results, output, outputWriteOptions) => {\n writeSync(output, results[0][1], outputWriteOptions);\n results[0][0] = output;\n return results;\n },\n flatten: multipleFilesOutputStrategy,\n 'preserve-structure': multipleFilesOutputStrategy,\n} satisfies Record<Strategy, OutputStrategyFnSync>;\n\nexport default ({ strategy = 'join', needle, replacement, ...args }: Args) => {\n let results: FileResult[];\n const replaceFn = getReplaceFn(needle, replacement);\n\n if ('content' in args && args.content !== undefined) {\n results = [['', replaceFn(args.content)]];\n } else if ('input' in args && args.input !== undefined) {\n args.inputReadOptions ??= 'utf8';\n results = [];\n\n const files = fastGlob.sync(args.input, args.inputGlobOptions);\n const len = files.length;\n for (let i = 0; i < len; ++i) {\n const filePath = files[i];\n results.push([\n filePath,\n replaceFn(readFileSync(filePath, args.inputReadOptions).toString()),\n ]);\n }\n } else {\n writeError(\n \"at least one input source must be defined! Use either 'content' or 'input' param.\",\n );\n }\n\n if (!inputStrategyMap[strategy])\n writeError(\n 'unsupported strategy used! Possible values are: \"join\", \"preserve-structure\" or \"flatten\"',\n );\n\n const outputJoinString =\n ('outputJoinString' in args ? args.outputJoinString : undefined) ?? '\\n';\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n [results] = inputStrategyMap[strategy](results!, outputJoinString);\n\n if ('output' in args && args.output !== undefined) {\n args.outputWriteOptions ??= 'utf8';\n\n results = outputStrategyMap[strategy](\n results,\n normalize(args.output),\n args.outputWriteOptions,\n );\n }\n\n return results;\n};\n","import { sep, join, normalize, dirname } from 'path';\nimport { readFile, promises as fs } from 'fs';\nimport fastGlob from 'fast-glob';\nimport { writeError, getReplaceFn } from './utils.js';\nimport type {\n Strategy,\n InputStrategyFn,\n OutputStrategyFn,\n Args,\n FileResult,\n} from './types.js';\n\nconst write = async (\n path: string,\n data: string,\n options: Parameters<(typeof fs)['writeFile']>[2],\n) => {\n await fs.mkdir(dirname(path), { recursive: true });\n await fs.writeFile(path, data, options);\n};\n\nconst inputStrategyMap = {\n join: async (results, outputJoinString) => [\n await Promise.all(await results).then((results) => {\n const len = results.length;\n let result = (results[0] && results[0][1]) || '';\n for (let i = 1; i < len; ++i) {\n result += outputJoinString + results[i][1];\n }\n return ['', result];\n }),\n ],\n flatten: async (results) =>\n await Promise.all(\n (await results).map(async (result) => {\n result = await result;\n result[0] = result[0].substring(result[0].lastIndexOf(sep));\n return result;\n }),\n ),\n 'preserve-structure': async (results) => await Promise.all(await results),\n} satisfies Record<Strategy, InputStrategyFn>;\n\nconst multipleFilesOutputStrategy: OutputStrategyFn = async (\n results,\n output,\n outputWriteOptions,\n) =>\n Promise.all(\n (await results).map(async (result) => {\n result[0] = join(output, result[0]);\n await write(result[0], result[1], outputWriteOptions);\n return result;\n }),\n );\n\nconst outputStrategyMap = {\n join: async (results, output, outputWriteOptions) => {\n const result = (await results)[0];\n await write(output, result[1], outputWriteOptions);\n result[0] = output;\n return [result];\n },\n flatten: multipleFilesOutputStrategy,\n 'preserve-structure': multipleFilesOutputStrategy,\n} satisfies Record<Strategy, OutputStrategyFn>;\n\nexport default async ({\n strategy = 'join',\n needle,\n replacement,\n ...args\n}: Args) => {\n let inputData: Parameters<InputStrategyFn>[0];\n const replaceFn = getReplaceFn(needle, replacement);\n\n if ('content' in args && args.content !== undefined) {\n inputData = [['', replaceFn(args.content)]];\n } else if ('input' in args && args.input !== undefined) {\n args.inputReadOptions ??= 'utf8';\n const replacePromises: Promise<FileResult>[] = [];\n\n const fileStream = fastGlob.stream(args.input, args.inputGlobOptions);\n fileStream.on('error', writeError);\n fileStream.on('data', (path) =>\n replacePromises.push(\n new Promise((resolve, reject) =>\n readFile(path, args.inputReadOptions, (error, data) => {\n /* c8 ignore next */\n if (error) return reject(error);\n\n resolve([path, replaceFn(data.toString())]);\n }),\n ),\n ),\n );\n inputData = new Promise<typeof replacePromises>((resolve) =>\n fileStream.once('end', () => resolve(replacePromises)),\n ).catch(writeError);\n } else {\n writeError('at least one input source must be defined!');\n }\n\n if (!inputStrategyMap[strategy])\n writeError(\n 'unsupported strategy used! Possible values are: \"join\", \"preserve-structure\" or \"flatten\"',\n );\n\n const outputJoinString =\n ('outputJoinString' in args ? args.outputJoinString : undefined) ?? '\\n';\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n let results = await inputStrategyMap[strategy](inputData!, outputJoinString);\n\n if ('output' in args && args.output !== undefined) {\n args.outputWriteOptions ??= 'utf8';\n\n results = await outputStrategyMap[strategy](\n results,\n normalize(args.output),\n args.outputWriteOptions,\n );\n }\n\n return results;\n};\n"],"names":["writeError","msg","Error","getReplaceFn","needle","replacement","content","needleLen","length","i","result","endIndex","indexOf","slice","replace","_excluded","writeSync","path","data","options","mkdirSync","dirname","recursive","writeFileSync","inputStrategyMap","join","results","outputJoinString","_results$","flatten","substring","lastIndexOf","sep","preserve-structure","args","multipleFilesOutputStrategy","output","outputWriteOptions","outputStrategyMap","_ref","_ref2","strategy","_objectWithoutPropertiesLoose","replaceFn","undefined","input","_args$inputReadOption","inputReadOptions","files","fastGlob","sync","inputGlobOptions","len","filePath","push","readFileSync","toString","_args$outputWriteOpti","normalize","write","async","fs","mkdir","writeFile","Promise","all","then","map","inputData","replacePromises","fileStream","stream","on","resolve","reject","readFile","error","once","catch"],"mappings":"mVAEO,MAAMA,EAAcC,IACzB,MAAM,IAAIC,kCAAkCD,IAAK,EAGtCE,EAAeA,CAACC,EAAwBC,IACjC,iBAAXD,EACFE,IACC,MAAMC,EAAYH,EAAOI,OACzB,IACIC,EADAC,EAAS,GAETC,EAAW,EAEf,MAAoD,KAA5CF,EAAIH,EAAQM,QAAQR,EAAQO,KAClCD,GAAUJ,EAAQO,MAAMF,EAAUF,GAAKJ,EACvCM,EAAWF,EAAIF,EAGjB,OAAOG,EAASJ,EAAQO,MAAMF,EAAUL,EAAQE,OAAM,EAEvDF,GAAoBA,EAAQQ,QAAQV,EAAQC,GCrBnDU,EAAA,CAAA,WAAA,SAAA,eAYMC,EAAYA,CAChBC,EACAC,EACAC,KAEAC,EAAUC,EAAQJ,GAAO,CAAEK,WAAW,IACtCC,EAAcN,EAAMC,EAAMC,EAC5B,EAEMK,EAAmB,CACvBC,KAAMA,CAACC,EAASC,KAAoBC,IAAAA,EAClC,IAAIlB,GAAmB,OAAVkB,EAAAF,EAAQ,SAAE,EAAVE,EAAa,KAAM,GAChC,IAAK,IAAInB,EAAI,EAAGA,EAAIiB,EAAQlB,SAAUC,EACpCC,GAAUiB,EAAmBD,EAAQjB,GAAG,GAE1C,MAAO,CAAC,CAAC,CAAC,GAAIC,IAAQ,EAExBmB,QAAUH,IACR,IAAK,IAAIjB,EAAI,EAAGA,EAAIiB,EAAQlB,SAAUC,EAAG,CACvC,MAAMC,EAASgB,EAAQjB,GAAG,GAC1BiB,EAAQjB,GAAG,GAAKC,EAAOoB,UAAUpB,EAAOqB,YAAYC,GACtD,CACA,MAAO,CAACN,EAAO,EAEjB,qBAAsBO,IAAIC,IAASA,GAG/BC,EAAoDA,CACxDT,EACAU,EACAC,KAEA,IAAK,IAAI5B,EAAI,EAAGA,EAAIiB,EAAQlB,SAAUC,EAAG,CACvC,MAAMC,EAASgB,EAAQjB,GACvBC,EAAO,GAAKe,EAAKW,EAAQ1B,EAAO,IAChCM,EAAUN,EAAO,GAAIA,EAAO,GAAI2B,EAClC,CACA,OAAOX,GAGHY,EAAoB,CACxBb,KAAMA,CAACC,EAASU,EAAQC,KACtBrB,EAAUoB,EAAQV,EAAQ,GAAG,GAAIW,GACjCX,EAAQ,GAAG,GAAKU,EACTV,GAETG,QAASM,EACT,qBAAsBA,GAGxB,MAAeI,IAA8DC,IAAAA,MACvEd,GADUe,SAAEA,EAAW,OAAMrC,OAAEA,EAAMC,YAAEA,GAA4BkC,EAAZL,EAAIQ,EAAAH,EAAAxB,GAE/D,MAAM4B,EAAYxC,EAAaC,EAAQC,GAEvC,GAAI,YAAa6B,QAAyBU,IAAjBV,EAAK5B,QAC5BoB,EAAU,CAAC,CAAC,GAAIiB,EAAUT,EAAK5B,gBAC1B,GAAI,UAAW4B,QAAuBU,IAAfV,EAAKW,MAAqB,CACjCC,MAArBZ,EAAKa,mBAALb,EAAKa,iBAAqB,QAC1BrB,EAAU,GAEV,MAAMsB,EAAQC,EAASC,KAAKhB,EAAKW,MAAOX,EAAKiB,kBACvCC,EAAMJ,EAAMxC,OAClB,IAAK,IAAIC,EAAI,EAAGA,EAAI2C,IAAO3C,EAAG,CAC5B,MAAM4C,EAAWL,EAAMvC,GACvBiB,EAAQ4B,KAAK,CACXD,EACAV,EAAUY,EAAaF,EAAUnB,EAAKa,kBAAkBS,aAE5D,CACF,MACExD,EACE,qFAICwB,EAAiBiB,IACpBzC,EACE,6FAGJ,MAAM2B,EAC2Da,OAD3CA,EACnB,qBAAsBN,EAAOA,EAAKP,sBAAmBiB,GAASJ,EAAK,KAetE,OAZCd,GAAWF,EAAiBiB,GAAUf,EAAUC,GAE7C,WAAYO,QAAwBU,IAAhBV,EAAKE,SACJqB,MAAvBvB,EAAKG,qBAALH,EAAKG,mBAAuB,QAE5BX,EAAUY,EAAkBG,GAC1Bf,EACAgC,EAAUxB,EAAKE,QACfF,EAAKG,qBAIFX,CACR,EC7GD,MAAAX,EAAA,CAAA,WAAA,SAAA,eAYM4C,EAAQC,MACZ3C,EACAC,EACAC,WAEM0C,EAAGC,MAAMzC,EAAQJ,GAAO,CAAEK,WAAW,UACrCuC,EAAGE,UAAU9C,EAAMC,EAAMC,EAAO,EAGlCK,EAAmB,CACvBC,KAAMmC,MAAOlC,EAASC,IAAqB,OACnCqC,QAAQC,UAAUvC,GAASwC,KAAMxC,IACrC,MAAM0B,EAAM1B,EAAQlB,OACpB,IAAIE,EAAUgB,EAAQ,IAAMA,EAAQ,GAAG,IAAO,GAC9C,IAAK,IAAIjB,EAAI,EAAGA,EAAI2C,IAAO3C,EACzBC,GAAUiB,EAAmBD,EAAQjB,GAAG,GAE1C,MAAO,CAAC,GAAIC,EAAM,IAGtBmB,QAAS+B,eACDI,QAAQC,WACLvC,GAASyC,IAAIP,WAClBlD,QAAeA,GACR,GAAKA,EAAO,GAAGoB,UAAUpB,EAAO,GAAGqB,YAAYC,IAC/CtB,KAGb,qBAAsBkD,eAAyBI,QAAQC,UAAUvC,IAG7DS,EAAgDyB,MACpDlC,EACAU,EACAC,IAEA2B,QAAQC,WACCvC,GAASyC,IAAIP,UAClBlD,EAAO,GAAKe,EAAKW,EAAQ1B,EAAO,UAC1BiD,EAAMjD,EAAO,GAAIA,EAAO,GAAI2B,GAC3B3B,KAIP4B,EAAoB,CACxBb,KAAMmC,MAAOlC,EAASU,EAAQC,KAC5B,MAAM3B,SAAgBgB,GAAS,GAG/B,aAFMiC,EAAMvB,EAAQ1B,EAAO,GAAI2B,GAC/B3B,EAAO,GAAK0B,EACL,CAAC1B,EAAM,EAEhBmB,QAASM,EACT,qBAAsBA,GAGxB,MAAe,MAAAyB,IAKJ,IAAApB,EALW,IAMhB4B,GANgB3B,SACpBA,EAAW,OAAMrC,OACjBA,EAAMC,YACNA,GAEKkC,EADFL,EAAIQ,EAAAH,EAAAxB,GAGP,MAAM4B,EAAYxC,EAAaC,EAAQC,GAEvC,GAAI,YAAa6B,QAAyBU,IAAjBV,EAAK5B,QAC5B8D,EAAY,CAAC,CAAC,GAAIzB,EAAUT,EAAK5B,gBACxB,GAAA,UAAW4B,QAAuBU,IAAfV,EAAKW,MAAqB,OACtDX,EAAKa,mBAALb,EAAKa,iBAAqB,QAC1B,MAAMsB,EAAyC,GAEzCC,EAAarB,EAASsB,OAAOrC,EAAKW,MAAOX,EAAKiB,kBACpDmB,EAAWE,GAAG,QAASxE,GACvBsE,EAAWE,GAAG,OAASvD,GACrBoD,EAAgBf,KACd,IAAIU,QAAQ,CAACS,EAASC,IACpBC,EAAS1D,EAAMiB,EAAKa,iBAAkB,CAAC6B,EAAO1D,KAE5C,GAAI0D,EAAO,OAAOF,EAAOE,GAEzBH,EAAQ,CAACxD,EAAM0B,EAAUzB,EAAKsC,aAAY,MAKlDY,EAAY,IAAIJ,QAAiCS,GAC/CH,EAAWO,KAAK,MAAO,IAAMJ,EAAQJ,KACrCS,MAAM9E,EACV,MACEA,EAAW,8CAGRwB,EAAiBiB,IACpBzC,EACE,6FAGJ,MAAM2B,EAC2D,OAD3Ca,EACnB,qBAAsBN,EAAOA,EAAKP,sBAAmBiB,GAASJ,EAAK,KAGtE,IAAId,QAAgBF,EAAiBiB,GAAU2B,EAAYzC,GAY3D,MAVI,WAAYO,QAAwBU,IAAhBV,EAAKE,SACJqB,MAAvBvB,EAAKG,qBAALH,EAAKG,mBAAuB,QAE5BX,QAAgBY,EAAkBG,GAChCf,EACAgC,EAAUxB,EAAKE,QACfF,EAAKG,qBAIFX,CACR"}
package/dist/sync.d.ts DELETED
@@ -1,3 +0,0 @@
1
- import type { Args, FileResult } from './types.js';
2
- declare const _default: ({ strategy, needle, replacement, ...args }: Args) => FileResult[];
3
- export default _default;
package/dist/types.d.ts DELETED
@@ -1,27 +0,0 @@
1
- /// <reference types="node" />
2
- import type { readFileSync, writeFileSync } from 'fs';
3
- import type { sync as globSync } from 'fast-glob';
4
- export type Strategy = 'join' | 'flatten' | 'preserve-structure';
5
- export type CommonArgs = {
6
- strategy?: Strategy;
7
- needle: string | RegExp;
8
- replacement: string;
9
- };
10
- export type InputArgs = {
11
- input: Parameters<typeof globSync>[0];
12
- inputReadOptions?: Parameters<typeof readFileSync>[1];
13
- inputGlobOptions?: Parameters<typeof globSync>[1];
14
- } | {
15
- content: string;
16
- };
17
- export type OutputArgs = {
18
- output?: string;
19
- outputWriteOptions?: Parameters<typeof writeFileSync>[2];
20
- outputJoinString?: string;
21
- } | object;
22
- export type Args = CommonArgs & InputArgs & OutputArgs;
23
- export type FileResult = [string, string];
24
- export type InputStrategyFnSync = (results: FileResult[], outputJoinString: string) => [FileResult[]] | [FileResult[], string];
25
- export type OutputStrategyFnSync = (results: FileResult[], output: string, outputWriteOptions: Parameters<typeof writeFileSync>[2]) => FileResult[];
26
- export type InputStrategyFn = (results: Promise<Promise<FileResult>[]> | FileResult[], outputJoinString: string) => Promise<FileResult[]> | FileResult[];
27
- export type OutputStrategyFn = (results: Promise<FileResult[]> | FileResult[], output: string, outputWriteOptions: Parameters<typeof writeFileSync>[2]) => Promise<FileResult[]>;
package/dist/utils.d.ts DELETED
@@ -1,3 +0,0 @@
1
- import type { Args } from './types.js';
2
- export declare const writeError: (msg: string) => never;
3
- export declare const getReplaceFn: (needle: Args['needle'], replacement: string) => (content: string) => string;