Skip to content

Commit cbc8075

Browse files
committed
Add add-story script and only format generated files
1 parent dec78d5 commit cbc8075

File tree

9 files changed

+426
-102
lines changed

9 files changed

+426
-102
lines changed

scripts/shared/postNgBuild.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ const distDirPath = pathJoin(getThisCodebaseRootDirPath(), 'dist');
1616
export function postNgBuild() {
1717
copyTransformSrcDirToDist();
1818

19+
transformCodebase({
20+
srcDirPath: pathJoin(getThisCodebaseRootDirPath(), 'stories'),
21+
destDirPath: pathJoin(distDirPath, 'stories'),
22+
transformSourceCode: ({ filePath, sourceCode }) => {
23+
if (!filePath.endsWith('stories.ts')) {
24+
return undefined;
25+
}
26+
27+
return { modifiedSourceCode: sourceCode };
28+
}
29+
});
30+
1931
for (const basename of ['README.md', 'LICENSE']) {
2032
fs.cpSync(
2133
pathJoin(getThisCodebaseRootDirPath(), basename),
@@ -38,7 +50,7 @@ function buildBin() {
3850

3951
const entrypointFilePath = pathJoin(distDirPath_bin, 'main.js');
4052

41-
run(`npx ncc build ${entrypointFilePath} -o ${nccOutDirPath}`);
53+
run(`npx ncc build ${entrypointFilePath} --external prettier -o ${nccOutDirPath}`);
4254

4355
transformCodebase({
4456
srcDirPath: distDirPath_bin,

src/bin/add-story.ts

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import { getThisCodebaseRootDirPath } from './tools/getThisCodebaseRootDirPath';
2+
import cliSelect from 'cli-select';
3+
import * as fs from 'fs';
4+
import { join as pathJoin, relative as pathRelative, dirname as pathDirname } from 'path';
5+
import { assert, Equals } from 'tsafe/assert';
6+
import chalk from 'chalk';
7+
import { runPrettier, getIsPrettierAvailable } from './tools/runPrettier';
8+
import {
9+
type BuildContext,
10+
LOGIN_THEME_PAGE_IDS,
11+
ACCOUNT_THEME_PAGE_IDS,
12+
type LoginThemePageId,
13+
type AccountThemePageId,
14+
THEME_TYPES
15+
} from './core';
16+
17+
export async function command(params: { buildContext: BuildContext }) {
18+
const { buildContext } = params;
19+
20+
console.log(chalk.cyan('Theme type:'));
21+
22+
const themeType = await (async () => {
23+
const values = THEME_TYPES.filter(themeType => {
24+
switch (themeType) {
25+
case 'account':
26+
return buildContext.implementedThemeTypes.account.isImplemented;
27+
case 'login':
28+
return buildContext.implementedThemeTypes.login.isImplemented;
29+
}
30+
assert<Equals<typeof themeType, never>>(false);
31+
});
32+
33+
assert(values.length > 0, 'No theme is implemented in this project');
34+
35+
if (values.length === 1) {
36+
return values[0];
37+
}
38+
39+
const { value } = await cliSelect({
40+
values
41+
}).catch(() => {
42+
process.exit(-1);
43+
});
44+
45+
return value;
46+
})();
47+
48+
console.log(`→ ${themeType}`);
49+
50+
console.log(chalk.cyan('Select the page you want to create a Storybook for:'));
51+
52+
const { value: pageId } = await cliSelect<LoginThemePageId | AccountThemePageId>({
53+
values: (() => {
54+
switch (themeType) {
55+
case 'login':
56+
return [...LOGIN_THEME_PAGE_IDS];
57+
case 'account':
58+
return [...ACCOUNT_THEME_PAGE_IDS];
59+
}
60+
assert<Equals<typeof themeType, never>>(false);
61+
})()
62+
}).catch(() => {
63+
process.exit(-1);
64+
});
65+
66+
console.log(`→ ${pageId}`);
67+
68+
const componentBasename = pageId.replace(/ftl$/, 'stories.ts');
69+
70+
const targetFilePath = pathJoin(
71+
buildContext.themeSrcDirPath,
72+
themeType,
73+
'pages',
74+
pageId.replace(/\.ftl$/, ''),
75+
componentBasename
76+
);
77+
78+
if (fs.existsSync(targetFilePath)) {
79+
console.log(`${pathRelative(process.cwd(), targetFilePath)} already exists`);
80+
81+
process.exit(-1);
82+
}
83+
84+
let sourceCode = fs
85+
.readFileSync(
86+
pathJoin(
87+
getThisCodebaseRootDirPath(),
88+
'stories',
89+
themeType,
90+
'pages',
91+
componentBasename
92+
)
93+
)
94+
.toString('utf8')
95+
.replace(/["']\.\.\/KcPageStory["']/, "'../../KcPageStory'");
96+
97+
run_prettier: {
98+
if (!(await getIsPrettierAvailable())) {
99+
break run_prettier;
100+
}
101+
102+
sourceCode = await runPrettier({
103+
filePath: targetFilePath,
104+
sourceCode: sourceCode
105+
});
106+
}
107+
108+
{
109+
const targetDirPath = pathDirname(targetFilePath);
110+
111+
if (!fs.existsSync(targetDirPath)) {
112+
fs.mkdirSync(targetDirPath, { recursive: true });
113+
}
114+
}
115+
116+
fs.writeFileSync(targetFilePath, Buffer.from(sourceCode, 'utf8'));
117+
118+
console.log(
119+
[
120+
`${chalk.green('✓')} ${chalk.bold(
121+
pathJoin('.', pathRelative(process.cwd(), targetFilePath))
122+
)} copy pasted from the Keycloakify source code into your project`,
123+
`You can start storybook with ${chalk.bold('npm run storybook')}`
124+
].join('\n')
125+
);
126+
}

src/bin/eject-page.ts

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ import {
2121
} from 'path';
2222
import { assert, Equals } from 'tsafe/assert';
2323
import chalk from 'chalk';
24-
import { transformCodebase } from './tools/transformCodebase';
24+
import { transformCodebase } from './tools/transformCodebase_async';
2525
import { kebabCaseToCamelCase } from './tools/kebabCaseToSnakeCase';
2626
import { replaceAll } from './tools/String.prototype.replaceAll';
2727
import { capitalize } from 'tsafe/capitalize';
28-
import { runFormat } from './tools/runFormat';
28+
import { getIsPrettierAvailable, runPrettier } from './tools/runPrettier';
2929

3030
export async function command(params: { buildContext: BuildContext }) {
3131
const { buildContext } = params;
@@ -149,15 +149,33 @@ export async function command(params: { buildContext: BuildContext }) {
149149
themeType
150150
);
151151

152-
transformCodebase({
152+
await transformCodebase({
153153
srcDirPath: pathJoin(
154154
localThemeTypeDirPath,
155155
componentDirRelativeToThemeTypePath_i
156156
),
157157
destDirPath,
158-
transformSourceCode: ({ filePath, sourceCode }) => {
158+
transformSourceCode: async ({ filePath, sourceCode }) => {
159159
if (!filePath.endsWith('.ts')) {
160-
return { modifiedSourceCode: sourceCode };
160+
let modifiedSourceCode_str = sourceCode.toString('utf8');
161+
162+
run_prettier: {
163+
if (!(await getIsPrettierAvailable())) {
164+
break run_prettier;
165+
}
166+
167+
modifiedSourceCode_str = await runPrettier({
168+
filePath,
169+
sourceCode: modifiedSourceCode_str
170+
});
171+
}
172+
173+
return {
174+
modifiedSourceCode: Buffer.from(
175+
modifiedSourceCode_str,
176+
'utf8'
177+
)
178+
};
161179
}
162180

163181
if (filePath.endsWith('index.ts')) {
@@ -229,6 +247,17 @@ export async function command(params: { buildContext: BuildContext }) {
229247
}
230248
);
231249

250+
run_prettier: {
251+
if (!(await getIsPrettierAvailable())) {
252+
break run_prettier;
253+
}
254+
255+
modifiedSourceCode_str = await runPrettier({
256+
filePath,
257+
sourceCode: modifiedSourceCode_str
258+
});
259+
}
260+
232261
return {
233262
modifiedSourceCode: Buffer.from(modifiedSourceCode_str, 'utf8')
234263
};
@@ -243,10 +272,6 @@ export async function command(params: { buildContext: BuildContext }) {
243272
}
244273
}
245274

246-
runFormat({
247-
packageJsonFilePath: buildContext.packageJsonFilePath
248-
});
249-
250275
edit_KcPage: {
251276
if (
252277
pageIdOrComponent !== templateValue &&
@@ -263,17 +288,30 @@ export async function command(params: { buildContext: BuildContext }) {
263288

264289
const kcAppTsCode = fs.readFileSync(kcAppTsFilePath).toString('utf8');
265290

266-
const modifiedKcAppTsCode = (() => {
291+
const modifiedKcAppTsCode = await (async () => {
267292
const componentRelativeDirPath_posix = componentDirRelativeToThemeTypePath
268293
.split(pathSep)
269294
.join('/');
270295

271-
return kcAppTsCode.replace(
296+
let sourceCode = kcAppTsCode.replace(
272297
`@keycloakify/angular/${themeType}/${componentRelativeDirPath_posix}`,
273298
componentRelativeDirPath_posix_to_componentRelativeFilePath_posix({
274299
componentRelativeDirPath_posix: `./${componentRelativeDirPath_posix}`
275300
})
276301
);
302+
303+
run_prettier: {
304+
if (!(await getIsPrettierAvailable())) {
305+
break run_prettier;
306+
}
307+
308+
sourceCode = await runPrettier({
309+
filePath: kcAppTsFilePath,
310+
sourceCode
311+
});
312+
}
313+
314+
return sourceCode;
277315
})();
278316

279317
if (modifiedKcAppTsCode === kcAppTsCode) {

src/bin/main.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@ const { buildContext, commandName } = readParams({ apiVersion: 'v1' });
88
switch (commandName) {
99
case 'add-story':
1010
{
11-
console.log(
12-
"Not yet supported by @keycloakify/angular, we're working on it!"
13-
);
14-
process.exit(-1);
11+
const { command } = await import('./add-story');
12+
command({ buildContext });
1513
}
1614
return;
1715
case 'eject-page':
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { sep as pathSep } from 'path';
2+
3+
let cache: string | undefined = undefined;
4+
5+
export function getNodeModulesBinDirPath() {
6+
if (cache !== undefined) {
7+
return cache;
8+
}
9+
10+
const binPath = process.argv[1];
11+
12+
const segments: string[] = ['.bin'];
13+
14+
let foundNodeModules = false;
15+
16+
for (const segment of binPath.split(pathSep).reverse()) {
17+
skip_segment: {
18+
if (foundNodeModules) {
19+
break skip_segment;
20+
}
21+
22+
if (segment === 'node_modules') {
23+
foundNodeModules = true;
24+
break skip_segment;
25+
}
26+
27+
continue;
28+
}
29+
30+
segments.unshift(segment);
31+
}
32+
33+
const nodeModulesBinDirPath = segments.join(pathSep);
34+
35+
cache = nodeModulesBinDirPath;
36+
37+
return nodeModulesBinDirPath;
38+
}

src/bin/tools/runFormat.ts

Lines changed: 0 additions & 71 deletions
This file was deleted.

0 commit comments

Comments
 (0)