Skip to content

Commit

Permalink
chore(docs): build up a list of mutations for docs information, keep …
Browse files Browse the repository at this point in the history
…version info
  • Loading branch information
bjoerge authored and binoy14 committed Sep 5, 2023
1 parent 0dd2464 commit 9a44b83
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 42 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
"@babel/preset-env": "^7.19.1",
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.18.6",
"@bjoerge/mutiny": "^0.0.1",
"@optimize-lodash/rollup-plugin": "^4.0.1",
"@playwright/test": "^1.37.0",
"@sanity/client": "^6.4.9",
Expand Down Expand Up @@ -132,6 +133,7 @@
"prettier-plugin-packagejson": "^2.4.5",
"pretty-quick": "^3.1.3",
"rimraf": "^3.0.2",
"rxjs": "^7.8.1",
"semver": "^7.3.5",
"turbo": "^1.10.12",
"typescript": "^5.1.6",
Expand Down
232 changes: 191 additions & 41 deletions scripts/docReport.ts
Original file line number Diff line number Diff line change
@@ -1,73 +1,223 @@
import path from 'path'
import fs from 'fs'
import {cwd} from 'process'
import ts from 'typescript'
import ts, {JSDoc, JSDocComment, SyntaxKind} from 'typescript'
import {createClient} from '@sanity/client'
import {
at,
createIfNotExists,
type Mutation,
patch,
SanityEncoder,
set,
setIfMissing,
upsert,
} from '@bjoerge/mutiny'
import {deburr} from 'lodash'
import {filter, map, mergeMap, of, tap} from 'rxjs'
import readPackages from './utils/readPackages'
import {PackageManifest} from './types'
import {readEnv} from 'sanity-perf-tests/config/envVars'

const ALLOWED_TAGS = ['public', 'alpha', 'beta', 'internal', 'experimental', 'deprecated']

interface Package {
path: string
dirname: string
manifest: PackageManifest
}
function getTags(node: ts.Node) {
const tags = ts.getJSDocTags(node).map((tag) => tag.tagName.getText())
return tags.filter((tag) => ALLOWED_TAGS.includes(tag))
}

function getDocReport(exportPath: string) {
export function sanityIdify(input: string) {
return deburr(input)
.replace(/[^a-zA-Z0-9_-]+/g, '_')
.replace(/^-/, '')
}

type SyntaxType = 'function' | 'class' | 'interface' | 'variable' | 'typeAlias' | 'enum' | 'module'

function getComment(comment: string | ts.NodeArray<JSDocComment>) {
// eslint-disable-next-line no-nested-ternary
return typeof comment === 'string' ? [comment] : comment.flatMap((c) => c.text)
}

function getCommentFromJSDoc(t: ts.JSDoc) {
return t.comment ? getComment(t.comment) : []
}

function getName(node: ts.Node) {
if (node.kind === ts.SyntaxKind.VariableStatement) {
return (node as ts.VariableStatement).declarationList.declarations[0].name.getText()
}
return (
node as ts.FunctionDeclaration | ts.ClassDeclaration | ts.InterfaceDeclaration
).name?.getText()
}

function getNodeType(node: ts.Node): SyntaxType {
if (node.kind === ts.SyntaxKind.VariableStatement) {
return 'variable'
}
if (node.kind === ts.SyntaxKind.InterfaceDeclaration) {
return 'interface'
}
if (node.kind === ts.SyntaxKind.FunctionDeclaration) {
return 'function'
}
if (node.kind === ts.SyntaxKind.ClassDeclaration) {
return 'class'
}
if (node.kind === ts.SyntaxKind.TypeAliasDeclaration) {
return 'typeAlias'
}
if (node.kind === ts.SyntaxKind.EnumDeclaration) {
return 'enum'
}
if (node.kind === ts.SyntaxKind.ModuleDeclaration) {
return 'module'
}
throw new Error(`Unsupported syntax kind for node: ${ts.SyntaxKind[node.kind]}`)
}

type ExportedSymbol = {
name: string
type: SyntaxType
tags: string[]
comment?: string | undefined
}

type ResolvedExport = {
exportName: string
normalized: string
dtsExport: string
dtsFilePath: string
}
function getExportedSymbols(exp: ResolvedExport): ExportedSymbol[] {
const exportedSymbols: ExportedSymbol[] = []
// Read the .d.ts file
const sourceFile = ts.createSourceFile(
exportPath,
fs.readFileSync(path.resolve(cwd(), `packages/sanity/lib/exports/${exportPath}`)).toString(),
exp.dtsExport!,
fs.readFileSync(exp.dtsFilePath!).toString('utf-8'),
// from tsconfig.settings.json
ts.ScriptTarget.ES2017,
true
true,
)

const exportNames: {name?: string; tags: string[]}[] = []

sourceFile.forEachChild((node) => {
// Get all the export items that are named or default export
const exportedItem = ts
.getModifiers(node as ts.HasModifiers)
?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword)

if (exportedItem) {
let name

if (node.kind === ts.SyntaxKind.VariableStatement) {
name = (node as ts.VariableStatement).declarationList.declarations[0].name.getText()
} else {
name = (
node as ts.FunctionDeclaration | ts.ClassDeclaration | ts.InterfaceDeclaration
).name?.getText()
}
const comment = ts
.getJSDocCommentsAndTags(node)
.filter((t): t is JSDoc => t.kind === SyntaxKind.JSDoc)
.flatMap((t) => getCommentFromJSDoc(t))

const name = getName(node)
if (!name) {
return
}
const tags = getTags(node)
const type = getNodeType(node)

exportNames.push({name, tags})
exportedSymbols.push({
name,
type,
comment: comment.length > 0 ? comment.join('\n') : undefined,
tags,
})
}
})

return exportNames
return exportedSymbols
}

// todo: make it work for different packages
fs.readdir(path.resolve(cwd(), 'packages/sanity/lib/exports'), (err, files) => {
if (err) {
console.error(err)
return
}

const result = files
.map((file) => {
if (file.endsWith('.d.ts')) {
return {
packageName: `sanity${file === 'index.d.ts' ? '' : `/${file.replace('.d.ts', '')}`}`,
properties: getDocReport(file),
function getResolvedExports(pkg: Package): ResolvedExport[] {
const manifest = pkg.manifest
return Object.entries(manifest.exports || {}).flatMap(([exportName, exportDefinition]) => {
return exportDefinition.types
? {
exportName,
normalized: path.join(manifest.name, exportName),
dtsExport: exportDefinition.types,
dtsFilePath: exportDefinition.types && path.join(pkg.dirname, exportDefinition.types),
}
}
: []
})
}

return undefined
})
.filter(Boolean)
function getPackageMutations(pkg: Package): Mutation[] {
const exports = getResolvedExports(pkg)
return exports.flatMap((exp) => {
const exportsDocId = `package-exports-${sanityIdify(exp.normalized)}`
const symbols = getExportedSymbols(exp)
return [
createIfNotExists({
_id: exportsDocId,
_type: 'packageExports',
}),
patch(exportsDocId, [
at('name', set(exp.exportName)),
at('normalized', set(exp.normalized)),
at('package', set(pkg.manifest.name)),
]),
...symbols.flatMap((symbol) => {
const symbolDocumentId = `symbol-${sanityIdify(symbol.name)}`
return [
createIfNotExists({
_id: symbolDocumentId,
_type: 'exportSymbol',
}),
patch(symbolDocumentId, [
at('exportedBy', setIfMissing({_type: 'ref', _ref: exportsDocId})),
]),
patch(symbolDocumentId, [
at('name', set(symbol.name)),
at('versions', setIfMissing([])),
at(
'versions',
upsert(
[
{
_key: pkg.manifest.version,
version: pkg.manifest.version,
type: symbol.type,
comment: symbol.comment,
tags: symbol.tags,
updatedAt: new Date().toISOString(),
},
],
'before',
0,
),
),
]),
]
}),
]
})
}

// TODO: Store this in studio
console.log(result)
const studioMetricsClient = createClient({
projectId: 'c1zuxvqn',
dataset: 'production',
token: readEnv('PERF_TEST_METRICS_TOKEN'),
apiVersion: '2023-02-03',
useCdn: false,
})

of(readPackages())
.pipe(
tap((packages) => console.log(`Updating docs for ${packages.length} packages`)),
mergeMap((packages) => packages),
map((pkg) => {
return {pkg, mutations: getPackageMutations(pkg)}
}),
filter(({mutations}) => mutations.length > 0),
mergeMap(({pkg, mutations}) => {
console.log(`Submitting ${mutations.length} mutations for ${pkg.manifest.name}`)
return studioMetricsClient.observable.transaction(SanityEncoder.encode(mutations)).commit()
}, 2),
)
.subscribe()
2 changes: 1 addition & 1 deletion scripts/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export interface PackageManifest {
name: string
private?: boolean
version: string
exports?: Record<string, string | Record<string, string>>
exports?: Record<string, Record<string, string>>
dependencies?: Record<string, string>
devDependencies?: Record<string, string>
engines?: Record<string, string>
Expand Down
18 changes: 18 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,14 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==

"@bjoerge/mutiny@^0.0.1":
version "0.0.1"
resolved "https://registry.yarnpkg.com/@bjoerge/mutiny/-/mutiny-0.0.1.tgz#02e050da524bf730a04f1287ed812d6e9ac2a4ec"
integrity sha512-xL8qsQovS1McDa+pDIJLZSo+sAyRiC5oe/k+T569oK97ka8Weu6XrzR5ypCtMN20TIduw9VV00nc3hv3E9gQmg==
dependencies:
diff-match-patch "^1.0.5"
hotscript "^1.0.13"

"@chevrotain/cst-dts-gen@10.5.0":
version "10.5.0"
resolved "https://registry.yarnpkg.com/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.5.0.tgz#922ebd8cc59d97241bb01b1b17561a5c1ae0124e"
Expand Down Expand Up @@ -8239,6 +8247,11 @@ didyoumean@^1.2.2:
resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==

diff-match-patch@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37"
integrity sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==

diff-sequences@^27.5.1:
version "27.5.1"
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327"
Expand Down Expand Up @@ -10643,6 +10656,11 @@ hosted-git-info@^4.0.0, hosted-git-info@^4.0.1:
dependencies:
lru-cache "^6.0.0"

hotscript@^1.0.13:
version "1.0.13"
resolved "https://registry.yarnpkg.com/hotscript/-/hotscript-1.0.13.tgz#6eb5de757e9b33444ffc22555e98dbc17fa31fb4"
integrity sha512-C++tTF1GqkGYecL+2S1wJTfoH6APGAsbb7PAWQ3iVIwgG/EFseAfEVOKFgAFq4yK3+6j1EjUD4UQ9dRJHX/sSQ==

hpack.js@^2.1.6:
version "2.1.6"
resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2"
Expand Down

0 comments on commit 9a44b83

Please sign in to comment.