Skip to content

Commit

Permalink
use sync apis for fs (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
AdrianGonz97 authored Aug 24, 2024
1 parent 7e2909e commit 753f76e
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 93 deletions.
30 changes: 13 additions & 17 deletions packages/core/adder/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import path from 'node:path';
import * as pc from 'picocolors';
import { serializeJson } from '@svelte-cli/ast-tooling';
import { commonFilePaths, format, writeFile } from '../files/utils';
import { type ProjectType, createProject, detectSvelteDirectory } from '../utils/create-project';
import { createProject, detectSvelteDirectory } from '../utils/create-project';
import { createOrUpdateFiles } from '../files/processors';
import { getPackageJson } from '../utils/common';
import {
Expand Down Expand Up @@ -36,6 +36,8 @@ import { displayNextSteps } from './nextSteps';
import { spinner, log, cancel } from '@svelte-cli/clack-prompts';
import { executeCli } from '../utils/cli';

export type ProjectType = 'svelte' | 'kit';

export type AdderDetails<Args extends OptionDefinition> = {
config: AdderConfig<Args>;
checks: AdderCheckConfig<Args>;
Expand Down Expand Up @@ -132,15 +134,13 @@ async function executePlan<Args extends OptionDefinition>(
// create project if required
if (executionPlan.createProject) {
const cwd = executionPlan.commonCliOptions.path ?? executionPlan.workingDirectory;
const supportKit = adderDetails.some((x) => x.config.metadata.environments.kit);
const supportSvelte = adderDetails.some((x) => x.config.metadata.environments.svelte);
const { projectCreated, directory } = await createProject(cwd, supportKit, supportSvelte);
const { projectCreated, directory } = await createProject(cwd);
if (!projectCreated) return;
executionPlan.workingDirectory = directory;
}

const workspace = createEmptyWorkspace();
await populateWorkspaceDetails(workspace, executionPlan.workingDirectory);
populateWorkspaceDetails(workspace, executionPlan.workingDirectory);
const projectType: ProjectType = workspace.kit.installed ? 'kit' : 'svelte';

// select appropriate adders
Expand Down Expand Up @@ -218,7 +218,7 @@ async function executePlan<Args extends OptionDefinition>(
const adderId = config.metadata.id;

const adderWorkspace = createEmptyWorkspace<Args>();
await populateWorkspaceDetails(adderWorkspace, executionPlan.workingDirectory);
populateWorkspaceDetails(adderWorkspace, executionPlan.workingDirectory);
if (executionPlan.cliOptionsByAdderId) {
for (const [key, value] of Object.entries(executionPlan.cliOptionsByAdderId[adderId])) {
addPropertyToWorkspaceOption(adderWorkspace, key, value);
Expand Down Expand Up @@ -252,7 +252,7 @@ async function executePlan<Args extends OptionDefinition>(
}

// reload workspace as adders might have changed i.e. dependencies
await populateWorkspaceDetails(workspace, executionPlan.workingDirectory);
populateWorkspaceDetails(workspace, executionPlan.workingDirectory);

let installStatus;
if (!remoteControlled && !executionPlan.commonCliOptions.skipInstall)
Expand Down Expand Up @@ -281,8 +281,8 @@ async function processInlineAdder<Args extends OptionDefinition>(
workspace: Workspace<Args>,
isInstall: boolean
) {
const pkgPath = await installPackages(config, workspace);
const updatedOrCreatedFiles = await createOrUpdateFiles(config.files, workspace);
const pkgPath = installPackages(config, workspace);
const updatedOrCreatedFiles = createOrUpdateFiles(config.files, workspace);
await runHooks(config, workspace, isInstall);

const changedFiles = [pkgPath, ...updatedOrCreatedFiles];
Expand Down Expand Up @@ -318,11 +318,11 @@ export function determineWorkingDirectory(directory: string | undefined): string
return cwd;
}

export async function installPackages<Args extends OptionDefinition>(
export function installPackages<Args extends OptionDefinition>(
config: InlineAdderConfig<Args>,
workspace: Workspace<Args>
): Promise<string> {
const { text: originalText, data } = await getPackageJson(workspace);
): string {
const { text: originalText, data } = getPackageJson(workspace);

for (const dependency of config.packages) {
if (dependency.condition && !dependency.condition(workspace)) {
Expand All @@ -347,11 +347,7 @@ export async function installPackages<Args extends OptionDefinition>(
if (data.dependencies) data.dependencies = alphabetizeProperties(data.dependencies);
if (data.devDependencies) data.devDependencies = alphabetizeProperties(data.devDependencies);

await writeFile(
workspace,
commonFilePaths.packageJsonFilePath,
serializeJson(originalText, data)
);
writeFile(workspace, commonFilePaths.packageJsonFilePath, serializeJson(originalText, data));
return commonFilePaths.packageJsonFilePath;
}

Expand Down
28 changes: 16 additions & 12 deletions packages/core/adder/postconditions.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import dedent from 'dedent';
import * as pc from 'picocolors';
import { messagePrompt } from '../utils/prompts';
import { fileExistsWorkspace, readFile } from '../files/utils';
Expand All @@ -7,12 +8,12 @@ import type { OptionDefinition } from './options';

export type PreconditionParameters<Args extends OptionDefinition> = {
workspace: Workspace<Args>;
fileExists: (path: string) => Promise<void>;
fileContains: (path: string, expectedContent: string) => Promise<void>;
fileExists: (path: string) => void;
fileContains: (path: string, expectedContent: string) => void;
};
export type Postcondition<Args extends OptionDefinition> = {
name: string;
run: (params: PreconditionParameters<Args>) => Promise<void>;
run: (params: PreconditionParameters<Args>) => Promise<void> | void;
};

export async function checkPostconditions<Args extends OptionDefinition>(
Expand Down Expand Up @@ -41,29 +42,32 @@ export async function checkPostconditions<Args extends OptionDefinition>(
return unmetPostconditions;
}

async function fileExists<Args extends OptionDefinition>(path: string, workspace: Workspace<Args>) {
if (await fileExistsWorkspace(workspace, path)) return;
function fileExists<Args extends OptionDefinition>(path: string, workspace: Workspace<Args>) {
if (fileExistsWorkspace(workspace, path)) return;

throw new Error(`File "${path}" does not exists`);
}

async function fileContains<Args extends OptionDefinition>(
function fileContains<Args extends OptionDefinition>(
path: string,
workspace: Workspace<Args>,
expectedContent: string
): Promise<void> {
await fileExists(path, workspace);
): void {
fileExists(path, workspace);

const content = await readFile(workspace, path);
const content = readFile(workspace, path);
if (content && content.includes(expectedContent)) return;

throw new Error(`File "${path}" does not contain "${expectedContent}"`);
}

export function printUnmetPostconditions(unmetPostconditions: string[]): void {
const postconditionList = unmetPostconditions.map((x) => pc.yellow(`- ${x}`)).join('\n');
const additionalText = `Postconditions are not supposed to fail.
Please open an issue providing the full console output:
https://github.com/sveltejs/cli/issues/new/choose`;
const additionalText = dedent`
Postconditions are not supposed to fail.
Please open an issue providing the full console output:
https://github.com/sveltejs/cli/issues/new/choose
`;

messagePrompt('Postconditions not met', `${postconditionList}\n\n${additionalText}`);
}
3 changes: 1 addition & 2 deletions packages/core/adder/preconditions.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import * as pc from 'picocolors';
import { booleanPrompt, endPrompts, messagePrompt } from '../utils/prompts';
import { executeCli } from '../utils/cli';
import type { AdderDetails } from './execute';
import type { AdderDetails, ProjectType } from './execute';
import type { Precondition } from './config';
import type { OptionDefinition } from './options';
import type { ProjectType } from '../utils/create-project';

function getGlobalPreconditions<Args extends OptionDefinition>(
executingCli: string,
Expand Down
10 changes: 5 additions & 5 deletions packages/core/files/processors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,24 +86,24 @@ export type FileTypes<Args extends OptionDefinition> =
* @param workspace
* @returns a list of paths of changed or created files
*/
export async function createOrUpdateFiles<Args extends OptionDefinition>(
export function createOrUpdateFiles<Args extends OptionDefinition>(
files: Array<FileTypes<Args>>,
workspace: Workspace<Args>
): Promise<string[]> {
): string[] {
const changedFiles = [];
for (const fileDetails of files) {
try {
if (fileDetails.condition && !fileDetails.condition(workspace)) {
continue;
}

const exists = await fileExistsWorkspace(workspace, fileDetails.name(workspace));
const exists = fileExistsWorkspace(workspace, fileDetails.name(workspace));

let content = '';
if (!exists) {
content = '';
} else {
content = await readFile(workspace, fileDetails.name(workspace));
content = readFile(workspace, fileDetails.name(workspace));
}

if (fileDetails.contentType == 'script') {
Expand All @@ -120,7 +120,7 @@ export async function createOrUpdateFiles<Args extends OptionDefinition>(
content = handleHtmlFile(content, fileDetails, workspace);
}

await writeFile(workspace, fileDetails.name(workspace), content);
writeFile(workspace, fileDetails.name(workspace), content);
changedFiles.push(fileDetails.name(workspace));
} catch (e) {
if (e instanceof Error)
Expand Down
50 changes: 14 additions & 36 deletions packages/core/files/utils.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,43 @@
import fs from 'node:fs/promises';
import fs from 'node:fs';
import path from 'node:path';
import { executeCli } from '../utils/cli';
import type { WorkspaceWithoutExplicitArgs } from '../utils/workspace';

export async function readFile(
workspace: WorkspaceWithoutExplicitArgs,
filePath: string
): Promise<string> {
export function readFile(workspace: WorkspaceWithoutExplicitArgs, filePath: string): string {
const fullFilePath = getFilePath(workspace.cwd, filePath);

if (!(await fileExistsWorkspace(workspace, filePath))) {
if (!fileExistsWorkspace(workspace, filePath)) {
return '';
}

const buffer = await fs.readFile(fullFilePath);
const text = buffer.toString();
const text = fs.readFileSync(fullFilePath, 'utf8');

return text;
}

export async function writeFile(
export function writeFile(
workspace: WorkspaceWithoutExplicitArgs,
filePath: string,
content: string
): Promise<void> {
): void {
const fullFilePath = getFilePath(workspace.cwd, filePath);
const fullDirectoryPath = path.dirname(fullFilePath);

if (content && !content.endsWith('\n')) content += '\n';

if (!(await directoryExists(fullDirectoryPath))) {
await fs.mkdir(fullDirectoryPath, { recursive: true });
if (!fs.existsSync(fullDirectoryPath)) {
fs.mkdirSync(fullDirectoryPath, { recursive: true });
}

await fs.writeFile(fullFilePath, content);
fs.writeFileSync(fullFilePath, content, 'utf8');
}

export async function fileExistsWorkspace(
export function fileExistsWorkspace(
workspace: WorkspaceWithoutExplicitArgs,
filePath: string
): Promise<boolean> {
): boolean {
const fullFilePath = getFilePath(workspace.cwd, filePath);
return await fileExists(fullFilePath);
}

export async function fileExists(filePath: string): Promise<boolean> {
try {
await fs.access(filePath, fs.constants.F_OK);
return true;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
return false;
}
}

export async function directoryExists(directoryPath: string): Promise<boolean> {
return await fileExists(directoryPath);
return fs.existsSync(fullFilePath);
}

export function getFilePath(cwd: string, fileName: string): string {
Expand All @@ -76,19 +58,15 @@ export const commonFilePaths = {
svelteConfigFilePath: 'svelte.config.js'
};

export async function findUp(
searchPath: string,
fileName: string,
maxDepth?: number
): Promise<boolean> {
export function findUp(searchPath: string, fileName: string, maxDepth?: number): boolean {
// partially sourced from https://github.com/privatenumber/get-tsconfig/blob/9e78ec52d450d58743439358dd88e2066109743f/src/utils/find-up.ts#L5
let depth = 0;
while (!maxDepth || depth < maxDepth) {
const configPath = path.posix.join(searchPath, fileName);

try {
// `access` throws an exception if the file could not be found
await fs.access(configPath);
fs.accessSync(configPath);
return true;
} catch {
const parentPath = path.dirname(searchPath);
Expand Down
6 changes: 3 additions & 3 deletions packages/core/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ export type Package = {
keywords?: string[];
};

export async function getPackageJson(workspace: WorkspaceWithoutExplicitArgs): Promise<{
export function getPackageJson(workspace: WorkspaceWithoutExplicitArgs): {
text: string;
data: Package;
}> {
const packageText = await readFile(workspace, commonFilePaths.packageJsonFilePath);
} {
const packageText = readFile(workspace, commonFilePaths.packageJsonFilePath);
if (!packageText) {
return {
text: '',
Expand Down
10 changes: 5 additions & 5 deletions packages/core/utils/create-project.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fs from 'node:fs';
import path from 'node:path';
import * as p from './prompts';
import { commonFilePaths, directoryExists, fileExists } from '../files/utils';
import { commonFilePaths } from '../files/utils';
import { getPackageJson } from './common';
import { createEmptyWorkspace } from './workspace';
import { spinner } from '@svelte-cli/clack-prompts';
Expand All @@ -14,21 +14,21 @@ export async function detectSvelteDirectory(directoryPath: string): Promise<stri
const parentDirectoryPath = path.normalize(path.join(directoryPath, '..'));
const isRoot = parentDirectoryPath == directoryPath;

if (!isRoot && !(await directoryExists(directoryPath))) {
if (!isRoot && !fs.existsSync(directoryPath)) {
return await detectSvelteDirectory(parentDirectoryPath);
}

if (!isRoot && !(await fileExists(packageJsonPath))) {
if (!isRoot && !fs.existsSync(packageJsonPath)) {
return await detectSvelteDirectory(parentDirectoryPath);
}

if (isRoot && !(await fileExists(packageJsonPath))) {
if (isRoot && !fs.existsSync(packageJsonPath)) {
return null;
}

const emptyWorkspace = createEmptyWorkspace();
emptyWorkspace.cwd = directoryPath;
const { data: packageJson } = await getPackageJson(emptyWorkspace);
const { data: packageJson } = getPackageJson(emptyWorkspace);

if (packageJson.devDependencies && 'svelte' in packageJson.devDependencies) {
return directoryPath;
Expand Down
Loading

0 comments on commit 753f76e

Please sign in to comment.