keycloakify 11.8.37 → 11.8.38

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.
@@ -37,6 +37,7 @@ import { createObjectThatThrowsIfAccessed } from "../../tools/createObjectThatTh
37
37
  import { listInstalledModules } from "../../tools/listInstalledModules";
38
38
  import { isInside } from "../../tools/isInside";
39
39
  import { id } from "tsafe/id";
40
+ import { KEYCLOAK_THEME } from "../../shared/constants";
40
41
 
41
42
  export type BuildContextLike = BuildContextLike_kcContextExclusionsFtlCode &
42
43
  BuildContextLike_generateMessageProperties & {
@@ -44,6 +45,7 @@ export type BuildContextLike = BuildContextLike_kcContextExclusionsFtlCode &
44
45
  extraThemeProperties: string[] | undefined;
45
46
  projectDirPath: string;
46
47
  projectBuildDirPath: string;
48
+ publicDirPath: string;
47
49
  environmentVariables: { name: string; default: string }[];
48
50
  implementedThemeTypes: BuildContext["implementedThemeTypes"];
49
51
  themeSrcDirPath: string;
@@ -153,10 +155,14 @@ export async function generateResources(params: {
153
155
  break apply_replacers_and_move_to_theme_resources;
154
156
  }
155
157
 
156
- {
158
+ for (const directoryBasename of [
159
+ KEYCLOAK_THEME,
160
+ // NOTE: This is legacy and should eventually be removed
161
+ WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES
162
+ ]) {
157
163
  const dirPath = pathJoin(
158
164
  buildContext.projectBuildDirPath,
159
- WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES
165
+ directoryBasename
160
166
  );
161
167
 
162
168
  if (fs.existsSync(dirPath)) {
@@ -164,7 +170,7 @@ export async function generateResources(params: {
164
170
 
165
171
  throw new Error(
166
172
  [
167
- `Keycloakify build error: The ${WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES} directory shouldn't exist in your build directory.`,
173
+ `Keycloakify build error: The ${directoryBasename} directory shouldn't exist in your build directory.`,
168
174
  `(${pathRelative(process.cwd(), dirPath)}).\n`,
169
175
  `Theses assets are only required for local development with Storybook.",
170
176
  "Please remove this directory as an additional step of your command.\n`,
@@ -569,6 +575,7 @@ export async function generateResources(params: {
569
575
  };
570
576
  }
571
577
 
578
+ // NOTE: Legacy
572
579
  keycloak_static_resources: {
573
580
  if (isNative) {
574
581
  break keycloak_static_resources;
@@ -578,6 +585,8 @@ export async function generateResources(params: {
578
585
  break keycloak_static_resources;
579
586
  }
580
587
 
588
+ // TODO: Implement a check to skip that.
589
+
581
590
  transformCodebase({
582
591
  srcDirPath: pathJoin(
583
592
  getThisCodebaseRootDirPath(),
@@ -590,6 +599,37 @@ export async function generateResources(params: {
590
599
  });
591
600
  }
592
601
 
602
+ extensions_static_resources: {
603
+ if (isNative) {
604
+ break extensions_static_resources;
605
+ }
606
+
607
+ if (isSpa) {
608
+ break extensions_static_resources;
609
+ }
610
+
611
+ const dirPath = pathJoin(
612
+ buildContext.publicDirPath,
613
+ KEYCLOAK_THEME,
614
+ themeType
615
+ );
616
+
617
+ if (!fs.existsSync(dirPath)) {
618
+ break extensions_static_resources;
619
+ }
620
+
621
+ transformCodebase({
622
+ srcDirPath: dirPath,
623
+ destDirPath: pathJoin(
624
+ themeTypeDirPath,
625
+ "resources",
626
+ WELL_KNOWN_DIRECTORY_BASE_NAME.DIST,
627
+ KEYCLOAK_THEME,
628
+ themeType
629
+ )
630
+ });
631
+ }
632
+
593
633
  bring_in_account_v1: {
594
634
  if (isNative) {
595
635
  break bring_in_account_v1;
package/src/bin/main.ts CHANGED
@@ -281,6 +281,7 @@ program
281
281
  .command<{
282
282
  path: string;
283
283
  revert: boolean;
284
+ public: boolean;
284
285
  }>({
285
286
  name: "own",
286
287
  description: [
@@ -331,14 +332,30 @@ program
331
332
  ].join(" "),
332
333
  defaultValue: false
333
334
  })
335
+ .option({
336
+ key: "public",
337
+ name: (() => {
338
+ const long = "public";
339
+ const short = "p";
340
+
341
+ optionsKeys.push(long, short);
342
+
343
+ return { long, short };
344
+ })(),
345
+ description: [
346
+ "Flag to use when targeting a file or directory in the public directory",
347
+ "instead of the src"
348
+ ].join(" "),
349
+ defaultValue: false
350
+ })
334
351
  .task({
335
352
  skip,
336
- handler: async ({ projectDirPath, path, revert }) => {
353
+ handler: async ({ projectDirPath, path, revert, public: public_params }) => {
337
354
  const { command } = await import("./own");
338
355
 
339
356
  await command({
340
357
  buildContext: getBuildContext({ projectDirPath }),
341
- cliCommandOptions: { path, isRevert: revert }
358
+ cliCommandOptions: { path, isRevert: revert, isPublic: public_params }
342
359
  });
343
360
  }
344
361
  });
package/src/bin/own.ts CHANGED
@@ -3,15 +3,17 @@ import { getExtensionModuleFileSourceCodeReadyToBeCopied } from "./sync-extensio
3
3
  import type { ExtensionModuleMeta } from "./sync-extensions/extensionModuleMeta";
4
4
  import { command as command_syncExtensions } from "./sync-extensions/sync-extension";
5
5
  import {
6
- readManagedGitignoreFile,
7
- writeManagedGitignoreFile
8
- } from "./sync-extensions/managedGitignoreFile";
6
+ readManagedGitignoresFile,
7
+ writeManagedGitignoreFiles
8
+ } from "./sync-extensions/managedGitignoreFiles";
9
9
  import { getExtensionModuleMetas } from "./sync-extensions/extensionModuleMeta";
10
10
  import { getAbsoluteAndInOsFormatPath } from "./tools/getAbsoluteAndInOsFormatPath";
11
11
  import { relative as pathRelative, dirname as pathDirname, join as pathJoin } from "path";
12
12
  import { getInstalledModuleDirPath } from "./tools/getInstalledModuleDirPath";
13
13
  import * as fsPr from "fs/promises";
14
14
  import { isInside } from "./tools/isInside";
15
+ import { KEYCLOAK_THEME } from "./shared/constants";
16
+ import { same } from "evt/tools/inDepth/same";
15
17
  import chalk from "chalk";
16
18
 
17
19
  export async function command(params: {
@@ -19,6 +21,7 @@ export async function command(params: {
19
21
  cliCommandOptions: {
20
22
  path: string;
21
23
  isRevert: boolean;
24
+ isPublic: boolean;
22
25
  };
23
26
  }) {
24
27
  const { buildContext, cliCommandOptions } = params;
@@ -26,27 +29,34 @@ export async function command(params: {
26
29
  const extensionModuleMetas = await getExtensionModuleMetas({ buildContext });
27
30
 
28
31
  const { targetFileRelativePathsByExtensionModuleMeta } = await (async () => {
29
- const fileOrDirectoryRelativePath = pathRelative(
30
- buildContext.themeSrcDirPath,
31
- getAbsoluteAndInOsFormatPath({
32
- cwd: buildContext.themeSrcDirPath,
33
- pathIsh: cliCommandOptions.path
34
- })
35
- );
32
+ const fileOrDirectoryRelativePath = (() => {
33
+ const dirPath_ctx = cliCommandOptions.isPublic
34
+ ? pathJoin(buildContext.publicDirPath, KEYCLOAK_THEME)
35
+ : buildContext.themeSrcDirPath;
36
+
37
+ return pathRelative(
38
+ dirPath_ctx,
39
+ getAbsoluteAndInOsFormatPath({
40
+ cwd: dirPath_ctx,
41
+ pathIsh: cliCommandOptions.path
42
+ })
43
+ );
44
+ })();
36
45
 
37
46
  const arr = extensionModuleMetas
38
47
  .map(extensionModuleMeta => ({
39
48
  extensionModuleMeta,
40
49
  fileRelativePaths: extensionModuleMeta.files
41
- .map(({ fileRelativePath }) => fileRelativePath)
42
50
  .filter(
43
- fileRelativePath =>
44
- fileRelativePath === fileOrDirectoryRelativePath ||
45
- isInside({
46
- dirPath: fileOrDirectoryRelativePath,
47
- filePath: fileRelativePath
48
- })
51
+ ({ fileRelativePath, isPublic }) =>
52
+ cliCommandOptions.isPublic === isPublic &&
53
+ (fileRelativePath === fileOrDirectoryRelativePath ||
54
+ isInside({
55
+ dirPath: fileOrDirectoryRelativePath,
56
+ filePath: fileRelativePath
57
+ }))
49
58
  )
59
+ .map(({ fileRelativePath }) => fileRelativePath)
50
60
  }))
51
61
  .filter(({ fileRelativePaths }) => fileRelativePaths.length !== 0);
52
62
 
@@ -75,12 +85,13 @@ export async function command(params: {
75
85
  }
76
86
 
77
87
  const { ownedFilesRelativePaths: ownedFilesRelativePaths_current } =
78
- await readManagedGitignoreFile({
88
+ await readManagedGitignoresFile({
79
89
  buildContext
80
90
  });
81
91
 
82
92
  await (cliCommandOptions.isRevert ? command_revert : command_own)({
83
93
  extensionModuleMetas,
94
+ isPublic: cliCommandOptions.isPublic,
84
95
  targetFileRelativePathsByExtensionModuleMeta,
85
96
  ownedFilesRelativePaths_current,
86
97
  buildContext
@@ -89,20 +100,22 @@ export async function command(params: {
89
100
 
90
101
  type Params_subcommands = {
91
102
  extensionModuleMetas: ExtensionModuleMeta[];
103
+ isPublic: boolean;
92
104
  targetFileRelativePathsByExtensionModuleMeta: Map<ExtensionModuleMeta, string[]>;
93
- ownedFilesRelativePaths_current: string[];
105
+ ownedFilesRelativePaths_current: { isPublic: boolean; fileRelativePath: string }[];
94
106
  buildContext: BuildContext;
95
107
  };
96
108
 
97
109
  async function command_own(params: Params_subcommands) {
98
110
  const {
99
111
  extensionModuleMetas,
112
+ isPublic,
100
113
  targetFileRelativePathsByExtensionModuleMeta,
101
114
  ownedFilesRelativePaths_current,
102
115
  buildContext
103
116
  } = params;
104
117
 
105
- await writeManagedGitignoreFile({
118
+ await writeManagedGitignoreFiles({
106
119
  buildContext,
107
120
  extensionModuleMetas,
108
121
  ownedFilesRelativePaths: [
@@ -111,8 +124,11 @@ async function command_own(params: Params_subcommands) {
111
124
  .flat()
112
125
  .filter(
113
126
  fileRelativePath =>
114
- !ownedFilesRelativePaths_current.includes(fileRelativePath)
127
+ !ownedFilesRelativePaths_current.some(entry =>
128
+ same(entry, { isPublic, fileRelativePath })
129
+ )
115
130
  )
131
+ .map(fileRelativePath => ({ isPublic, fileRelativePath }))
116
132
  ]
117
133
  });
118
134
 
@@ -128,7 +144,11 @@ async function command_own(params: Params_subcommands) {
128
144
  });
129
145
 
130
146
  for (const fileRelativePath of fileRelativePaths) {
131
- if (ownedFilesRelativePaths_current.includes(fileRelativePath)) {
147
+ if (
148
+ ownedFilesRelativePaths_current.some(entry =>
149
+ same(entry, { isPublic, fileRelativePath })
150
+ )
151
+ ) {
132
152
  console.log(
133
153
  chalk.grey(`You already have ownership over '${fileRelativePath}'.`)
134
154
  );
@@ -138,6 +158,7 @@ async function command_own(params: Params_subcommands) {
138
158
  writeActions.push(async () => {
139
159
  const sourceCode = await getExtensionModuleFileSourceCodeReadyToBeCopied({
140
160
  buildContext,
161
+ isPublic,
141
162
  fileRelativePath,
142
163
  isOwnershipAction: true,
143
164
  extensionModuleName: extensionModuleMeta.moduleName,
@@ -146,7 +167,12 @@ async function command_own(params: Params_subcommands) {
146
167
  });
147
168
 
148
169
  await fsPr.writeFile(
149
- pathJoin(buildContext.themeSrcDirPath, fileRelativePath),
170
+ pathJoin(
171
+ isPublic
172
+ ? pathJoin(buildContext.publicDirPath, KEYCLOAK_THEME)
173
+ : buildContext.themeSrcDirPath,
174
+ fileRelativePath
175
+ ),
150
176
  sourceCode
151
177
  );
152
178
 
@@ -166,6 +192,7 @@ async function command_own(params: Params_subcommands) {
166
192
  async function command_revert(params: Params_subcommands) {
167
193
  const {
168
194
  extensionModuleMetas,
195
+ isPublic,
169
196
  targetFileRelativePathsByExtensionModuleMeta,
170
197
  ownedFilesRelativePaths_current,
171
198
  buildContext
@@ -176,7 +203,11 @@ async function command_revert(params: Params_subcommands) {
176
203
  )
177
204
  .flat()
178
205
  .filter(fileRelativePath => {
179
- if (!ownedFilesRelativePaths_current.includes(fileRelativePath)) {
206
+ if (
207
+ !ownedFilesRelativePaths_current.some(entry =>
208
+ same(entry, { isPublic, fileRelativePath })
209
+ )
210
+ ) {
180
211
  console.log(
181
212
  chalk.grey(`Ownership over '${fileRelativePath}' wasn't claimed.`)
182
213
  );
@@ -195,12 +226,14 @@ async function command_revert(params: Params_subcommands) {
195
226
  return;
196
227
  }
197
228
 
198
- await writeManagedGitignoreFile({
229
+ await writeManagedGitignoreFiles({
199
230
  buildContext,
200
231
  extensionModuleMetas,
201
232
  ownedFilesRelativePaths: ownedFilesRelativePaths_current.filter(
202
- fileRelativePath =>
203
- !ownedFilesRelativePaths_toRemove.includes(fileRelativePath)
233
+ entry =>
234
+ !ownedFilesRelativePaths_toRemove.some(fileRelativePath =>
235
+ same(entry, { isPublic, fileRelativePath })
236
+ )
204
237
  )
205
238
  });
206
239
 
@@ -1,7 +1,12 @@
1
1
  import { assert, type Equals, is } from "tsafe/assert";
2
2
  import { id } from "tsafe/id";
3
3
  import { z } from "zod";
4
- import { join as pathJoin, dirname as pathDirname } from "path";
4
+ import {
5
+ join as pathJoin,
6
+ dirname as pathDirname,
7
+ relative as pathRelative,
8
+ sep as pathSep
9
+ } from "path";
5
10
  import * as fsPr from "fs/promises";
6
11
  import type { BuildContext } from "../shared/buildContext";
7
12
  import { existsAsync } from "../tools/fs.existsAsync";
@@ -22,6 +27,7 @@ export type ExtensionModuleMeta = {
22
27
  moduleName: string;
23
28
  version: string;
24
29
  files: {
30
+ isPublic: boolean;
25
31
  fileRelativePath: string;
26
32
  hash: string;
27
33
  copyableFilePath: string;
@@ -37,6 +43,7 @@ const zExtensionModuleMeta = (() => {
37
43
  version: z.string(),
38
44
  files: z.array(
39
45
  z.object({
46
+ isPublic: z.boolean(),
40
47
  fileRelativePath: z.string(),
41
48
  hash: z.string(),
42
49
  copyableFilePath: z.string()
@@ -222,49 +229,55 @@ export async function getExtensionModuleMetas(params: {
222
229
 
223
230
  const files: ExtensionModuleMeta["files"] = [];
224
231
 
225
- {
226
- const srcDirPath = pathJoin(dirPath, KEYCLOAK_THEME);
227
-
228
- await crawlAsync({
229
- dirPath: srcDirPath,
230
- returnedPathsType: "relative to dirPath",
231
- onFileFound: async fileRelativePath => {
232
- const sourceCode =
233
- await getExtensionModuleFileSourceCodeReadyToBeCopied({
234
- buildContext,
235
- fileRelativePath,
236
- isOwnershipAction: false,
237
- extensionModuleDirPath: dirPath,
238
- extensionModuleName: moduleName,
239
- extensionModuleVersion: version
240
- });
241
-
242
- const hash = computeHash(sourceCode);
243
-
244
- const copyableFilePath = pathJoin(
245
- pathDirname(cacheFilePath),
246
- KEYCLOAK_THEME,
247
- fileRelativePath
248
- );
249
-
250
- {
251
- const dirPath = pathDirname(copyableFilePath);
252
-
253
- if (!(await existsAsync(dirPath))) {
254
- await fsPr.mkdir(dirPath, { recursive: true });
255
- }
256
- }
232
+ await crawlAsync({
233
+ dirPath: pathJoin(dirPath, KEYCLOAK_THEME),
234
+ returnedPathsType: "relative to dirPath",
235
+ onFileFound: async fileRelativePath_fromReservedDir => {
236
+ const isPublic = fileRelativePath_fromReservedDir.startsWith(
237
+ `public${pathSep}`
238
+ );
257
239
 
258
- fsPr.writeFile(copyableFilePath, sourceCode);
240
+ const fileRelativePath = isPublic
241
+ ? pathRelative("public", fileRelativePath_fromReservedDir)
242
+ : fileRelativePath_fromReservedDir;
259
243
 
260
- files.push({
244
+ const sourceCode =
245
+ await getExtensionModuleFileSourceCodeReadyToBeCopied({
246
+ buildContext,
247
+ isPublic,
261
248
  fileRelativePath,
262
- hash,
263
- copyableFilePath
249
+ isOwnershipAction: false,
250
+ extensionModuleDirPath: dirPath,
251
+ extensionModuleName: moduleName,
252
+ extensionModuleVersion: version
264
253
  });
254
+
255
+ const hash = computeHash(sourceCode);
256
+
257
+ const copyableFilePath = pathJoin(
258
+ pathDirname(cacheFilePath),
259
+ KEYCLOAK_THEME,
260
+ fileRelativePath_fromReservedDir
261
+ );
262
+
263
+ {
264
+ const dirPath = pathDirname(copyableFilePath);
265
+
266
+ if (!(await existsAsync(dirPath))) {
267
+ await fsPr.mkdir(dirPath, { recursive: true });
268
+ }
265
269
  }
266
- });
267
- }
270
+
271
+ fsPr.writeFile(copyableFilePath, sourceCode);
272
+
273
+ files.push({
274
+ isPublic,
275
+ fileRelativePath,
276
+ hash,
277
+ copyableFilePath
278
+ });
279
+ }
280
+ });
268
281
 
269
282
  return id<ExtensionModuleMeta>({
270
283
  moduleName,