@hanseltime/template-repo-sync 1.0.1 → 1.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/CHANGELOG.md +7 -0
- package/README.md +66 -3
- package/lib/cjs/plugins/json-merge.js +2 -2
- package/lib/cjs/ref-drivers/git-current-ref.d.ts +3 -0
- package/lib/cjs/ref-drivers/git-current-ref.js +12 -0
- package/lib/cjs/ref-drivers/index.d.ts +1 -0
- package/lib/cjs/ref-drivers/index.js +17 -0
- package/lib/cjs/ref-drivers/types.d.ts +10 -0
- package/lib/cjs/ref-drivers/types.js +2 -0
- package/lib/cjs/template-sync.d.ts +10 -0
- package/lib/cjs/template-sync.js +18 -0
- package/lib/esm/plugins/json-merge.js +2 -2
- package/lib/esm/ref-drivers/git-current-ref.js +12 -0
- package/lib/esm/ref-drivers/index.js +17 -0
- package/lib/esm/ref-drivers/types.js +2 -0
- package/lib/esm/template-sync.js +18 -0
- package/package.json +1 -1
- package/src/plugins/json-merge.ts +10 -2
- package/src/ref-drivers/git-current-ref.spec.ts +12 -0
- package/src/ref-drivers/git-current-ref.ts +9 -0
- package/src/ref-drivers/index.ts +1 -0
- package/src/ref-drivers/types.ts +10 -0
- package/src/template-sync.spec.ts +121 -0
- package/src/template-sync.ts +38 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [1.1.0](https://github.com/HanseltimeIndustries/template-repo-sync/compare/v1.0.1...v1.1.0) (2024-03-04)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* adding updateRef Option ([b553e65](https://github.com/HanseltimeIndustries/template-repo-sync/commit/b553e65ebce59777ccb80728d540c5734d41cab7))
|
|
7
|
+
|
|
1
8
|
## [1.0.1](https://github.com/HanseltimeIndustries/template-repo-sync/compare/v1.0.0...v1.0.1) (2024-03-03)
|
|
2
9
|
|
|
3
10
|
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Template Sync
|
|
1
|
+
# Template Sync
|
|
2
2
|
|
|
3
3
|
This npm package seeks to provide further granularity for people hoping to maintain a base template repo in github that
|
|
4
4
|
is either imported or used as a literal template repo.
|
|
@@ -61,7 +61,30 @@ export interface Config {
|
|
|
61
61
|
}
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
### Example 1
|
|
64
|
+
### Example 1 - Using a custom plugin
|
|
65
|
+
|
|
66
|
+
In this scenario, you have installed a package that exposes the correct plugin interface for handling .ini file contents in
|
|
67
|
+
your implementing repository and set up this templatesync.local config file. Because of this, we can be assured that .ini files
|
|
68
|
+
in the local repo will be merged using the plugin we specified.
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
{
|
|
72
|
+
|
|
73
|
+
merge: {
|
|
74
|
+
".ini": {
|
|
75
|
+
// If you are running under pacakge manager like yarn or npm,
|
|
76
|
+
// you can provide a valid pacakge or .js fil from your package to run
|
|
77
|
+
plugin: 'my-installed-npm-package',
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Example 2 - Using a custom plugin for some paths
|
|
84
|
+
|
|
85
|
+
Just like in example 1, we have installed a plugin that exposes the correct plugin interface. Now though,
|
|
86
|
+
instead of applying that plugin to all '.ini' files, we are saying that, for this particular set of .ini
|
|
87
|
+
files, only the ones in custom-configs/ will use this merge operator.
|
|
65
88
|
|
|
66
89
|
```typescript
|
|
67
90
|
{
|
|
@@ -70,7 +93,15 @@ export interface Config {
|
|
|
70
93
|
".ini": {
|
|
71
94
|
// If you are running under pacakge manager like yarn or npm,
|
|
72
95
|
// you can provide a valid pacakge or .js fil from your package to run
|
|
73
|
-
|
|
96
|
+
plugin: 'my-installed-npm-package',
|
|
97
|
+
rule: [
|
|
98
|
+
{
|
|
99
|
+
glob: 'custom-configs/**',
|
|
100
|
+
options: {
|
|
101
|
+
myPluginParam: 'some parameter',
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
]
|
|
74
105
|
}
|
|
75
106
|
}
|
|
76
107
|
}
|
|
@@ -91,3 +122,35 @@ but it does mean that you will only see the changes to files that are newer than
|
|
|
91
122
|
|
|
92
123
|
As always, you can remove the SHA/Tag from your local config and this will trigger a full sync in the event that you made the wrong
|
|
93
124
|
assumption about merging templates correctly.
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
{
|
|
128
|
+
afterRef: 'git sha',
|
|
129
|
+
merge: {
|
|
130
|
+
".ini": {
|
|
131
|
+
// If you are running under pacakge manager like yarn or npm,
|
|
132
|
+
// you can provide a valid pacakge or .js fil from your package to run
|
|
133
|
+
plugin: 'my-installed-npm-package',
|
|
134
|
+
rule: [
|
|
135
|
+
{
|
|
136
|
+
glob: 'custom-configs/**',
|
|
137
|
+
options: {
|
|
138
|
+
myPluginParam: 'some parameter',
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Programmatic API
|
|
148
|
+
|
|
149
|
+
The programmatic api for this package is centered around `templateSync`. The way the function is written, we try to
|
|
150
|
+
allow escape hatches for other styles of comparison in the form of "TemplateDriver" functions. As part of the current
|
|
151
|
+
implementation, all of these `drivers` represent git actions, but for the sake of expandability, may be set up to evaluate
|
|
152
|
+
things like helm chart renderings (at least that is the hope). If you write a driver, please consider contributing it back.
|
|
153
|
+
|
|
154
|
+
Please see [template-sync](./src/template-sync.ts) for the most up to date options.
|
|
155
|
+
|
|
156
|
+
TODO: we should update use case examples
|
|
@@ -82,11 +82,11 @@ async function merge(current, fromTemplateRepo, context) {
|
|
|
82
82
|
const fromTemplateJson = JSON.parse(fromTemplateRepo);
|
|
83
83
|
if (context.mergeArguments === "merge-current") {
|
|
84
84
|
// Performs Lodash Merge with current as the override
|
|
85
|
-
return JSON.stringify((0, lodash_merge_1.default)(fromTemplateJson, currentJson), null,
|
|
85
|
+
return JSON.stringify((0, lodash_merge_1.default)(fromTemplateJson, currentJson), null, (0, infer_json_indent_1.inferJSONIndent)(current));
|
|
86
86
|
}
|
|
87
87
|
if (context.mergeArguments === "merge-template") {
|
|
88
88
|
// Performs Lodash Merge with current as the override
|
|
89
|
-
return JSON.stringify((0, lodash_merge_1.default)(currentJson, fromTemplateJson), null,
|
|
89
|
+
return JSON.stringify((0, lodash_merge_1.default)(currentJson, fromTemplateJson), null, (0, infer_json_indent_1.inferJSONIndent)(current));
|
|
90
90
|
}
|
|
91
91
|
const { missingIsDelete, ignoreNewProperties, paths } = context.mergeArguments;
|
|
92
92
|
const returnJson = (0, lodash_clonedeep_1.default)(currentJson);
|
|
@@ -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 @@
|
|
|
1
|
+
export * from "./git-current-ref";
|
|
@@ -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,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>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Change } from "diff";
|
|
2
2
|
import { TemplateCloneDriverFn } from "./clone-drivers";
|
|
3
3
|
import { TemplateDiffDriverFn } from "./diff-drivers";
|
|
4
|
+
import { TemplateRefDriverFn } from "./ref-drivers/types";
|
|
4
5
|
export interface TemplateSyncOptions {
|
|
5
6
|
repoUrl: string;
|
|
6
7
|
/**
|
|
@@ -11,6 +12,11 @@ export interface TemplateSyncOptions {
|
|
|
11
12
|
* The repo directory path that we are going to merge toward
|
|
12
13
|
*/
|
|
13
14
|
repoDir: string;
|
|
15
|
+
/**
|
|
16
|
+
* If set to true, template sync will apply the current ref
|
|
17
|
+
* of the template repo to afterRef
|
|
18
|
+
*/
|
|
19
|
+
updateAfterRef?: boolean;
|
|
14
20
|
/**
|
|
15
21
|
* Defaults to using git clone
|
|
16
22
|
*/
|
|
@@ -19,6 +25,10 @@ export interface TemplateSyncOptions {
|
|
|
19
25
|
* Defaults to using git diff
|
|
20
26
|
*/
|
|
21
27
|
diffDriver?: TemplateDiffDriverFn;
|
|
28
|
+
/**
|
|
29
|
+
* Defaults to using git current ref
|
|
30
|
+
*/
|
|
31
|
+
currentRefDriver?: TemplateRefDriverFn;
|
|
22
32
|
}
|
|
23
33
|
export interface TemplateSyncReturn {
|
|
24
34
|
/**
|
package/lib/cjs/template-sync.js
CHANGED
|
@@ -7,11 +7,14 @@ const match_1 = require("./match");
|
|
|
7
7
|
const merge_file_1 = require("./merge-file");
|
|
8
8
|
const git_clone_1 = require("./clone-drivers/git-clone");
|
|
9
9
|
const diff_drivers_1 = require("./diff-drivers");
|
|
10
|
+
const ref_drivers_1 = require("./ref-drivers");
|
|
11
|
+
const formatting_1 = require("./formatting");
|
|
10
12
|
exports.TEMPLATE_SYNC_CONFIG = "templatesync";
|
|
11
13
|
exports.TEMPLATE_SYNC_LOCAL_CONFIG = "templatesync.local";
|
|
12
14
|
async function templateSync(options) {
|
|
13
15
|
const cloneDriver = options.cloneDriver ?? git_clone_1.gitClone;
|
|
14
16
|
const diffDriver = options.diffDriver ?? diff_drivers_1.gitDiff;
|
|
17
|
+
const currentRefDriver = options.currentRefDriver ?? ref_drivers_1.gitCurrentRef;
|
|
15
18
|
const tempCloneDir = await cloneDriver(options.tmpCloneDir, options.repoUrl);
|
|
16
19
|
// Get the clone Config
|
|
17
20
|
const cloneConfigPath = (0, path_1.join)(tempCloneDir, `${exports.TEMPLATE_SYNC_CONFIG}.json`);
|
|
@@ -48,6 +51,21 @@ async function templateSync(options) {
|
|
|
48
51
|
localFileChanges[f] = result.localChanges;
|
|
49
52
|
}
|
|
50
53
|
}));
|
|
54
|
+
// apply after ref
|
|
55
|
+
if (options.updateAfterRef) {
|
|
56
|
+
const ref = await currentRefDriver({
|
|
57
|
+
rootDir: tempCloneDir,
|
|
58
|
+
});
|
|
59
|
+
if ((0, fs_1.existsSync)(localConfigPath)) {
|
|
60
|
+
const configStr = (0, fs_1.readFileSync)(localConfigPath).toString();
|
|
61
|
+
const config = JSON.parse(configStr);
|
|
62
|
+
config.afterRef = ref;
|
|
63
|
+
(0, fs_1.writeFileSync)(localConfigPath, JSON.stringify(config, null, (0, formatting_1.inferJSONIndent)(configStr)));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
(0, fs_1.writeFileSync)(localConfigPath, JSON.stringify({ afterRef: ref }, null, 4));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
51
69
|
return {
|
|
52
70
|
localSkipFiles,
|
|
53
71
|
localFileChanges,
|
|
@@ -82,11 +82,11 @@ async function merge(current, fromTemplateRepo, context) {
|
|
|
82
82
|
const fromTemplateJson = JSON.parse(fromTemplateRepo);
|
|
83
83
|
if (context.mergeArguments === "merge-current") {
|
|
84
84
|
// Performs Lodash Merge with current as the override
|
|
85
|
-
return JSON.stringify((0, lodash_merge_1.default)(fromTemplateJson, currentJson), null,
|
|
85
|
+
return JSON.stringify((0, lodash_merge_1.default)(fromTemplateJson, currentJson), null, (0, infer_json_indent_1.inferJSONIndent)(current));
|
|
86
86
|
}
|
|
87
87
|
if (context.mergeArguments === "merge-template") {
|
|
88
88
|
// Performs Lodash Merge with current as the override
|
|
89
|
-
return JSON.stringify((0, lodash_merge_1.default)(currentJson, fromTemplateJson), null,
|
|
89
|
+
return JSON.stringify((0, lodash_merge_1.default)(currentJson, fromTemplateJson), null, (0, infer_json_indent_1.inferJSONIndent)(current));
|
|
90
90
|
}
|
|
91
91
|
const { missingIsDelete, ignoreNewProperties, paths } = context.mergeArguments;
|
|
92
92
|
const returnJson = (0, lodash_clonedeep_1.default)(currentJson);
|
|
@@ -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);
|
package/lib/esm/template-sync.js
CHANGED
|
@@ -7,11 +7,14 @@ const match_1 = require("./match");
|
|
|
7
7
|
const merge_file_1 = require("./merge-file");
|
|
8
8
|
const git_clone_1 = require("./clone-drivers/git-clone");
|
|
9
9
|
const diff_drivers_1 = require("./diff-drivers");
|
|
10
|
+
const ref_drivers_1 = require("./ref-drivers");
|
|
11
|
+
const formatting_1 = require("./formatting");
|
|
10
12
|
exports.TEMPLATE_SYNC_CONFIG = "templatesync";
|
|
11
13
|
exports.TEMPLATE_SYNC_LOCAL_CONFIG = "templatesync.local";
|
|
12
14
|
async function templateSync(options) {
|
|
13
15
|
const cloneDriver = options.cloneDriver ?? git_clone_1.gitClone;
|
|
14
16
|
const diffDriver = options.diffDriver ?? diff_drivers_1.gitDiff;
|
|
17
|
+
const currentRefDriver = options.currentRefDriver ?? ref_drivers_1.gitCurrentRef;
|
|
15
18
|
const tempCloneDir = await cloneDriver(options.tmpCloneDir, options.repoUrl);
|
|
16
19
|
// Get the clone Config
|
|
17
20
|
const cloneConfigPath = (0, path_1.join)(tempCloneDir, `${exports.TEMPLATE_SYNC_CONFIG}.json`);
|
|
@@ -48,6 +51,21 @@ async function templateSync(options) {
|
|
|
48
51
|
localFileChanges[f] = result.localChanges;
|
|
49
52
|
}
|
|
50
53
|
}));
|
|
54
|
+
// apply after ref
|
|
55
|
+
if (options.updateAfterRef) {
|
|
56
|
+
const ref = await currentRefDriver({
|
|
57
|
+
rootDir: tempCloneDir,
|
|
58
|
+
});
|
|
59
|
+
if ((0, fs_1.existsSync)(localConfigPath)) {
|
|
60
|
+
const configStr = (0, fs_1.readFileSync)(localConfigPath).toString();
|
|
61
|
+
const config = JSON.parse(configStr);
|
|
62
|
+
config.afterRef = ref;
|
|
63
|
+
(0, fs_1.writeFileSync)(localConfigPath, JSON.stringify(config, null, (0, formatting_1.inferJSONIndent)(configStr)));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
(0, fs_1.writeFileSync)(localConfigPath, JSON.stringify({ afterRef: ref }, null, 4));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
51
69
|
return {
|
|
52
70
|
localSkipFiles,
|
|
53
71
|
localFileChanges,
|
package/package.json
CHANGED
|
@@ -93,12 +93,20 @@ export async function merge(
|
|
|
93
93
|
|
|
94
94
|
if (context.mergeArguments === "merge-current") {
|
|
95
95
|
// Performs Lodash Merge with current as the override
|
|
96
|
-
return JSON.stringify(
|
|
96
|
+
return JSON.stringify(
|
|
97
|
+
lodashMerge(fromTemplateJson, currentJson),
|
|
98
|
+
null,
|
|
99
|
+
inferJSONIndent(current),
|
|
100
|
+
);
|
|
97
101
|
}
|
|
98
102
|
|
|
99
103
|
if (context.mergeArguments === "merge-template") {
|
|
100
104
|
// Performs Lodash Merge with current as the override
|
|
101
|
-
return JSON.stringify(
|
|
105
|
+
return JSON.stringify(
|
|
106
|
+
lodashMerge(currentJson, fromTemplateJson),
|
|
107
|
+
null,
|
|
108
|
+
inferJSONIndent(current),
|
|
109
|
+
);
|
|
102
110
|
}
|
|
103
111
|
|
|
104
112
|
const { missingIsDelete, ignoreNewProperties, paths } =
|
|
@@ -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 @@
|
|
|
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
|
package/src/template-sync.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { join } from "path";
|
|
2
|
-
import { existsSync, readFileSync } from "fs";
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
3
3
|
import { getAllFilesInDir } from "./match";
|
|
4
4
|
import { Config, LocalConfig } from "./types";
|
|
5
5
|
import { mergeFile } from "./merge-file";
|
|
@@ -7,6 +7,9 @@ import { gitClone } from "./clone-drivers/git-clone";
|
|
|
7
7
|
import { Change } from "diff";
|
|
8
8
|
import { TemplateCloneDriverFn } from "./clone-drivers";
|
|
9
9
|
import { TemplateDiffDriverFn, gitDiff } from "./diff-drivers";
|
|
10
|
+
import { gitCurrentRef } from "./ref-drivers";
|
|
11
|
+
import { TemplateRefDriverFn } from "./ref-drivers/types";
|
|
12
|
+
import { inferJSONIndent } from "./formatting";
|
|
10
13
|
|
|
11
14
|
export interface TemplateSyncOptions {
|
|
12
15
|
repoUrl: string;
|
|
@@ -21,6 +24,12 @@ export interface TemplateSyncOptions {
|
|
|
21
24
|
*/
|
|
22
25
|
repoDir: string;
|
|
23
26
|
|
|
27
|
+
/**
|
|
28
|
+
* If set to true, template sync will apply the current ref
|
|
29
|
+
* of the template repo to afterRef
|
|
30
|
+
*/
|
|
31
|
+
updateAfterRef?: boolean;
|
|
32
|
+
|
|
24
33
|
/**
|
|
25
34
|
* Defaults to using git clone
|
|
26
35
|
*/
|
|
@@ -30,6 +39,11 @@ export interface TemplateSyncOptions {
|
|
|
30
39
|
* Defaults to using git diff
|
|
31
40
|
*/
|
|
32
41
|
diffDriver?: TemplateDiffDriverFn;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Defaults to using git current ref
|
|
45
|
+
*/
|
|
46
|
+
currentRefDriver?: TemplateRefDriverFn;
|
|
33
47
|
}
|
|
34
48
|
|
|
35
49
|
export interface TemplateSyncReturn {
|
|
@@ -56,6 +70,7 @@ export async function templateSync(
|
|
|
56
70
|
): Promise<TemplateSyncReturn> {
|
|
57
71
|
const cloneDriver = options.cloneDriver ?? gitClone;
|
|
58
72
|
const diffDriver = options.diffDriver ?? gitDiff;
|
|
73
|
+
const currentRefDriver = options.currentRefDriver ?? gitCurrentRef;
|
|
59
74
|
const tempCloneDir = await cloneDriver(options.tmpCloneDir, options.repoUrl);
|
|
60
75
|
|
|
61
76
|
// Get the clone Config
|
|
@@ -106,6 +121,28 @@ export async function templateSync(
|
|
|
106
121
|
}),
|
|
107
122
|
);
|
|
108
123
|
|
|
124
|
+
// apply after ref
|
|
125
|
+
if (options.updateAfterRef) {
|
|
126
|
+
const ref = await currentRefDriver({
|
|
127
|
+
rootDir: tempCloneDir,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
if (existsSync(localConfigPath)) {
|
|
131
|
+
const configStr = readFileSync(localConfigPath).toString();
|
|
132
|
+
const config = JSON.parse(configStr) as LocalConfig;
|
|
133
|
+
config.afterRef = ref;
|
|
134
|
+
writeFileSync(
|
|
135
|
+
localConfigPath,
|
|
136
|
+
JSON.stringify(config, null, inferJSONIndent(configStr)),
|
|
137
|
+
);
|
|
138
|
+
} else {
|
|
139
|
+
writeFileSync(
|
|
140
|
+
localConfigPath,
|
|
141
|
+
JSON.stringify({ afterRef: ref }, null, 4),
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
109
146
|
return {
|
|
110
147
|
localSkipFiles,
|
|
111
148
|
localFileChanges,
|