Skip to content
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

Passport tsup migration #1963

Draft
wants to merge 27 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d86407b
Use src folder for types inference
zaidarain1 Jul 1, 2024
e128666
remove rollup from generated-clients
zaidarain1 Jul 1, 2024
4f21c52
remove tests from tsconfig exclude
zaidarain1 Jul 1, 2024
8be2200
finish dev mode recursive script, and add dev mode lock files to prev…
zaidarain1 Jul 2, 2024
ba7d649
fix yarn gitignore
zaidarain1 Jul 3, 2024
5febc6d
fix relative path script runs
zaidarain1 Jul 3, 2024
89b44a0
fix relative paths
zaidarain1 Jul 3, 2024
d0da17d
complete entire passport dev flow
zaidarain1 Jul 4, 2024
0b973d8
readd blockchain data rollup
zaidarain1 Jul 4, 2024
c1b0092
consistent swc version
zaidarain1 Jul 4, 2024
da4bdf9
update lockfile
zaidarain1 Jul 4, 2024
876244e
readd dts generation when building
zaidarain1 Jul 4, 2024
bc1028c
fix dts creation for all affected packages and optimize tsup configs
zaidarain1 Jul 4, 2024
f7b3705
subtle tweaks and improvements
zaidarain1 Jul 5, 2024
4c38a1e
make concurrently raw for sdk sample app
zaidarain1 Jul 5, 2024
c67b99f
cleanup changes and fix star import issues
zaidarain1 Jul 5, 2024
db44f58
remove console logs
zaidarain1 Jul 5, 2024
aa893d8
test tsup config changes
zaidarain1 Jul 8, 2024
0c2a5d7
fix re-exporting imported namespaces as esbuild (used by tsup) doesnt…
zaidarain1 Jul 8, 2024
2de8d0b
cleanup changes and add build:all scripts to changed packages
zaidarain1 Jul 8, 2024
15ca93e
add custom eslint rule to packages to notify devs of esbuild namespac…
zaidarain1 Jul 9, 2024
bbadb53
fix syncpack check
zaidarain1 Jul 9, 2024
2e58b0a
silent only on dev mode for tsup and fix missing build script
zaidarain1 Jul 9, 2024
09456db
update lockfile and package.json cleanups
zaidarain1 Jul 9, 2024
016aa91
fix type export
zaidarain1 Jul 9, 2024
6bc283b
revert metrics commonjs
zaidarain1 Jul 9, 2024
e18b03b
update rule for normal namespace exports, and set up autofixing for t…
zaidarain1 Jul 9, 2024
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
9 changes: 2 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,8 @@ cache/
*version.properties

.pnp.*
.yarn/
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
.yarn/cache
.yarn/install-state.gz

.yalc
yalc.lock
Expand Down
541 changes: 541 additions & 0 deletions .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
nodeLinker: node-modules

plugins:
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
spec: "@yarnpkg/plugin-workspace-tools"
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: "@yarnpkg/plugin-interactive-tools"

yarnPath: .yarn/releases/yarn-3.6.1.cjs
163 changes: 163 additions & 0 deletions dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/* eslint-disable no-control-regex */
/* eslint-disable no-console */
/* eslint-disable no-continue */

import fs from 'fs';
import { execSync, spawn } from 'child_process';
import path from 'path';

type Workspace = `@imtbl/${string}@workspace:${string}`;

const lockFileName = `dev-mode-${process.pid}.lock`;

const childProcesses: ReturnType<typeof spawn>[] = [];

const packageName = process.argv[2];
if (!packageName) {
console.error('Please specify a package name, e.g., @imtbl/passport');
process.exit(1);
}

// Function to check for the existence of a lock file in a workspace
const workspaceLocked = (workspacePath: string) => {
const lockFiles = fs.readdirSync(workspacePath)
.filter((file) => file.startsWith('dev-mode-') && file.endsWith('.lock'));

for (const lockFile of lockFiles) {
const lockFilePath = path.join(workspacePath, lockFile);
// Extract PID from the lock file name
const pidMatch = lockFile.match(/dev-mode-(\d+)\.lock/);
if (pidMatch) {
const pid = parseInt(pidMatch[1], 10);
try {
// Attempt to send a signal 0 to the process. If the process exists, no error is thrown.
process.kill(pid, 0);
return true; // PID is still running
} catch (e: any) {
if (e.code === 'ESRCH') {
// No process with the given PID exists, meaning the lock file is stale
fs.unlinkSync(lockFilePath); // Consider cleaning up the stale lock file
continue; // Check next lock file if any
}
// For other errors (e.g., permission issues), assume the process is still running
return true;
}
}
}
return false; // No relevant lock file exists or all found were stale and removed
};

// Function to run the "dev" script in a workspace
const runDevScript = (workspace: Workspace) => {
const workspacePath = path.join(__dirname, workspace.split('@workspace:')[1]);
// if lockfile exists and the pid in the lockfile name is still running, skip running the dev script
if (workspaceLocked(workspacePath)) return;

const lockFilePath = path.join(workspacePath, lockFileName);

const devProcess = spawn('yarn', ['run', 'dev'], {
cwd: workspacePath,
stdio: 'inherit',
shell: true, // Use shell to interpret the command correctly on all platforms
});

childProcesses.push(devProcess);

// Write the PID of the dev process to the lock file
fs.writeFileSync(lockFilePath, '');

devProcess.on('error', (error) => {
console.error(`Error running 'dev' script for ${workspace}: ${error}`);
});
};

const workspaces = (execSync(`yarn workspace ${packageName} info --dependents --name-only --recursive`)
.toString()
.trim()
.split('\n')
.filter((line) => line.includes('@imtbl') && !line.includes('@npm')))
.map((line) => line.split('─ ')[1].trim().replace(/\x1B\[[0-9;]*m/g, '') as Workspace);

if (!workspaces.some((workspace) => workspace.split('@workspace')[0] === packageName)) {
console.error(`No workspaces found for package ${packageName}`);
process.exit(1);
}

const mainWorkspacePath = workspaces.find((workspace) => workspace.includes(packageName))?.split('@workspace:')[1];

if (!mainWorkspacePath) {
console.error(`Could not find path for ${packageName}`);
process.exit(1);
}

const fixedMainWorkspacePath = path.join(__dirname, mainWorkspacePath);

const watchPaths = workspaces
.filter((workspace) => !workspace.includes(packageName))
.map((workspace) => {
if (!fixedMainWorkspacePath) {
console.error(`Could not find path for ${packageName}`);
process.exit(1);
}

const workspacePath = workspace.split('@workspace:')[1].concat('/dist/index.js');

// Assuming the script is run from the package directory, make paths relative to it
const relativePath = path.relative(mainWorkspacePath, workspacePath);
return relativePath;
});

const removeLockFile = () => {
workspaces.forEach((workspace) => {
const workspacePath = path.join(__dirname, workspace.split('@workspace:')[1]);
const lockFilePath = path.join(workspacePath, lockFileName);

if (fs.existsSync(lockFilePath)) {
fs.rmSync(lockFilePath);
}
});
};

if (workspaceLocked(fixedMainWorkspacePath)) {
console.error(`A lock file and running dev process exists for ${packageName}. Exiting...`);
process.exit(1);
}

execSync(`yarn workspace ${packageName} build:all`, {
cwd: __dirname,
stdio: 'inherit',
});

workspaces.forEach((workspace) => {
if (!workspace.includes(packageName)) {
runDevScript(workspace);
}
});

const tsupCommand = `yarn workspace ${packageName} tsup --watch --silent src --watch ${watchPaths.join(' --watch ')}`;
// eslint-disable-next-line max-len
const tscCommand = `yarn workspace ${packageName} tsc --watch --noEmit false --declaration --emitDeclarationOnly --preserveWatchOutput`;

fs.writeFileSync(path.join(fixedMainWorkspacePath, lockFileName), '');

const [command, ...args] = tsupCommand.split(/\s+/);
const tsupProcess = spawn(command, args, { stdio: 'inherit' });

tsupProcess.on('error', (error) => console.error(`Spawn error: ${error}`));

const [tscCommandName, ...tscArgs] = tscCommand.split(/\s+/);
const tscProcess = spawn(tscCommandName, tscArgs, { stdio: 'inherit' });

tscProcess.on('error', (error) => console.error(`Spawn error: ${error}`));

childProcesses.push(tsupProcess, tscProcess);

const handleClose = () => {
childProcesses.forEach((child) => child.kill());
removeLockFile();
process.exit(0);
};

process.on('SIGINT', handleClose);
process.on('SIGTERM', handleClose);
process.on('close', handleClose);
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
"packages/internal/dex/sdk",
"packages/internal/dex/sdk-sample-app",
"packages/internal/bridge/sdk",
"packages/internal/eslint-rules",
"packages/internal/factory/sdk",
"packages/internal/factory/factory-sample-app",
"packages/internal/generated-clients",
Expand Down
12 changes: 12 additions & 0 deletions packages/config/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": ["../../.eslintrc"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json",
"tsconfigRootDir": "."
},
"plugins": ["@imtbl/imtbl"],
"rules": {
"@imtbl/imtbl/no-namespace-export": "error"
}
}
11 changes: 7 additions & 4 deletions packages/config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,20 @@
"@imtbl/metrics": "0.0.0"
},
"devDependencies": {
"@rollup/plugin-typescript": "^11.0.0",
"@imtbl/eslint-plugin-imtbl": "0.0.0",
"@swc/core": "^1.3.36",
"@swc/jest": "^0.2.24",
"@types/jest": "^29.4.3",
"@types/node": "^18.14.2",
"@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.57.1",
"concurrently": "^8.2.2",
"eslint": "^8.40.0",
"jest": "^29.4.3",
"jest-environment-jsdom": "^29.4.3",
"prettier": "^2.8.7",
"rollup": "^3.17.2",
"ts-node": "^10.9.1",
"tsup": "^8.1.0",
"typescript": "^4.9.5"
},
"engines": {
Expand All @@ -35,8 +36,10 @@
"private": true,
"repository": "immutable/ts-immutable-sdk.git",
"scripts": {
"build": "NODE_ENV=production rollup --config rollup.config.js",
"dev": "rollup --config rollup.config.js -w",
"build": "tsup & tsc --noEmit false --declaration --emitDeclarationOnly",
"build:all": "yarn workspaces foreach --parallel --recursive --topological-dev --jobs unlimited --verbose run build",
"dev": "concurrently --raw 'tsup --watch --silent' 'tsc --watch --noEmit false --declaration --emitDeclarationOnly --preserveWatchOutput'",
"dev:all": "ts-node ../../dev.ts @imtbl/config",
"lint": "eslint ./src --ext .ts,.jsx,.tsx --max-warnings=0",
"test": "jest",
"test:watch": "jest --watch",
Expand Down
10 changes: 0 additions & 10 deletions packages/config/rollup.config.js

This file was deleted.

11 changes: 11 additions & 0 deletions packages/config/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { defineConfig } from 'tsup';

export default defineConfig({
entry: ['src/index.ts'],
outDir: 'dist',
format: ['esm'],
target: 'es2022',
external: ['axios'],
silent: false,
bundle: true,
});
11 changes: 11 additions & 0 deletions packages/internal/eslint-rules/eslint-plugin-imtbl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* eslint-disable @typescript-eslint/naming-convention */
const noNamespaceExportRule = require('./rules/no-namespace-export');

module.exports = {
meta: {
name: 'eslint-plugin-imtbl',
},
rules: {
'no-namespace-export': noNamespaceExportRule,
},
};
17 changes: 17 additions & 0 deletions packages/internal/eslint-rules/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "@imtbl/eslint-plugin-imtbl",
"description": "Custom eslint rules in the Typescript SDK",
"version": "0.0.0",
"author": "Immutable",
"bugs": "https://github.com/immutable/ts-immutable-sdk/issues",
"homepage": "https://github.com/immutable/ts-immutable-sdk#readme",
"license": "Apache-2.0",
"main": "eslint-plugin-imtbl.js",
"packageManager": "[email protected]",
"private": true,
"repository": "immutable/ts-immutable-sdk.git",
"scripts": {
"build": ""
},
"type": "commonjs"
}
75 changes: 75 additions & 0 deletions packages/internal/eslint-rules/rules/no-namespace-export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* eslint-disable @typescript-eslint/brace-style */
/* eslint-disable @typescript-eslint/naming-convention */
/* eslint-disable max-len */
module.exports = {
meta: {
type: 'problem',
docs: {
description: 'disallow exporting namespace imports directly or as part of an object, including direct namespace exports like export * as name from \'module\'',
category: 'Possible Errors',
recommended: true,
},
schema: [], // No options
fixable: 'code', // Indicate that this rule supports automatic fixing
messages: {
namespaceExport: 'Exporting namespace imports directly or as part of an object may lead to issues with esbuild. Please refactor to avoid this pattern.',
directNamespaceExport: 'Direct namespace exports like export * as name from \'module\' are disallowed due to potential issues with esbuild.',
},
},
create(context) {
const namespaceImports = new Map();
const variableMappings = new Map();

return {
ImportDeclaration(node) {
node.specifiers.forEach((specifier) => {
if (specifier.type === 'ImportNamespaceSpecifier') {
namespaceImports.set(specifier.local.name, true);
}
});
},
VariableDeclarator(node) {
if (node.init && node.init.type === 'Identifier' && namespaceImports.has(node.init.name)) {
variableMappings.set(node.id.name, true);
}
},
ExportNamedDeclaration(node) {
if (node.declaration && node.declaration.declarations) {
node.declaration.declarations.forEach((declarator) => {
if (declarator.init && declarator.init.type === 'Identifier' && (namespaceImports.has(declarator.init.name) || variableMappings.has(declarator.init.name))) {
context.report({
node: declarator,
messageId: 'namespaceExport',
});
} else if (declarator.init && declarator.init.type === 'ObjectExpression') {
declarator.init.properties.forEach((property) => {
if (property.value && property.value.type === 'Identifier' && (namespaceImports.has(property.value.name) || variableMappings.has(property.value.name))) {
context.report({
node: property,
messageId: 'namespaceExport',
});
}
});
}
});
}
},
ExportAllDeclaration(node) {
if (node.exported) {
context.report({
node,
messageId: 'directNamespaceExport',
fix(fixer) {
const importDeclaration = `import * as ${node.exported.name}Import from '${node.source.value}';\n`;
const exportDeclaration = `export const ${node.exported.name} = { ...${node.exported.name}Import };\n`; // Added newline here
const rangeToRemove = [node.range[0], node.range[1] + 1]; // +1 to include the semicolon
return [
fixer.replaceTextRange(rangeToRemove, `${importDeclaration}${exportDeclaration}\n`), // Added newline here
];
},
});
}
},
};
},
};
12 changes: 12 additions & 0 deletions packages/internal/generated-clients/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": ["../../../.eslintrc"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json",
"tsconfigRootDir": "."
},
"plugins": ["@imtbl/imtbl"],
"rules": {
"@imtbl/imtbl/no-namespace-export": "error"
}
}
Loading
Loading