Skip to content

Commit

Permalink
avoid cyclic dependency by expanding the segment of code that is dupl…
Browse files Browse the repository at this point in the history
…icated between schema tests and the testtools package.

Might want to look for a better solution in the future.
  • Loading branch information
WimTibackx committed Jun 26, 2024
1 parent f694528 commit 96a92a3
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 5 deletions.
1 change: 0 additions & 1 deletion packages/schema/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@
"@types/vscode": "^1.56.0",
"@vscode/vsce": "^2.19.0",
"@zenstackhq/runtime": "workspace:*",
"@zenstackhq/testtools": "workspace:*",
"dotenv": "^16.0.3",
"esbuild": "^0.15.12",
"prisma": "^5.15.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/schema/tests/generator/prisma-generator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import tmp from 'tmp';
import { loadDocument } from '../../src/cli/cli-util';
import { PrismaSchemaGenerator } from '../../src/plugins/prisma/schema-generator';
import { loadModel } from '../utils';
import { buildPackageJsonContents, initProjectDir } from '@zenstackhq/testtools';
import { buildPackageJsonContents, initProjectDir } from '../utils';

tmp.setGracefulCleanup();

Expand Down
105 changes: 105 additions & 0 deletions packages/schema/tests/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import * as tmp from 'tmp';
import { URI } from 'vscode-uri';
import { createZModelServices } from '../src/language-server/zmodel-module';
import { mergeBaseModels } from '../src/utils/ast-utils';
import { execSync } from 'node:child_process';

/* This file contains narrowly duplicated contents from the testtools package to avoid a cyclic dependency between testtools and schema */

/* Duplicated from testtools model.ts to avoid cyclic dependency */

tmp.setGracefulCleanup();

Expand Down Expand Up @@ -97,3 +102,103 @@ export const errorLike = (msg: string) => ({
message: expect.stringContaining(msg),
},
});


/* Duplicated from testtools schema.ts to avoid cyclic dependency */

export function normalizePath(p: string) {
return p ? p.split(path.sep).join(path.posix.sep) : p;
}

export function getWorkspaceRoot(start: string) {
let curr = normalizePath(start);
while (curr && curr !== '/') {
if (fs.existsSync(path.join(curr, 'pnpm-workspace.yaml'))) {
return curr;
} else {
curr = normalizePath(path.dirname(curr));
}
}
return undefined;
}

/* Duplicated from testtools pnpm-project.ts to avoid cyclic dependency */

export const PNPM_STORE_PATH = path.resolve(__dirname, '../../../.pnpm-test-store');
export const NPM_RC_FILE = '.npmrc';
export const NPM_RC_CONTENTS = `store-dir = ${PNPM_STORE_PATH}`;
export const PACKAGE_JSON_FILE = 'package.json';
export const PACKAGE_JSON_CONTENTS = '{"name":"test-project","version":"1.0.0"}';

export function preparePackageJson(dependencies: {[key: string]: string} = {}, devDependencies: {[key: string]: string} = {}, includeDefaults: boolean = true): string {
const tmpDir = tmp.dirSync({ unsafeCleanup: true }).name;
console.log(`Loading dependencies into store via temp dir ${tmpDir}`);
try {
const packageJsonContents = buildPackageJsonContents(dependencies, devDependencies, includeDefaults);

// I considered doing a `pnpm store add` here instead of a plain install. While that worked, I decided against it in the end because it's a secondary way of processing the dependencies and I didn't see a significant downside to just installing and throwing the local project away right after.
initProjectDir(tmpDir, packageJsonContents, false);

return packageJsonContents;
} finally {
fs.rmSync(tmpDir, {recursive: true, force: true});
}
}

export function buildPackageJsonContents(dependencies: {[key: string]: string} = {}, devDependencies: {[key: string]: string} = {}, includeDefaults: boolean = true): string {
if (includeDefaults) {
dependencies = {
"@prisma/client": "^5.14.0",
"zod": "^3.21.0",
"decimal.js": "^10.4.0",
...dependencies
},
devDependencies = {
"prisma": "^5.14.0",
"typescript": "^5.4.0",
"@types/node": "^20.0.0",
...devDependencies
}
}

const absoluteWorkspacePath = getWorkspaceRoot(__dirname);

return `{
"name":"test-project",
"version":"1.0.0",
"dependencies": {
${Object.entries(dependencies).map(([k, v]) => `"${k}": "${v}"`).join(',\n')}
},
"devDependencies": {
${Object.entries(devDependencies).map(([k, v]) => `"${k}": "${v}"`).join(',\n')}
},
"pnpm": {
"overrides": {
"@zenstackhq/language": "file:${absoluteWorkspacePath}/packages/language/dist",
"@zenstackhq/sdk": "file:${absoluteWorkspacePath}/packages/sdk/dist",
"@zenstackhq/runtime": "file:${absoluteWorkspacePath}/packages/runtime/dist"
}
}
}`;
}

export function initProjectDir(projectDir: string, packageJsonContents: string, offline = true) {
try {
if (!fs.existsSync(projectDir)) {
fs.mkdirSync(projectDir, { recursive: true });
}
fs.writeFileSync(path.join(projectDir, PACKAGE_JSON_FILE), packageJsonContents, { flag: 'w+' });
fs.writeFileSync(path.join(projectDir, NPM_RC_FILE), NPM_RC_CONTENTS, { flag: 'w+' });
} catch (e) {
console.error(`Failed to set up project dir in ${projectDir}`);
throw e;
}

try {
execSync(`pnpm install ${offline ? '--prefer-offline ' : ''}--ignore-workspace`, {cwd: projectDir, stdio: 'ignore'});
} catch (e) {
console.error(`Failed to initialize project dependencies in ${projectDir}${offline ? '(offline mode)' : '(online mode)'}`);
throw e;
}
}

3 changes: 0 additions & 3 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 96a92a3

Please sign in to comment.