Skip to content

Commit

Permalink
Feature: <packagemanager> install is now ran at the end of the migr…
Browse files Browse the repository at this point in the history
…ation.

Feature: Better error handling is now in place.
  • Loading branch information
Hugos68 committed Jan 14, 2025
1 parent 7e29a8c commit e0950e8
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 88 deletions.
5 changes: 5 additions & 0 deletions .changeset/early-suns-cry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@skeletonlabs/skeleton-cli': patch
---

Feature: Better error handling is now in place.
5 changes: 5 additions & 0 deletions .changeset/itchy-knives-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@skeletonlabs/skeleton-cli': patch
---

Feature: `<packagemanager> install` is now ran at the end of the migration.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import type { MigrateOptions } from '../../index.js';
import { isCancel, multiselect, spinner } from '@clack/prompts';
import { cli } from '../../../../index.js';
import { extname } from 'node:path';
import { transformSvelte } from './transformers/transform-svelte';
import { transformModule } from './transformers/transform-module';
import { transformApp } from './transformers/transform-app';
import { transformSvelte } from './transformers/transform-svelte.js';
import { transformModule } from './transformers/transform-module.js';
import { transformApp } from './transformers/transform-app.js';
import { readFile, writeFile } from 'node:fs/promises';
import { installDependencies } from '../../../../utility/install-dependencies.js';

export default async function (options: MigrateOptions) {
const cwd = options.cwd ?? process.cwd();
Expand All @@ -35,59 +36,107 @@ export default async function (options: MigrateOptions) {
}
}

const availableSourceFolders = await fg('*', { cwd, onlyDirectories: true, ignore: ['node_modules'] });
const availableSourceFolders = await fg('*', {
cwd: cwd,
onlyDirectories: true,
ignore: ['node_modules']
});
const sourceFolders = await multiselect({
message: 'What folders contain usage of Skeleton? (classes, imports, etc.)',
options: availableSourceFolders.map((folder) => ({ label: folder, value: folder })),
initialValues: availableSourceFolders
});

if (isCancel(sourceFolders)) {
cli.error('Migration cancelled.');
cli.error('Migration cancelled by user.');
return;
}

const packageSpinner = spinner();
packageSpinner.start(`Migrating ${pkg.matcher}...`);
const pkgCode = await readFile(pkg.paths[0], 'utf-8');
const transformedPkg = await transformPackage(pkgCode);
await writeFile(pkg.paths[0], transformedPkg.code);
packageSpinner.stop(`Successfully migrated ${pkg.matcher}`);
try {
const pkgCode = await readFile(pkg.paths[0], 'utf-8');
const transformedPkg = await transformPackage(pkgCode);
await writeFile(pkg.paths[0], transformedPkg.code);
packageSpinner.stop(`Successfully migrated ${pkg.matcher}`);
} catch (e) {
if (e instanceof Error) {
packageSpinner.stop(`Failed to migrate ${pkg.matcher}: ${e.message}`);
}
packageSpinner.stop(`Failed to migrate ${pkg.matcher}`);
}

let themeName: string | null = null;

const tailwindSpinner = spinner();
tailwindSpinner.start(`Migrating ${tailwindConfig.matcher}...`);
const tailwindCode = await readFile(tailwindConfig.paths[0], 'utf-8');
const transformedTailwind = transformTailwindConfig(tailwindCode);
await writeFile(tailwindConfig.paths[0], transformedTailwind.code);
tailwindSpinner.stop(`Successfully migrated ${tailwindConfig.matcher}`);

const theme = transformedTailwind.meta.themes.find((theme) => theme.type === 'preset');
try {
const tailwindCode = await readFile(tailwindConfig.paths[0], 'utf-8');
const transformedTailwind = transformTailwindConfig(tailwindCode);
themeName = transformedTailwind.meta.themes.find((theme) => theme.type === 'preset')?.name ?? null;
await writeFile(tailwindConfig.paths[0], transformedTailwind.code);
tailwindSpinner.stop(`Successfully migrated ${tailwindConfig.matcher}`);
} catch (e) {
if (e instanceof Error) {
tailwindSpinner.stop(`Failed to migrate ${tailwindConfig.matcher}: ${e.message}`);
}
tailwindSpinner.stop(`Failed to migrate ${tailwindConfig.matcher}`);
}

const appSpinner = spinner();
appSpinner.start(`Migrating ${app.matcher}...`);
const appCode = await readFile(app.paths[0], 'utf-8');
const transformedApp = transformApp(appCode, theme?.name ?? 'cerberus');
await writeFile(app.paths[0], transformedApp.code);
appSpinner.stop(`Successfully migrated ${app.matcher}`);
try {
const appCode = await readFile(app.paths[0], 'utf-8');
const transformedApp = transformApp(appCode, themeName ?? 'cerberus');
await writeFile(app.paths[0], transformedApp.code);
appSpinner.stop(`Successfully migrated ${app.matcher}!`);
} catch (e) {
if (e instanceof Error) {
appSpinner.stop(`Failed to migrate ${app.matcher}: ${e.message}`);
}
appSpinner.stop(`Failed to migrate ${app.matcher}.`);
}

const sourceFileMatcher = `{${sourceFolders.join(',')}}/**/*.{js,mjs,ts,mts,svelte}`;
const sourceFiles = await fg(sourceFileMatcher, { cwd, ignore: ['node_modules', 'dist', 'build', 'public'] });
const sourceFiles = await fg(sourceFileMatcher, {
cwd: cwd,
ignore: ['node_modules']
});

const sourceFilesSpinner = spinner();
sourceFilesSpinner.start(`Migrating source files...`);
for (const sourceFile of sourceFiles) {
sourceFilesSpinner.message(`Migrating ${sourceFile}...`);
const extension = extname(sourceFile);
if (extension === '.svelte') {
const svelteCode = await readFile(sourceFile, 'utf-8');
const transformedSvelte = transformSvelte(svelteCode);
await writeFile(sourceFile, transformedSvelte.code);
} else {
const moduleCode = await readFile(sourceFile, 'utf-8');
const transformedModule = transformModule(moduleCode);
await writeFile(sourceFile, transformedModule.code);
try {
for (const sourceFile of sourceFiles) {
sourceFilesSpinner.message(`Migrating ${sourceFile}...`);
const extension = extname(sourceFile);
if (extension === '.svelte') {
const svelteCode = await readFile(sourceFile, 'utf-8');
const transformedSvelte = transformSvelte(svelteCode);
await writeFile(sourceFile, transformedSvelte.code);
} else {
const moduleCode = await readFile(sourceFile, 'utf-8');
const transformedModule = transformModule(moduleCode);
await writeFile(sourceFile, transformedModule.code);
}
sourceFilesSpinner.message(`Successfully migrated ${sourceFile}!`);
}
sourceFilesSpinner.stop('Successfully migrated all source files!');
} catch (error) {
if (error instanceof Error) {
sourceFilesSpinner.stop(`Failed to migrate source files: ${error.message}`);
}
sourceFilesSpinner.stop('Failed to migrate source files.');
}

const installDependenciesSpinner = spinner();
installDependenciesSpinner.start('Installing dependencies...');
try {
await installDependencies(cwd);
installDependenciesSpinner.stop('Successfully installed dependencies!');
} catch (e) {
if (e instanceof Error) {
installDependenciesSpinner.stop(`Failed to install dependencies: ${e.message}`);
}
sourceFilesSpinner.message(`Successfully migrated ${sourceFile}`);
installDependenciesSpinner.stop('Failed to install dependencies.');
}
sourceFilesSpinner.stop('Successfully migrated all source files');
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest';
import { transformApp } from './transform-app.js';

describe('transformsApp', () => {
it('edits the `data-them` attribute when already present', () => {
it('transforms the `data-them` attribute when present', () => {
expect(
transformApp(
`
Expand All @@ -27,7 +27,7 @@ describe('transformsApp', () => {
.replace(/\r\n|\r|\n/g, '\n')
);
});
it('adds the `data-theme` attribute ', () => {
it('adds the `data-theme` attribute', () => {
expect(
transformApp(
`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ function transformApp(code: string, theme: string) {
const dataThemeAttribute = node.attributes.find((attribute) => {
return attribute.type === 'Attribute' && attribute.name === 'data-theme';
});
const newDataThemeAttribute = `data-theme="${theme}"`;
if (dataThemeAttribute) {
s.update(dataThemeAttribute.start, dataThemeAttribute.end, `data-theme="${theme}"`);
s.update(dataThemeAttribute.start, dataThemeAttribute.end, newDataThemeAttribute);
} else {
s.appendRight(node.start + '<body'.length, ` data-theme="${theme}"`);
s.appendLeft(node.start + '<body'.length, ` ${newDataThemeAttribute}`);
}
}
}
Expand Down
18 changes: 18 additions & 0 deletions packages/skeleton-cli/src/utility/install-dependencies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { detect, resolveCommand } from 'package-manager-detector';
import { execSync } from 'node:child_process';

async function installDependencies(cwd = process.cwd()) {
const pm = await detect({
cwd: cwd
});
const resolvedCommand = resolveCommand(pm?.agent ?? 'npm', 'install', ['--force']);
if (!resolvedCommand) {
throw new Error('Could not resolve package manager command.');
}
execSync(`${resolvedCommand.command} ${resolvedCommand.args.join(' ')}`, {
cwd: cwd,
stdio: 'ignore'
});
}

export { installDependencies };
1 change: 1 addition & 0 deletions packages/skeleton-cli/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"noEmit": true,
"esModuleInterop": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"skipDefaultLibCheck": true,
"skipLibCheck": true
},
Expand Down
51 changes: 0 additions & 51 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e0950e8

Please sign in to comment.