Skip to content

Commit

Permalink
feat: add init script to CLI using the same logic as create-tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
unekinn committed Jun 25, 2024
1 parent 9f1452e commit 84a8060
Show file tree
Hide file tree
Showing 30 changed files with 62 additions and 101 deletions.
9 changes: 6 additions & 3 deletions packages/cli/bin/designsystemet.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#!/usr/bin/env node
import { Argument, program } from '@commander-js/extra-typings';
import { Argument, Command, program } from '@commander-js/extra-typings';
import chalk from 'chalk';

import migrations from './../src/migrations/index.js';
import { run } from './../src/tokens/build.js';
import migrations from '../src/migrations/index.js';
import { run } from '../src/tokens/build.js';
import { makeInitCommand } from '../src/init/index.js';

program.name('Designsystemet').description('CLI for working with Designsystemet');

Expand Down Expand Up @@ -52,4 +53,6 @@ program
}
});

program.addCommand(makeInitCommand(new Command('init')));

await program.parseAsync(process.argv);
3 changes: 3 additions & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,15 @@
"@commander-js/extra-typings": "^12.0.1",
"@tokens-studio/sd-transforms": "^0.16.1",
"chalk": "^5.3.0",
"change-case": "^5.3.0",
"chroma-js": "^2.4.2",
"commander": "^12.0.0",
"fast-glob": "^3.3.2",
"hsluv": "^1.0.1",
"jscodeshift": "^0.15.2",
"object-hash": "^3.0.0",
"postcss": "^8.4.38",
"prompts": "^2.4.0",
"ramda": "^0.29.1",
"rimraf": "^5.0.5",
"style-dictionary": "^4.0.0-prerelease.34"
Expand All @@ -65,6 +67,7 @@
"@types/jscodeshift": "^0.11.11",
"@types/node": "^20.12.7",
"@types/object-hash": "^3",
"@types/prompts": "^2.4.9",
"@types/ramda": "^0.29.9",
"fs-extra": "^11.2.0",
"tsup": "^8.1.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,16 @@
import path from 'node:path';
import fs from 'node:fs/promises';

import { bold, dim, red, green } from 'kleur';
import chalk from 'chalk';
import type { Choice, Options } from 'prompts';
import prompts from 'prompts';

import packageJsonTemplate from '../template/template-files/package.json';

import packageJsonTemplate from './template/template-files/package.json';
import generateMetadata from './generateMetadataJson.js';
import generateThemes from './generateThemesJson.js';
import {
toGeneratedCssFileName,
normalizeTokenSetName,
toValidPackageName,
} from './utils.js';
import { toGeneratedCssFileName, normalizeTokenSetName, toValidPackageName } from './utils.js';
import { nextStepsMarkdown } from './nextStepsMarkdown.js';

const DEFAULT_FILES_PATH = path.join(__dirname, '../template/default-files');

const TOKEN_TEMPLATE_FILES_PATH = path.join(
__dirname,
'../template/template-files/design-tokens',
);

const MODES = ['Light', 'Dark', 'Contrast'] as const;
export type Mode = (typeof MODES)[number];

Expand All @@ -45,12 +33,17 @@ interface ThemeAnswers {

const promptOptions: Options = {
onCancel: () => {
console.log(`${red('✖')} Operation cancelled`);
console.log(`${chalk.red('✖')} Operation cancelled`);
process.exit();
},
};

export async function createTokensPackage(targetDir: string) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const DIRNAME: string = import.meta.dirname || __dirname;
const DEFAULT_FILES_PATH = path.join(DIRNAME, './template/default-files');
const TOKEN_TEMPLATE_FILES_PATH = path.join(DIRNAME, './template/template-files/design-tokens');

const TARGET_DIR = path.resolve(process.cwd(), targetDir);
const initialPackageName = toValidPackageName(path.basename(TARGET_DIR));

Expand Down Expand Up @@ -82,8 +75,7 @@ export async function createTokensPackage(targetDir: string) {
{
title: 'Ignore',
value: 'ignore',
description:
'Keep directory as is. Files may be overwritten with new output.',
description: 'Keep directory as is. Files may be overwritten with new output.',
},
{
title: 'Exit',
Expand Down Expand Up @@ -134,7 +126,7 @@ export async function createTokensPackage(targetDir: string) {
←/→/[space]: Toggle selection
a: Toggle all
enter/return: Complete answer
${green('◉')} Light ${dim('- This is the default mode, and cannot be disabled')}`,
${chalk.green('◉')} Light ${chalk.dim('- This is the default mode, and cannot be disabled')}`,
onState: (obj: { value: Choice[] }) => {
obj.value.unshift({ title: 'Light', value: 'Light', selected: true });
},
Expand Down Expand Up @@ -180,25 +172,19 @@ ${green('◉')} Light ${dim('- This is the default mode, and cannot be disable
console.log(
`
Will now create the following:
${bold('Package name')}: ${packageName}
${bold('Directory')}: ${TARGET_DIR}
${bold('Tokens directory')}: ${TOKENS_TARGET_DIR}
${bold('Themes')}: ${themes.join(', ')}
${bold('Default theme')}: ${defaultTheme}
${bold('Color modes')}: ${modes.join(', ')}
${chalk.bold('Package name')}: ${packageName}
${chalk.bold('Directory')}: ${TARGET_DIR}
${chalk.bold('Tokens directory')}: ${TOKENS_TARGET_DIR}
${chalk.bold('Themes')}: ${themes.join(', ')}
${chalk.bold('Default theme')}: ${defaultTheme}
${chalk.bold('Color modes')}: ${modes.join(', ')}
`,
);
if (directoryAction === 'clean') {
console.log(
bold().red(`Warning: Contents of ${TARGET_DIR} will be deleted`),
);
console.log(chalk.bold.red(`Warning: Contents of ${TARGET_DIR} will be deleted`));
}
if (directoryAction === 'ignore') {
console.log(
bold().yellow(
`Warning: Existing files in ${TARGET_DIR} may be overwritten`,
),
);
console.log(chalk.bold.yellow(`Warning: Existing files in ${TARGET_DIR} may be overwritten`));
}

const res = await prompts(
Expand All @@ -223,10 +209,7 @@ Will now create the following:
recursive: true,
});
if (tokensDir !== 'design-tokens') {
await fs.rename(
path.join(TARGET_DIR, 'design-tokens'),
path.join(TOKENS_TARGET_DIR),
);
await fs.rename(path.join(TARGET_DIR, 'design-tokens'), path.join(TOKENS_TARGET_DIR));
}

try {
Expand All @@ -239,20 +222,14 @@ Will now create the following:
for (const mode of modes.map(normalizeTokenSetName)) {
// Copy the global file for the color mode
await fs.cp(
path.join(
TOKEN_TEMPLATE_FILES_PATH,
`primitives/colors/${mode}/global.json`,
),
path.join(TOKEN_TEMPLATE_FILES_PATH, `primitives/colors/${mode}/global.json`),
path.join(TOKENS_TARGET_DIR, `primitives/colors/${mode}/global.json`),
{ recursive: true },
);

// Create theme primitives for the color mode
const template = await fs.readFile(
path.join(
TOKEN_TEMPLATE_FILES_PATH,
`primitives/colors/${mode}/theme-template.json`,
),
path.join(TOKEN_TEMPLATE_FILES_PATH, `primitives/colors/${mode}/theme-template.json`),
);
await fs.writeFile(
path.join(TOKENS_TARGET_DIR, `primitives/colors/${mode}/${theme}.json`),
Expand All @@ -261,9 +238,7 @@ Will now create the following:
}

// Create main theme token set
const template = await fs.readFile(
path.join(TOKEN_TEMPLATE_FILES_PATH, `themes/theme-template.json`),
);
const template = await fs.readFile(path.join(TOKEN_TEMPLATE_FILES_PATH, `themes/theme-template.json`));
await fs.writeFile(
path.join(TOKENS_TARGET_DIR, `themes/${theme}.json`),
template.toString('utf-8').replaceAll('<theme>', theme),
Expand All @@ -282,29 +257,18 @@ Will now create the following:

// Configure package.json file
packageJsonTemplate.name = packageName;
packageJsonTemplate.main = packageJsonTemplate.main.replace(
'<default-theme>',
toGeneratedCssFileName(defaultTheme),
);
await fs.writeFile(
path.join(TARGET_DIR, 'package.json'),
JSON.stringify(packageJsonTemplate, undefined, 2),
);
packageJsonTemplate.main = packageJsonTemplate.main.replace('<default-theme>', toGeneratedCssFileName(defaultTheme));
await fs.writeFile(path.join(TARGET_DIR, 'package.json'), JSON.stringify(packageJsonTemplate, undefined, 2));

const readmePath = path.join(TARGET_DIR, 'README.md');
const currentReadme = await fs.readFile(readmePath);
await fs.writeFile(
readmePath,
[
currentReadme.toString('utf-8'),
nextStepsMarkdown(themes, modes, tokensDir, packageName),
].join('\n'),
[currentReadme.toString('utf-8'), nextStepsMarkdown(themes, modes, tokensDir, packageName)].join('\n'),
);

console.log('🎉 Files successfully generated!');
console.log(
`Read about the next steps in the generated README at ${readmePath}`,
);
console.log(`Read about the next steps in the generated README at ${readmePath}`);
}

function isValidThemeName(themes: string[], value: string): true | string {
Expand Down
File renamed without changes.
13 changes: 13 additions & 0 deletions packages/cli/src/init/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Argument, type Command } from '@commander-js/extra-typings';

import { createTokensPackage } from './createTokensPackage';

export function makeInitCommand(command: Command) {
return command
.showHelpAfterError()
.description('create an initial token structure for Designsystemet')
.addArgument(new Argument('<targetDir>', 'Target directory for the generated code'))
.action(async (targetDir) => {
await createTokensPackage(targetDir);
});
}
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion packages/create-tokens/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

import { require } from 'tsx/cjs/api';

require('./src/bin/create-tokens.ts', import.meta.url);
require('./src/create-tokens.ts', import.meta.url);
7 changes: 0 additions & 7 deletions packages/create-tokens/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,7 @@
},
"dependencies": {
"@commander-js/extra-typings": "^12.0.1",
"change-case": "^5.3.0",
"commander": "^12.0.0",
"kleur": "^3.0.3",
"prompts": "^2.4.0",
"tsx": "^4.11.2"
},
"devDependencies": {
"@tokens-studio/types": "^0.4.0",
"@types/prompts": "^2.4.9"
}
}
21 changes: 0 additions & 21 deletions packages/create-tokens/src/bin/create-tokens.ts

This file was deleted.

8 changes: 8 additions & 0 deletions packages/create-tokens/src/create-tokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { program } from '@commander-js/extra-typings';

import { makeInitCommand } from '../../cli/src/init';

program.name('npm create @digdir/tokens');
makeInitCommand(program);

void program.parseAsync(process.argv);
2 changes: 1 addition & 1 deletion packages/create-tokens/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
"composite": false
},
"rootDir": "./src",
"include": ["src", "template"]
"include": ["src"]
}
8 changes: 3 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2285,12 +2285,7 @@ __metadata:
resolution: "@digdir/create-tokens@workspace:packages/create-tokens"
dependencies:
"@commander-js/extra-typings": "npm:^12.0.1"
"@tokens-studio/types": "npm:^0.4.0"
"@types/prompts": "npm:^2.4.9"
change-case: "npm:^5.3.0"
commander: "npm:^12.0.0"
kleur: "npm:^3.0.3"
prompts: "npm:^2.4.0"
tsx: "npm:^4.11.2"
bin:
create-tokens: index.js
Expand Down Expand Up @@ -2380,8 +2375,10 @@ __metadata:
"@types/jscodeshift": "npm:^0.11.11"
"@types/node": "npm:^20.12.7"
"@types/object-hash": "npm:^3"
"@types/prompts": "npm:^2.4.9"
"@types/ramda": "npm:^0.29.9"
chalk: "npm:^5.3.0"
change-case: "npm:^5.3.0"
chroma-js: "npm:^2.4.2"
commander: "npm:^12.0.0"
fast-glob: "npm:^3.3.2"
Expand All @@ -2390,6 +2387,7 @@ __metadata:
jscodeshift: "npm:^0.15.2"
object-hash: "npm:^3.0.0"
postcss: "npm:^8.4.38"
prompts: "npm:^2.4.0"
ramda: "npm:^0.29.1"
rimraf: "npm:^5.0.5"
style-dictionary: "npm:^4.0.0-prerelease.34"
Expand Down

0 comments on commit 84a8060

Please sign in to comment.