From 34be70e5b3e37615b563da02bff5ae89de63b713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90=20Kevin=20Deng?= Date: Fri, 26 May 2023 16:33:40 +0800 Subject: [PATCH] fix(api): resolve json file closes #381 --- .changeset/tasty-cars-check.md | 8 ++++ packages/api/src/ts/namespace.ts | 2 +- packages/api/src/ts/scope.ts | 17 +++++-- packages/api/tests/ts.test.ts | 6 +-- .../tests/__snapshots__/fixtures.test.ts.snap | 46 +++++++++++++++++++ packages/better-define/tests/fixtures.test.ts | 2 + .../tests/fixtures/json-resolve.vue | 7 +++ .../better-define/tests/fixtures/json.json | 3 ++ packages/common/src/constants.ts | 1 + packages/common/src/vue.ts | 8 +++- packages/test-utils/package.json | 1 + packages/test-utils/src/rollup.ts | 2 + pnpm-lock.yaml | 16 +++++++ 13 files changed, 109 insertions(+), 10 deletions(-) create mode 100644 .changeset/tasty-cars-check.md create mode 100644 packages/better-define/tests/fixtures/json-resolve.vue create mode 100644 packages/better-define/tests/fixtures/json.json diff --git a/.changeset/tasty-cars-check.md b/.changeset/tasty-cars-check.md new file mode 100644 index 000000000..0bf36f984 --- /dev/null +++ b/.changeset/tasty-cars-check.md @@ -0,0 +1,8 @@ +--- +'@vue-macros/better-define': patch +'@vue-macros/test-utils': patch +'@vue-macros/common': patch +'@vue-macros/api': patch +--- + +resolve json file diff --git a/packages/api/src/ts/namespace.ts b/packages/api/src/ts/namespace.ts index 4cc0dbbbc..e10618783 100644 --- a/packages/api/src/ts/namespace.ts +++ b/packages/api/src/ts/namespace.ts @@ -35,7 +35,7 @@ export async function resolveTSNamespace(scope: TSScope): Promise { scope.declarations = declarations const { body, file } = resolveTSScope(scope) - for (const stmt of body) { + for (const stmt of body || []) { if ( stmt.type === 'ExportDefaultDeclaration' && isTSDeclaration(stmt.declaration) diff --git a/packages/api/src/ts/scope.ts b/packages/api/src/ts/scope.ts index 1df6c6856..39718f5bc 100644 --- a/packages/api/src/ts/scope.ts +++ b/packages/api/src/ts/scope.ts @@ -1,6 +1,10 @@ import { readFile } from 'node:fs/promises' import { type Statement, type TSModuleBlock } from '@babel/types' -import { babelParse, getFileCodeAndLang } from '@vue-macros/common' +import { + REGEX_SUPPORTED_EXT, + babelParse, + getFileCodeAndLang, +} from '@vue-macros/common' import { type TSNamespace } from './namespace' export interface TSScopeBase { @@ -12,7 +16,8 @@ export interface TSFile extends TSScopeBase { kind: 'file' filePath: string content: string - ast: Statement[] + /** could be undefined if it's a JSON file */ + ast: Statement[] | undefined } export interface TSModule extends TSScopeBase { @@ -28,19 +33,21 @@ export async function getTSFile(filePath: string): Promise { if (tsFileCache[filePath]) return tsFileCache[filePath] const content = await readFile(filePath, 'utf-8') const { code, lang } = getFileCodeAndLang(content, filePath) - const program = babelParse(code, lang) + return (tsFileCache[filePath] = { kind: 'file', filePath, content, - ast: program.body, + ast: REGEX_SUPPORTED_EXT.test(filePath) + ? babelParse(code, lang).body + : undefined, }) } interface ResolvedTSScope { isFile: boolean file: TSFile - body: Statement[] + body: Statement[] | undefined exports?: TSNamespace declarations?: TSNamespace } diff --git a/packages/api/tests/ts.test.ts b/packages/api/tests/ts.test.ts index 30af137c4..fbfe09c4e 100644 --- a/packages/api/tests/ts.test.ts +++ b/packages/api/tests/ts.test.ts @@ -68,7 +68,7 @@ type Base2 = { ) const interfaceProperties = await resolveTSProperties({ scope: file, - type: file.ast[0] as TSInterfaceDeclaration, + type: file.ast![0] as TSInterfaceDeclaration, }) expect(hideAstLocation(interfaceProperties)).toMatchInlineSnapshot(` @@ -156,7 +156,7 @@ type Base2 = { const intersectionProperties = await resolveTSProperties({ scope: file, - type: (file.ast[1] as TSTypeAliasDeclaration) + type: (file.ast![1] as TSTypeAliasDeclaration) .typeAnnotation as TSIntersectionType, }) expect(hideAstLocation(intersectionProperties)).toMatchInlineSnapshot(` @@ -201,7 +201,7 @@ type Base2 = { type AliasString2 = AliasString1 type Foo = AliasString` ) - const node = file.ast[1] as TSTypeAliasDeclaration + const node = file.ast![1] as TSTypeAliasDeclaration const result = (await resolveTSReferencedType({ scope: file, type: node.typeAnnotation, diff --git a/packages/better-define/tests/__snapshots__/fixtures.test.ts.snap b/packages/better-define/tests/__snapshots__/fixtures.test.ts.snap index 43f416704..59f5c2314 100644 --- a/packages/better-define/tests/__snapshots__/fixtures.test.ts.snap +++ b/packages/better-define/tests/__snapshots__/fixtures.test.ts.snap @@ -568,6 +568,52 @@ export { issue362 as default }; " `; +exports[`fixtures > tests/fixtures/json-resolve.vue > isProduction = false 1`] = ` +"import { defineComponent } from 'vue'; +import _export_sfc from '/plugin-vue/export-helper'; + +var _sfc_main = /* @__PURE__ */ defineComponent({ + __name: \\"json-resolve\\", + props: { + \\"foo\\": { type: String, required: true }, + \\"bar\\": { type: Object, required: false } + }, + setup(__props) { + const props = __props; + return () => { + }; + } +}); + +var jsonResolve = /* @__PURE__ */ _export_sfc(_sfc_main, [__FILE__]); + +export { jsonResolve as default }; +" +`; + +exports[`fixtures > tests/fixtures/json-resolve.vue > isProduction = true 1`] = ` +"import { defineComponent } from 'vue'; +import _export_sfc from '/plugin-vue/export-helper'; + +var _sfc_main = /* @__PURE__ */ defineComponent({ + __name: \\"json-resolve\\", + props: { + \\"foo\\": null, + \\"bar\\": null + }, + setup(__props) { + const props = __props; + return () => { + }; + } +}); + +var jsonResolve = /* @__PURE__ */ _export_sfc(_sfc_main, [__FILE__]); + +export { jsonResolve as default }; +" +`; + exports[`fixtures > tests/fixtures/namespace.vue > isProduction = false 1`] = ` "import { defineComponent } from 'vue'; import _export_sfc from '/plugin-vue/export-helper'; diff --git a/packages/better-define/tests/fixtures.test.ts b/packages/better-define/tests/fixtures.test.ts index 8d6cf0c63..2e4d0e52b 100644 --- a/packages/better-define/tests/fixtures.test.ts +++ b/packages/better-define/tests/fixtures.test.ts @@ -2,6 +2,7 @@ import { resolve } from 'node:path' import { describe } from 'vitest' import { RollupEsbuildPlugin, + RollupJson, RollupRemoveVueFilePathPlugin, RollupVue, RollupVueJsx, @@ -19,6 +20,7 @@ describe('fixtures', async () => { RollupVue(), RollupVueJsx(), RollupRemoveVueFilePathPlugin(), + RollupJson(), RollupEsbuildPlugin({ target: 'esnext', }), diff --git a/packages/better-define/tests/fixtures/json-resolve.vue b/packages/better-define/tests/fixtures/json-resolve.vue new file mode 100644 index 000000000..90f99b415 --- /dev/null +++ b/packages/better-define/tests/fixtures/json-resolve.vue @@ -0,0 +1,7 @@ + diff --git a/packages/better-define/tests/fixtures/json.json b/packages/better-define/tests/fixtures/json.json new file mode 100644 index 000000000..c8c4105eb --- /dev/null +++ b/packages/better-define/tests/fixtures/json.json @@ -0,0 +1,3 @@ +{ + "foo": "bar" +} diff --git a/packages/common/src/constants.ts b/packages/common/src/constants.ts index e52d6439a..ba7985b4e 100644 --- a/packages/common/src/constants.ts +++ b/packages/common/src/constants.ts @@ -20,6 +20,7 @@ export const REGEX_VUE_SFC = /\.vue$/ export const REGEX_VUE_SUB = /\.vue\?vue&type=script/ export const REGEX_DTS = /\.d\.[cm]?ts$/ export const REGEX_NODE_MODULES = /node_modules/ +export const REGEX_SUPPORTED_EXT = /\.([cm]?[jt]sx?|vue)$/ export const REGEX_LANG_TS = /^[cm]?tsx?$/ export const REGEX_LANG_JSX = /^[cm]?[jt]sx$/ diff --git a/packages/common/src/vue.ts b/packages/common/src/vue.ts index 97835b01b..b074917bf 100644 --- a/packages/common/src/vue.ts +++ b/packages/common/src/vue.ts @@ -65,7 +65,13 @@ export function getFileCodeAndLang( code: string, id: string ): { code: string; lang: string } { - if (!REGEX_VUE_SFC.test(id)) return { code, lang: getLang(id) } + if (!REGEX_VUE_SFC.test(id)) { + return { + code, + lang: getLang(id), + } + } + const sfc = parseSFC(code, id) const scriptCode = sfc.script?.content ?? '' return { diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 1a41627e2..e93872f04 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -59,6 +59,7 @@ "unplugin-vue": "^4.1.0" }, "devDependencies": { + "@rollup/plugin-json": "^6.0.0", "vite": "^4.3.8", "vue": "^3.3.4" }, diff --git a/packages/test-utils/src/rollup.ts b/packages/test-utils/src/rollup.ts index 0ae54d11d..90d171431 100644 --- a/packages/test-utils/src/rollup.ts +++ b/packages/test-utils/src/rollup.ts @@ -9,6 +9,8 @@ export { default as RollupVue } from 'unplugin-vue/rollup' export { default as RollupVue2 } from '@vitejs/plugin-vue2' export const RollupVueJsx = ViteVueJsx as (options?: VueJsxOptions) => Plugin +export { default as RollupJson } from '@rollup/plugin-json' + export const RollupToStringPlugin = (): Plugin => { return { name: 'to-string', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5de24bbcc..e40a5b64e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -605,6 +605,9 @@ importers: specifier: ^4.1.0 version: 4.1.0(vite@4.3.8)(vue@3.3.4) devDependencies: + '@rollup/plugin-json': + specifier: ^6.0.0 + version: 6.0.0(rollup@3.23.0) vite: specifier: ^4.3.8 version: 4.3.8(@types/node@20.2.3) @@ -2925,6 +2928,19 @@ packages: rollup: 3.23.0 dev: true + /@rollup/plugin-json@6.0.0(rollup@3.23.0): + resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.0.2(rollup@3.23.0) + rollup: 3.23.0 + dev: true + /@rollup/plugin-node-resolve@11.2.1(rollup@2.79.1): resolution: {integrity: sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==} engines: {node: '>= 10.0.0'}