@hanseltime/template-repo-sync 1.0.1 → 1.2.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.
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  Object.defineProperty(exports, "__esModule", { value: true });
3
26
  exports.templateSync = exports.TEMPLATE_SYNC_LOCAL_CONFIG = exports.TEMPLATE_SYNC_CONFIG = void 0;
4
27
  const path_1 = require("path");
@@ -7,21 +30,25 @@ const match_1 = require("./match");
7
30
  const merge_file_1 = require("./merge-file");
8
31
  const git_clone_1 = require("./clone-drivers/git-clone");
9
32
  const diff_drivers_1 = require("./diff-drivers");
33
+ const ref_drivers_1 = require("./ref-drivers");
34
+ const formatting_1 = require("./formatting");
35
+ const commentJSON = __importStar(require("comment-json"));
10
36
  exports.TEMPLATE_SYNC_CONFIG = "templatesync";
11
37
  exports.TEMPLATE_SYNC_LOCAL_CONFIG = "templatesync.local";
12
38
  async function templateSync(options) {
13
39
  const cloneDriver = options.cloneDriver ?? git_clone_1.gitClone;
14
40
  const diffDriver = options.diffDriver ?? diff_drivers_1.gitDiff;
41
+ const currentRefDriver = options.currentRefDriver ?? ref_drivers_1.gitCurrentRef;
15
42
  const tempCloneDir = await cloneDriver(options.tmpCloneDir, options.repoUrl);
16
43
  // Get the clone Config
17
44
  const cloneConfigPath = (0, path_1.join)(tempCloneDir, `${exports.TEMPLATE_SYNC_CONFIG}.json`);
18
45
  const templateSyncConfig = (0, fs_1.existsSync)(cloneConfigPath)
19
- ? JSON.parse((0, fs_1.readFileSync)(cloneConfigPath).toString())
20
- : {};
46
+ ? commentJSON.parse((0, fs_1.readFileSync)(cloneConfigPath).toString())
47
+ : { ignore: [] };
21
48
  const localConfigPath = (0, path_1.join)(options.repoDir, `${exports.TEMPLATE_SYNC_LOCAL_CONFIG}.json`);
22
49
  const localTemplateSyncConfig = (0, fs_1.existsSync)(localConfigPath)
23
- ? JSON.parse((0, fs_1.readFileSync)(localConfigPath).toString())
24
- : {};
50
+ ? commentJSON.parse((0, fs_1.readFileSync)(localConfigPath).toString())
51
+ : { ignore: [] };
25
52
  let filesToSync;
26
53
  if (localTemplateSyncConfig.afterRef) {
27
54
  filesToSync = await diffDriver(tempCloneDir, localTemplateSyncConfig.afterRef);
@@ -48,6 +75,21 @@ async function templateSync(options) {
48
75
  localFileChanges[f] = result.localChanges;
49
76
  }
50
77
  }));
78
+ // apply after ref
79
+ if (options.updateAfterRef) {
80
+ const ref = await currentRefDriver({
81
+ rootDir: tempCloneDir,
82
+ });
83
+ if ((0, fs_1.existsSync)(localConfigPath)) {
84
+ const configStr = (0, fs_1.readFileSync)(localConfigPath).toString();
85
+ const config = commentJSON.parse(configStr);
86
+ config.afterRef = ref;
87
+ (0, fs_1.writeFileSync)(localConfigPath, commentJSON.stringify(config, null, (0, formatting_1.inferJSONIndent)(configStr)));
88
+ }
89
+ else {
90
+ (0, fs_1.writeFileSync)(localConfigPath, commentJSON.stringify({ afterRef: ref }, null, 4));
91
+ }
92
+ }
51
93
  return {
52
94
  localSkipFiles,
53
95
  localFileChanges,
@@ -36,7 +36,7 @@ export interface MergeConfig<T> {
36
36
  */
37
37
  plugin?: string;
38
38
  /**
39
- * An array of first match file globs that will
39
+ * An array of first match file globs that will then call the plugin with the appropriate options
40
40
  */
41
41
  rules: {
42
42
  glob: string;
@@ -1,13 +1,36 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
5
28
  Object.defineProperty(exports, "__esModule", { value: true });
6
29
  exports.merge = exports.validate = void 0;
7
30
  const lodash_merge_1 = __importDefault(require("lodash.merge"));
8
- const lodash_clonedeep_1 = __importDefault(require("lodash.clonedeep"));
9
31
  const jsonpath_1 = __importDefault(require("jsonpath"));
10
32
  const infer_json_indent_1 = require("../formatting/infer-json-indent");
33
+ const commentJSON = __importStar(require("comment-json"));
11
34
  function stringOptionError(value) {
12
35
  if (value === "overwrite" ||
13
36
  value === "merge-template" ||
@@ -78,18 +101,18 @@ async function merge(current, fromTemplateRepo, context) {
78
101
  if (context.mergeArguments === "overwrite") {
79
102
  return fromTemplateRepo;
80
103
  }
81
- const currentJson = JSON.parse(current);
82
- const fromTemplateJson = JSON.parse(fromTemplateRepo);
104
+ const currentJson = commentJSON.parse(current);
105
+ const fromTemplateJson = commentJSON.parse(fromTemplateRepo);
83
106
  if (context.mergeArguments === "merge-current") {
84
107
  // Performs Lodash Merge with current as the override
85
- return JSON.stringify((0, lodash_merge_1.default)(fromTemplateJson, currentJson), null, 4);
108
+ return commentJSON.stringify((0, lodash_merge_1.default)(fromTemplateJson, currentJson), null, (0, infer_json_indent_1.inferJSONIndent)(current));
86
109
  }
87
110
  if (context.mergeArguments === "merge-template") {
88
111
  // Performs Lodash Merge with current as the override
89
- return JSON.stringify((0, lodash_merge_1.default)(currentJson, fromTemplateJson), null, 4);
112
+ return commentJSON.stringify((0, lodash_merge_1.default)(currentJson, fromTemplateJson), null, (0, infer_json_indent_1.inferJSONIndent)(current));
90
113
  }
91
114
  const { missingIsDelete, ignoreNewProperties, paths } = context.mergeArguments;
92
- const returnJson = (0, lodash_clonedeep_1.default)(currentJson);
115
+ const returnJson = commentJSON.parse(current);
93
116
  paths.forEach((p) => {
94
117
  const [jPath, overrideType] = p;
95
118
  const fromTemplatePaths = new Map();
@@ -143,7 +166,7 @@ async function merge(current, fromTemplateRepo, context) {
143
166
  }
144
167
  });
145
168
  }
146
- return JSON.stringify(returnJson, null, (0, infer_json_indent_1.inferJSONIndent)(current));
169
+ return commentJSON.stringify(returnJson, null, (0, infer_json_indent_1.inferJSONIndent)(current));
147
170
  }
148
171
  exports.merge = merge;
149
172
  /**
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.gitCurrentRef = void 0;
4
+ const child_process_1 = require("child_process");
5
+ async function gitCurrentRef(options) {
6
+ return (0, child_process_1.execSync)(`git rev-parse HEAD`, {
7
+ cwd: options.rootDir,
8
+ })
9
+ .toString()
10
+ .trim();
11
+ }
12
+ exports.gitCurrentRef = gitCurrentRef;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./git-current-ref"), exports);
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  Object.defineProperty(exports, "__esModule", { value: true });
3
26
  exports.templateSync = exports.TEMPLATE_SYNC_LOCAL_CONFIG = exports.TEMPLATE_SYNC_CONFIG = void 0;
4
27
  const path_1 = require("path");
@@ -7,21 +30,25 @@ const match_1 = require("./match");
7
30
  const merge_file_1 = require("./merge-file");
8
31
  const git_clone_1 = require("./clone-drivers/git-clone");
9
32
  const diff_drivers_1 = require("./diff-drivers");
33
+ const ref_drivers_1 = require("./ref-drivers");
34
+ const formatting_1 = require("./formatting");
35
+ const commentJSON = __importStar(require("comment-json"));
10
36
  exports.TEMPLATE_SYNC_CONFIG = "templatesync";
11
37
  exports.TEMPLATE_SYNC_LOCAL_CONFIG = "templatesync.local";
12
38
  async function templateSync(options) {
13
39
  const cloneDriver = options.cloneDriver ?? git_clone_1.gitClone;
14
40
  const diffDriver = options.diffDriver ?? diff_drivers_1.gitDiff;
41
+ const currentRefDriver = options.currentRefDriver ?? ref_drivers_1.gitCurrentRef;
15
42
  const tempCloneDir = await cloneDriver(options.tmpCloneDir, options.repoUrl);
16
43
  // Get the clone Config
17
44
  const cloneConfigPath = (0, path_1.join)(tempCloneDir, `${exports.TEMPLATE_SYNC_CONFIG}.json`);
18
45
  const templateSyncConfig = (0, fs_1.existsSync)(cloneConfigPath)
19
- ? JSON.parse((0, fs_1.readFileSync)(cloneConfigPath).toString())
20
- : {};
46
+ ? commentJSON.parse((0, fs_1.readFileSync)(cloneConfigPath).toString())
47
+ : { ignore: [] };
21
48
  const localConfigPath = (0, path_1.join)(options.repoDir, `${exports.TEMPLATE_SYNC_LOCAL_CONFIG}.json`);
22
49
  const localTemplateSyncConfig = (0, fs_1.existsSync)(localConfigPath)
23
- ? JSON.parse((0, fs_1.readFileSync)(localConfigPath).toString())
24
- : {};
50
+ ? commentJSON.parse((0, fs_1.readFileSync)(localConfigPath).toString())
51
+ : { ignore: [] };
25
52
  let filesToSync;
26
53
  if (localTemplateSyncConfig.afterRef) {
27
54
  filesToSync = await diffDriver(tempCloneDir, localTemplateSyncConfig.afterRef);
@@ -48,6 +75,21 @@ async function templateSync(options) {
48
75
  localFileChanges[f] = result.localChanges;
49
76
  }
50
77
  }));
78
+ // apply after ref
79
+ if (options.updateAfterRef) {
80
+ const ref = await currentRefDriver({
81
+ rootDir: tempCloneDir,
82
+ });
83
+ if ((0, fs_1.existsSync)(localConfigPath)) {
84
+ const configStr = (0, fs_1.readFileSync)(localConfigPath).toString();
85
+ const config = commentJSON.parse(configStr);
86
+ config.afterRef = ref;
87
+ (0, fs_1.writeFileSync)(localConfigPath, commentJSON.stringify(config, null, (0, formatting_1.inferJSONIndent)(configStr)));
88
+ }
89
+ else {
90
+ (0, fs_1.writeFileSync)(localConfigPath, commentJSON.stringify({ afterRef: ref }, null, 4));
91
+ }
92
+ }
51
93
  return {
52
94
  localSkipFiles,
53
95
  localFileChanges,
package/package.json CHANGED
@@ -1,29 +1,27 @@
1
1
  {
2
2
  "name": "@hanseltime/template-repo-sync",
3
- "version": "1.0.1",
3
+ "version": "1.2.0",
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
8
  "scripts": {
9
- "format": "npx prettier . --write",
10
- "lint": "npx eslint .",
9
+ "format": "prettier . --write",
10
+ "lint": "eslint .",
11
11
  "test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest",
12
12
  "run-script": "node --loader ts-node/esm",
13
13
  "build": "tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json",
14
14
  "prepare": "husky",
15
- "release": "npx semantic-release"
15
+ "release": "semantic-release"
16
16
  },
17
17
  "keywords": [],
18
18
  "author": "",
19
19
  "license": "ISC",
20
20
  "dependencies": {
21
- "@actions/core": "^1.10.1",
22
- "@actions/github": "^6.0.0",
21
+ "comment-json": "^4.2.3",
23
22
  "diff": "^5.1.0",
24
23
  "fs-extra": "^11.2.0",
25
24
  "jsonpath": "^1.1.1",
26
- "lodash.clonedeep": "^4.5.0",
27
25
  "lodash.merge": "^4.6.2",
28
26
  "micromatch": "^4.0.5"
29
27
  },
@@ -35,7 +33,6 @@
35
33
  "@types/fs-extra": "^11.0.4",
36
34
  "@types/jest": "^29.5.11",
37
35
  "@types/jsonpath": "^0.2.4",
38
- "@types/lodash.clonedeep": "^4.5.9",
39
36
  "@types/lodash.merge": "^4.6.9",
40
37
  "@types/micromatch": "^4.0.6",
41
38
  "@types/node": "^20.11.7",
@@ -1,6 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import { JsonPathOverrides } from "../types";
3
3
  import { merge, validate } from "./json-merge";
4
+ import * as commentJson from "comment-json";
4
5
 
5
6
  const testFileJson = {
6
7
  here: "here",
@@ -24,6 +25,21 @@ const templateFileJson = {
24
25
  },
25
26
  };
26
27
 
28
+ const testCommentJson = `{
29
+ // This is a top comment
30
+ "here": "here",
31
+ "another": 23, // this is inline
32
+ "inner": {
33
+ "el1": "el1",
34
+ "arr1": ["a1", "a2"],
35
+ "nested": {
36
+ // Upper comment
37
+ "final": "final", // Inline commment
38
+ "final2": "final2",
39
+ },
40
+ },
41
+ }`;
42
+
27
43
  describe("merge", () => {
28
44
  it("performs overwrite when specified", async () => {
29
45
  const fromTemplateJson = {
@@ -291,6 +307,76 @@ describe("merge", () => {
291
307
  },
292
308
  });
293
309
  });
310
+ it("performs pathjson merges on comment json", async () => {
311
+ const template = { ...templateFileJson };
312
+ (template.inner as any).nested = {
313
+ final: { something: 44 },
314
+ newThing: "this",
315
+ };
316
+
317
+ const testTemplateCommentJson = `{
318
+ "here": "heretemplate",
319
+ /** New comment explaining extra **/
320
+ "extra": "extra",
321
+ "inner": {
322
+ "arr1": ["b1", "b2"],
323
+ "extra2": "extra2",
324
+ "nested": {
325
+ "final": {
326
+ // New comment explaining final
327
+ "something": 44,
328
+ },
329
+ "newThing": {
330
+ // new thing comment
331
+ "this": 23,
332
+ },
333
+ }
334
+ },
335
+ }`;
336
+
337
+ expect(
338
+ commentJson.stringify(
339
+ commentJson.parse(
340
+ await merge(testCommentJson, testTemplateCommentJson, {
341
+ relFilePath: "somepath",
342
+ mergeArguments: {
343
+ paths: [
344
+ ["$.here", "merge-template"],
345
+ ["$.inner.nested.*", "merge-template"],
346
+ ["$.inner.nested.final", "merge-current"],
347
+ ],
348
+ },
349
+ }),
350
+ ),
351
+ null,
352
+ 4,
353
+ ),
354
+ ).toEqual(
355
+ commentJson.stringify(
356
+ commentJson.parse(`{
357
+ // This is a top comment
358
+ "here": "heretemplate",
359
+ "another": 23, // this is inline
360
+ "inner": {
361
+ "el1": "el1",
362
+ "arr1": ["a1", "a2"],
363
+ "nested": {
364
+ // Upper comment
365
+ "final": "final", // Inline commment
366
+ "final2": "final2",
367
+ "newThing": {
368
+ // new thing comment
369
+ "this": 23,
370
+ },
371
+ },
372
+ },
373
+ "extra": "extra",
374
+ }`),
375
+ null,
376
+ 4,
377
+ ),
378
+ );
379
+ });
294
380
  });
295
381
 
296
382
  describe("validate", () => {
@@ -4,9 +4,9 @@ import {
4
4
  JsonPathOverrides,
5
5
  } from "../types";
6
6
  import lodashMerge from "lodash.merge";
7
- import locashCloneDeep from "lodash.clonedeep";
8
7
  import jp, { PathComponent } from "jsonpath";
9
8
  import { inferJSONIndent } from "../formatting/infer-json-indent";
9
+ import * as commentJSON from "comment-json";
10
10
 
11
11
  function stringOptionError(value: string) {
12
12
  if (
@@ -88,23 +88,33 @@ export async function merge(
88
88
  return fromTemplateRepo;
89
89
  }
90
90
 
91
- const currentJson = JSON.parse(current);
92
- const fromTemplateJson = JSON.parse(fromTemplateRepo);
91
+ const currentJson = commentJSON.parse(current) as commentJSON.CommentObject;
92
+ const fromTemplateJson = commentJSON.parse(
93
+ fromTemplateRepo,
94
+ ) as commentJSON.CommentObject;
93
95
 
94
96
  if (context.mergeArguments === "merge-current") {
95
97
  // Performs Lodash Merge with current as the override
96
- return JSON.stringify(lodashMerge(fromTemplateJson, currentJson), null, 4);
98
+ return commentJSON.stringify(
99
+ lodashMerge(fromTemplateJson, currentJson),
100
+ null,
101
+ inferJSONIndent(current),
102
+ );
97
103
  }
98
104
 
99
105
  if (context.mergeArguments === "merge-template") {
100
106
  // Performs Lodash Merge with current as the override
101
- return JSON.stringify(lodashMerge(currentJson, fromTemplateJson), null, 4);
107
+ return commentJSON.stringify(
108
+ lodashMerge(currentJson, fromTemplateJson),
109
+ null,
110
+ inferJSONIndent(current),
111
+ );
102
112
  }
103
113
 
104
114
  const { missingIsDelete, ignoreNewProperties, paths } =
105
115
  context.mergeArguments as JsonPathOverrides;
106
116
 
107
- const returnJson = locashCloneDeep(currentJson);
117
+ const returnJson = commentJSON.parse(current) as commentJSON.CommentObject;
108
118
  paths.forEach((p) => {
109
119
  const [jPath, overrideType] = p;
110
120
 
@@ -158,7 +168,7 @@ export async function merge(
158
168
  });
159
169
  }
160
170
 
161
- return JSON.stringify(returnJson, null, inferJSONIndent(current));
171
+ return commentJSON.stringify(returnJson, null, inferJSONIndent(current));
162
172
  }
163
173
 
164
174
  /**
@@ -0,0 +1,12 @@
1
+ import { execSync } from "child_process";
2
+ import { gitCurrentRef } from "./git-current-ref";
3
+
4
+ describe("getCurrentRef", () => {
5
+ it("gets the current sha", async () => {
6
+ expect(
7
+ await gitCurrentRef({
8
+ rootDir: process.cwd(),
9
+ }),
10
+ ).toEqual(execSync("git rev-parse HEAD").toString().trim());
11
+ });
12
+ });
@@ -0,0 +1,9 @@
1
+ import { execSync } from "child_process";
2
+
3
+ export async function gitCurrentRef(options: { rootDir: string }) {
4
+ return execSync(`git rev-parse HEAD`, {
5
+ cwd: options.rootDir,
6
+ })
7
+ .toString()
8
+ .trim();
9
+ }
@@ -0,0 +1 @@
1
+ export * from "./git-current-ref";
@@ -0,0 +1,10 @@
1
+ /**
2
+ * A function that operates within the root dir and returns the
3
+ * current ref for its state. This abstracts the idea of getting
4
+ * the current commit sha, so that things like other custom templating
5
+ * frameworks can provide their own ref
6
+ */
7
+ export type TemplateRefDriverFn = (options: {
8
+ /** The root dir where we want to get the "current" ref */
9
+ rootDir: string;
10
+ }) => Promise<string>;
@@ -192,6 +192,127 @@ describe("templateSync", () => {
192
192
  await fileMatchDownstream(tmpDir, "plugins/custom-plugin.js");
193
193
  await fileMatchDownstream(tmpDir, "package.json");
194
194
  });
195
+ it("updates the local templatesync with the current ref if updateAfterRef is true", async () => {
196
+ // Remove the local sync overrides
197
+ await rm(join(tmpDir, "templatesync.local.json"));
198
+
199
+ const mockLocalConfig = {
200
+ afterRef: "dummySha",
201
+ ignore: [
202
+ // We don't have a need for this in here, but it's an example of keeping things cleaner for our custom plugins
203
+ "plugins/**",
204
+ ],
205
+ };
206
+
207
+ writeFileSync(
208
+ join(tmpDir, "templatesync.local.json"),
209
+ JSON.stringify(mockLocalConfig),
210
+ );
211
+
212
+ // We will only update the templated.ts
213
+ const mockDiffDriver = jest
214
+ .fn()
215
+ .mockImplementation(async () => ["src/templated.ts"]);
216
+ const mockCurrentRefDriver = jest
217
+ .fn()
218
+ .mockImplementation(async () => "newestSha");
219
+ const result = await templateSync({
220
+ tmpCloneDir: "stubbed-by-driver",
221
+ cloneDriver: dummyCloneDriver,
222
+ repoUrl: "not-important",
223
+ repoDir: tmpDir,
224
+ updateAfterRef: true,
225
+ diffDriver: mockDiffDriver,
226
+ currentRefDriver: mockCurrentRefDriver,
227
+ });
228
+
229
+ // since there was no override for this file, not changes from the local file
230
+ expect(result.localFileChanges).toEqual(expect.objectContaining({}));
231
+
232
+ // Verify the files
233
+ await fileMatchTemplate(tmpDir, "templatesync.json");
234
+ await fileMatchTemplate(tmpDir, "src/templated.ts");
235
+
236
+ // Expect the none of the diff files to work
237
+ await fileMatchDownstream(tmpDir, "src/index.ts");
238
+ await fileMatchDownstream(tmpDir, "plugins/custom-plugin.js");
239
+ await fileMatchDownstream(tmpDir, "package.json");
240
+
241
+ // Ensure we have updated the local template field
242
+ expect(
243
+ JSON.parse(
244
+ (await readFile(join(tmpDir, "templatesync.local.json"))).toString(),
245
+ ),
246
+ ).toEqual({
247
+ ...mockLocalConfig,
248
+ afterRef: "newestSha",
249
+ });
250
+ });
251
+ it("creates the local templatesync with the current ref if updateAfterRef is true and no local template exists", async () => {
252
+ // Remove the local sync overrides
253
+ await rm(join(tmpDir, "templatesync.local.json"));
254
+
255
+ // We will only update the templated.ts
256
+ const mockDiffDriver = jest
257
+ .fn()
258
+ .mockImplementation(async () => ["src/templated.ts"]);
259
+ const mockCurrentRefDriver = jest
260
+ .fn()
261
+ .mockImplementation(async () => "newestSha");
262
+ const result = await templateSync({
263
+ tmpCloneDir: "stubbed-by-driver",
264
+ cloneDriver: dummyCloneDriver,
265
+ repoUrl: "not-important",
266
+ repoDir: tmpDir,
267
+ updateAfterRef: true,
268
+ diffDriver: mockDiffDriver,
269
+ currentRefDriver: mockCurrentRefDriver,
270
+ });
271
+
272
+ // since there was no override for this file, not changes from the local file
273
+ expect(result.localFileChanges).toEqual(expect.objectContaining({}));
274
+
275
+ // Verify the files
276
+ await fileMatchTemplate(tmpDir, "templatesync.json");
277
+ await fileMatchTemplate(tmpDir, "src/templated.ts");
278
+ const packageJson = JSON.parse(
279
+ readFileSync(resolve(tmpDir, "package.json")).toString(),
280
+ );
281
+
282
+ expect(packageJson).toEqual({
283
+ name: "mypkg",
284
+ description: "my description",
285
+ dependencies: {
286
+ mypackage: "^1.2.0",
287
+ newpacakge: "^22.2.2",
288
+ package2: "3.22.1",
289
+ huh: "~1.0.0",
290
+ },
291
+ engines: {
292
+ node: ">=15",
293
+ },
294
+ scripts: {
295
+ build: "build",
296
+ test: "jest",
297
+ myscript: "somescript",
298
+ },
299
+ // By default we add new top-level fields
300
+ version: "new-version",
301
+ });
302
+
303
+ // Expect the none of the diff files to work
304
+ await fileMatchDownstream(tmpDir, "src/index.ts");
305
+ await fileMatchDownstream(tmpDir, "plugins/custom-plugin.js");
306
+
307
+ // Ensure we have updated the local template field
308
+ expect(
309
+ JSON.parse(
310
+ (await readFile(join(tmpDir, "templatesync.local.json"))).toString(),
311
+ ),
312
+ ).toEqual({
313
+ afterRef: "newestSha",
314
+ });
315
+ });
195
316
  });
196
317
 
197
318
  // helper