@hanseltime/template-repo-sync 1.3.1 → 2.0.4

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.
@@ -4,36 +4,42 @@ exports.loadPlugin = void 0;
4
4
  const plugins_1 = require("./plugins");
5
5
  const fs_1 = require("fs");
6
6
  const path_1 = require("path");
7
- async function loadPlugin(mergeConfig, forExt, configDir) {
7
+ /**
8
+ * Loads the plugin associated with the merge config
9
+ * @param mergeConfig
10
+ * @param forExt
11
+ * @param configDir
12
+ * @returns
13
+ */
14
+ async function loadPlugin(mergeConfig, configDir) {
15
+ if (mergeConfig.plugin.startsWith("_")) {
16
+ const defaultHandler = Object.values(plugins_1.defaultExtensionMap).find((el) => el.builtinName === mergeConfig.plugin);
17
+ if (!defaultHandler) {
18
+ throw new Error(`No builtin merge function supplied for ${mergeConfig.plugin}. Cannot have merge config without custom plugin supplied.`);
19
+ }
20
+ return defaultHandler;
21
+ }
8
22
  let handler;
9
- if (mergeConfig.plugin) {
10
- // First check if this is a loal .js file
11
- const localPath = (0, path_1.resolve)(configDir, mergeConfig.plugin);
12
- const importPath = (0, fs_1.existsSync)(localPath) ? localPath : mergeConfig.plugin;
13
- try {
14
- // Sad workaround for testing since dynamic import segfaults
15
- if (process.env.JEST_WORKER_ID !== undefined) {
16
- // eslint-disable-next-line @typescript-eslint/no-var-requires
17
- handler = require(importPath);
18
- }
19
- else {
20
- handler = (await import(importPath));
21
- }
22
- if (!handler.merge) {
23
- handler = handler
24
- .default;
25
- }
23
+ // First check if this is a local .js file
24
+ const localPath = (0, path_1.resolve)(configDir, mergeConfig.plugin);
25
+ const importPath = (0, fs_1.existsSync)(localPath) ? localPath : mergeConfig.plugin;
26
+ try {
27
+ // Sad workaround for testing since dynamic import segfaults
28
+ if (process.env.JEST_WORKER_ID !== undefined) {
29
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
30
+ handler = require(importPath);
26
31
  }
27
- catch (err) {
28
- console.error(err);
29
- throw err;
32
+ else {
33
+ handler = (await import(importPath));
30
34
  }
31
- }
32
- else {
33
- if (!plugins_1.defaultExtensionMap[forExt]) {
34
- throw new Error(`No default merge function supplied for ${forExt}. Cannot have mere config without custom plugin supplied.`);
35
+ if (!handler.merge) {
36
+ handler = handler
37
+ .default;
35
38
  }
36
- handler = plugins_1.defaultExtensionMap[forExt];
39
+ }
40
+ catch (err) {
41
+ console.error(err);
42
+ throw err;
37
43
  }
38
44
  return handler;
39
45
  }
@@ -26,50 +26,39 @@ async function mergeFile(relPath, context) {
26
26
  const ext = (0, path_1.extname)(relPath);
27
27
  const filePath = (0, path_1.join)(cwd, relPath);
28
28
  const templatePath = (0, path_1.join)(tempCloneDir, relPath);
29
- const mergeConfig = templateSyncConfig.merge?.[ext];
30
- const localMergeConfig = localTemplateSyncConfig.merge?.[ext];
31
- // Either write the merge or write
29
+ const mergeConfig = templateSyncConfig.merge?.find((mergeConfig) => (0, micromatch_1.isMatch)(relPath, mergeConfig.glob));
30
+ const localMergeConfig = localTemplateSyncConfig.merge?.find((mergeConfig) => (0, micromatch_1.isMatch)(relPath, mergeConfig.glob));
31
+ const mergeHandler = mergeConfig
32
+ ? await (0, load_plugin_1.loadPlugin)(mergeConfig, tempCloneDir)
33
+ : undefined;
34
+ const localMergeHandler = localMergeConfig
35
+ ? await (0, load_plugin_1.loadPlugin)(localMergeConfig, cwd)
36
+ : undefined;
37
+ // Either write the merge or write the file
32
38
  let fileContents;
33
39
  const localChanges = [];
34
- if ((0, fs_1.existsSync)(filePath) && (mergeConfig || localMergeConfig)) {
40
+ if ((0, fs_1.existsSync)(filePath) && (mergeHandler || localMergeHandler)) {
35
41
  const originalCurrentFile = (await (0, promises_1.readFile)(filePath)).toString();
36
- if (mergeConfig) {
37
- // Apply the template's most recent merges
38
- const handler = await (0, load_plugin_1.loadPlugin)(mergeConfig, ext, tempCloneDir);
39
- const mergeOptions = mergeConfig.rules.find((rule) => {
40
- return (0, micromatch_1.isMatch)(relPath, rule.glob);
42
+ if (mergeHandler) {
43
+ fileContents = await safeMerge(mergeHandler, mergeConfig?.plugin ?? `default for ${ext}`, originalCurrentFile, (await (0, promises_1.readFile)(templatePath)).toString(), {
44
+ relFilePath: relPath,
45
+ mergeArguments: mergeConfig?.options ?? {},
46
+ isLocalOptions: false,
41
47
  });
42
- if (mergeOptions) {
43
- fileContents = await safeMerge(handler, mergeConfig.plugin ?? `default for ${ext}`, originalCurrentFile, (await (0, promises_1.readFile)(templatePath)).toString(), {
44
- relFilePath: relPath,
45
- mergeArguments: mergeOptions.options,
46
- isLocalOptions: true,
47
- });
48
- }
49
- else {
50
- // Apply overwrite if we didn't set up merge
51
- fileContents = (await (0, promises_1.readFile)(templatePath)).toString();
52
- }
53
48
  }
54
49
  else {
55
50
  // Apply overwrite if we didn't set up merge
56
51
  fileContents = (await (0, promises_1.readFile)(templatePath)).toString();
57
52
  }
58
53
  // We apply the localMerge Config to the fileContent output by the template merge
59
- if (localMergeConfig) {
60
- const handler = await (0, load_plugin_1.loadPlugin)(localMergeConfig, ext, cwd);
61
- const mergeOptions = localMergeConfig.rules.find((rule) => {
62
- return (0, micromatch_1.isMatch)(relPath, rule.glob);
54
+ if (localMergeHandler) {
55
+ const localContents = await safeMerge(localMergeHandler, localMergeConfig?.plugin ?? `default for ${ext}`, originalCurrentFile, fileContents, {
56
+ relFilePath: relPath,
57
+ mergeArguments: localMergeConfig?.options ?? {},
58
+ isLocalOptions: true,
63
59
  });
64
- if (mergeOptions) {
65
- const localContents = await safeMerge(handler, localMergeConfig.plugin ?? `default for ${ext}`, originalCurrentFile, fileContents, {
66
- relFilePath: relPath,
67
- mergeArguments: mergeOptions.options,
68
- isLocalOptions: true,
69
- });
70
- localChanges.push(...(0, diff_1.diffLines)(fileContents, localContents));
71
- fileContents = localContents;
72
- }
60
+ localChanges.push(...(0, diff_1.diffLines)(fileContents, localContents));
61
+ fileContents = localContents;
73
62
  }
74
63
  }
75
64
  else {
@@ -6,5 +6,6 @@ exports.defaultExtensionMap = {
6
6
  ".json": {
7
7
  merge: json_merge_1.merge,
8
8
  validate: json_merge_1.validate,
9
+ builtinName: "_json",
9
10
  },
10
11
  };
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "@hanseltime/template-repo-sync",
3
- "version": "1.3.1",
3
+ "version": "2.0.4",
4
4
  "description": "An npm library that enables pluggable, customizable synchronization between template repos",
5
5
  "main": "lib/cjs/index.js",
6
6
  "types": "lib/cjs/index.d.ts",
7
7
  "module": "lib/esm/index.js",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/HanseltimeIndustries/template-repo-sync.git"
11
+ },
8
12
  "scripts": {
9
13
  "format": "prettier . --write",
10
14
  "lint": "eslint .",
@@ -28,6 +32,7 @@
28
32
  "devDependencies": {
29
33
  "@commitlint/config-angular": "^19.0.3",
30
34
  "@semantic-release/changelog": "^6.0.3",
35
+ "@semantic-release/exec": "^6.0.3",
31
36
  "@semantic-release/git": "^10.0.1",
32
37
  "@types/diff": "^5.0.9",
33
38
  "@types/fs-extra": "^11.0.4",
package/release.config.js CHANGED
@@ -19,7 +19,13 @@ module.exports = {
19
19
  "@semantic-release/commit-analyzer",
20
20
  "@semantic-release/release-notes-generator",
21
21
  "@semantic-release/changelog",
22
- "@semantic-release/npm",
22
+ [
23
+ "@semantic-release/npm",
24
+ {
25
+ npmPublish: false, // We just use this to increment the versions since semantic-release doesn't handle OIDC well
26
+ // Call the publish comand in the CI/CD
27
+ },
28
+ ],
23
29
  [
24
30
  "@semantic-release/git",
25
31
  {
@@ -3,39 +3,48 @@ import { MergeConfig, MergePlugin } from "./types";
3
3
  import { existsSync } from "fs";
4
4
  import { resolve } from "path";
5
5
 
6
+ /**
7
+ * Loads the plugin associated with the merge config
8
+ * @param mergeConfig
9
+ * @param forExt
10
+ * @param configDir
11
+ * @returns
12
+ */
6
13
  export async function loadPlugin<T>(
7
14
  mergeConfig: MergeConfig<T>,
8
- forExt: string,
9
15
  configDir: string,
10
16
  ): Promise<MergePlugin<T>> {
11
- let handler: MergePlugin<unknown>;
12
- if (mergeConfig.plugin) {
13
- // First check if this is a loal .js file
14
- const localPath = resolve(configDir, mergeConfig.plugin);
15
- const importPath = existsSync(localPath) ? localPath : mergeConfig.plugin;
16
- try {
17
- // Sad workaround for testing since dynamic import segfaults
18
- if (process.env.JEST_WORKER_ID !== undefined) {
19
- // eslint-disable-next-line @typescript-eslint/no-var-requires
20
- handler = require(importPath) as MergePlugin<unknown>;
21
- } else {
22
- handler = (await import(importPath)) as MergePlugin<unknown>;
23
- }
24
- if (!handler.merge) {
25
- handler = (handler as unknown as { default: MergePlugin<unknown> })
26
- .default;
27
- }
28
- } catch (err) {
29
- console.error(err);
30
- throw err;
31
- }
32
- } else {
33
- if (!defaultExtensionMap[forExt]) {
17
+ if (mergeConfig.plugin.startsWith("_")) {
18
+ const defaultHandler = Object.values(defaultExtensionMap).find(
19
+ (el) => el.builtinName === mergeConfig.plugin,
20
+ );
21
+ if (!defaultHandler) {
34
22
  throw new Error(
35
- `No default merge function supplied for ${forExt}. Cannot have mere config without custom plugin supplied.`,
23
+ `No builtin merge function supplied for ${mergeConfig.plugin}. Cannot have merge config without custom plugin supplied.`,
36
24
  );
37
25
  }
38
- handler = defaultExtensionMap[forExt];
26
+ return defaultHandler as MergePlugin<T>;
27
+ }
28
+
29
+ let handler: MergePlugin<unknown>;
30
+ // First check if this is a local .js file
31
+ const localPath = resolve(configDir, mergeConfig.plugin);
32
+ const importPath = existsSync(localPath) ? localPath : mergeConfig.plugin;
33
+ try {
34
+ // Sad workaround for testing since dynamic import segfaults
35
+ if (process.env.JEST_WORKER_ID !== undefined) {
36
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
37
+ handler = require(importPath) as MergePlugin<unknown>;
38
+ } else {
39
+ handler = (await import(importPath)) as MergePlugin<unknown>;
40
+ }
41
+ if (!handler.merge) {
42
+ handler = (handler as unknown as { default: MergePlugin<unknown> })
43
+ .default;
44
+ }
45
+ } catch (err) {
46
+ console.error(err);
47
+ throw err;
39
48
  }
40
49
 
41
50
  return handler as MergePlugin<T>;
@@ -42,7 +42,7 @@ describe("mergeFile", () => {
42
42
  tempCloneDir: testTemplateDir,
43
43
  localTemplateSyncConfig: {
44
44
  ignore: ["**/package.json"],
45
- merge: {},
45
+ merge: [],
46
46
  },
47
47
  templateSyncConfig: {
48
48
  ignore: ["**/*.txt"],
@@ -85,21 +85,18 @@ describe("mergeFile", () => {
85
85
  },
86
86
  templateSyncConfig: {
87
87
  ignore: ["**/*.txt"],
88
- merge: {
89
- ".json": {
90
- // no plugins
91
- rules: [
92
- {
93
- glob: "**/package.json",
94
- options: "merge-current",
95
- },
96
- {
97
- glob: "**/package.json",
98
- options: "merge-template",
99
- },
100
- ],
88
+ merge: [
89
+ {
90
+ glob: "**/package.json",
91
+ options: "merge-current",
92
+ plugin: "_json",
101
93
  },
102
- },
94
+ {
95
+ glob: "**/package.json",
96
+ options: "merge-template",
97
+ plugin: "_json",
98
+ },
99
+ ],
103
100
  },
104
101
  }),
105
102
  ).toEqual({
@@ -140,21 +137,18 @@ describe("mergeFile", () => {
140
137
  },
141
138
  templateSyncConfig: {
142
139
  ignore: ["**/*.txt"],
143
- merge: {
144
- ".json": {
145
- // no plugins
146
- rules: [
147
- {
148
- glob: "**/package.json",
149
- options: "merge-template",
150
- },
151
- {
152
- glob: "**/package.json",
153
- options: "merge-current",
154
- },
155
- ],
140
+ merge: [
141
+ {
142
+ glob: "**/package.json",
143
+ options: "merge-template",
144
+ plugin: "_json",
145
+ },
146
+ {
147
+ glob: "**/package.json",
148
+ options: "merge-current",
149
+ plugin: "_json",
156
150
  },
157
- },
151
+ ],
158
152
  },
159
153
  }),
160
154
  ).toEqual({
@@ -192,45 +186,34 @@ describe("mergeFile", () => {
192
186
  tempCloneDir: testTemplateDir,
193
187
  localTemplateSyncConfig: {
194
188
  ignore: [],
195
- merge: {
196
- ".json": {
197
- rules: [
198
- {
199
- glob: "**/package.json",
200
- options: {
201
- paths: [
202
- // Do not touch huh
203
- ["$.dependencies.huh", "merge-current"],
204
- ],
205
- },
206
- },
207
- ],
189
+ merge: [
190
+ {
191
+ plugin: "_json",
192
+ glob: "**/package.json",
193
+ options: {
194
+ paths: [
195
+ // Do not touch huh
196
+ ["$.dependencies.huh", "merge-current"],
197
+ ],
198
+ },
208
199
  },
209
- },
200
+ ],
210
201
  },
211
202
  templateSyncConfig: {
212
203
  ignore: ["**/*.txt"],
213
- merge: {
214
- ".json": {
215
- // no plugins
216
- rules: [
217
- {
218
- glob: "**/package.json",
219
- options: {
220
- missingIsDelete: true,
221
- paths: [
222
- // Merge all template dependencies
223
- ["$.dependencies", "merge-template"],
224
- ],
225
- } as JsonFileMergeOptions,
226
- },
227
- {
228
- glob: "**/package.json",
229
- options: "merge-current",
230
- },
231
- ],
204
+ merge: [
205
+ {
206
+ glob: "**/package.json",
207
+ plugin: "_json",
208
+ options: {
209
+ missingIsDelete: true,
210
+ paths: [
211
+ // Merge all template dependencies
212
+ ["$.dependencies", "merge-template"],
213
+ ],
214
+ } as JsonFileMergeOptions,
232
215
  },
233
- },
216
+ ],
234
217
  },
235
218
  }),
236
219
  ).toEqual({
@@ -281,47 +264,34 @@ describe("mergeFile", () => {
281
264
  tempCloneDir: testTemplateDir,
282
265
  localTemplateSyncConfig: {
283
266
  ignore: [],
284
- merge: {
285
- ".json": {
286
- // simulates a "node" plugin since we're pulling from the current context
267
+ merge: [
268
+ {
287
269
  plugin: "../test-fixtures/dummy-plugin.js",
288
- rules: [
289
- {
290
- glob: "**/package.json",
291
- options: {
292
- paths: [
293
- // Do not touch huh
294
- ["$.dependencies.huh", "merge-current"],
295
- ],
296
- },
297
- },
298
- ],
270
+ options: {
271
+ paths: [
272
+ // Do not touch huh
273
+ ["$.dependencies.huh", "merge-current"],
274
+ ],
275
+ },
276
+ glob: "**/package.json",
299
277
  },
300
- },
278
+ ],
301
279
  },
302
280
  templateSyncConfig: {
303
281
  ignore: ["**/*.txt"],
304
- merge: {
305
- ".json": {
306
- // no plugins
307
- rules: [
308
- {
309
- glob: "**/package.json",
310
- options: {
311
- missingIsDelete: true,
312
- paths: [
313
- // Merge all template dependencies
314
- ["$.dependencies", "merge-template"],
315
- ],
316
- } as JsonFileMergeOptions,
317
- },
318
- {
319
- glob: "**/package.json",
320
- options: "merge-current",
321
- },
322
- ],
282
+ merge: [
283
+ {
284
+ plugin: "_json",
285
+ glob: "**/package.json",
286
+ options: {
287
+ missingIsDelete: true,
288
+ paths: [
289
+ // Merge all template dependencies
290
+ ["$.dependencies", "merge-template"],
291
+ ],
292
+ } as JsonFileMergeOptions,
323
293
  },
324
- },
294
+ ],
325
295
  },
326
296
  }),
327
297
  ).toEqual({
@@ -366,54 +336,62 @@ describe("mergeFile", () => {
366
336
  tested: true,
367
337
  });
368
338
  });
369
- it("[inverse] applies default [.json] and custom merge for local with sync plugin and then local override", async () => {
339
+ it("[inverse] applies builtin _json and custom merge for local with sync plugin and then local override", async () => {
370
340
  expect(
371
341
  await mergeFile("package.json", {
372
342
  cwd: tmpDir,
373
343
  tempCloneDir: testTemplateDir,
374
344
  localTemplateSyncConfig: {
375
345
  ignore: [],
376
- merge: {
377
- ".json": {
378
- // This is a relative path to ht
346
+ merge: [
347
+ {
348
+ glob: "**/package.json",
379
349
  plugin: "plugins/custom-plugin.js",
380
- rules: [
381
- {
382
- glob: "**/package.json",
383
- options: {
384
- paths: [
385
- // Do not touch huh
386
- ["$.dependencies.huh", "merge-current"],
387
- ],
388
- },
389
- },
390
- ],
350
+ options: {
351
+ paths: [
352
+ // Do not touch huh
353
+ ["$.dependencies.huh", "merge-current"],
354
+ ],
355
+ },
391
356
  },
392
- },
357
+ ],
393
358
  },
394
359
  templateSyncConfig: {
395
360
  ignore: ["**/*.txt"],
396
- merge: {
397
- ".json": {
398
- // no plugins
399
- rules: [
400
- {
401
- glob: "**/package.json",
402
- options: {
403
- missingIsDelete: true,
404
- paths: [
405
- // Merge all template dependencies
406
- ["$.dependencies", "merge-template"],
407
- ],
408
- } as JsonFileMergeOptions,
409
- },
410
- {
411
- glob: "**/package.json",
412
- options: "merge-current",
413
- },
414
- ],
361
+ merge: [
362
+ {
363
+ glob: "**/package.json",
364
+ // TODO - we need to handle the weird implicit case I added here. It's dumb
365
+ options: {
366
+ missingIsDelete: true,
367
+ paths: [
368
+ // Merge all template dependencies
369
+ ["$.dependencies", "merge-template"],
370
+ ],
371
+ } as JsonFileMergeOptions,
372
+ plugin: "_json",
415
373
  },
416
- },
374
+ ],
375
+ // ".json": {
376
+ // // no plugins
377
+ // rules: [
378
+ // {
379
+ // glob: "**/package.json",
380
+ // options: {
381
+ // missingIsDelete: true,
382
+ // paths: [
383
+ // // Merge all template dependencies
384
+ // ["$.dependencies", "merge-template"],
385
+ // ],
386
+ // } as JsonFileMergeOptions,
387
+ // },
388
+ // {
389
+ // glob: "**/package.json",
390
+ // options: "merge-current",
391
+ // },
392
+ // ],
393
+ // },
394
+ // },
417
395
  },
418
396
  }),
419
397
  ).toEqual({