Skip to content

Commit

Permalink
Merge pull request #6 from sanity-io/quickfix-test-module
Browse files Browse the repository at this point in the history
fix: filter out test modules and comments
  • Loading branch information
snorrees authored Nov 4, 2022
2 parents b58ead6 + c3050d0 commit c41c2d3
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 28 deletions.
4 changes: 4 additions & 0 deletions playground/ts/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
/** @public */
export const VERSION = '1.0.0'
export * from './module1'

//if this line is uncommented, a test should fail
//export * from './not-imported'
39 changes: 39 additions & 0 deletions playground/ts/src/module1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export * from './module2'

/**
* @internal
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export interface _Dummy {
field: string
}

declare module './module2' {
export interface IncludedModuleDummy {
addedField: string
}
}

// Note: dont remove these blocks, they test that we dont include them in the final bundle

/**
* declare module './module2' {
* interface TSDocsDummy {
* field: string
* }
* }
*/

/*
declare module './module2' {
interface BlockCommentDummy {
field: string
}
}
*/

// declare module './module2' {
// interface CommentDummy {
// field: string
// }
// }
6 changes: 6 additions & 0 deletions playground/ts/src/module2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* @public
*/
export interface IncludedModuleDummy {
field: string
}
10 changes: 10 additions & 0 deletions playground/ts/src/not-imported.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars
//@ts-expect-error unused
import {IncludedModuleDummy} from './module2'

//this should not appear in our final bundle
declare module './module2' {
interface Excluded {
field: string
}
}
64 changes: 38 additions & 26 deletions src/node/_tasks/dts/_declareModuleFix.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,81 @@
import fs from 'fs/promises'
import path from 'path'
import {ExtractorResult} from '@microsoft/api-extractor'
import {Program} from 'typescript'

/**
* '@microsoft/api-extractor' omits declare module blocks
* This is a workaround that finds all module blocks in ts files and appends them to the result
*/
export async function _appendModuleBlocks({
tsOutDir,
extractResult,
extractTypesOutFile,
}: {
tsOutDir: string
extractResult: ExtractorResult
extractTypesOutFile: string
}): Promise<void> {
const moduleBlocks = await _extractModuleBlocksFromTypes(tsOutDir)
const moduleBlocks = await _extractModuleBlocksFromTypes({tsOutDir, extractResult})

if (moduleBlocks.length) {
await fs.appendFile(extractTypesOutFile, '\n' + moduleBlocks.join('\n\n'))
}
}

async function _extractModuleBlocksFromTypes(dirname: string): Promise<string[]> {
async function _extractModuleBlocksFromTypes({
tsOutDir,
extractResult,
}: {
tsOutDir: string
extractResult: ExtractorResult
}): Promise<string[]> {
const moduleBlocks: string[] = []

const files = await _getFileList(dirname)

for (const fileName of files) {
const content = await fs.readFile(path.resolve(dirname, fileName), {
encoding: 'utf-8',
})
const program = extractResult.compilerState.program as Program

if (content.includes('declare module')) {
moduleBlocks.push(..._extractModuleBlocks(content))
}
}
// all program files, including node_modules
const allProgramFiles = [...program.getSourceFiles()]

return moduleBlocks
}
// just our compiled files used in the program
const sourceFiles = allProgramFiles.filter((sourceFile) => sourceFile.fileName.includes(tsOutDir))

async function _getFileList(dirName: string): Promise<string[]> {
let files: string[] = []
const filesInCurrentDir = await fs.readdir(dirName, {withFileTypes: true})

for (const fileInDir of filesInCurrentDir) {
if (fileInDir.isDirectory()) {
files = [...files, ...(await _getFileList(path.resolve(dirName, fileInDir.name)))]
} else {
files.push(path.resolve(dirName, fileInDir.name))
for (const sourceFile of sourceFiles) {
if (sourceFile.text.includes('declare module')) {
moduleBlocks.push(..._extractModuleBlocks(sourceFile.text))
}
}

return files
return moduleBlocks
}

export function _extractModuleBlocks(fileContent: string): string[] {
const moduleBlocks: string[] = []

let moduleIndentLevel = 0
let insideComment = false
let moduleLines: string[] = []

const lines = fileContent.split('\n')

for (const line of lines) {
// Note: Extractor already removes comment blocks, so fileContent is typically already comment free
// This is just defensive code, just in case
if (insideComment && line.includes('*/')) {
insideComment = false
} else if (!insideComment && line.includes('/*') && line.includes('*/')) {
continue // it's a one-line comment
} else if (!insideComment && line.includes('/*')) {
insideComment = true
}

if (insideComment) {
continue
}

if (!moduleLines.length) {
const isModuleDeclaration = line.match(/^\s*declare module.+$/)?.length
const moduleIndex = line.indexOf('declare module')
const isModuleStart = moduleIndex > -1
const isModuleStart = isModuleDeclaration && moduleIndex > -1

if (isModuleStart) {
moduleIndentLevel = moduleIndex
Expand Down
5 changes: 3 additions & 2 deletions src/node/_tasks/dts/_doExtract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ export async function _doExtract(
)

const targetPath = path.resolve(cwd, entry.targetPath)

const filePath = path.relative(outDir, targetPath)
const result = await _extractTypes({
customTags: config?.extract?.customTags,
cwd,
exportPath,
files,
filePath: path.relative(outDir, targetPath),
filePath: filePath,
projectPath: cwd,
rules: config?.extract?.rules,
sourceTypesPath: sourceTypesPath,
Expand All @@ -64,6 +64,7 @@ export async function _doExtract(

await _appendModuleBlocks({
tsOutDir: tmpPath,
extractResult: result.extractorResult,
extractTypesOutFile: path.resolve(outDir, targetPath),
})

Expand Down
27 changes: 27 additions & 0 deletions test/__snapshots__/cli.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,30 @@ declare interface Plugin_2 {
export {}
"
`;

exports[`should build ts package 1`] = `
"/**
* @internal
*/
export declare interface _Dummy {
field: string
}
/**
* @public
*/
export declare interface IncludedModuleDummy {
field: string
}
/** @public */
export declare const VERSION = '1.0.0'
export {}
declare module './module2' {
interface IncludedModuleDummy {
addedField: string;
}
}"
`;
22 changes: 22 additions & 0 deletions test/_extractModuleBlocks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,31 @@ test('extract module block', () => {
x: string
}
}
const a = 0; /*declare module 'sanity' {}*/ const b = 0;
/*declare module 'sanity' {}*/
/* declare module 'sanity' {} */
/**
* declare module 'sanity' {
* export interface StringOptions {
* myCustomOption?: boolean
* }
* }
* /
/*
declare module 'BB' {
export interface BB {
a: string
}
}
* /
`
)

expect(blocks.length).toEqual(2)

expect(blocks[0]).toEqual(outdent`
declare module X {
interface A {
Expand Down
14 changes: 14 additions & 0 deletions test/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,20 @@ test('should build `multi-export` package', async () => {
await project.remove()
})

test('should build ts package', async () => {
const project = await _spawnProject('ts')

await project.install()

const {stdout} = await project.run('build')

expect(stdout).toContain('./src/index.ts -> ./dist/src/index.d.ts')

expect(await project.readFile('dist/src/index.d.ts')).toMatchSnapshot()

await project.remove()
})

describe.skip('runtime: webpack v3', () => {
test('import `dist/*.browser.js` from package', async () => {
const exportsDummy = await _spawnProject('exports-dummy')
Expand Down

0 comments on commit c41c2d3

Please sign in to comment.