mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 16:51:55 +00:00
remove gulp (task runner) (#57963)
Removed usage of gulp for running commands. Instead, we just use `package.json` scripts (that mostly invoke `ts-node -T ...`). The purpose of removing gulp is to remove a layer of duplication/indirection between the tasks we need to run and where they are defined. The code generation tasks (GraphQL operations, CSS modules types, and schema/ JSON Schema types) no longer run in watch mode in local dev. If you make changes that require regeneration of this code, run `pnpm run generate` from the root. This is for simplicity and speed (they would run on many unrelated changes and slow down local dev).
This commit is contained in:
parent
f60deb13df
commit
90c6683218
10
.eslintrc.js
10
.eslintrc.js
@ -23,7 +23,6 @@ const config = {
|
||||
'**/*.d.ts',
|
||||
'eslint-relative-formatter.js',
|
||||
'jest.config.js',
|
||||
'gulpfile.js',
|
||||
'typedoc.js',
|
||||
'bundlesize.config.js',
|
||||
],
|
||||
@ -320,14 +319,7 @@ See https://handbook.sourcegraph.com/community/faq#is-all-of-sourcegraph-open-so
|
||||
},
|
||||
},
|
||||
{
|
||||
files: [
|
||||
'**/dev/**/*.ts',
|
||||
'**/gulpfile.js',
|
||||
'**/story/**.tsx',
|
||||
'**/story/**.ts',
|
||||
'*.story.tsx',
|
||||
'client/build-config/**',
|
||||
],
|
||||
files: ['**/dev/**/*.ts', '**/story/**.tsx', '**/story/**.ts', '*.story.tsx', 'client/build-config/**'],
|
||||
rules: {
|
||||
'no-console': 'off',
|
||||
'no-sync': 'off',
|
||||
|
||||
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -38,7 +38,6 @@
|
||||
"local": "github.com/sourcegraph/sourcegraph"
|
||||
},
|
||||
"jest.jestCommandLine": "pnpm run test",
|
||||
"gulp.autoDetect": "off",
|
||||
"npm.packageManager": "pnpm",
|
||||
"npm.runSilent": true,
|
||||
"typescript.preferences.quoteStyle": "single",
|
||||
|
||||
9
.vscode/tasks.json
vendored
9
.vscode/tasks.json
vendored
@ -24,15 +24,6 @@
|
||||
"problemMatcher": [],
|
||||
"isBackground": true
|
||||
},
|
||||
{
|
||||
"label": "Watch code generation",
|
||||
"detail": "Watch files and generate types when files are changed",
|
||||
"type": "npm",
|
||||
"script": "watch-generate",
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"isBackground": true
|
||||
},
|
||||
{
|
||||
"label": "stylelint",
|
||||
"command": "pnpm",
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
const { spawn } = require('child_process')
|
||||
|
||||
function build() {
|
||||
return spawn('pnpm', ['run', 'build'], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
env: { ...process.env, NODE_OPTIONS: '--max_old_space_size=8192' },
|
||||
})
|
||||
}
|
||||
|
||||
function watch() {
|
||||
return spawn('pnpm', ['run', 'dev'], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
env: { ...process.env, NODE_OPTIONS: '--max_old_space_size=8192' },
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = { build, watch }
|
||||
@ -10,7 +10,7 @@
|
||||
"rootDir": ".",
|
||||
"outDir": "out",
|
||||
},
|
||||
"include": ["src", "config", "gulpfile.js", "src/**/*.json", "src/types/**/*.d.ts", "./code-intel-extensions.json"],
|
||||
"include": ["src", "config", "src/**/*.json", "src/types/**/*.d.ts", "./code-intel-extensions.json"],
|
||||
"exclude": [
|
||||
"out",
|
||||
"node_modules",
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
const path = require('path')
|
||||
|
||||
require('ts-node').register({
|
||||
transpileOnly: true,
|
||||
// Use config with "module": "commonjs" because not all modules involved in tasks are esnext modules.
|
||||
project: path.resolve(__dirname, './tsconfig.json'),
|
||||
})
|
||||
|
||||
const buildScripts = require('./scripts/build')
|
||||
|
||||
async function esbuild() {
|
||||
await buildScripts.build()
|
||||
}
|
||||
|
||||
module.exports = { esbuild }
|
||||
@ -13,15 +13,14 @@
|
||||
"directory": "client/jetbrains"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "pnpm task:gulp esbuild",
|
||||
"build": "ts-node -T scripts/build.ts",
|
||||
"watch": "WATCH=1 pnpm run build",
|
||||
"lint": "pnpm run lint:js && pnpm run lint:css",
|
||||
"lint:js": "eslint --cache 'webview/**/*.[jt]s?(x)'",
|
||||
"lint:css": "stylelint 'webview/**/*.scss'",
|
||||
"standalone": "ts-node standalone/src/server.ts",
|
||||
"storybook": "STORIES_GLOB='client/jetbrains/webview/src/**/*.story.tsx' pnpm --filter @sourcegraph/storybook run start",
|
||||
"task:gulp": "cross-env NODE_OPTIONS=\"--max_old_space_size=8192\" gulp",
|
||||
"typecheck": "tsc -b",
|
||||
"watch": "WATCH=true pnpm task:gulp esbuild"
|
||||
"typecheck": "tsc -b"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sourcegraph/build-config": "workspace:*",
|
||||
|
||||
@ -67,3 +67,17 @@ export async function build(): Promise<void> {
|
||||
await ctx.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
async function main(args: string[]): Promise<void> {
|
||||
if (args.length !== 0) {
|
||||
throw new Error('Usage: (no options)')
|
||||
}
|
||||
await build()
|
||||
}
|
||||
// eslint-disable-next-line unicorn/prefer-top-level-await
|
||||
main(process.argv.slice(2)).catch(error => {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
load("@aspect_rules_js//js:defs.bzl", "js_binary", "js_library")
|
||||
load("//dev:defs.bzl", "ts_project")
|
||||
load("//dev:defs.bzl", "ts_binary", "ts_project")
|
||||
|
||||
# gazelle:ignore
|
||||
|
||||
# dev/ does not contain a src/
|
||||
# gazelle:js_files **/*.{ts,tsx}
|
||||
|
||||
js_binary(
|
||||
ts_binary(
|
||||
name = "generate_schema",
|
||||
data = [
|
||||
"//:node_modules/json-schema-to-typescript",
|
||||
"//:node_modules/mz",
|
||||
],
|
||||
entry_point = "generateSchema.js",
|
||||
entry_point = "generateSchema.ts",
|
||||
visibility = ["//client/shared:__pkg__"],
|
||||
)
|
||||
|
||||
@ -37,7 +36,7 @@ js_binary(
|
||||
visibility = ["//client:__subpackages__"],
|
||||
)
|
||||
|
||||
js_binary(
|
||||
ts_binary(
|
||||
name = "generate_graphql_operations",
|
||||
data = [
|
||||
":extract_graphql_operation_codegen_plugin",
|
||||
@ -48,7 +47,7 @@ js_binary(
|
||||
"//:node_modules/prettier",
|
||||
"//cmd/frontend/graphqlbackend:graphql_schema",
|
||||
],
|
||||
entry_point = "generateGraphQlOperations.js",
|
||||
entry_point = "generateGraphQlOperations.ts",
|
||||
visibility = ["//client:__subpackages__"],
|
||||
)
|
||||
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
const { spawn } = require('child_process')
|
||||
const path = require('path')
|
||||
|
||||
const REPO_ROOT = path.join(__dirname, '../../..')
|
||||
const CSS_MODULES_GLOB = path.resolve(__dirname, '../../*/src/**/*.module.scss')
|
||||
const JETBRAINS_CSS_MODULES_GLOB = path.resolve(__dirname, '../../jetbrains/webview/**/*.module.scss')
|
||||
const TSM_COMMAND = `pnpm tsm --logLevel error "{${CSS_MODULES_GLOB},${JETBRAINS_CSS_MODULES_GLOB}}" --includePaths node_modules client`
|
||||
const [BIN, ...ARGS] = TSM_COMMAND.split(' ')
|
||||
|
||||
/**
|
||||
* Generates the TypeScript types CSS modules.
|
||||
*/
|
||||
function cssModulesTypings() {
|
||||
return spawn(BIN, ARGS, {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
cwd: REPO_ROOT,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch CSS modules and generates the TypeScript types for them.
|
||||
*/
|
||||
function watchCSSModulesTypings() {
|
||||
return spawn(BIN, [...ARGS, '--watch'], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
cwd: REPO_ROOT,
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
cssModulesTypings,
|
||||
watchCSSModulesTypings,
|
||||
}
|
||||
46
client/shared/dev/generateCssModulesTypes.ts
Normal file
46
client/shared/dev/generateCssModulesTypes.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { spawn } from 'child_process'
|
||||
import path from 'path'
|
||||
|
||||
const REPO_ROOT = path.join(__dirname, '../../..')
|
||||
const CSS_MODULES_GLOB = path.resolve(__dirname, '../../*/src/**/*.module.scss')
|
||||
const JETBRAINS_CSS_MODULES_GLOB = path.resolve(__dirname, '../../jetbrains/webview/**/*.module.scss')
|
||||
const TSM_COMMAND = `pnpm exec tsm --logLevel error "{${CSS_MODULES_GLOB},${JETBRAINS_CSS_MODULES_GLOB}}" --includePaths node_modules client`
|
||||
const [BIN, ...ARGS] = TSM_COMMAND.split(' ')
|
||||
|
||||
/**
|
||||
* Generates the TypeScript types CSS modules.
|
||||
*/
|
||||
export function cssModulesTypings(extraArgs: string[] = []): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const process = spawn(BIN, [...ARGS, ...extraArgs], {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
cwd: REPO_ROOT,
|
||||
})
|
||||
process.on('exit', code => {
|
||||
if (code) {
|
||||
reject(new Error(`exited with code ${code}`))
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
process.on('error', err => reject(err))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch CSS modules and generates the TypeScript types for them.
|
||||
*/
|
||||
export function watchCSSModulesTypings(): Promise<void> {
|
||||
return cssModulesTypings(['--watch'])
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
async function main(args: string[]) {
|
||||
cssModulesTypings(args)
|
||||
}
|
||||
main(process.argv.slice(2)).catch(error => {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
@ -1,188 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
const path = require('path')
|
||||
|
||||
const { generate } = require('@graphql-codegen/cli')
|
||||
|
||||
const ROOT_FOLDER = path.resolve(__dirname, '../../../')
|
||||
|
||||
const WEB_FOLDER = path.resolve(ROOT_FOLDER, './client/web')
|
||||
const SVELTEKIT_FOLDER = path.resolve(ROOT_FOLDER, './client/web-sveltekit')
|
||||
const BROWSER_FOLDER = path.resolve(ROOT_FOLDER, './client/browser')
|
||||
const SHARED_FOLDER = path.resolve(ROOT_FOLDER, './client/shared')
|
||||
const VSCODE_FOLDER = path.resolve(ROOT_FOLDER, './client/vscode')
|
||||
const JETBRAINS_FOLDER = path.resolve(ROOT_FOLDER, './client/jetbrains')
|
||||
const SCHEMA_PATH = path.join(ROOT_FOLDER, './cmd/frontend/graphqlbackend/*.graphql')
|
||||
|
||||
const SHARED_DOCUMENTS_GLOB = [`${SHARED_FOLDER}/src/**/*.{ts,tsx}`]
|
||||
|
||||
const WEB_DOCUMENTS_GLOB = [
|
||||
`${WEB_FOLDER}/src/**/*.{ts,tsx}`,
|
||||
`${WEB_FOLDER}/src/regression/**/*.*`,
|
||||
`!${WEB_FOLDER}/src/end-to-end/**/*.*`, // TODO(bazel): can remove when non-bazel dropped
|
||||
]
|
||||
|
||||
const SVELTEKIT_DOCUMENTS_GLOB = [`${SVELTEKIT_FOLDER}/src/lib/**/*.ts`]
|
||||
|
||||
const BROWSER_DOCUMENTS_GLOB = [
|
||||
`${BROWSER_FOLDER}/src/**/*.{ts,tsx}`,
|
||||
`!${BROWSER_FOLDER}/src/end-to-end/**/*.*`, // TODO(bazel): can remove when non-bazel dropped
|
||||
'!**/*.d.ts',
|
||||
]
|
||||
|
||||
const VSCODE_DOCUMENTS_GLOB = [`${VSCODE_FOLDER}/src/**/*.{ts,tsx}`]
|
||||
|
||||
const JETBRAINS_DOCUMENTS_GLOB = [`${JETBRAINS_FOLDER}/webview/src/**/*.{ts,tsx}`]
|
||||
|
||||
const GLOBS = {
|
||||
BrowserGraphQlOperations: BROWSER_DOCUMENTS_GLOB,
|
||||
JetBrainsGraphQlOperations: JETBRAINS_DOCUMENTS_GLOB,
|
||||
SharedGraphQlOperations: SHARED_DOCUMENTS_GLOB,
|
||||
VSCodeGraphQlOperations: VSCODE_DOCUMENTS_GLOB,
|
||||
WebGraphQlOperations: WEB_DOCUMENTS_GLOB,
|
||||
SvelteKitGraphQlOperations: SVELTEKIT_DOCUMENTS_GLOB,
|
||||
}
|
||||
|
||||
const EXTRA_PLUGINS = {
|
||||
SharedGraphQlOperations: ['typescript-apollo-client-helpers'],
|
||||
}
|
||||
|
||||
// Define ALL_DOCUMENTS_GLOB as the union of the previous glob arrays.
|
||||
const ALL_DOCUMENTS_GLOB = [
|
||||
...new Set([
|
||||
...SHARED_DOCUMENTS_GLOB,
|
||||
...WEB_DOCUMENTS_GLOB,
|
||||
...SVELTEKIT_DOCUMENTS_GLOB,
|
||||
...BROWSER_DOCUMENTS_GLOB,
|
||||
...VSCODE_DOCUMENTS_GLOB,
|
||||
...JETBRAINS_DOCUMENTS_GLOB,
|
||||
]),
|
||||
]
|
||||
|
||||
const SHARED_PLUGINS = [
|
||||
`${SHARED_FOLDER}/dev/extractGraphQlOperationCodegenPlugin.js`,
|
||||
'typescript',
|
||||
'typescript-operations',
|
||||
]
|
||||
|
||||
const PRETTIER = path.join(path.dirname(require.resolve('prettier')), 'bin-prettier.js')
|
||||
|
||||
/**
|
||||
* Generates TypeScript files with types for all GraphQL operations.
|
||||
*/
|
||||
async function generateGraphQlOperations() {
|
||||
try {
|
||||
await generate(
|
||||
createCodegenConfig([
|
||||
{
|
||||
interfaceNameForOperations: 'BrowserGraphQlOperations',
|
||||
outputPath: path.join(BROWSER_FOLDER, './src/graphql-operations.ts'),
|
||||
},
|
||||
{
|
||||
interfaceNameForOperations: 'WebGraphQlOperations',
|
||||
outputPath: path.join(WEB_FOLDER, './src/graphql-operations.ts'),
|
||||
},
|
||||
{
|
||||
interfaceNameForOperations: 'SvelteKitGraphQlOperations',
|
||||
outputPath: path.join(SVELTEKIT_FOLDER, './src/lib/graphql-operations.ts'),
|
||||
},
|
||||
{
|
||||
interfaceNameForOperations: 'SharedGraphQlOperations',
|
||||
outputPath: path.join(SHARED_FOLDER, './src/graphql-operations.ts'),
|
||||
},
|
||||
{
|
||||
interfaceNameForOperations: 'VSCodeGraphQlOperations',
|
||||
outputPath: path.join(VSCODE_FOLDER, './src/graphql-operations.ts'),
|
||||
},
|
||||
{
|
||||
interfaceNameForOperations: 'JetBrainsGraphQlOperations',
|
||||
outputPath: path.join(JETBRAINS_FOLDER, './webview/src/graphql-operations.ts'),
|
||||
},
|
||||
])
|
||||
)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
function createCodegenConfig(operations) {
|
||||
const generates = operations.reduce((generates, operation) => {
|
||||
generates[operation.outputPath] = {
|
||||
documents: GLOBS[operation.interfaceNameForOperations],
|
||||
config: {
|
||||
onlyOperationTypes: true,
|
||||
noExport: false,
|
||||
enumValues:
|
||||
operation.interfaceNameForOperations === 'SharedGraphQlOperations'
|
||||
? undefined
|
||||
: '@sourcegraph/shared/src/graphql-operations',
|
||||
interfaceNameForOperations: operation.interfaceNameForOperations,
|
||||
},
|
||||
plugins: [...SHARED_PLUGINS, ...(EXTRA_PLUGINS[operation.interfaceNameForOperations] || [])],
|
||||
}
|
||||
return generates
|
||||
}, {})
|
||||
|
||||
return {
|
||||
schema: SCHEMA_PATH,
|
||||
hooks: {
|
||||
afterOneFileWrite: `${PRETTIER} --write`,
|
||||
},
|
||||
errorsOnly: true,
|
||||
config: {
|
||||
// https://the-guild.dev/graphql/codegen/plugins/typescript/typescript-operations#config-api-reference
|
||||
arrayInputCoercion: false,
|
||||
preResolveTypes: true,
|
||||
operationResultSuffix: 'Result',
|
||||
omitOperationSuffix: true,
|
||||
namingConvention: {
|
||||
typeNames: 'keep',
|
||||
enumValues: 'keep',
|
||||
transformUnderscore: true,
|
||||
},
|
||||
declarationKind: 'interface',
|
||||
avoidOptionals: {
|
||||
field: true,
|
||||
inputValue: false,
|
||||
object: true,
|
||||
},
|
||||
scalars: {
|
||||
DateTime: 'string',
|
||||
JSON: 'object',
|
||||
JSONValue: 'unknown',
|
||||
GitObjectID: 'string',
|
||||
JSONCString: 'string',
|
||||
PublishedValue: "boolean | 'draft'",
|
||||
BigInt: 'string',
|
||||
},
|
||||
},
|
||||
generates,
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
generateGraphQlOperations,
|
||||
createCodegenConfig,
|
||||
SHARED_DOCUMENTS_GLOB,
|
||||
WEB_DOCUMENTS_GLOB,
|
||||
ALL_DOCUMENTS_GLOB,
|
||||
}
|
||||
|
||||
// Bazel entry point to generate a single graphql operations file; the legacy build
|
||||
// continues to import `generateGraphQlOperations` and generate all operations files.
|
||||
async function main(args) {
|
||||
if (args.length !== 2) {
|
||||
throw new Error('Usage: <schemaName> <outputPath>')
|
||||
}
|
||||
|
||||
const [interfaceNameForOperations, outputPath] = args
|
||||
|
||||
await generate(createCodegenConfig([{ interfaceNameForOperations, outputPath }]))
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
main(process.argv.slice(2)).catch(error => {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
159
client/shared/dev/generateGraphQlOperations.ts
Normal file
159
client/shared/dev/generateGraphQlOperations.ts
Normal file
@ -0,0 +1,159 @@
|
||||
import path from 'path'
|
||||
|
||||
import { CodegenConfig, generate } from '@graphql-codegen/cli'
|
||||
|
||||
const ROOT_FOLDER = path.resolve(__dirname, '../../../')
|
||||
|
||||
const WEB_FOLDER = path.resolve(ROOT_FOLDER, './client/web')
|
||||
const SVELTEKIT_FOLDER = path.resolve(ROOT_FOLDER, './client/web-sveltekit')
|
||||
const BROWSER_FOLDER = path.resolve(ROOT_FOLDER, './client/browser')
|
||||
const SHARED_FOLDER = path.resolve(ROOT_FOLDER, './client/shared')
|
||||
const VSCODE_FOLDER = path.resolve(ROOT_FOLDER, './client/vscode')
|
||||
const JETBRAINS_FOLDER = path.resolve(ROOT_FOLDER, './client/jetbrains')
|
||||
const SCHEMA_PATH = path.join(ROOT_FOLDER, './cmd/frontend/graphqlbackend/*.graphql')
|
||||
|
||||
const SHARED_DOCUMENTS_GLOB = [`${SHARED_FOLDER}/src/**/*.{ts,tsx}`]
|
||||
|
||||
const WEB_DOCUMENTS_GLOB = [
|
||||
`${WEB_FOLDER}/src/**/*.{ts,tsx}`,
|
||||
`${WEB_FOLDER}/src/regression/**/*.*`,
|
||||
`!${WEB_FOLDER}/src/end-to-end/**/*.*`, // TODO(bazel): can remove when non-bazel dropped
|
||||
]
|
||||
|
||||
const SVELTEKIT_DOCUMENTS_GLOB = [`${SVELTEKIT_FOLDER}/src/lib/**/*.ts`]
|
||||
|
||||
const BROWSER_DOCUMENTS_GLOB = [
|
||||
`${BROWSER_FOLDER}/src/**/*.{ts,tsx}`,
|
||||
`!${BROWSER_FOLDER}/src/end-to-end/**/*.*`, // TODO(bazel): can remove when non-bazel dropped
|
||||
'!**/*.d.ts',
|
||||
]
|
||||
|
||||
const VSCODE_DOCUMENTS_GLOB = [`${VSCODE_FOLDER}/src/**/*.{ts,tsx}`]
|
||||
|
||||
const JETBRAINS_DOCUMENTS_GLOB = [`${JETBRAINS_FOLDER}/webview/src/**/*.{ts,tsx}`]
|
||||
|
||||
const GLOBS: Record<string, string[]> = {
|
||||
BrowserGraphQlOperations: BROWSER_DOCUMENTS_GLOB,
|
||||
JetBrainsGraphQlOperations: JETBRAINS_DOCUMENTS_GLOB,
|
||||
SharedGraphQlOperations: SHARED_DOCUMENTS_GLOB,
|
||||
VSCodeGraphQlOperations: VSCODE_DOCUMENTS_GLOB,
|
||||
WebGraphQlOperations: WEB_DOCUMENTS_GLOB,
|
||||
SvelteKitGraphQlOperations: SVELTEKIT_DOCUMENTS_GLOB,
|
||||
}
|
||||
|
||||
const EXTRA_PLUGINS: Record<string, string[]> = {
|
||||
SharedGraphQlOperations: ['typescript-apollo-client-helpers'],
|
||||
}
|
||||
|
||||
const SHARED_PLUGINS = [
|
||||
`${SHARED_FOLDER}/dev/extractGraphQlOperationCodegenPlugin.js`,
|
||||
'typescript',
|
||||
'typescript-operations',
|
||||
]
|
||||
|
||||
const PRETTIER = path.join(path.dirname(require.resolve('prettier')), 'bin-prettier.js')
|
||||
|
||||
interface Input {
|
||||
interfaceNameForOperations: string
|
||||
outputPath: string
|
||||
}
|
||||
|
||||
export const ALL_INPUTS: Input[] = [
|
||||
{
|
||||
interfaceNameForOperations: 'BrowserGraphQlOperations',
|
||||
outputPath: path.join(BROWSER_FOLDER, './src/graphql-operations.ts'),
|
||||
},
|
||||
{
|
||||
interfaceNameForOperations: 'WebGraphQlOperations',
|
||||
outputPath: path.join(WEB_FOLDER, './src/graphql-operations.ts'),
|
||||
},
|
||||
{
|
||||
interfaceNameForOperations: 'SvelteKitGraphQlOperations',
|
||||
outputPath: path.join(SVELTEKIT_FOLDER, './src/lib/graphql-operations.ts'),
|
||||
},
|
||||
{
|
||||
interfaceNameForOperations: 'SharedGraphQlOperations',
|
||||
outputPath: path.join(SHARED_FOLDER, './src/graphql-operations.ts'),
|
||||
},
|
||||
{
|
||||
interfaceNameForOperations: 'VSCodeGraphQlOperations',
|
||||
outputPath: path.join(VSCODE_FOLDER, './src/graphql-operations.ts'),
|
||||
},
|
||||
{
|
||||
interfaceNameForOperations: 'JetBrainsGraphQlOperations',
|
||||
outputPath: path.join(JETBRAINS_FOLDER, './webview/src/graphql-operations.ts'),
|
||||
},
|
||||
]
|
||||
|
||||
export function createCodegenConfig(operations: Input[]): CodegenConfig {
|
||||
const generates = operations.reduce<CodegenConfig['generates']>((generates, operation) => {
|
||||
generates[operation.outputPath] = {
|
||||
documents: GLOBS[operation.interfaceNameForOperations],
|
||||
config: {
|
||||
onlyOperationTypes: true,
|
||||
noExport: false,
|
||||
enumValues:
|
||||
operation.interfaceNameForOperations === 'SharedGraphQlOperations'
|
||||
? undefined
|
||||
: '@sourcegraph/shared/src/graphql-operations',
|
||||
interfaceNameForOperations: operation.interfaceNameForOperations,
|
||||
},
|
||||
plugins: [...SHARED_PLUGINS, ...(EXTRA_PLUGINS[operation.interfaceNameForOperations] || [])],
|
||||
}
|
||||
return generates
|
||||
}, {})
|
||||
|
||||
return {
|
||||
schema: SCHEMA_PATH,
|
||||
hooks: {
|
||||
afterOneFileWrite: `${PRETTIER} --write`,
|
||||
},
|
||||
errorsOnly: true,
|
||||
config: {
|
||||
// https://the-guild.dev/graphql/codegen/plugins/typescript/typescript-operations#config-api-reference
|
||||
arrayInputCoercion: false,
|
||||
preResolveTypes: true,
|
||||
operationResultSuffix: 'Result',
|
||||
omitOperationSuffix: true,
|
||||
namingConvention: {
|
||||
typeNames: 'keep',
|
||||
enumValues: 'keep',
|
||||
transformUnderscore: true,
|
||||
},
|
||||
declarationKind: 'interface',
|
||||
avoidOptionals: {
|
||||
field: true,
|
||||
inputValue: false,
|
||||
object: true,
|
||||
},
|
||||
scalars: {
|
||||
DateTime: 'string',
|
||||
JSON: 'object',
|
||||
JSONValue: 'unknown',
|
||||
GitObjectID: 'string',
|
||||
JSONCString: 'string',
|
||||
PublishedValue: "boolean | 'draft'",
|
||||
BigInt: 'string',
|
||||
},
|
||||
},
|
||||
generates,
|
||||
}
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
// Entry point to generate all GraphQL operations files, or a single one.
|
||||
async function main(args: string[]) {
|
||||
if (args.length !== 0 && args.length !== 2) {
|
||||
throw new Error('Usage: [<schemaName> <outputPath>]')
|
||||
}
|
||||
await generate(
|
||||
createCodegenConfig(
|
||||
args.length === 0 ? ALL_INPUTS : [{ interfaceNameForOperations: args[0], outputPath: args[1] }]
|
||||
)
|
||||
)
|
||||
}
|
||||
main(process.argv.slice(2)).catch(error => {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
/**
|
||||
* Generates the TypeScript types for the JSON schemas.
|
||||
*
|
||||
* Usage: <schemaName>
|
||||
*
|
||||
* schemaName - extensionless name of the schema.json file to generate types for
|
||||
*/
|
||||
|
||||
const path = require('path')
|
||||
|
||||
const { compile: compileJSONSchema } = require('json-schema-to-typescript')
|
||||
const { mkdir, readFile, writeFile } = require('mz/fs')
|
||||
|
||||
const schemaDirectory = path.join(__dirname, '..', '..', '..', 'schema')
|
||||
const outputDirectory = path.join(__dirname, '..', 'src', 'schema')
|
||||
|
||||
/**
|
||||
* Allow json-schema-ref-parser to resolve the v7 draft of JSON Schema
|
||||
* using a local copy of the spec, enabling developers to run/develop Sourcegraph offline
|
||||
*/
|
||||
const draftV7resolver = {
|
||||
order: 1,
|
||||
read: () => readFile(path.join(schemaDirectory, 'json-schema-draft-07.schema.json')),
|
||||
canRead: file => file.url === 'http://json-schema.org/draft-07/schema',
|
||||
}
|
||||
|
||||
async function generateSchema(schemaName) {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
let schema = await readFile(path.join(schemaDirectory, `${schemaName}.schema.json`), 'utf8')
|
||||
|
||||
// HACK: Rewrite absolute $refs to be relative. They need to be absolute for Monaco to resolve them
|
||||
// when the schema is in a oneOf (to be merged with extension schemas).
|
||||
schema = schema.replaceAll('https://sourcegraph.com/v1/settings.schema.json#/definitions/', '#/definitions/')
|
||||
|
||||
const types = await compileJSONSchema(JSON.parse(schema), 'settings.schema', {
|
||||
cwd: schemaDirectory,
|
||||
$refOptions: {
|
||||
resolve: /** @type {import('json-schema-ref-parser').Options['resolve']} */ ({
|
||||
draftV7resolver,
|
||||
// there should be no reason to make network calls during this process,
|
||||
// and if there are we've broken env for offline devs/increased dev startup time
|
||||
http: false,
|
||||
}),
|
||||
},
|
||||
})
|
||||
|
||||
await mkdir(outputDirectory, { recursive: true })
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
await writeFile(path.join(outputDirectory, `${schemaName}.schema.d.ts`), types)
|
||||
}
|
||||
|
||||
// Entry point for Bazel binary
|
||||
async function main(args) {
|
||||
if (args.length !== 1) {
|
||||
throw new Error('Usage: <schemaName>')
|
||||
}
|
||||
|
||||
const schemaName = args[0]
|
||||
await generateSchema(schemaName)
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
main(process.argv.slice(2)).catch(error => {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
generateSchema,
|
||||
}
|
||||
67
client/shared/dev/generateSchema.ts
Normal file
67
client/shared/dev/generateSchema.ts
Normal file
@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Generates the TypeScript types for the JSON schemas.
|
||||
*
|
||||
* Usage: <schemaName1> <schemaName2> ...
|
||||
*
|
||||
* schemaName - extensionless name of the schema.json file to generate types for
|
||||
*/
|
||||
|
||||
import { mkdir, readFile, writeFile } from 'fs/promises'
|
||||
import path from 'path'
|
||||
|
||||
import { ResolverOptions } from 'json-schema-ref-parser'
|
||||
import { compile as compileJSONSchema } from 'json-schema-to-typescript'
|
||||
|
||||
const schemaDirectory = path.join(__dirname, '..', '..', '..', 'schema')
|
||||
const outputDirectory = path.join(__dirname, '..', 'src', 'schema')
|
||||
|
||||
/**
|
||||
* Allow json-schema-ref-parser to resolve the v7 draft of JSON Schema
|
||||
* using a local copy of the spec, enabling developers to run/develop Sourcegraph offline
|
||||
*/
|
||||
const draftV7resolver: ResolverOptions = {
|
||||
order: 1,
|
||||
read: () => readFile(path.join(schemaDirectory, 'json-schema-draft-07.schema.json')),
|
||||
canRead: file => file.url === 'http://json-schema.org/draft-07/schema',
|
||||
}
|
||||
|
||||
export async function generateSchema(schemaName: string): Promise<void> {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
let schema = await readFile(path.join(schemaDirectory, `${schemaName}.schema.json`), 'utf8')
|
||||
|
||||
// HACK: Rewrite absolute $refs to be relative. They need to be absolute for Monaco to resolve them
|
||||
// when the schema is in a oneOf (to be merged with extension schemas).
|
||||
schema = schema.replaceAll('https://sourcegraph.com/v1/settings.schema.json#/definitions/', '#/definitions/')
|
||||
|
||||
const types = await compileJSONSchema(JSON.parse(schema), 'settings.schema', {
|
||||
cwd: schemaDirectory,
|
||||
$refOptions: {
|
||||
resolve: {
|
||||
draftV7resolver,
|
||||
// there should be no reason to make network calls during this process,
|
||||
// and if there are we've broken env for offline devs/increased dev startup time
|
||||
http: false as any,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
await mkdir(outputDirectory, { recursive: true })
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
await writeFile(path.join(outputDirectory, `${schemaName}.schema.d.ts`), types)
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
async function main(schemas: string[]) {
|
||||
if (schemas.length === 0) {
|
||||
throw new Error('Usage: <schemaName1> <schemaName2> ...')
|
||||
}
|
||||
|
||||
for (const schema of schemas) {
|
||||
await generateSchema(schema)
|
||||
}
|
||||
}
|
||||
main(process.argv.slice(2)).catch(error => {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
@ -1,111 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
const path = require('path')
|
||||
|
||||
const gulp = require('gulp')
|
||||
const { readFile } = require('mz/fs')
|
||||
|
||||
const { cssModulesTypings, watchCSSModulesTypings } = require('./dev/generateCssModulesTypes')
|
||||
const { generateGraphQlOperations, ALL_DOCUMENTS_GLOB } = require('./dev/generateGraphQlOperations')
|
||||
const { generateSchema } = require('./dev/generateSchema')
|
||||
|
||||
/**
|
||||
* Determine whether to regenerate GraphQL operations based on the given
|
||||
* Chokidar event. If we can determine that the file being modified is a
|
||||
* non-GraphQL-using TypeScript or JavaScript file, then we can skip the
|
||||
* expensive generation step.
|
||||
*
|
||||
* @param {string} type
|
||||
* @param {string} name
|
||||
* @returns bool
|
||||
*/
|
||||
async function shouldRegenerateGraphQlOperations(type, name) {
|
||||
if (type === 'unlink' || type === 'unlinkDir') {
|
||||
// For all deletions, we'll regenerate, since we don't know if the file(s)
|
||||
// that were deleted were used when generating the GraphQL operations.
|
||||
return true
|
||||
}
|
||||
|
||||
// If we're watching a JavaScript or TypeScript file, then we should only
|
||||
// regenerate if there are gql-tagged strings. But first, we have to figure
|
||||
// out if it is that type of file.
|
||||
const isJS = ['.tsx', '.ts', '.jsx', '.js'].reduce((previous, extension) => {
|
||||
if (previous) {
|
||||
return previous
|
||||
}
|
||||
return name.endsWith(extension)
|
||||
}, false)
|
||||
if (isJS) {
|
||||
// Look for the tagged string in the most naïve way imaginable.
|
||||
return (await readFile(name)).includes('gql`')
|
||||
}
|
||||
|
||||
// Finally, for non-JavaScript/TypeScript files, we'll be safe and always
|
||||
// regenerate.
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the new query-specific types on file changes.
|
||||
*/
|
||||
function watchGraphQlOperations() {
|
||||
if (process.env.DEV_WEB_BUILDER_UNSAFE_FAST) {
|
||||
// Setting the env var DEV_WEB_BUILDER_UNSAFE_FAST skips various operations in frontend dev.
|
||||
// It's not safe, but if you know what you're doing, go ahead and use it. (CI will catch any
|
||||
// issues you forgot about.)
|
||||
return
|
||||
}
|
||||
|
||||
// Although graphql-codegen has watching capabilities, they don't appear to
|
||||
// use chokidar correctly and rely on polling. Instead, let's get gulp to
|
||||
// watch for us, since we know it'll do it more efficiently, and then we can
|
||||
// trigger the code generation more selectively.
|
||||
return gulp
|
||||
.watch(ALL_DOCUMENTS_GLOB, {
|
||||
ignored: /** @param {string} name */ name => name.endsWith('graphql-operations.ts'),
|
||||
})
|
||||
.on('all', (type, name) => {
|
||||
;(async () => {
|
||||
if (await shouldRegenerateGraphQlOperations(type, name)) {
|
||||
console.log('Regenerating GraphQL types')
|
||||
await generateGraphQlOperations()
|
||||
console.log('Done regenerating GraphQL types')
|
||||
}
|
||||
})().catch(error => {
|
||||
console.error(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the new query-specific types.
|
||||
*/
|
||||
async function graphQlOperations() {
|
||||
await generateGraphQlOperations()
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the TypeScript types for the JSON schemas.
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function schema() {
|
||||
await Promise.all(
|
||||
['json-schema-draft-07', 'settings', 'site', 'batch_spec'].map(async name => {
|
||||
await generateSchema(name)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
function watchSchema() {
|
||||
return gulp.watch(path.join(__dirname, '../schema/*.schema.json'), schema)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
watchSchema,
|
||||
schema,
|
||||
graphQlOperations,
|
||||
watchGraphQlOperations,
|
||||
cssModulesTypings,
|
||||
watchCSSModulesTypings,
|
||||
}
|
||||
@ -8,9 +8,10 @@
|
||||
"lint:js": "eslint --cache '**/*.[jt]s?(x)'",
|
||||
"lint:css": "stylelint 'src/**/*.scss' --quiet",
|
||||
"test": "jest",
|
||||
"schema": "gulp schema",
|
||||
"graphql-operations": "gulp graphQlOperations",
|
||||
"watch-schema": "gulp watchSchema"
|
||||
"generate": "concurrently -r npm:generate:*",
|
||||
"generate:graphql-operations": "ts-node -T dev/generateGraphQlOperations.ts",
|
||||
"generate:schema": "ts-node -T dev/generateSchema.ts json-schema-draft-07 settings site batch_spec",
|
||||
"generate:css-modules-types": "ts-node -T dev/generateCssModulesTypes.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sourcegraph/testing": "workspace:*",
|
||||
|
||||
@ -43,6 +43,6 @@
|
||||
"path": "../wildcard",
|
||||
},
|
||||
],
|
||||
"include": ["src", "dev", "gulpfile.js", "./src/**/*.json"],
|
||||
"include": ["src", "dev", "./src/**/*.json"],
|
||||
"exclude": ["../../node_modules", "./node_modules", "./out", "./src/end-to-end"],
|
||||
}
|
||||
|
||||
@ -36,3 +36,17 @@ export async function build(): Promise<void> {
|
||||
await new Promise(() => {}) // wait forever
|
||||
}
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
async function main(args: string[]): Promise<void> {
|
||||
if (args.length !== 0) {
|
||||
throw new Error('Usage: (no options)')
|
||||
}
|
||||
await build()
|
||||
}
|
||||
// eslint-disable-next-line unicorn/prefer-top-level-await
|
||||
main(process.argv.slice(2)).catch(error => {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,7 +8,13 @@ import signale from 'signale'
|
||||
import { STATIC_ASSETS_PATH } from '@sourcegraph/build-config'
|
||||
import { buildMonaco } from '@sourcegraph/build-config/src/esbuild/monacoPlugin'
|
||||
|
||||
import { ENVIRONMENT_CONFIG, HTTPS_WEB_SERVER_URL, printSuccessBanner } from '../utils'
|
||||
import {
|
||||
DEV_SERVER_LISTEN_ADDR,
|
||||
DEV_SERVER_PROXY_TARGET_ADDR,
|
||||
ENVIRONMENT_CONFIG,
|
||||
HTTPS_WEB_SERVER_URL,
|
||||
printSuccessBanner,
|
||||
} from '../utils'
|
||||
|
||||
import { esbuildBuildOptions } from './config'
|
||||
import { assetPathPrefix } from './manifest'
|
||||
@ -67,3 +73,29 @@ export const esbuildDevelopmentServer = async (
|
||||
proxyServer.once('error', error => reject(error))
|
||||
})
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
async function main(args: string[]): Promise<void> {
|
||||
if (args.length !== 0) {
|
||||
throw new Error('Usage: (no options)')
|
||||
}
|
||||
await esbuildDevelopmentServer(DEV_SERVER_LISTEN_ADDR, app => {
|
||||
app.use(
|
||||
'/',
|
||||
createProxyMiddleware({
|
||||
target: {
|
||||
protocol: 'http:',
|
||||
host: DEV_SERVER_PROXY_TARGET_ADDR.host,
|
||||
port: DEV_SERVER_PROXY_TARGET_ADDR.port,
|
||||
},
|
||||
logLevel: 'error',
|
||||
})
|
||||
)
|
||||
})
|
||||
}
|
||||
// eslint-disable-next-line unicorn/prefer-top-level-await
|
||||
main(process.argv.slice(2)).catch(error => {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
@ -71,7 +71,6 @@ export function getAPIProxySettings(options: GetAPIProxySettingsOptions): ProxyS
|
||||
// we add it ourselves.
|
||||
proxyRequest.setHeader('Origin', apiURL)
|
||||
},
|
||||
// TODO: share with `client/web/gulpfile.js`
|
||||
// Avoid crashing on "read ECONNRESET".
|
||||
onError: () => undefined,
|
||||
// Don't log proxy errors, these usually just contain
|
||||
|
||||
@ -1,89 +0,0 @@
|
||||
const path = require('path')
|
||||
|
||||
require('ts-node').register({
|
||||
transpileOnly: true,
|
||||
// Use config with "module": "commonjs" because not all modules involved in tasks are esnext modules.
|
||||
project: path.resolve(__dirname, './dev/tsconfig.json'),
|
||||
})
|
||||
|
||||
const gulp = require('gulp')
|
||||
const { createProxyMiddleware } = require('http-proxy-middleware')
|
||||
|
||||
const {
|
||||
graphQlOperations,
|
||||
schema,
|
||||
watchGraphQlOperations,
|
||||
watchSchema,
|
||||
cssModulesTypings,
|
||||
watchCSSModulesTypings,
|
||||
} = require('../shared/gulpfile')
|
||||
|
||||
const { build: buildEsbuild } = require('./dev/esbuild/build')
|
||||
const { esbuildDevelopmentServer } = require('./dev/esbuild/server')
|
||||
const { DEV_SERVER_LISTEN_ADDR, DEV_SERVER_PROXY_TARGET_ADDR } = require('./dev/utils')
|
||||
|
||||
const webBuild = buildEsbuild
|
||||
|
||||
const esbuildDevelopmentProxy = () =>
|
||||
esbuildDevelopmentServer(DEV_SERVER_LISTEN_ADDR, app => {
|
||||
app.use(
|
||||
'/',
|
||||
createProxyMiddleware({
|
||||
target: {
|
||||
protocol: 'http:',
|
||||
host: DEV_SERVER_PROXY_TARGET_ADDR.host,
|
||||
port: DEV_SERVER_PROXY_TARGET_ADDR.port,
|
||||
},
|
||||
logLevel: 'error',
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
const developmentServer = esbuildDevelopmentProxy
|
||||
|
||||
// Ensure the typings that TypeScript depends on are build to avoid first-time-run errors
|
||||
const generate = gulp.parallel(schema, graphQlOperations, cssModulesTypings)
|
||||
|
||||
// Watches code generation only, rebuilds on file changes
|
||||
const watchGenerators = gulp.parallel(watchSchema, watchGraphQlOperations, watchCSSModulesTypings)
|
||||
|
||||
/**
|
||||
* Builds everything.
|
||||
*/
|
||||
const build = gulp.series(generate, webBuild)
|
||||
|
||||
/**
|
||||
* Starts a development server without initial code generation, watches everything and rebuilds on file changes.
|
||||
*/
|
||||
const developmentWithoutInitialCodeGen = gulp.parallel(watchGenerators, developmentServer)
|
||||
|
||||
/**
|
||||
* Runs code generation first, then starts a development server, watches everything and rebuilds on file changes.
|
||||
*/
|
||||
const development = gulp.series(
|
||||
// Ensure the typings that TypeScript depends on are build to avoid first-time-run errors
|
||||
generate,
|
||||
developmentWithoutInitialCodeGen
|
||||
)
|
||||
|
||||
/**
|
||||
* Watches everything, rebuilds on file changes and writes the bundle to disk.
|
||||
* Useful to running integration tests.
|
||||
*/
|
||||
const watch = gulp.series(
|
||||
// Ensure the typings that TypeScript depends on are build to avoid first-time-run errors
|
||||
generate,
|
||||
// invoked with WATCH=1
|
||||
gulp.parallel(watchGenerators, webBuild)
|
||||
)
|
||||
|
||||
module.exports = {
|
||||
build,
|
||||
watch,
|
||||
dev: development,
|
||||
unsafeDev: developmentWithoutInitialCodeGen,
|
||||
webBuild,
|
||||
developmentServer,
|
||||
generate,
|
||||
watchGenerators,
|
||||
}
|
||||
@ -18,11 +18,10 @@
|
||||
"storybook": "STORIES_GLOB='client/web/src/**/*.story.tsx' pnpm --filter @sourcegraph/storybook run start",
|
||||
"serve:dev": "ts-node-transpile-only --project ./dev/tsconfig.json ./dev/server/development.server.ts",
|
||||
"serve:prod": "ts-node-transpile-only --project ./dev/tsconfig.json ./dev/server/production.server.ts",
|
||||
"task:gulp": "cross-env NODE_OPTIONS=\"--max_old_space_size=8192\" gulp",
|
||||
"dev": "pnpm task:gulp dev",
|
||||
"unsafeDev": "pnpm task:gulp unsafeDev",
|
||||
"build": "pnpm task:gulp build",
|
||||
"watch": "WATCH=1 pnpm task:gulp watch",
|
||||
"generate": "pnpm -w run generate",
|
||||
"dev": "ts-node -T dev/esbuild/server.ts",
|
||||
"build": "pnpm run generate && ts-node -T dev/esbuild/build.ts",
|
||||
"watch": "WATCH=1 pnpm run --silent build",
|
||||
"lint": "pnpm lint:js && pnpm:lint:css",
|
||||
"lint:js": "NODE_OPTIONS=\"--max_old_space_size=16192\" eslint --cache '**/*.[tj]s?(x)'",
|
||||
"lint:css": "stylelint 'src/**/*.scss' --quiet",
|
||||
|
||||
@ -22,7 +22,6 @@ var clientRootFiles = []string{
|
||||
"tsconfig.json",
|
||||
".percy.yml",
|
||||
".eslintrc.js",
|
||||
"gulpfile.js",
|
||||
}
|
||||
|
||||
func isRootClientFile(p string) bool {
|
||||
|
||||
@ -189,7 +189,7 @@ func clientChromaticTests(opts CoreTestOperationsOptions) operations.Operation {
|
||||
withPnpmCache(),
|
||||
bk.AutomaticRetry(3),
|
||||
bk.Cmd("./dev/ci/pnpm-install-with-retry.sh"),
|
||||
bk.Cmd("pnpm gulp generate"),
|
||||
bk.Cmd("pnpm run generate"),
|
||||
bk.Env("MINIFY", "1"),
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ echo "--- pnpm install"
|
||||
./dev/ci/pnpm-install-with-retry.sh
|
||||
|
||||
echo "--- generate"
|
||||
pnpm gulp generate
|
||||
pnpm run generate
|
||||
|
||||
for cmd in "$@"; do
|
||||
echo "--- $cmd"
|
||||
|
||||
@ -6,7 +6,7 @@ echo "--- pnpm install in root"
|
||||
./dev/ci/pnpm-install-with-retry.sh
|
||||
|
||||
echo "--- generate"
|
||||
pnpm gulp generate
|
||||
pnpm run generate
|
||||
|
||||
echo "--- test"
|
||||
|
||||
|
||||
12
dev/defs.bzl
12
dev/defs.bzl
@ -5,6 +5,7 @@ load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
|
||||
load("@aspect_rules_js//npm:defs.bzl", _npm_package = "npm_package")
|
||||
load("@aspect_rules_ts//ts:defs.bzl", _ts_project = "ts_project")
|
||||
load("@aspect_rules_jest//jest:defs.bzl", _jest_test = "jest_test")
|
||||
load("@aspect_rules_js//js:defs.bzl", "js_binary")
|
||||
load("//dev:eslint.bzl", "eslint_test_with_types", "get_client_package_path")
|
||||
load(":sass.bzl", _sass = "sass")
|
||||
load(":babel.bzl", _babel = "babel")
|
||||
@ -135,3 +136,14 @@ def jest_test(name, data = [], **kwargs):
|
||||
data = data + native.glob(["**/__fixtures__/**/*"]),
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def ts_binary(name, entry_point, data = [], env = {}, **kwargs):
|
||||
"""A wrapper around js_binary that invokes a TypeScript entrypoint using ts-node."""
|
||||
js_binary(
|
||||
name = name,
|
||||
entry_point = entry_point,
|
||||
data = data + ["//:node_modules/ts-node"],
|
||||
env = dict(env, **{"TS_NODE_TRANSPILE_ONLY": "1"}),
|
||||
node_options = ["--require", "ts-node/register"],
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -73,8 +73,10 @@ commands:
|
||||
SOURCEGRAPH_HTTPS_PORT: 3443
|
||||
|
||||
web:
|
||||
cmd: ./node_modules/.bin/gulp --silent --color dev
|
||||
install: pnpm install
|
||||
cmd: pnpm --filter @sourcegraph/web dev
|
||||
install: |
|
||||
pnpm install
|
||||
pnpm run generate
|
||||
env:
|
||||
WEB_BUILDER_DEV_SERVER: 1
|
||||
NODE_ENV: development
|
||||
|
||||
@ -14,7 +14,7 @@ Each query must have a globally unique name as per the [GraphQL specification](h
|
||||
|
||||
Using each unique query, we can generate specific types so you can receive autocompletion, syntax highlighting, hover tooltips and validation in your IDE.
|
||||
|
||||
Once you have built your query, `graphql-codegen` will generate the correct request and response types. This process should happen automatically through local development, you can also manually trigger this by running `pnpm generate` or `pnpm watch-generate`. Since the generator is lazy and won't generate types for fields that aren't used, if you're adding a new field then you **must** write at least one query that actually uses the field before running the generator.
|
||||
Once you have built your query, `graphql-codegen` will generate the correct request and response types. This process should happen automatically through local development, you can also manually trigger this by running `pnpm generate`. Since the generator is lazy and won't generate types for fields that aren't used, if you're adding a new field then you **must** write at least one query that actually uses the field before running the generator.
|
||||
|
||||
Using a `useQuery` hook, we can easily fire a request and handle the response correctly.
|
||||
|
||||
|
||||
@ -76,7 +76,7 @@ To use this approach, colocate a SCSS stylesheet with the React component and us
|
||||
Example:
|
||||
|
||||
- `PageSelector.tsx` component would have a `PageSelector.module.scss` file next to it.
|
||||
- Use `pnpm watch-generate` to generate a Typescript type declaration file: `PageSelector.module.scss.d.ts` in the same folder.
|
||||
- Use `pnpm generate` to generate a TypeScript type declaration file: `PageSelector.module.scss.d.ts` in the same folder.
|
||||
- After that, it's possible to type-safely use class names from the CSS module.
|
||||
|
||||
```tsx
|
||||
|
||||
@ -45,12 +45,6 @@ To install it, [see the instructions](../../setup/quickstart.md).
|
||||
pnpm generate
|
||||
```
|
||||
|
||||
To regenerate on file change:
|
||||
|
||||
```sh
|
||||
pnpm watch-generate
|
||||
```
|
||||
|
||||
### Storybook
|
||||
|
||||
Storybook is used to work on the components in isolation. The latest version is deployed at http://storybook.sgdev.org/.
|
||||
|
||||
@ -110,8 +110,6 @@ On first install, the program will use quite a bit of bandwidth to concurrently
|
||||
|
||||
After the initial install/compile is complete, the Docker for Mac binary uses about 1.5GB of RAM. The numerous different Go binaries don't use that much RAM or CPU each, about 5MB of RAM each.
|
||||
|
||||
If you notice heavy battery and CPU usage running `gulp --color watch`, please first [double check that Spotlight is not indexing your Sourcegraph repository](https://www.macobserver.com/tips/how-to/stop-spotlight-indexing/), as this can lead to additional, unnecessary, poll events.
|
||||
|
||||
If you're running macOS 10.15.x (Catalina) reinstalling the Xcode Command Line Tools may be necessary as follows:
|
||||
|
||||
1. Uninstall the Command Line Tools with `rm -rf /Library/Developer/CommandLineTools`
|
||||
|
||||
38
gulpfile.js
38
gulpfile.js
@ -1,38 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
const gulp = require('gulp')
|
||||
|
||||
const { graphQlOperations, schema, watchGraphQlOperations } = require('./client/shared/gulpfile')
|
||||
const { buildSvelteKit } = require('./client/web-sveltekit/gulpfile.cjs')
|
||||
const { build: webBuild, developmentServer, generate, watchGenerators } = require('./client/web/gulpfile')
|
||||
|
||||
/**
|
||||
* Generates files needed for builds whenever files change.
|
||||
*/
|
||||
const watchGenerate = gulp.series(generate, watchGenerators)
|
||||
|
||||
/**
|
||||
* Builds everything.
|
||||
*/
|
||||
const build = gulp.series(generate, webBuild)
|
||||
|
||||
const tasks = [watchGenerators, developmentServer]
|
||||
|
||||
if (process.env.SVELTEKIT) {
|
||||
tasks.push(buildSvelteKit)
|
||||
}
|
||||
|
||||
/**
|
||||
* Watches everything and rebuilds on file changes.
|
||||
*/
|
||||
const development = gulp.series(generate, gulp.parallel(...tasks))
|
||||
|
||||
module.exports = {
|
||||
generate,
|
||||
watchGenerate,
|
||||
build,
|
||||
dev: development,
|
||||
schema,
|
||||
graphQlOperations,
|
||||
watchGraphQlOperations,
|
||||
}
|
||||
@ -27,8 +27,7 @@
|
||||
"build-web": "pnpm --filter @sourcegraph/web run build",
|
||||
"build-app-shell": "pnpm --filter @sourcegraph/app-shell run build",
|
||||
"watch-web": "pnpm --filter @sourcegraph/web run watch",
|
||||
"generate": "gulp generate",
|
||||
"watch-generate": "gulp watchGenerate",
|
||||
"generate": "pnpm --filter @sourcegraph/shared run generate",
|
||||
"test": "jest --testPathIgnorePatterns end-to-end --testPathIgnorePatterns regression --testPathIgnorePatterns integration --testPathIgnorePatterns storybook \"/out/.*test.js\" \"/out/.*test.d.ts\"",
|
||||
"_test-integration": "TS_NODE_PROJECT=client/web/src/integration/tsconfig.json mocha --parallel=${CI:-\"false\"} --retries=1 --jobs=2",
|
||||
"test-integration": "NODE_ENV=production pnpm _test-integration \"./client/web/src/integration/**/*.test.ts\"",
|
||||
@ -146,7 +145,6 @@
|
||||
"@types/glob": "7.1.3",
|
||||
"@types/google-spreadsheet": "^3.3.1",
|
||||
"@types/got": "9.6.11",
|
||||
"@types/gulp": "4.0.7",
|
||||
"@types/highlight.js": "9.12.4",
|
||||
"@types/history": "^4.7.11",
|
||||
"@types/isomorphic-fetch": "^0.0.36",
|
||||
@ -225,7 +223,6 @@
|
||||
"gql2ts": "^1.10.1",
|
||||
"graphql": "^15.4.0",
|
||||
"graphql-schema-linter": "^2.0.1",
|
||||
"gulp": "^4.0.2",
|
||||
"http-proxy-middleware": "^2.0.6",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"jest": "^29.7.0",
|
||||
|
||||
1505
pnpm-lock.yaml
1505
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -385,8 +385,10 @@ commands:
|
||||
|
||||
web:
|
||||
description: Enterprise version of the web app
|
||||
cmd: ./node_modules/.bin/gulp --color dev
|
||||
install: pnpm install
|
||||
cmd: pnpm --filter @sourcegraph/web dev
|
||||
install: |
|
||||
pnpm install
|
||||
pnpm run generate
|
||||
env:
|
||||
ENABLE_OPEN_TELEMETRY: true
|
||||
|
||||
@ -395,7 +397,7 @@ commands:
|
||||
cmd: pnpm --filter @sourcegraph/web serve:dev --color
|
||||
install: |
|
||||
pnpm install
|
||||
pnpm generate
|
||||
pnpm run generate
|
||||
env:
|
||||
WEB_BUILDER_SERVE_INDEX: true
|
||||
SOURCEGRAPH_API_URL: https://k8s.sgdev.org
|
||||
|
||||
Loading…
Reference in New Issue
Block a user