-
Notifications
You must be signed in to change notification settings - Fork 1.2k
feat(editor): Implement dynamic type loading for TS/JS autocompletion #6425
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
base: master
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for reliable-cocada-166884 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
0a4592c
to
d44da42
Compare
4f32187
to
6b51d07
Compare
// Transforms the script into an executable format using the function defined above. | ||
const transformedScript = transformScriptForRuntime(script) | ||
|
||
console.log('--- [ScriptRunner] Original Script ---') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for which reason do you need to transform the script? isn't the transpiling already done in the script runner side?
Also please try to run the script storage.test.ts
from the basic contract template (compile the contract before). It fails with this error:
{"message":"Failed to fetch dynamically imported module: https://cdn.jsdelivr.net/npm/ethers-lib/+esm","name":"TypeError","stack":"TypeError: Failed to fetch dynamically imported module: https://cdn.jsdelivr.net/npm/ethers-lib/+esm"}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't transform relative imports @hsy822
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yann300 and @bunsenstraat. Thank you for the feedback! I’ve made updates based on your comments and would like to share the changes with you.
Intelligent Transformation for Handling Built-in and External Libraries
I've implemented a system that analyzes which libraries are imported in a script and transforms the code in two different ways depending on the context.
When Only Built-in Libraries Are Used
If the script only imports built-in libraries such as ethers or noir, the code is passed to the Script Runner with minimal modification.
The built-in bundler of Script Runner handles these imports quickly and reliably.
When External Libraries Are Mixed In
If even one external library (e.g., axios) is included, the entire script is wrapped in an async environment.
- External libraries (axios): dynamically imported from CDN using a reliable
import(...)
statement. - Built-in libraries (ethers): converted to
require(...)
to ensure stability in async environments.
This allows scripts to safely import and use new external libraries without breaking existing functionality.
Enhanced Package.json Interpretation for Type Resolution
The type loader (type-fetcher) for autocomplete has been upgraded to better understand various NPM package structures.
Previous Issue
Previously, the loader failed to locate type definitions for complex libraries like noir, which use the exports
field in package.json
or type file extensions like .d.cts
.
Improved Logic
The new loader now works like a smart detective, checking multiple clues in order:
- Primary: Looks for the official
types
path in theexports
field (most accurate). - Secondary: Falls back to the top-level
types
field if not found. - Tertiary: If neither exists, it guesses the file path as before.
Thanks to this improvement, type definitions for modern, complex libraries such as noir are now correctly resolved, making editor autocomplete much more stable and comprehensive.
You can verify that this works by selecting noir in your script configuration and running the following code:
const { expect } = require('chai')
import { compile, createFileManager } from '@noir-lang/noir_wasm'
import { Noir } from '@noir-lang/noir_js'
import { UltraPlonkBackend } from '@aztec/bb.js'
const mainNrContent = `
fn main(age: u8) {
assert(age >= 18);
}
`
const nargoTomlContent = `
[package]
name = "age_verification"
version = "0.1.0"
type="bin"
authors = ["Your Name <[email protected]>"]
edition = "2018"
[dependencies]
`
async function getCircuit() {
const fm = createFileManager('/')
const tomlBytes = new TextEncoder().encode(nargoTomlContent)
const mainBytes = new TextEncoder().encode(mainNrContent)
await fm.writeFile('./src/main.nr', new Blob([mainBytes]).stream())
await fm.writeFile('Nargo.toml', new Blob([tomlBytes]).stream())
const result = await compile(fm)
if (!('program' in result)) {
throw new Error('Compilation failed')
}
return result.program
}
describe('Noir Program Test', () => {
it('should compile, execute, prove, and verify', async () => {
const noir_program = await getCircuit()
const inputs = { age: 20 }
// JS Proving
const program = new Noir(noir_program)
const { witness } = await program.execute(inputs)
const backend = new UltraPlonkBackend(noir_program.bytecode)
const proof = await backend.generateProof(witness)
// JS verification
const verified = await backend.verifyProof(proof)
expect(verified, 'Proof fails verification in JS').to.be.true
})
})
There are still some remaining issues and additional test cases to cover, but this shares the core implementation logic for feedback and further discussion.
really cool but aside from relative imports you will override deps we set in our script runner builds with (async () => { so if we have ethers6 or 5 built this will override that versioning... but we DO have a dep json available https://remix-project-org.github.io/script-runner-generator/projects.json and we do some webpack stuff in the builds to make things work like
so I don't think we should transform everything but maybe yeah https://cdn.jsdelivr.net/npm/@aztec/[email protected]/+esm the point is let's test these things. we have tests for our implementations https://github.com/remix-project-org/script-runner-generator/blob/main/test/src/tests/noir.test.ts we should check |
fb9642d
to
7a659ff
Compare
0093f62
to
2596dee
Compare
Description
This PR introduces an initial implementation of a dynamic type acquisition system aimed at significantly improving the autocompletion experience for TypeScript and JavaScript files.
Previously, the editor relied on static, bundled type definitions (
web-types.ts
), which were often outdated and limited support to a few pre-defined libraries. This change seeks to address these limitations.Now, when a user imports an NPM package (e.g.,
import { createPublicClient } from 'viem'
), the system automatically fetches the corresponding type definitions (.d.ts
) and their dependencies from thejsdelivr
CDN. These types are then injected into the editor, providing a more up-to-date and useful autocompletion experience for a wider range of libraries.Implementation Details
editor.js
(Editor
Plugin):_onChange
method now detects newimport
statements to trigger the type loading process.type-fetcher.ts
(Type Acquisition Service):.d.ts
files for a given package and its dependencies.package.json
(exports
,types
fields) to find all entry points and handles packages that rely on the@types
repository.Current Status & Request for Feedback
The core functionality is now in place and appears to be working correctly with several key libraries. However, this is an initial version, and further testing, refinements, and bug fixes will be necessary.
We are requesting feedback on the overall architecture and implementation. Your insights will be crucial as we move forward with the next steps.
Next Steps
Test Cases
The system has been confirmed to work with the following scripts. They can be used to verify both autocompletion and
Run Script
execution.Viem & Viem Subpaths
Ethers v6
Lodash-es (from
@types
)Axios
Web3.js
Related Issues
Fixes #6410