Skip to content

feat: yarn support #1027

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 42 additions & 24 deletions packages/api/src/codegen/languages/typescript/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,10 @@ function handleExecFailure(err: Error, opts: InstallerOptions = {}) {
throw err;
}

async function detectPackageManager(installDir: string) {
const pm = await preferredPM(installDir);
async function detectPackageManager() {
const projectDir = Storage.getProjectDir();

const pm = await preferredPM(projectDir);
if (pm) {
return pm.name;
}
Expand Down Expand Up @@ -162,35 +164,50 @@ export default class TSGenerator extends CodeGenerator {
// eslint-disable-next-line class-methods-use-this
async install(storage: Storage, opts: InstallerOptions = {}): Promise<void> {
const installDir = storage.getIdentifierStorageDir();
const packageManager = await detectPackageManager(installDir);
const packageManager = await detectPackageManager();

const handleError = (err: Error, options: InstallerOptions): void => {
// If `npm install` throws this error it always happens **after** our dependencies have been
// installed and is an annoying quirk that sometimes occurs when installing a package within
// our workspace as we're creating a circular dependency on `@readme/api-core`.
if (
process.env.NODE_ENV === 'test' &&
err.message.includes("npm ERR! Cannot set properties of null (setting 'dev')")
) {
(options.logger ? options.logger : logger)("npm threw an error but we're ignoring it");
return;
}

const installCommand = ['install', '--save', opts.dryRun ? '--dry-run' : ''].filter(Boolean);
handleExecFailure(err, options);
};

// This will install the installed SDK as a dependency within the current working directory,
// adding `@api/<sdk identifier>` as a dependency there so you can load it with
// `require('@api/<sdk identifier>)`.
return execa(packageManager, [...installCommand, installDir].filter(Boolean))
.then(res => handleExecSuccess(res, opts))
.catch(err => {
// If `npm install` throws this error it always happens **after** our dependencies have been
// installed and is an annoying quirk that sometimes occurs when installing a package within
// our workspace as we're creating a circular dependency on `@readme/api-core`.
if (
process.env.NODE_ENV === 'test' &&
err.message.includes("npm ERR! Cannot set properties of null (setting 'dev')")
) {
(opts.logger ? opts.logger : logger)("npm threw an error but we're ignoring it");
return;
}
if (packageManager === 'yarn') {
const installCommand = ['add', opts.dryRun ? '--dry-run' : ''].filter(Boolean);
const installSubPackagesCommand = ['install', opts.dryRun ? '--dry-run' : ''].filter(Boolean);

try {
const subPackagesResult = await execa(packageManager, [...installSubPackagesCommand], { cwd: installDir });
handleExecSuccess(subPackagesResult, opts);
const packageResult = await execa(packageManager, [...installCommand, installDir]);
handleExecSuccess(packageResult, opts);
} catch (err) {
handleError(err, opts);
}
} else {
const installCommand = ['install', opts.dryRun ? '--dry-run' : ''].filter(Boolean);

handleExecFailure(err, opts);
});
try {
const result = await execa(packageManager, [...installCommand, installDir]);
handleExecSuccess(result, opts);
} catch (err) {
handleError(err, opts);
}
}
}

static async uninstall(storage: Storage, opts: InstallerOptions = {}): Promise<void> {
const pkgName = storage.getPackageName() as string;
const installDir = storage.getIdentifierStorageDir();
const packageManager = await detectPackageManager(installDir);
const packageManager = await detectPackageManager();

const args = ['uninstall', pkgName, opts.dryRun ? '--dry-run' : ''].filter(Boolean);
return execa(packageManager, args)
Expand Down Expand Up @@ -620,6 +637,7 @@ dist/
// If the version that's in `info.version` isn't compatible with semver NPM won't be able to
// handle it properly so we need to fallback to something it can.
pkgVersion = semver.coerce('0.0.0') as SemVer;
logger(`Warning: OpenAPI info.version is missing or invalid. Defaulting to ${pkgVersion.version}`);
}

const tsupOptions: Options = {
Expand Down
15 changes: 15 additions & 0 deletions packages/api/src/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ export default class Storage {
fs.mkdirSync(Storage.getAPIsDir(), { recursive: true });
}

/**
* Retrieves the project's root directory path.
*
* If a storage directory has not been explicitly set, this method will default it to
* the current working directory. It then returns the directory name of the storage path.
*
*/
static getProjectDir() {
if (!Storage.dir) {
Storage.setStorageDir();
}

return path.dirname(Storage.dir);
}

/**
* Reset the state of the entire storage system.
*
Expand Down
Loading