Skip to content

Commit

Permalink
feat: support named import from json (#20)
Browse files Browse the repository at this point in the history
- Close #18
  • Loading branch information
Brooooooklyn authored Jul 18, 2024
1 parent d61f04f commit 622f1fa
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 126 deletions.
7 changes: 2 additions & 5 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,9 @@ jobs:
uses: actions/cache@v4
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
~/.cargo
~/.napi-rs
.cargo-cache
target/
./target
key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.host }}
- uses: goto-bus-stop/setup-zig@v2
if: ${{ contains(matrix.settings.target, 'musl') }}
Expand Down
89 changes: 1 addition & 88 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ version = "0.0.0"
crate-type = ["cdylib"]

[dependencies]
napi = { version = "3.0.0-alpha.7", default-features = false, features = ["async", "serde-json"] }
napi = { version = "3.0.0-alpha.7", default-features = false, features = ["serde-json", "napi3"] }
napi-derive = { version = "3.0.0-alpha.6", default-features = false, features = ["type-def"] }
oxc = { version = "0.20", features = ["codegen", "transformer"] }
oxc_resolver = "1"
phf = "0.11"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1"
tracing = "0.1"
tracing-subscriber = { version = "0.3", default-features = false, features = ["std", "fmt"] } # Omit the `regex` feature

Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
],
"*.@(js|ts|tsx)": [
"oxlint --fix"
],
"*.toml": [
"taplo fmt"
]
},
"prettier": {
Expand Down
11 changes: 11 additions & 0 deletions packages/integrate-module/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import assert from 'node:assert'
import test from 'node:test'

import { RepositoryState } from '@napi-rs/simple-git'
import { transform } from '@oxc-node/core'
import { bar as subBar } from '@subdirectory/bar.mjs'
import { supportedExtensions } from 'file-type'
import { renderToString } from 'react-dom/server'
Expand All @@ -17,6 +18,7 @@ import { baz } from './subdirectory/index.mjs'
import { Component } from './component.js'
import './js-module.mjs'
import pkgJson from '../package.json'
import { version } from '../package.json'

const { foo: fooWithQuery } = await import(`./foo.mjs?q=${Date.now()}`)

Expand Down Expand Up @@ -65,6 +67,10 @@ await test('resolve package.json', () => {
assert.equal(pkgJson.name, 'integrate-module')
})

await test('named import from json', () => {
assert.equal(version, '0.0.0')
})

await test('resolve ipaddr.js', () => {
assert.ok(ipaddr.isValid('::1'))
})
Expand All @@ -83,3 +89,8 @@ await test('resolve canvaskit-wasm', async () => {
const canvas = await canvaskit()
assert.ok(canvas.MakeSurface(100, 100))
})

await test('should resolve native addon', async () => {
const result = await transform('index.ts', 'const a: number = 1')
assert.equal(result.source(), 'const a = 1;\n')
})
84 changes: 52 additions & 32 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ pub struct ResolveFnOutput {
#[napi(ts_return_type = "ResolveFnOutput | Promise<ResolveFnOutput>")]
pub fn resolve(
specifier: String,
mut context: ResolveContext,
context: ResolveContext,
next_resolve: Function<
(String, Option<ResolveContext>),
Either<ResolveFnOutput, PromiseRaw<ResolveFnOutput>>,
Expand Down Expand Up @@ -388,37 +388,28 @@ pub fn resolve(
short_circuit: Some(true),
format: {
let ext = p.extension().and_then(|ext| ext.to_str());
// handle TypeScript `resolveJsonModule` option
if ext.map(|e| e == "json").unwrap_or(false) {
context
.import_attributes
.insert("type".to_owned(), "json".to_owned());
Either3::A("json".to_owned())
} else if ext.map(|e| e == "wasm").unwrap_or(false) {
Either3::A("wasm".to_owned())
} else {
let format = ext
.and_then(|ext| {
if ext == "cjs" || ext == "cts" || ext == "node" {
None
} else {
resolution
.package_json()
.and_then(|p| p.r#type.as_ref())
.and_then(|t| t.as_str())
.and_then(|format| {
if format == "module" {
Some("module".to_owned())
} else {
None
}
})
}
})
.unwrap_or_else(|| "commonjs".to_owned());
tracing::debug!(path = ?p, format = ?format);
Either3::A(format)
}

let format = ext
.and_then(|ext| {
if ext == "cjs" || ext == "cts" || ext == "node" {
None
} else {
resolution
.package_json()
.and_then(|p| p.r#type.as_ref())
.and_then(|t| t.as_str())
.and_then(|format| {
if format == "module" {
Some("module".to_owned())
} else {
None
}
})
}
})
.unwrap_or_else(|| "commonjs".to_owned());
tracing::debug!(path = ?p, format = ?format);
Either3::A(format)
},
url,
import_attributes: Some(Either::A(context.import_attributes.clone())),
Expand Down Expand Up @@ -504,6 +495,35 @@ fn transform_output(url: String, output: LoadFnOutput) -> Result<LoadFnOutput> {
.map(|ext| ext == "tsx" || ext == "jsx")
.unwrap_or_default();
let ts = ext.map(|ext| ext.contains("ts")).unwrap_or(false);
if ext.map(|ext| ext == "json").unwrap_or(false) {
let source_str = output.source.as_ref().unwrap().try_as_str()?;
let json: serde_json::Value = serde_json::from_str(source_str)?;
if let serde_json::Value::Object(obj) = json {
let obj_len = obj.len();
let mut source = String::with_capacity(obj_len * 24 + source_str.len() * 2);
source.push_str("const json = ");
source.push_str(source_str);
source.push('\n');
source.push_str("export default json\n");
for key in obj.keys() {
if !oxc::syntax::keyword::is_reserved_keyword(key)
&& oxc::syntax::identifier::is_identifier_name(key)
{
source.push_str(&format!("export const {key} = json.{key};\n"));
}
}
return Ok(LoadFnOutput {
format: "module".to_owned(),
source: Some(Either4::A(source)),
response_url: Some(url),
});
}
return Ok(LoadFnOutput {
format: "commonjs".to_owned(),
source: Some(Either4::A(format!("module.exports = {}", source_str))),
response_url: Some(url),
});
}
let source_type = match output.format.as_str() {
"commonjs" => SourceType::default()
.with_script(true)
Expand Down

0 comments on commit 622f1fa

Please sign in to comment.