Skip to content
Merged
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
2 changes: 2 additions & 0 deletions packages/dashboard/src/initialization/plugins.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// This file is used to skip the type check to the ./plugins file.
export {}
1 change: 1 addition & 0 deletions packages/dashboard/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"tsBuildInfoFile": "./dist/src.tsbuildinfo"
},
"include": ["./src", "./src/**/*.json"],
"exclude": ["./src/initialization/plugins.js"],
"references": [
{ "path": "../public-api" },
{ "path": "../theme/" },
Expand Down
2 changes: 2 additions & 0 deletions packages/mask/src/plugin-infra/register.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// This file is used to skip the type check to the ./register file.
export {}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// This file is a JavaScript file because it's reference to the plugins should not be counted as a project reference.
// If your plugin also works in isolated dashboard, please also register it in
// packages/dashboard/src/initialization/plugins.ts

Expand Down
1 change: 1 addition & 0 deletions packages/mask/src/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"lib": ["ES2021"]
},
"include": ["./", "./**/*.json"],
"exclude": ["./plugin-infra/register.js"],

// ! Note: mask/ depends dashboard/ on source-code level
// ! but dashboard/ depends mask/ on type level
Expand Down
11 changes: 8 additions & 3 deletions packages/scripts/src/commands/new-package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,16 @@ async function createNewPackage({ path, npmName, type, pluginID }: PackageOption
content.replace(INSERT_HERE, `${NormativeName} = '${pluginID}'\n${INSERT_HERE}`),
)
await changeFile.typescript(
resolve(ROOT_PATH, `packages/mask/src/plugin-infra/register.ts`),
resolve(ROOT_PATH, `packages/mask/src/plugin-infra/register.js`),
(content) => `${content}import '${npmName}'`,
)
await awaitChildProcess(shell.cwd(ROOT_PATH)`pnpm install --prefer-offline -C packages/mask ${npmName}`)
await changeFile(resolve(ROOT_PATH, 'packages/mask/package.json'), (content) =>
content.replaceAll(/workspace:\^undefined/g, 'workspace:*'),
)
await changeFile(resolve(ROOT_PATH, 'tsconfig.json'), (content) =>
content.replace(INSERT_HERE + ' 3', `"${npmName}": ["./${path}/src"],\n ${INSERT_HERE} 3`),
)
} else {
// cp -r packages/empty packages/NEW_PACKAGE
await copy(resolve(ROOT_PATH, 'packages/empty'), packagePath, {
Expand All @@ -134,9 +137,11 @@ async function createNewPackage({ path, npmName, type, pluginID }: PackageOption
content.name = npmName
})
await changeFile(resolve(ROOT_PATH, 'tsconfig.json'), (content) =>
content.replace(INSERT_HERE, `${INSERT_HERE}\n { "path": "./${path}/tsconfig.tests.json" },`),
content
.replace(INSERT_HERE + ' 1', `${INSERT_HERE} 1\n { "path": "./${path}/tsconfig.tests.json" },`)
.replace(INSERT_HERE + ' 2', `"${npmName}": ["./${path}/src"],\n ${INSERT_HERE} 2`),
)
await changeFile(resolve(packagePath, 'README.md'), (content) => `# ${npmName}`)
await changeFile(resolve(packagePath, 'README.md'), () => `# ${npmName}`)
}

// regenerate lockfile and install dependencies for newly installed packages
Expand Down
81 changes: 80 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,93 @@
{ "path": "./packages/dashboard/stories" },
{ "path": "./packages/theme/stories" },
// Tests
// @masknet/scripts: insert-here
// @masknet/scripts: insert-here 1
{ "path": "./packages/backup-format/tsconfig.tests.json" },
{ "path": "./packages/encryption/tsconfig.tests.json" },
{ "path": "./packages/shared-base/tsconfig.tests.json" },
// All plugins should be type checked too
{ "path": "./packages/plugins" }
],
"compilerOptions": {
"paths": {
// # Why?
// TypeScript project reference requires manually declaring all referenced projects.

// For example, we have 2 projects A and B under /projects/a and /projects/b and B depends on A,
// if we do not list A in the references, when we write

// > /packages/b/src/index.ts

// ```ts
// import { something } from '../../a'
// ```

// If there is no "reference": [{ "path": "../a/tsconfig.json" }] in /packages/b/tsconfig.json,
// TypeScript will complain TS6307: "File '/packages/b/src/index.ts' is not listed within the file list of the project '/packages/b/tsconfig.json'. Projects must list all files or use an 'include' pattern."

// This is error is GOOD because it means TypeScript _can_ automatically detect the missing references.

// # What about monorepo?
// But TypeScript cannot detect the missing references when we install them as monorepo packages.
// Still the project structure above, but A is installed as "@masknet/a" in /packages/b/node_modules/@masknet/a,
// TypeScript will accept the missing reference to the A project,
// because it will go through the "moduleResolution": "Node" resolution, if `.d.ts` file is found,
// the project will _accidentally_ compiles, but TypeScript does DON'T know those packages has dependencies in the project reference graph.
// This will cause the project to randomly fail to be type-checked.

// # Solution
// We use "paths" to map the Node-style import path back to the relative style,
// therefore TypeScript can check the missing dependencies again.

// This will not introduce problems like mapping "@src/" to "/packages/a/src" which is problematic,
// because those projects (if they're correctly configured) is installed in the node_modules,
// so if any toolchain does not support the "paths" feature, it will still work.

// This will bring another problem: now we can reference a project without installing it as a monorepo dependency,
// which is unwanted. We need to take care of this.

"@masknet/backup-format": ["./packages/backup-format/src"],
// ! dashboard is explicitly opt-out of this feature, it and the /packages/mask has circulare reference that TypeScript does not allows.
// "@masknet/dashboard": ["./packages/dashboard/src"],
"@masknet/encryption": ["./packages/encryption/src"],
"@masknet/external-plugin-previewer": ["./packages/external-plugin-previewer/src"],
"@masknet/gun-utils": ["./packages/gun-utils/src"],
"@masknet/icons": ["./packages/icons"],
"@masknet/injected-script": ["./packages/injected-script/sdk"],
// @masknet/mask is not listed. it does not have a exports/main field in the package.json.
"@masknet/mask-sdk": ["./packages/mask-sdk/server"],
"@masknet/plugin-infra": ["./packages/plugin-infra/src"],
"@masknet/global-types/*": ["./packages/polyfills/types/*"],
"@masknet/provider-proxy": ["./packages/provider-proxy/src"],
"@masknet/public-api": ["./packages/public-api/src"],
// @masknet/scripts is not listed. It does not mean to be installed as a dependency and not join the type check.
"@masknet/shared": ["./packages/shared/src"],
"@masknet/shared-base": ["./packages/shared-base/src"],
"@masknet/storybook-shared": ["./packages/storybook-shared/src"],
"@masknet/theme": ["./packages/theme/src"],
// @masknet/web3-constants is not listed. It is not a TS project (only contains JSON files).
// @masknet/web3-contracts is not listed. It is not a TS project (only contains generated JSON and .d.ts files).
"@masknet/web3-kit": ["./packages/web3-kit/src"],
"@masknet/web3-providers": ["./packages/web3-providers/src"],
"@masknet/web3-shared-base": ["./packages/web3-shared/base/src"],
"@masknet/web3-shared-evm": ["./packages/web3-shared/evm/src"],
"@masknet/web3-shared-flow": ["./packages/web3-shared/flow/src"],
"@masknet/web3-shared-solana": ["./packages/web3-shared/solana/src"],
// @masknet/scripts: insert-here 2

// Plugins
"@masknet/plugin-dao": ["./packages/plugins/DAO/src"],
"@masknet/plugin-debugger": ["./packages/plugins/Debugger/src"],
"@masknet/plugin-example": ["./packages/plugins/example/src"],
"@masknet/plugin-file-service": ["./packages/plugins/FileService/src"],
"@masknet/plugin-flow": ["./packages/plugins/Flow/src"],
"@masknet/plugin-rss3": ["./packages/plugins/RSS3/src"],
"@masknet/plugin-solana": ["./packages/plugins/Solana/src"],
"@masknet/plugin-template": ["./packages/plugins/template/src"],
"@masknet/plugin-cyber-connect": ["./packages/plugins/CyberConnect/src"],
// @masknet/scripts: insert-here 3
"@masknet/plugin-wallet": ["./packages/plugins/Wallet/src"]
},
// Classification follows https://www.typescriptlang.org/tsconfig

// Type Checking
Expand Down