keycloakify 11.6.0 → 11.6.2
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/bin/{805.index.js → 174.index.js} +111 -2
- package/bin/363.index.js +1528 -0
- package/bin/453.index.js +1 -1
- package/bin/{33.index.js → 568.index.js} +2 -113
- package/bin/735.index.js +53 -24
- package/bin/{653.index.js → 840.index.js} +387 -213
- package/bin/921.index.js +1 -1
- package/bin/930.index.js +165 -0
- package/bin/946.index.js +20 -0
- package/bin/initialize-admin-theme.d.ts +4 -0
- package/bin/main.js +72 -18
- package/bin/{eject-file.d.ts → own.d.ts} +2 -1
- package/bin/shared/addSyncExtensionsToPostinstallScript.d.ts +10 -0
- package/bin/shared/customHandler.d.ts +1 -1
- package/bin/shared/customHandler.js.map +1 -1
- package/bin/{postinstall/uiModuleMeta.d.ts → sync-extensions/extensionModuleMeta.d.ts} +5 -5
- package/bin/sync-extensions/getExtensionModuleFileSourceCodeReadyToBeCopied.d.ts +12 -0
- package/bin/sync-extensions/index.d.ts +1 -0
- package/bin/{postinstall/installUiModulesPeerDependencies.d.ts → sync-extensions/installExtensionModulesPeerDependencies.d.ts} +3 -3
- package/bin/{postinstall → sync-extensions}/managedGitignoreFile.d.ts +4 -4
- package/bin/tools/isKnownByGit.d.ts +3 -0
- package/bin/tools/npmInstall.d.ts +1 -1
- package/package.json +27 -22
- package/src/bin/eject-page.ts +1 -3
- package/src/bin/initialize-account-theme/initializeAccountTheme_singlePage.ts +3 -1
- package/src/bin/initialize-admin-theme.ts +146 -0
- package/src/bin/main.ts +76 -17
- package/src/bin/own.ts +209 -0
- package/src/bin/shared/addSyncExtensionsToPostinstallScript.ts +70 -0
- package/src/bin/shared/customHandler.ts +1 -0
- package/src/bin/{postinstall/uiModuleMeta.ts → sync-extensions/extensionModuleMeta.ts} +55 -43
- package/src/bin/{postinstall/getUiModuleFileSourceCodeReadyToBeCopied.ts → sync-extensions/getExtensionModuleFileSourceCodeReadyToBeCopied.ts} +32 -21
- package/src/bin/sync-extensions/index.ts +1 -0
- package/src/bin/{postinstall/installUiModulesPeerDependencies.ts → sync-extensions/installExtensionModulesPeerDependencies.ts} +16 -14
- package/src/bin/{postinstall → sync-extensions}/managedGitignoreFile.ts +18 -18
- package/src/bin/{postinstall/postinstall.ts → sync-extensions/sync-extension.ts} +14 -26
- package/src/bin/tools/isKnownByGit.ts +45 -0
- package/src/bin/tools/listInstalledModules.ts +2 -2
- package/src/bin/tools/npmInstall.ts +46 -9
- package/src/bin/tools/untrackFromGit.ts +19 -3
- package/bin/356.index.js +0 -755
- package/bin/854.index.js +0 -68
- package/bin/postinstall/getUiModuleFileSourceCodeReadyToBeCopied.d.ts +0 -12
- package/bin/postinstall/index.d.ts +0 -1
- package/bin/tools/isTrackedByGit.d.ts +0 -3
- package/src/bin/eject-file.ts +0 -68
- package/src/bin/postinstall/index.ts +0 -1
- package/src/bin/tools/isTrackedByGit.ts +0 -29
- /package/bin/{postinstall/postinstall.d.ts → sync-extensions/sync-extension.d.ts} +0 -0
@@ -10,14 +10,15 @@ import { crawlAsync } from "../tools/crawlAsync";
|
|
10
10
|
import { getIsPrettierAvailable, getPrettier } from "../tools/runPrettier";
|
11
11
|
import { readThisNpmPackageVersion } from "../tools/readThisNpmPackageVersion";
|
12
12
|
import {
|
13
|
-
|
14
|
-
type BuildContextLike as
|
15
|
-
} from "./
|
13
|
+
getExtensionModuleFileSourceCodeReadyToBeCopied,
|
14
|
+
type BuildContextLike as BuildContextLike_getExtensionModuleFileSourceCodeReadyToBeCopied
|
15
|
+
} from "./getExtensionModuleFileSourceCodeReadyToBeCopied";
|
16
16
|
import * as crypto from "crypto";
|
17
17
|
import { KEYCLOAK_THEME } from "../shared/constants";
|
18
18
|
import { exclude } from "tsafe/exclude";
|
19
|
+
import { isAmong } from "tsafe/isAmong";
|
19
20
|
|
20
|
-
export type
|
21
|
+
export type ExtensionModuleMeta = {
|
21
22
|
moduleName: string;
|
22
23
|
version: string;
|
23
24
|
files: {
|
@@ -28,8 +29,8 @@ export type UiModuleMeta = {
|
|
28
29
|
peerDependencies: Record<string, string>;
|
29
30
|
};
|
30
31
|
|
31
|
-
const
|
32
|
-
type ExpectedType =
|
32
|
+
const zExtensionModuleMeta = (() => {
|
33
|
+
type ExpectedType = ExtensionModuleMeta;
|
33
34
|
|
34
35
|
const zTargetType = z.object({
|
35
36
|
moduleName: z.string(),
|
@@ -55,7 +56,7 @@ type ParsedCacheFile = {
|
|
55
56
|
keycloakifyVersion: string;
|
56
57
|
prettierConfigHash: string | null;
|
57
58
|
thisFilePath: string;
|
58
|
-
|
59
|
+
extensionModuleMetas: ExtensionModuleMeta[];
|
59
60
|
};
|
60
61
|
|
61
62
|
const zParsedCacheFile = (() => {
|
@@ -65,7 +66,7 @@ const zParsedCacheFile = (() => {
|
|
65
66
|
keycloakifyVersion: z.string(),
|
66
67
|
prettierConfigHash: z.union([z.string(), z.null()]),
|
67
68
|
thisFilePath: z.string(),
|
68
|
-
|
69
|
+
extensionModuleMetas: z.array(zExtensionModuleMeta)
|
69
70
|
});
|
70
71
|
|
71
72
|
type InferredType = z.infer<typeof zTargetType>;
|
@@ -75,10 +76,10 @@ const zParsedCacheFile = (() => {
|
|
75
76
|
return id<z.ZodType<ExpectedType>>(zTargetType);
|
76
77
|
})();
|
77
78
|
|
78
|
-
const CACHE_FILE_RELATIVE_PATH = pathJoin("
|
79
|
+
const CACHE_FILE_RELATIVE_PATH = pathJoin("extension-modules", "cache.json");
|
79
80
|
|
80
81
|
export type BuildContextLike =
|
81
|
-
|
82
|
+
BuildContextLike_getExtensionModuleFileSourceCodeReadyToBeCopied & {
|
82
83
|
cacheDirPath: string;
|
83
84
|
packageJsonFilePath: string;
|
84
85
|
projectDirPath: string;
|
@@ -86,9 +87,9 @@ export type BuildContextLike =
|
|
86
87
|
|
87
88
|
assert<BuildContext extends BuildContextLike ? true : false>();
|
88
89
|
|
89
|
-
export async function
|
90
|
+
export async function getExtensionModuleMetas(params: {
|
90
91
|
buildContext: BuildContextLike;
|
91
|
-
}): Promise<
|
92
|
+
}): Promise<ExtensionModuleMeta[]> {
|
92
93
|
const { buildContext } = params;
|
93
94
|
|
94
95
|
const cacheFilePath = pathJoin(buildContext.cacheDirPath, CACHE_FILE_RELATIVE_PATH);
|
@@ -105,7 +106,7 @@ export async function getUiModuleMetas(params: {
|
|
105
106
|
return configHash;
|
106
107
|
})();
|
107
108
|
|
108
|
-
const
|
109
|
+
const installedExtensionModules = await (async () => {
|
109
110
|
const installedModulesWithKeycloakifyInTheName = await listInstalledModules({
|
110
111
|
packageJsonFilePath: buildContext.packageJsonFilePath,
|
111
112
|
projectDirPath: buildContext.packageJsonFilePath,
|
@@ -133,7 +134,7 @@ export async function getUiModuleMetas(params: {
|
|
133
134
|
return await fsPr.readFile(cacheFilePath);
|
134
135
|
})();
|
135
136
|
|
136
|
-
const
|
137
|
+
const extensionModuleMetas_cacheUpToDate: ExtensionModuleMeta[] = await (async () => {
|
137
138
|
const parsedCacheFile: ParsedCacheFile | undefined = await (async () => {
|
138
139
|
if (cacheContent === undefined) {
|
139
140
|
return undefined;
|
@@ -176,45 +177,51 @@ export async function getUiModuleMetas(params: {
|
|
176
177
|
return [];
|
177
178
|
}
|
178
179
|
|
179
|
-
const
|
180
|
-
|
181
|
-
const
|
182
|
-
|
183
|
-
|
184
|
-
|
180
|
+
const extensionModuleMetas_cacheUpToDate =
|
181
|
+
parsedCacheFile.extensionModuleMetas.filter(extensionModuleMeta => {
|
182
|
+
const correspondingInstalledExtensionModule =
|
183
|
+
installedExtensionModules.find(
|
184
|
+
installedExtensionModule =>
|
185
|
+
installedExtensionModule.moduleName ===
|
186
|
+
extensionModuleMeta.moduleName
|
187
|
+
);
|
185
188
|
|
186
|
-
if (
|
189
|
+
if (correspondingInstalledExtensionModule === undefined) {
|
187
190
|
return false;
|
188
191
|
}
|
189
192
|
|
190
|
-
return
|
191
|
-
|
192
|
-
|
193
|
+
return (
|
194
|
+
correspondingInstalledExtensionModule.version ===
|
195
|
+
extensionModuleMeta.version
|
196
|
+
);
|
197
|
+
});
|
193
198
|
|
194
|
-
return
|
199
|
+
return extensionModuleMetas_cacheUpToDate;
|
195
200
|
})();
|
196
201
|
|
197
|
-
const
|
198
|
-
|
202
|
+
const extensionModuleMetas = await Promise.all(
|
203
|
+
installedExtensionModules.map(
|
199
204
|
async ({
|
200
205
|
moduleName,
|
201
206
|
version,
|
202
207
|
peerDependencies,
|
203
208
|
dirPath
|
204
|
-
}): Promise<
|
209
|
+
}): Promise<ExtensionModuleMeta> => {
|
205
210
|
use_cache: {
|
206
|
-
const
|
207
|
-
|
208
|
-
|
211
|
+
const extensionModuleMeta_cache =
|
212
|
+
extensionModuleMetas_cacheUpToDate.find(
|
213
|
+
extensionModuleMeta =>
|
214
|
+
extensionModuleMeta.moduleName === moduleName
|
215
|
+
);
|
209
216
|
|
210
|
-
if (
|
217
|
+
if (extensionModuleMeta_cache === undefined) {
|
211
218
|
break use_cache;
|
212
219
|
}
|
213
220
|
|
214
|
-
return
|
221
|
+
return extensionModuleMeta_cache;
|
215
222
|
}
|
216
223
|
|
217
|
-
const files:
|
224
|
+
const files: ExtensionModuleMeta["files"] = [];
|
218
225
|
|
219
226
|
{
|
220
227
|
const srcDirPath = pathJoin(dirPath, KEYCLOAK_THEME);
|
@@ -224,13 +231,13 @@ export async function getUiModuleMetas(params: {
|
|
224
231
|
returnedPathsType: "relative to dirPath",
|
225
232
|
onFileFound: async fileRelativePath => {
|
226
233
|
const sourceCode =
|
227
|
-
await
|
234
|
+
await getExtensionModuleFileSourceCodeReadyToBeCopied({
|
228
235
|
buildContext,
|
229
236
|
fileRelativePath,
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
237
|
+
isOwnershipAction: false,
|
238
|
+
extensionModuleDirPath: dirPath,
|
239
|
+
extensionModuleName: moduleName,
|
240
|
+
extensionModuleVersion: version
|
234
241
|
});
|
235
242
|
|
236
243
|
const hash = computeHash(sourceCode);
|
@@ -260,11 +267,16 @@ export async function getUiModuleMetas(params: {
|
|
260
267
|
});
|
261
268
|
}
|
262
269
|
|
263
|
-
return id<
|
270
|
+
return id<ExtensionModuleMeta>({
|
264
271
|
moduleName,
|
265
272
|
version,
|
266
273
|
files,
|
267
|
-
peerDependencies
|
274
|
+
peerDependencies: Object.fromEntries(
|
275
|
+
Object.entries(peerDependencies).filter(
|
276
|
+
([moduleName]) =>
|
277
|
+
!isAmong(["react", "@types/react"], moduleName)
|
278
|
+
)
|
279
|
+
)
|
268
280
|
});
|
269
281
|
}
|
270
282
|
)
|
@@ -275,7 +287,7 @@ export async function getUiModuleMetas(params: {
|
|
275
287
|
keycloakifyVersion,
|
276
288
|
prettierConfigHash,
|
277
289
|
thisFilePath: cacheFilePath,
|
278
|
-
|
290
|
+
extensionModuleMetas
|
279
291
|
});
|
280
292
|
|
281
293
|
const cacheContent_new = Buffer.from(
|
@@ -300,7 +312,7 @@ export async function getUiModuleMetas(params: {
|
|
300
312
|
await fsPr.writeFile(cacheFilePath, cacheContent_new);
|
301
313
|
}
|
302
314
|
|
303
|
-
return
|
315
|
+
return extensionModuleMetas;
|
304
316
|
}
|
305
317
|
|
306
318
|
export function computeHash(data: Buffer) {
|
@@ -11,40 +11,51 @@ export type BuildContextLike = {
|
|
11
11
|
|
12
12
|
assert<BuildContext extends BuildContextLike ? true : false>();
|
13
13
|
|
14
|
-
export async function
|
14
|
+
export async function getExtensionModuleFileSourceCodeReadyToBeCopied(params: {
|
15
15
|
buildContext: BuildContextLike;
|
16
16
|
fileRelativePath: string;
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
isOwnershipAction: boolean;
|
18
|
+
extensionModuleDirPath: string;
|
19
|
+
extensionModuleName: string;
|
20
|
+
extensionModuleVersion: string;
|
21
21
|
}): Promise<Buffer> {
|
22
22
|
const {
|
23
23
|
buildContext,
|
24
|
-
|
24
|
+
extensionModuleDirPath,
|
25
25
|
fileRelativePath,
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
isOwnershipAction,
|
27
|
+
extensionModuleName,
|
28
|
+
extensionModuleVersion
|
29
29
|
} = params;
|
30
30
|
|
31
31
|
let sourceCode = (
|
32
|
-
await fsPr.readFile(
|
32
|
+
await fsPr.readFile(
|
33
|
+
pathJoin(extensionModuleDirPath, KEYCLOAK_THEME, fileRelativePath)
|
34
|
+
)
|
33
35
|
).toString("utf8");
|
34
36
|
|
35
37
|
sourceCode = addCommentToSourceCode({
|
36
38
|
sourceCode,
|
37
39
|
fileRelativePath,
|
38
|
-
commentLines:
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
40
|
+
commentLines: (() => {
|
41
|
+
const path = fileRelativePath.split(pathSep).join("/");
|
42
|
+
|
43
|
+
return isOwnershipAction
|
44
|
+
? [
|
45
|
+
`This file has been claimed for ownership from ${extensionModuleName} version ${extensionModuleVersion}.`,
|
46
|
+
`To relinquish ownership and restore this file to its original content, run the following command:`,
|
47
|
+
``,
|
48
|
+
`$ npx keycloakify own --path '${path}' --revert`
|
49
|
+
]
|
50
|
+
: [
|
51
|
+
`WARNING: Before modifying this file, run the following command:`,
|
52
|
+
``,
|
53
|
+
`$ npx keycloakify own --path '${path}'`,
|
54
|
+
``,
|
55
|
+
`This file is provided by ${extensionModuleName} version ${extensionModuleVersion}.`,
|
56
|
+
`It was copied into your repository by the postinstall script: \`keycloakify sync-extensions\`.`
|
57
|
+
];
|
58
|
+
})()
|
48
59
|
});
|
49
60
|
|
50
61
|
const destFilePath = pathJoin(buildContext.themeSrcDirPath, fileRelativePath);
|
@@ -93,7 +104,7 @@ function addCommentToSourceCode(params: {
|
|
93
104
|
`<!--`,
|
94
105
|
...commentLines.map(
|
95
106
|
line =>
|
96
|
-
` ${line.replace("--
|
107
|
+
` ${line.replace("--path", "-p").replace("Before modifying", "Before modifying or replacing")}`
|
97
108
|
),
|
98
109
|
`-->`
|
99
110
|
].join("\n");
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from "./sync-extension";
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { assert, type Equals, is } from "tsafe/assert";
|
2
2
|
import type { BuildContext } from "../shared/buildContext";
|
3
|
-
import type {
|
3
|
+
import type { ExtensionModuleMeta } from "./extensionModuleMeta";
|
4
4
|
import { z } from "zod";
|
5
5
|
import { id } from "tsafe/id";
|
6
6
|
import * as fsPr from "fs/promises";
|
@@ -16,29 +16,29 @@ export type BuildContextLike = {
|
|
16
16
|
|
17
17
|
assert<BuildContext extends BuildContextLike ? true : false>();
|
18
18
|
|
19
|
-
export type
|
19
|
+
export type ExtensionModuleMetaLike = {
|
20
20
|
moduleName: string;
|
21
21
|
peerDependencies: Record<string, string>;
|
22
22
|
};
|
23
23
|
|
24
|
-
assert<
|
24
|
+
assert<ExtensionModuleMeta extends ExtensionModuleMetaLike ? true : false>();
|
25
25
|
|
26
|
-
export async function
|
26
|
+
export async function installExtensionModulesPeerDependencies(params: {
|
27
27
|
buildContext: BuildContextLike;
|
28
|
-
|
28
|
+
extensionModuleMetas: ExtensionModuleMetaLike[];
|
29
29
|
}): Promise<void | never> {
|
30
|
-
const { buildContext,
|
30
|
+
const { buildContext, extensionModuleMetas } = params;
|
31
31
|
|
32
|
-
const {
|
33
|
-
const
|
32
|
+
const { extensionModulesPerDependencies } = (() => {
|
33
|
+
const extensionModulesPerDependencies: Record<string, string> = {};
|
34
34
|
|
35
|
-
for (const { peerDependencies } of
|
35
|
+
for (const { peerDependencies } of extensionModuleMetas) {
|
36
36
|
for (const [peerDependencyName, versionRange_candidate] of Object.entries(
|
37
37
|
peerDependencies
|
38
38
|
)) {
|
39
39
|
const versionRange = (() => {
|
40
40
|
const versionRange_current =
|
41
|
-
|
41
|
+
extensionModulesPerDependencies[peerDependencyName];
|
42
42
|
|
43
43
|
if (versionRange_current === undefined) {
|
44
44
|
return versionRange_candidate;
|
@@ -76,11 +76,11 @@ export async function installUiModulesPeerDependencies(params: {
|
|
76
76
|
return versionRange;
|
77
77
|
})();
|
78
78
|
|
79
|
-
|
79
|
+
extensionModulesPerDependencies[peerDependencyName] = versionRange;
|
80
80
|
}
|
81
81
|
}
|
82
82
|
|
83
|
-
return {
|
83
|
+
return { extensionModulesPerDependencies };
|
84
84
|
})();
|
85
85
|
|
86
86
|
const parsedPackageJson = await (async () => {
|
@@ -117,7 +117,9 @@ export async function installUiModulesPeerDependencies(params: {
|
|
117
117
|
|
118
118
|
const parsedPackageJson_before = JSON.parse(JSON.stringify(parsedPackageJson));
|
119
119
|
|
120
|
-
for (const [moduleName, versionRange] of Object.entries(
|
120
|
+
for (const [moduleName, versionRange] of Object.entries(
|
121
|
+
extensionModulesPerDependencies
|
122
|
+
)) {
|
121
123
|
if (moduleName.startsWith("@types/")) {
|
122
124
|
(parsedPackageJson.devDependencies ??= {})[moduleName] = versionRange;
|
123
125
|
continue;
|
@@ -149,7 +151,7 @@ export async function installUiModulesPeerDependencies(params: {
|
|
149
151
|
|
150
152
|
await fsPr.writeFile(buildContext.packageJsonFilePath, packageJsonContentStr);
|
151
153
|
|
152
|
-
npmInstall({
|
154
|
+
await npmInstall({
|
153
155
|
packageJsonDirPath: pathDirname(buildContext.packageJsonFilePath)
|
154
156
|
});
|
155
157
|
|
@@ -7,7 +7,7 @@ import {
|
|
7
7
|
} from "path";
|
8
8
|
import { assert } from "tsafe/assert";
|
9
9
|
import type { BuildContext } from "../shared/buildContext";
|
10
|
-
import type {
|
10
|
+
import type { ExtensionModuleMeta } from "./extensionModuleMeta";
|
11
11
|
import { existsAsync } from "../tools/fs.existsAsync";
|
12
12
|
import { getAbsoluteAndInOsFormatPath } from "../tools/getAbsoluteAndInOsFormatPath";
|
13
13
|
|
@@ -17,17 +17,17 @@ export type BuildContextLike = {
|
|
17
17
|
|
18
18
|
assert<BuildContext extends BuildContextLike ? true : false>();
|
19
19
|
|
20
|
-
const DELIMITER_START = `# ===
|
21
|
-
const DELIMITER_END = `# ===
|
20
|
+
const DELIMITER_START = `# === Owned files start ===`;
|
21
|
+
const DELIMITER_END = `# === Owned files end =====`;
|
22
22
|
|
23
23
|
export async function writeManagedGitignoreFile(params: {
|
24
24
|
buildContext: BuildContextLike;
|
25
|
-
|
26
|
-
|
25
|
+
extensionModuleMetas: ExtensionModuleMeta[];
|
26
|
+
ownedFilesRelativePaths: string[];
|
27
27
|
}): Promise<void> {
|
28
|
-
const { buildContext,
|
28
|
+
const { buildContext, extensionModuleMetas, ownedFilesRelativePaths } = params;
|
29
29
|
|
30
|
-
if (
|
30
|
+
if (extensionModuleMetas.length === 0) {
|
31
31
|
return;
|
32
32
|
}
|
33
33
|
|
@@ -38,19 +38,19 @@ export async function writeManagedGitignoreFile(params: {
|
|
38
38
|
`# This file is managed by Keycloakify, do not edit it manually.`,
|
39
39
|
``,
|
40
40
|
DELIMITER_START,
|
41
|
-
...
|
41
|
+
...ownedFilesRelativePaths
|
42
42
|
.map(fileRelativePath => fileRelativePath.split(pathSep).join("/"))
|
43
43
|
.map(line => `# ${line}`),
|
44
44
|
DELIMITER_END,
|
45
45
|
``,
|
46
|
-
...
|
47
|
-
.map(
|
48
|
-
`# === ${
|
49
|
-
...
|
46
|
+
...extensionModuleMetas
|
47
|
+
.map(extensionModuleMeta => [
|
48
|
+
`# === ${extensionModuleMeta.moduleName} v${extensionModuleMeta.version} ===`,
|
49
|
+
...extensionModuleMeta.files
|
50
50
|
.map(({ fileRelativePath }) => fileRelativePath)
|
51
51
|
.filter(
|
52
52
|
fileRelativePath =>
|
53
|
-
!
|
53
|
+
!ownedFilesRelativePaths.includes(fileRelativePath)
|
54
54
|
)
|
55
55
|
.map(
|
56
56
|
fileRelativePath =>
|
@@ -92,14 +92,14 @@ export async function writeManagedGitignoreFile(params: {
|
|
92
92
|
export async function readManagedGitignoreFile(params: {
|
93
93
|
buildContext: BuildContextLike;
|
94
94
|
}): Promise<{
|
95
|
-
|
95
|
+
ownedFilesRelativePaths: string[];
|
96
96
|
}> {
|
97
97
|
const { buildContext } = params;
|
98
98
|
|
99
99
|
const filePath = pathJoin(buildContext.themeSrcDirPath, ".gitignore");
|
100
100
|
|
101
101
|
if (!(await existsAsync(filePath))) {
|
102
|
-
return {
|
102
|
+
return { ownedFilesRelativePaths: [] };
|
103
103
|
}
|
104
104
|
|
105
105
|
const contentStr = (await fsPr.readFile(filePath)).toString("utf8");
|
@@ -116,10 +116,10 @@ export async function readManagedGitignoreFile(params: {
|
|
116
116
|
})();
|
117
117
|
|
118
118
|
if (payload === undefined) {
|
119
|
-
return {
|
119
|
+
return { ownedFilesRelativePaths: [] };
|
120
120
|
}
|
121
121
|
|
122
|
-
const
|
122
|
+
const ownedFilesRelativePaths = payload
|
123
123
|
.split("\n")
|
124
124
|
.map(line => line.trim())
|
125
125
|
.map(line => line.replace(/^# /, ""))
|
@@ -132,5 +132,5 @@ export async function readManagedGitignoreFile(params: {
|
|
132
132
|
)
|
133
133
|
.map(filePath => pathRelative(buildContext.themeSrcDirPath, filePath));
|
134
134
|
|
135
|
-
return {
|
135
|
+
return { ownedFilesRelativePaths };
|
136
136
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import type { BuildContext } from "../shared/buildContext";
|
2
|
-
import {
|
3
|
-
import {
|
2
|
+
import { getExtensionModuleMetas, computeHash } from "./extensionModuleMeta";
|
3
|
+
import { installExtensionModulesPeerDependencies } from "./installExtensionModulesPeerDependencies";
|
4
4
|
import {
|
5
5
|
readManagedGitignoreFile,
|
6
6
|
writeManagedGitignoreFile
|
@@ -9,36 +9,36 @@ import { dirname as pathDirname } from "path";
|
|
9
9
|
import { join as pathJoin } from "path";
|
10
10
|
import { existsAsync } from "../tools/fs.existsAsync";
|
11
11
|
import * as fsPr from "fs/promises";
|
12
|
-
import {
|
12
|
+
import { getIsKnownByGit } from "../tools/isKnownByGit";
|
13
13
|
import { untrackFromGit } from "../tools/untrackFromGit";
|
14
14
|
|
15
15
|
export async function command(params: { buildContext: BuildContext }) {
|
16
16
|
const { buildContext } = params;
|
17
17
|
|
18
|
-
const
|
18
|
+
const extensionModuleMetas = await getExtensionModuleMetas({ buildContext });
|
19
19
|
|
20
|
-
await
|
20
|
+
await installExtensionModulesPeerDependencies({
|
21
21
|
buildContext,
|
22
|
-
|
22
|
+
extensionModuleMetas
|
23
23
|
});
|
24
24
|
|
25
|
-
const {
|
25
|
+
const { ownedFilesRelativePaths } = await readManagedGitignoreFile({
|
26
26
|
buildContext
|
27
27
|
});
|
28
28
|
|
29
29
|
await writeManagedGitignoreFile({
|
30
30
|
buildContext,
|
31
|
-
|
32
|
-
|
31
|
+
ownedFilesRelativePaths,
|
32
|
+
extensionModuleMetas
|
33
33
|
});
|
34
34
|
|
35
35
|
await Promise.all(
|
36
|
-
|
37
|
-
.map(
|
36
|
+
extensionModuleMetas
|
37
|
+
.map(extensionModuleMeta =>
|
38
38
|
Promise.all(
|
39
|
-
|
39
|
+
extensionModuleMeta.files.map(
|
40
40
|
async ({ fileRelativePath, copyableFilePath, hash }) => {
|
41
|
-
if (
|
41
|
+
if (ownedFilesRelativePaths.includes(fileRelativePath)) {
|
42
42
|
return;
|
43
43
|
}
|
44
44
|
|
@@ -65,19 +65,7 @@ export async function command(params: { buildContext: BuildContext }) {
|
|
65
65
|
return;
|
66
66
|
}
|
67
67
|
|
68
|
-
|
69
|
-
if (!doesFileExist) {
|
70
|
-
break git_untrack;
|
71
|
-
}
|
72
|
-
|
73
|
-
const isTracked = await getIsTrackedByGit({
|
74
|
-
filePath: destFilePath
|
75
|
-
});
|
76
|
-
|
77
|
-
if (!isTracked) {
|
78
|
-
break git_untrack;
|
79
|
-
}
|
80
|
-
|
68
|
+
if (await getIsKnownByGit({ filePath: destFilePath })) {
|
81
69
|
await untrackFromGit({
|
82
70
|
filePath: destFilePath
|
83
71
|
});
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import * as child_process from "child_process";
|
2
|
+
import {
|
3
|
+
dirname as pathDirname,
|
4
|
+
basename as pathBasename,
|
5
|
+
join as pathJoin,
|
6
|
+
sep as pathSep
|
7
|
+
} from "path";
|
8
|
+
import { Deferred } from "evt/tools/Deferred";
|
9
|
+
import * as fs from "fs";
|
10
|
+
|
11
|
+
export function getIsKnownByGit(params: { filePath: string }): Promise<boolean> {
|
12
|
+
const { filePath } = params;
|
13
|
+
|
14
|
+
const dIsKnownByGit = new Deferred<boolean>();
|
15
|
+
|
16
|
+
let relativePath = pathBasename(filePath);
|
17
|
+
|
18
|
+
let dirPath = pathDirname(filePath);
|
19
|
+
|
20
|
+
while (!fs.existsSync(dirPath)) {
|
21
|
+
relativePath = pathJoin(pathBasename(dirPath), relativePath);
|
22
|
+
|
23
|
+
dirPath = pathDirname(dirPath);
|
24
|
+
}
|
25
|
+
|
26
|
+
child_process.exec(
|
27
|
+
`git ls-files --error-unmatch '${relativePath.split(pathSep).join("/")}'`,
|
28
|
+
{ cwd: dirPath },
|
29
|
+
error => {
|
30
|
+
if (error === null) {
|
31
|
+
dIsKnownByGit.resolve(true);
|
32
|
+
return;
|
33
|
+
}
|
34
|
+
|
35
|
+
if (error.code === 1) {
|
36
|
+
dIsKnownByGit.resolve(false);
|
37
|
+
return;
|
38
|
+
}
|
39
|
+
|
40
|
+
dIsKnownByGit.reject(error);
|
41
|
+
}
|
42
|
+
);
|
43
|
+
|
44
|
+
return dIsKnownByGit.pr;
|
45
|
+
}
|
@@ -24,7 +24,7 @@ export async function listInstalledModules(params: {
|
|
24
24
|
packageJsonFilePath
|
25
25
|
});
|
26
26
|
|
27
|
-
const
|
27
|
+
const extensionModuleNames = (
|
28
28
|
[parsedPackageJson.dependencies, parsedPackageJson.devDependencies] as const
|
29
29
|
)
|
30
30
|
.filter(exclude(undefined))
|
@@ -33,7 +33,7 @@ export async function listInstalledModules(params: {
|
|
33
33
|
.filter(moduleName => filter({ moduleName }));
|
34
34
|
|
35
35
|
const result = await Promise.all(
|
36
|
-
|
36
|
+
extensionModuleNames.map(async moduleName => {
|
37
37
|
const dirPath = await getInstalledModuleDirPath({
|
38
38
|
moduleName,
|
39
39
|
packageJsonDirPath: pathDirname(packageJsonFilePath),
|