mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 13:11:49 +00:00
This reverts commit 86180de04a.
This commit is contained in:
parent
3fa35fff73
commit
0f8b28b5b9
@ -22,6 +22,7 @@ ts_config(
|
||||
ts_project(
|
||||
name = "build-config_lib",
|
||||
srcs = [
|
||||
"src/esbuild/monacoPlugin.ts",
|
||||
"src/esbuild/packageResolutionPlugin.ts",
|
||||
"src/esbuild/plugins.ts",
|
||||
"src/esbuild/stylePlugin.ts",
|
||||
|
||||
76
client/build-config/src/esbuild/monacoPlugin.ts
Normal file
76
client/build-config/src/esbuild/monacoPlugin.ts
Normal file
@ -0,0 +1,76 @@
|
||||
import path from 'path'
|
||||
|
||||
import * as esbuild from 'esbuild'
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { type EditorFeature, featuresArr } from 'monaco-editor-webpack-plugin/out/features'
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { type EditorLanguage, languagesArr } from 'monaco-editor-webpack-plugin/out/languages'
|
||||
|
||||
import type { MONACO_LANGUAGES_AND_FEATURES } from '../monaco-editor'
|
||||
import { ROOT_PATH } from '../paths'
|
||||
|
||||
const monacoModulePath = (modulePath: string): string =>
|
||||
require.resolve(path.join('monaco-editor/esm', modulePath), {
|
||||
paths: [path.join(ROOT_PATH, 'node_modules')],
|
||||
})
|
||||
|
||||
/**
|
||||
* An esbuild plugin that omits some unneeded features and languages from monaco-editor when
|
||||
* bundling, to reduce bundle size and speed up builds. Similar to
|
||||
* https://github.com/microsoft/monaco-editor-webpack-plugin.
|
||||
*/
|
||||
export const monacoPlugin = ({
|
||||
languages,
|
||||
features,
|
||||
}: Required<typeof MONACO_LANGUAGES_AND_FEATURES>): esbuild.Plugin => ({
|
||||
name: 'monaco',
|
||||
setup: build => {
|
||||
for (const feature of features) {
|
||||
if (feature.startsWith('!')) {
|
||||
throw new Error('negated features (starting with "!") are not supported')
|
||||
}
|
||||
}
|
||||
|
||||
// Some feature exclusions don't work because their module exports a symbol needed by
|
||||
// another feature.
|
||||
const ALWAYS_ENABLED_FEATURES = new Set<EditorFeature>(['snippets'])
|
||||
|
||||
const skipLanguageModules = languagesArr
|
||||
.filter(({ label }) => !languages.includes(label as EditorLanguage))
|
||||
.flatMap(({ entry }) => entry || [])
|
||||
const skipFeatureModules = featuresArr
|
||||
.filter(
|
||||
({ label }) =>
|
||||
!features.includes(label as EditorFeature) && !ALWAYS_ENABLED_FEATURES.has(label as EditorFeature)
|
||||
)
|
||||
.flatMap(({ entry }) => entry || [])
|
||||
|
||||
const skipModulePaths = [...skipLanguageModules, ...skipFeatureModules].map(monacoModulePath)
|
||||
const filter = new RegExp(`^(${skipModulePaths.join('|')})$`)
|
||||
|
||||
// For omitted features and languages, treat their modules as empty files.
|
||||
//
|
||||
// TODO(sqs): This is different from how
|
||||
// https://github.com/microsoft/monaco-editor-webpack-plugin does it. The
|
||||
// monaco-editor-webpack-plugin approach relies on injecting a different central module
|
||||
// file, rather than zeroing out each feature/language module. Our approach necessitates the
|
||||
// ALWAYS_ENABLED_FEATURES hack above.
|
||||
build.onLoad({ filter }, () => ({ contents: '', loader: 'js' }))
|
||||
},
|
||||
})
|
||||
|
||||
// TODO(sqs): These Monaco Web Workers could be built as part of the main build if we switch to
|
||||
// using MonacoEnvironment#getWorker (from #getWorkerUrl), which would then let us use the worker
|
||||
// plugin (and in Webpack the worker-loader) to load these instead of needing to hardcode them as
|
||||
// build entrypoints.
|
||||
export const buildMonaco = async (outdir: string): Promise<esbuild.BuildContext> =>
|
||||
esbuild.context({
|
||||
entryPoints: {
|
||||
'scripts/editor.worker.bundle': 'monaco-editor/esm/vs/editor/editor.worker.js',
|
||||
'scripts/json.worker.bundle': 'monaco-editor/esm/vs/language/json/json.worker.js',
|
||||
},
|
||||
format: 'iife',
|
||||
target: 'es2021',
|
||||
bundle: true,
|
||||
outdir,
|
||||
})
|
||||
@ -1,5 +1,6 @@
|
||||
import type * as esbuild from 'esbuild'
|
||||
|
||||
export * from './monacoPlugin'
|
||||
export * from './packageResolutionPlugin'
|
||||
export * from './stylePlugin'
|
||||
export * from './workerPlugin'
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
load("@aspect_rules_js//js:defs.bzl", "js_library")
|
||||
load("@aspect_rules_ts//ts:defs.bzl", "ts_config")
|
||||
load("@bazel_skylib//rules:build_test.bzl", "build_test")
|
||||
load("@npm//:bundlesize2/package_json.bzl", bundlesize_bin = "bin")
|
||||
load("@aspect_rules_js//js:defs.bzl", "js_library")
|
||||
load("@npm//:defs.bzl", "npm_link_all_packages")
|
||||
load("@npm//:bundlesize2/package_json.bzl", bundlesize_bin = "bin")
|
||||
load("//client/shared/dev:generate_graphql_operations.bzl", "generate_graphql_operations")
|
||||
load("//client/shared/dev:tools.bzl", "module_style_typings")
|
||||
load("//dev:defs.bzl", "npm_package", "sass", "ts_project", "vitest_test")
|
||||
load("@aspect_rules_esbuild//esbuild:defs.bzl", "esbuild")
|
||||
load("//dev:esbuild.bzl", "esbuild_web_app")
|
||||
load("@aspect_rules_ts//ts:defs.bzl", "ts_config")
|
||||
load("//dev:eslint.bzl", "eslint_config_and_lint_root", "eslint_test_with_types")
|
||||
load("//dev:vite/vite.bzl", "vite_project", "vite_web_app")
|
||||
|
||||
# TODO(bazel): storybook build
|
||||
# gazelle:exclude **/*.story.{ts,tsx}
|
||||
@ -1823,7 +1824,6 @@ ts_project(
|
||||
"//:node_modules/copy-to-clipboard",
|
||||
"//:node_modules/d3-time-format",
|
||||
"//:node_modules/date-fns",
|
||||
"//:node_modules/events",
|
||||
"//:node_modules/fast-json-stable-stringify",
|
||||
"//:node_modules/focus-visible",
|
||||
"//:node_modules/fzf",
|
||||
@ -2096,11 +2096,22 @@ vitest_test(
|
||||
],
|
||||
)
|
||||
|
||||
VITE_PROJECT_DEPS = [
|
||||
# esbuild dev environment -------------------
|
||||
ESBUILD_CONFIG_DEPS = [
|
||||
":node_modules/@sourcegraph/build-config",
|
||||
"//:node_modules/open-color",
|
||||
"//:node_modules/buffer",
|
||||
"//:node_modules/lodash",
|
||||
"//:node_modules/path-browserify",
|
||||
"//:node_modules/punycode",
|
||||
"//:node_modules/util",
|
||||
"//:node_modules/events",
|
||||
"//:node_modules/monaco-editor",
|
||||
"//:node_modules/esbuild",
|
||||
"//:node_modules/react-visibility-sensor", # required for https://github.com/joshwnj/react-visibility-sensor/issues/148 workaround
|
||||
"//:postcss_config_js",
|
||||
"//client/web/dev",
|
||||
|
||||
# HACKS: bundle-time css import
|
||||
"//:node_modules/open-color",
|
||||
]
|
||||
|
||||
# Bundled data which was replaced with *.d.ts files at ts compiletime
|
||||
@ -2111,40 +2122,50 @@ BUNDLE_DATA_DEPS = [
|
||||
# TODO(bazel): this is already in the main ts_project(srcs). Why also here?
|
||||
"src/enterprise/codeintel/configuration/schema.json",
|
||||
":enterprise-yaml",
|
||||
"//client/web/dev:esbuild-config-production_bundle",
|
||||
]
|
||||
|
||||
vite_project(
|
||||
esbuild(
|
||||
name = "bundle",
|
||||
srcs = BUNDLE_DATA_DEPS + [
|
||||
":web_lib",
|
||||
"//:package_json",
|
||||
],
|
||||
config = "//client/web/dev:vite-config",
|
||||
data = BUNDLE_DATA_DEPS,
|
||||
config = "//client/web/dev:esbuild-config-production_bundle",
|
||||
entry_points = [
|
||||
"src/enterprise/main.js",
|
||||
"src/enterprise/embed/embedMain.js",
|
||||
],
|
||||
minify = True,
|
||||
sourcemap = "linked",
|
||||
splitting = True,
|
||||
tags = ["exclusive"],
|
||||
tsconfig = ":tsconfig",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = VITE_PROJECT_DEPS,
|
||||
visibility = ["//client/web/dist:__subpackages__"],
|
||||
deps = ESBUILD_CONFIG_DEPS,
|
||||
)
|
||||
|
||||
# Used for integration tests.
|
||||
vite_web_app(
|
||||
esbuild_web_app(
|
||||
name = "app",
|
||||
srcs = BUNDLE_DATA_DEPS + [
|
||||
":web_lib",
|
||||
"//:package_json",
|
||||
],
|
||||
config = "//client/web/dev:vite-config",
|
||||
env = {
|
||||
"INTEGRATION_TESTS": "true",
|
||||
config = "//client/web/dev:esbuild-config-production_bundle",
|
||||
define = {
|
||||
"process.env.INTEGRATION_TESTS": "true",
|
||||
},
|
||||
tsconfig = ":tsconfig",
|
||||
entry_points = [
|
||||
"src/enterprise/main.js",
|
||||
"src/enterprise/embed/embedMain.js",
|
||||
],
|
||||
sourcemap = "linked",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = VITE_PROJECT_DEPS,
|
||||
deps = ESBUILD_CONFIG_DEPS,
|
||||
)
|
||||
|
||||
build_test(
|
||||
name = "vite_test",
|
||||
name = "esbuild_test",
|
||||
size = "enormous",
|
||||
targets = [
|
||||
":bundle",
|
||||
|
||||
@ -29,6 +29,16 @@ To use a public API that doesn't require authentication for most of the function
|
||||
SOURCEGRAPH_API_URL=https://sourcegraph.com sg start web-standalone
|
||||
```
|
||||
|
||||
### Production server
|
||||
|
||||
```sh
|
||||
sg start web-standalone-prod
|
||||
```
|
||||
|
||||
Web app should be available at `https://${SOURCEGRAPH_HTTPS_DOMAIN}:${SOURCEGRAPH_HTTPS_PORT}`. Build artifacts will be served from `<rootRepoPath>/client/web/dist`.
|
||||
|
||||
Note: If you are unable to use the above commands (e.g. you can't install Caddy), you can use `sg run web-standalone-http` instead. This will start a development server using only Node, and will be available at `http://localhost:${SOURCEGRAPH_HTTP_PORT}`.
|
||||
|
||||
### API proxy
|
||||
|
||||
In both environments, server proxies API requests to `SOURCEGRAPH_API_URL` provided as the `.env` variable.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
const path = require('path')
|
||||
|
||||
const STATIC_ASSETS_PATH = path.join(process.env.WEB_BUNDLE_PATH || path.join(__dirname, 'dist'), 'assets')
|
||||
const STATIC_ASSETS_PATH = process.env.WEB_BUNDLE_PATH || path.join(__dirname, 'dist')
|
||||
|
||||
const config = {
|
||||
files: [
|
||||
@ -21,7 +21,7 @@ const config = {
|
||||
maxSize: '155kb',
|
||||
},
|
||||
{
|
||||
path: path.join(STATIC_ASSETS_PATH, '*.js'),
|
||||
path: path.join(STATIC_ASSETS_PATH, 'chunks/chunk-*.js'),
|
||||
maxSize: '600kb', // 2 monaco chunks are very big
|
||||
},
|
||||
/**
|
||||
@ -39,7 +39,7 @@ const config = {
|
||||
maxSize: '350kb',
|
||||
},
|
||||
{
|
||||
path: path.join(STATIC_ASSETS_PATH, '*.css'),
|
||||
path: path.join(STATIC_ASSETS_PATH, 'chunks/chunk-*.css'),
|
||||
maxSize: '45kb',
|
||||
},
|
||||
],
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
load("@aspect_rules_esbuild//esbuild:defs.bzl", "esbuild")
|
||||
load("@aspect_rules_js//js:defs.bzl", "js_library")
|
||||
load("@aspect_rules_ts//ts:defs.bzl", "ts_config")
|
||||
load("//dev:defs.bzl", "ts_project", "vitest_test")
|
||||
|
||||
@ -18,67 +19,104 @@ ts_config(
|
||||
ts_project(
|
||||
name = "dev",
|
||||
srcs = [
|
||||
"server/apiProxySettings.ts",
|
||||
"server/devProxyServer.ts",
|
||||
"esbuild/build.ts",
|
||||
"esbuild/config.ts",
|
||||
"esbuild/manifest.ts",
|
||||
"esbuild/manifestPlugin.ts",
|
||||
"esbuild/server.ts",
|
||||
"server/development.server.ts",
|
||||
"server/production.server.ts",
|
||||
"utils/constants.ts",
|
||||
"utils/create-js-context.ts",
|
||||
"utils/environment-config.ts",
|
||||
"utils/get-api-proxy-settings.ts",
|
||||
"utils/get-index-html.ts",
|
||||
"utils/get-site-config.ts",
|
||||
"utils/index.ts",
|
||||
"utils/should-compress-response.ts",
|
||||
"utils/success-banner.ts",
|
||||
"utils/webBuildManifest.ts",
|
||||
"vite/manifestPlugin.ts",
|
||||
"vite/vite.config.ts",
|
||||
],
|
||||
tsconfig = ":tsconfig",
|
||||
visibility = ["//client/web:__subpackages__"],
|
||||
deps = [
|
||||
"//:node_modules/@sentry/esbuild-plugin",
|
||||
"//:node_modules/@types/compression",
|
||||
"//:node_modules/@types/connect-history-api-fallback",
|
||||
"//:node_modules/@types/express",
|
||||
"//:node_modules/@types/lodash",
|
||||
"//:node_modules/@types/node",
|
||||
"//:node_modules/@types/signale",
|
||||
"//:node_modules/@vitejs/plugin-react",
|
||||
"//:node_modules/chalk",
|
||||
"//:node_modules/compression",
|
||||
"//:node_modules/connect-history-api-fallback",
|
||||
"//:node_modules/esbuild",
|
||||
"//:node_modules/express",
|
||||
"//:node_modules/express-static-gzip",
|
||||
"//:node_modules/http-proxy-middleware",
|
||||
"//:node_modules/jsonc-parser",
|
||||
"//:node_modules/lodash",
|
||||
"//:node_modules/signale",
|
||||
"//:node_modules/vite",
|
||||
"//client/web:node_modules/@sourcegraph/build-config",
|
||||
"//client/web:web_lib",
|
||||
],
|
||||
)
|
||||
|
||||
esbuild(
|
||||
name = "vite-config",
|
||||
srcs = [
|
||||
":dev",
|
||||
js_library(
|
||||
name = "esbuild-config-production",
|
||||
srcs = ["esbuild/bazel/esbuild.bazel.production.js"],
|
||||
deps = [
|
||||
"//client/build-config:build-config_lib",
|
||||
"//client/web:node_modules/@sourcegraph/build-config",
|
||||
"//client/web/dev",
|
||||
],
|
||||
entry_point = "vite/vite.config.js",
|
||||
)
|
||||
|
||||
esbuild(
|
||||
name = "esbuild-config-production_bundle",
|
||||
srcs = [
|
||||
":esbuild-config-production",
|
||||
],
|
||||
entry_point = "esbuild/bazel/esbuild.bazel.production.js",
|
||||
external = [
|
||||
# suppress vite require-resolve-not-external warnings
|
||||
"lightningcss",
|
||||
"fsevents",
|
||||
"pnpapi",
|
||||
"../../../../postcss.config",
|
||||
|
||||
# suppress esbuild require-resolve-not-external warnings
|
||||
"esbuild",
|
||||
"@vitejs/plugin-react",
|
||||
"vite",
|
||||
"path-browserify",
|
||||
"monaco-yaml/lib/esm/monaco.contribution",
|
||||
"monaco-yaml/lib/esm/yaml.worker",
|
||||
"rxjs/_esm5/internal/OuterSubscriber",
|
||||
"rxjs/_esm5/internal/util/subscribeToResult",
|
||||
"rxjs/_esm5/internal/util/subscribeToArray",
|
||||
"rxjs/_esm5/internal/Observable",
|
||||
],
|
||||
format = "cjs",
|
||||
platform = "node",
|
||||
sourcemap = False,
|
||||
splitting = False,
|
||||
target = "es2022",
|
||||
visibility = ["//client/web:__subpackages__"],
|
||||
visibility = ["//client:__subpackages__"],
|
||||
deps = [
|
||||
"//:node_modules/@vitejs/plugin-react",
|
||||
"//:node_modules/esbuild",
|
||||
"//:node_modules/path-browserify",
|
||||
"//:node_modules/vite",
|
||||
"//:postcss_config_js",
|
||||
],
|
||||
)
|
||||
|
||||
ts_project(
|
||||
name = "dev_tests",
|
||||
testonly = True,
|
||||
srcs = ["esbuild/manifest.test.ts"],
|
||||
tsconfig = ":tsconfig",
|
||||
deps = [
|
||||
":dev",
|
||||
"//:node_modules/vitest",
|
||||
],
|
||||
)
|
||||
|
||||
vitest_test(
|
||||
name = "test",
|
||||
data = [
|
||||
":dev_tests",
|
||||
],
|
||||
)
|
||||
|
||||
18
client/web/dev/esbuild/bazel/esbuild.bazel.production.js
Normal file
18
client/web/dev/esbuild/bazel/esbuild.bazel.production.js
Normal file
@ -0,0 +1,18 @@
|
||||
// This file is only used by Bazel production builds.
|
||||
|
||||
process.env.NODE_ENV = 'production'
|
||||
|
||||
const { esbuildBuildOptions } = require('../config.js')
|
||||
const { ENVIRONMENT_CONFIG } = require('../../utils/environment-config.js')
|
||||
|
||||
module.exports = {
|
||||
...esbuildBuildOptions(ENVIRONMENT_CONFIG),
|
||||
|
||||
// Unset configuration properties that are provided by Bazel.
|
||||
entryPoints: undefined,
|
||||
bundle: undefined,
|
||||
outdir: undefined,
|
||||
sourcemap: undefined,
|
||||
splitting: undefined,
|
||||
external: undefined,
|
||||
}
|
||||
52
client/web/dev/esbuild/build.ts
Normal file
52
client/web/dev/esbuild/build.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { writeFileSync } from 'fs'
|
||||
|
||||
import * as esbuild from 'esbuild'
|
||||
|
||||
import { buildMonaco } from '@sourcegraph/build-config/src/esbuild/plugins'
|
||||
|
||||
import { ENVIRONMENT_CONFIG } from '../utils'
|
||||
|
||||
import { esbuildBuildOptions } from './config'
|
||||
|
||||
export async function build(): Promise<void> {
|
||||
const buildOptions = esbuildBuildOptions(ENVIRONMENT_CONFIG)
|
||||
|
||||
if (!buildOptions.outdir) {
|
||||
throw new Error('no outdir')
|
||||
}
|
||||
|
||||
const metafile = process.env.ESBUILD_METAFILE
|
||||
const options: esbuild.BuildOptions = {
|
||||
...buildOptions,
|
||||
metafile: Boolean(metafile),
|
||||
}
|
||||
const result = await esbuild.build(options)
|
||||
if (metafile) {
|
||||
writeFileSync(metafile, JSON.stringify(result.metafile), 'utf-8')
|
||||
}
|
||||
if (!ENVIRONMENT_CONFIG.DEV_WEB_BUILDER_OMIT_SLOW_DEPS) {
|
||||
const ctx = await buildMonaco(buildOptions.outdir)
|
||||
await ctx.rebuild()
|
||||
await ctx.dispose()
|
||||
}
|
||||
|
||||
if (process.env.WATCH) {
|
||||
const ctx = await esbuild.context(options)
|
||||
await ctx.watch()
|
||||
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)
|
||||
})
|
||||
}
|
||||
106
client/web/dev/esbuild/config.ts
Normal file
106
client/web/dev/esbuild/config.ts
Normal file
@ -0,0 +1,106 @@
|
||||
import path from 'path'
|
||||
|
||||
import { sentryEsbuildPlugin } from '@sentry/esbuild-plugin'
|
||||
import type * as esbuild from 'esbuild'
|
||||
|
||||
import { ROOT_PATH, STATIC_ASSETS_PATH } from '@sourcegraph/build-config'
|
||||
import {
|
||||
stylePlugin,
|
||||
packageResolutionPlugin,
|
||||
monacoPlugin,
|
||||
RXJS_RESOLUTIONS,
|
||||
buildTimerPlugin,
|
||||
} from '@sourcegraph/build-config/src/esbuild/plugins'
|
||||
import { MONACO_LANGUAGES_AND_FEATURES } from '@sourcegraph/build-config/src/monaco-editor'
|
||||
|
||||
import type { EnvironmentConfig } from '../utils'
|
||||
|
||||
import { manifestPlugin } from './manifestPlugin'
|
||||
|
||||
/**
|
||||
* Creates esbuild build options for the client/web app.
|
||||
*/
|
||||
export function esbuildBuildOptions(ENVIRONMENT_CONFIG: EnvironmentConfig): esbuild.BuildOptions {
|
||||
return {
|
||||
entryPoints: ENVIRONMENT_CONFIG.CODY_APP
|
||||
? [path.join(ROOT_PATH, 'client/web/src/enterprise/app/main.tsx')]
|
||||
: [
|
||||
path.join(ROOT_PATH, 'client/web/src/enterprise/main.tsx'),
|
||||
path.join(ROOT_PATH, 'client/web/src/enterprise/embed/embedMain.tsx'),
|
||||
],
|
||||
bundle: true,
|
||||
minify: ENVIRONMENT_CONFIG.NODE_ENV === 'production',
|
||||
treeShaking: true,
|
||||
|
||||
format: 'esm',
|
||||
logLevel: 'error',
|
||||
jsx: 'automatic',
|
||||
jsxDev: ENVIRONMENT_CONFIG.NODE_ENV === 'development',
|
||||
splitting: !ENVIRONMENT_CONFIG.DEV_WEB_BUILDER_NO_SPLITTING,
|
||||
chunkNames: 'chunks/chunk-[name]-[hash]',
|
||||
entryNames: '[name]-[hash]',
|
||||
outdir: STATIC_ASSETS_PATH,
|
||||
plugins: [
|
||||
stylePlugin,
|
||||
manifestPlugin,
|
||||
packageResolutionPlugin({
|
||||
path: require.resolve('path-browserify'),
|
||||
...RXJS_RESOLUTIONS,
|
||||
...(ENVIRONMENT_CONFIG.DEV_WEB_BUILDER_OMIT_SLOW_DEPS
|
||||
? {
|
||||
// Monaco
|
||||
'@sourcegraph/shared/src/components/MonacoEditor':
|
||||
'@sourcegraph/shared/src/components/NoMonacoEditor',
|
||||
'monaco-editor': '/dev/null',
|
||||
'monaco-editor/esm/vs/editor/editor.api': '/dev/null',
|
||||
'monaco-yaml': '/dev/null',
|
||||
|
||||
// GraphiQL
|
||||
'./api/ApiConsole': path.join(ROOT_PATH, 'client/web/src/api/NoApiConsole.tsx'),
|
||||
'@graphiql/react': '/dev/null',
|
||||
graphiql: '/dev/null',
|
||||
|
||||
// Misc.
|
||||
recharts: '/dev/null',
|
||||
|
||||
// TODO(sqs): force use of same version when developing on opencodegraph because `pnpm link` breaks
|
||||
'@codemirror/state': path.join(ROOT_PATH, 'node_modules/@codemirror/state'),
|
||||
'@codemirror/view': path.join(ROOT_PATH, 'node_modules/@codemirror/view'),
|
||||
react: path.join(ROOT_PATH, 'node_modules/react'),
|
||||
'react-dom': path.join(ROOT_PATH, 'node_modules/react-dom'),
|
||||
'react-dom/client': path.join(ROOT_PATH, 'node_modules/react-dom/client'),
|
||||
}
|
||||
: null),
|
||||
}),
|
||||
ENVIRONMENT_CONFIG.DEV_WEB_BUILDER_OMIT_SLOW_DEPS ? null : monacoPlugin(MONACO_LANGUAGES_AND_FEATURES),
|
||||
buildTimerPlugin,
|
||||
ENVIRONMENT_CONFIG.SENTRY_UPLOAD_SOURCE_MAPS
|
||||
? sentryEsbuildPlugin({
|
||||
org: ENVIRONMENT_CONFIG.SENTRY_ORGANIZATION,
|
||||
project: ENVIRONMENT_CONFIG.SENTRY_PROJECT,
|
||||
authToken: ENVIRONMENT_CONFIG.SENTRY_DOT_COM_AUTH_TOKEN,
|
||||
silent: true,
|
||||
release: { name: `frontend@${ENVIRONMENT_CONFIG.VERSION}` },
|
||||
sourcemaps: { assets: [path.join('dist', '*.map'), path.join('dist', 'chunks', '*.map')] },
|
||||
})
|
||||
: null,
|
||||
].filter((plugin): plugin is esbuild.Plugin => plugin !== null),
|
||||
define: {
|
||||
...Object.fromEntries(
|
||||
Object.entries({ ...ENVIRONMENT_CONFIG, SOURCEGRAPH_API_URL: undefined }).map(([key, value]) => [
|
||||
`process.env.${key}`,
|
||||
JSON.stringify(value === undefined ? null : value),
|
||||
])
|
||||
),
|
||||
global: 'window',
|
||||
},
|
||||
loader: {
|
||||
'.yaml': 'text',
|
||||
'.ttf': 'file',
|
||||
'.woff2': 'file',
|
||||
'.png': 'file',
|
||||
},
|
||||
target: 'esnext',
|
||||
sourcemap: true,
|
||||
}
|
||||
}
|
||||
66
client/web/dev/esbuild/manifest.test.ts
Normal file
66
client/web/dev/esbuild/manifest.test.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import { expect, describe, test } from 'vitest'
|
||||
|
||||
import { type WebBuildManifest, createManifestFromBuildResult } from './manifest'
|
||||
|
||||
describe('createManifestFromBuildResult', () => {
|
||||
test('non-bazel', () =>
|
||||
expect(
|
||||
createManifestFromBuildResult(
|
||||
{ entryPoints: ['src/enterprise/main.tsx', 'src/enterprise/embed/embedMain.tsx'], outdir: 'dist' },
|
||||
{
|
||||
'dist/main-AAA.js': {
|
||||
entryPoint: 'src/enterprise/main.tsx',
|
||||
cssBundle: 'dist/main-BBB.css',
|
||||
imports: [],
|
||||
exports: [],
|
||||
inputs: {},
|
||||
bytes: 123,
|
||||
},
|
||||
'dist/embedMain-CCC.js': {
|
||||
entryPoint: 'src/enterprise/embed/embedMain.tsx',
|
||||
cssBundle: 'dist/embedMain-DDD.css',
|
||||
imports: [],
|
||||
exports: [],
|
||||
inputs: {},
|
||||
bytes: 123,
|
||||
},
|
||||
}
|
||||
)
|
||||
).toEqual({
|
||||
'main.js': 'main-AAA.js',
|
||||
'main.css': 'main-BBB.css',
|
||||
'embed.js': 'embedMain-CCC.js',
|
||||
'embed.css': 'embedMain-DDD.css',
|
||||
} satisfies WebBuildManifest))
|
||||
|
||||
test('bazel', () =>
|
||||
expect(
|
||||
createManifestFromBuildResult(
|
||||
{ entryPoints: ['src/enterprise/main.js', 'src/enterprise/embed/embedMain.js'], outdir: 'dist' },
|
||||
{
|
||||
'client/web/bundle/main-AAA.js': {
|
||||
entryPoint: 'src/enterprise/main.js',
|
||||
cssBundle: 'client/web/bundle/main-BBB.css',
|
||||
imports: [],
|
||||
exports: [],
|
||||
inputs: {},
|
||||
bytes: 123,
|
||||
},
|
||||
'client/web/bundle/embedMain-CCC.js': {
|
||||
entryPoint: 'src/enterprise/embed/embedMain.js',
|
||||
cssBundle: 'client/web/bundle/embedMain-DDD.css',
|
||||
imports: [],
|
||||
exports: [],
|
||||
inputs: {},
|
||||
bytes: 123,
|
||||
},
|
||||
},
|
||||
true
|
||||
)
|
||||
).toEqual({
|
||||
'main.js': 'main-AAA.js',
|
||||
'main.css': 'main-BBB.css',
|
||||
'embed.js': 'embedMain-CCC.js',
|
||||
'embed.css': 'embedMain-DDD.css',
|
||||
} satisfies WebBuildManifest))
|
||||
})
|
||||
90
client/web/dev/esbuild/manifest.ts
Normal file
90
client/web/dev/esbuild/manifest.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import path from 'path'
|
||||
|
||||
import type * as esbuild from 'esbuild'
|
||||
|
||||
export interface WebBuildManifest {
|
||||
/** Main JS bundle. */
|
||||
'main.js': string
|
||||
|
||||
/** Main CSS bundle. */
|
||||
'main.css': string
|
||||
|
||||
/** Embed JS bundle. */
|
||||
'embed.js': string
|
||||
|
||||
/** Embed CSS bundle. */
|
||||
'embed.css': string
|
||||
}
|
||||
|
||||
export const assetPathPrefix = '/.assets'
|
||||
|
||||
export const WEB_BUILD_MANIFEST_FILENAME = 'web.manifest.json'
|
||||
|
||||
/**
|
||||
* Create a web manifest from esbuild build results.
|
||||
*
|
||||
*
|
||||
* @param buildOptions The esbuild options
|
||||
* @param outputs The esbuild metafile outputs
|
||||
* @param inBazel Whether the build is running in Bazel
|
||||
*/
|
||||
export function createManifestFromBuildResult(
|
||||
buildOptions: { entryPoints: string[]; outdir: string },
|
||||
outputs: esbuild.Metafile['outputs'],
|
||||
inBazel = Boolean(process.env.BAZEL_BINDIR)
|
||||
): WebBuildManifest {
|
||||
const outdir = path.relative(process.cwd(), buildOptions.outdir)
|
||||
|
||||
const assetPath = (filePath: string): string => {
|
||||
if (inBazel) {
|
||||
const BAZEL_PATH_PREFIX = /^client\/web\/(app_)?bundle\//
|
||||
if (!BAZEL_PATH_PREFIX.test(filePath)) {
|
||||
throw new Error(`expected filePath to match ${BAZEL_PATH_PREFIX}, got ${filePath}`)
|
||||
}
|
||||
return filePath.replace(BAZEL_PATH_PREFIX, '')
|
||||
}
|
||||
return path.relative(outdir, filePath)
|
||||
}
|
||||
|
||||
if (buildOptions.entryPoints.length !== 2) {
|
||||
throw new Error('expected 2 entryPoints (main and embed)')
|
||||
}
|
||||
const [mainEntrypoint, embedEntrypoint] = buildOptions.entryPoints.map(filePath =>
|
||||
path.relative(process.cwd(), filePath)
|
||||
)
|
||||
|
||||
const manifest: Partial<WebBuildManifest> = {}
|
||||
|
||||
// Find the entrypoint in the output files
|
||||
for (const [asset, output] of Object.entries(outputs)) {
|
||||
if (!output.entryPoint) {
|
||||
continue
|
||||
}
|
||||
if (output.entryPoint.endsWith(mainEntrypoint)) {
|
||||
manifest['main.js'] = assetPath(asset)
|
||||
if (output.cssBundle) {
|
||||
manifest['main.css'] = assetPath(output.cssBundle)
|
||||
}
|
||||
} else if (output.entryPoint.endsWith(embedEntrypoint)) {
|
||||
manifest['embed.js'] = assetPath(asset)
|
||||
if (output.cssBundle) {
|
||||
manifest['embed.css'] = assetPath(output.cssBundle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!manifest['main.js']) {
|
||||
throw new Error('no main.js found in outputs')
|
||||
}
|
||||
if (!manifest['main.css']) {
|
||||
throw new Error('no main.css found in outputs')
|
||||
}
|
||||
if (!manifest['embed.js']) {
|
||||
throw new Error('no embed.js found in outputs')
|
||||
}
|
||||
if (!manifest['embed.css']) {
|
||||
throw new Error('no embed.css found in outputs')
|
||||
}
|
||||
|
||||
return manifest as WebBuildManifest
|
||||
}
|
||||
50
client/web/dev/esbuild/manifestPlugin.ts
Normal file
50
client/web/dev/esbuild/manifestPlugin.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import type * as esbuild from 'esbuild'
|
||||
|
||||
import { WEB_BUILD_MANIFEST_FILENAME, createManifestFromBuildResult } from './manifest'
|
||||
|
||||
/**
|
||||
* An esbuild plugin to write a web.manifest.json file.
|
||||
*/
|
||||
export const manifestPlugin: esbuild.Plugin = {
|
||||
name: 'manifest',
|
||||
setup: build => {
|
||||
const origMetafile = build.initialOptions.metafile
|
||||
build.initialOptions.metafile = true
|
||||
|
||||
build.onEnd(async result => {
|
||||
const { entryPoints } = build.initialOptions
|
||||
const outputs = result?.metafile?.outputs
|
||||
|
||||
if (!origMetafile) {
|
||||
// If we were the only consumers of the metafile, then delete it from the result to
|
||||
// avoid unexpected behavior from other downstream consumers relying on the metafile
|
||||
// despite not actually enabling it in the config.
|
||||
delete result.metafile
|
||||
}
|
||||
|
||||
if (!checkEntryPoints(entryPoints)) {
|
||||
throw new Error('[manifestPlugin] Unexpected entryPoints format')
|
||||
}
|
||||
|
||||
const { outdir } = build.initialOptions
|
||||
if (!outdir) {
|
||||
throw new Error('[manifestPlugin] No outdir found')
|
||||
}
|
||||
|
||||
if (!outputs) {
|
||||
throw new Error('[manifestPlugin] No outputs found')
|
||||
}
|
||||
|
||||
const manifest = createManifestFromBuildResult({ entryPoints, outdir }, outputs)
|
||||
const manifestPath = path.join(outdir, WEB_BUILD_MANIFEST_FILENAME)
|
||||
await fs.promises.writeFile(manifestPath, JSON.stringify(manifest, null, 2))
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
function checkEntryPoints(entryPoints: esbuild.BuildOptions['entryPoints']): entryPoints is string[] {
|
||||
return Array.isArray(entryPoints) && typeof entryPoints[0] === 'string'
|
||||
}
|
||||
101
client/web/dev/esbuild/server.ts
Normal file
101
client/web/dev/esbuild/server.ts
Normal file
@ -0,0 +1,101 @@
|
||||
import path from 'path'
|
||||
|
||||
import { context as esbuildContext } from 'esbuild'
|
||||
import express from 'express'
|
||||
import { createProxyMiddleware } from 'http-proxy-middleware'
|
||||
import signale from 'signale'
|
||||
|
||||
import { STATIC_ASSETS_PATH } from '@sourcegraph/build-config'
|
||||
import { buildMonaco } from '@sourcegraph/build-config/src/esbuild/monacoPlugin'
|
||||
|
||||
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'
|
||||
|
||||
export const esbuildDevelopmentServer = async (
|
||||
listenAddress: { host: string; port: number },
|
||||
configureProxy: (app: express.Application) => void
|
||||
): Promise<void> => {
|
||||
const start = performance.now()
|
||||
|
||||
// One-time build (these files only change when the monaco-editor npm package is changed, which
|
||||
// is rare enough to ignore here).
|
||||
if (!ENVIRONMENT_CONFIG.DEV_WEB_BUILDER_OMIT_SLOW_DEPS) {
|
||||
const ctx = await buildMonaco(STATIC_ASSETS_PATH)
|
||||
await ctx.rebuild()
|
||||
await ctx.dispose()
|
||||
}
|
||||
|
||||
const ctx = await esbuildContext(esbuildBuildOptions(ENVIRONMENT_CONFIG))
|
||||
|
||||
await ctx.watch()
|
||||
|
||||
// Start esbuild's server on a random local port.
|
||||
const { host: esbuildHost, port: esbuildPort } = await ctx.serve({
|
||||
host: 'localhost',
|
||||
servedir: STATIC_ASSETS_PATH,
|
||||
})
|
||||
|
||||
// Start a proxy at :3080. Asset requests (underneath /.assets/) go to esbuild; all other
|
||||
// requests go to the upstream.
|
||||
const proxyApp = express()
|
||||
proxyApp.use(
|
||||
assetPathPrefix,
|
||||
createProxyMiddleware({
|
||||
target: { protocol: 'http:', host: esbuildHost, port: esbuildPort },
|
||||
pathRewrite: { [`^${assetPathPrefix}`]: '' },
|
||||
onProxyRes: (_proxyResponse, request, response) => {
|
||||
// Cache chunks because their filename includes a hash of the content.
|
||||
const isCacheableChunk = path.basename(request.url).startsWith('chunk-')
|
||||
if (isCacheableChunk) {
|
||||
response.setHeader('Cache-Control', 'max-age=3600')
|
||||
}
|
||||
},
|
||||
logLevel: 'error',
|
||||
})
|
||||
)
|
||||
configureProxy(proxyApp)
|
||||
|
||||
const proxyServer = proxyApp.listen(listenAddress)
|
||||
// eslint-disable-next-line @typescript-eslint/return-await
|
||||
return await new Promise<void>((_resolve, reject) => {
|
||||
proxyServer.once('listening', () => {
|
||||
signale.success(`esbuild server is ready after ${Math.round(performance.now() - start)}ms`)
|
||||
printSuccessBanner(['✱ Sourcegraph is really ready now!', `Click here: ${HTTPS_WEB_SERVER_URL}/search`])
|
||||
})
|
||||
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)
|
||||
})
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
import express from 'express'
|
||||
import { createProxyMiddleware } from 'http-proxy-middleware'
|
||||
import signale from 'signale'
|
||||
|
||||
import { ENVIRONMENT_CONFIG, HTTPS_WEB_SERVER_URL } from '../utils/environment-config'
|
||||
import { getIndexHTML, getWebBuildManifest } from '../utils/get-index-html'
|
||||
import { printSuccessBanner } from '../utils/success-banner'
|
||||
|
||||
import { getAPIProxySettings } from './apiProxySettings'
|
||||
|
||||
const { SOURCEGRAPH_API_URL, SOURCEGRAPH_HTTP_PORT } = ENVIRONMENT_CONFIG
|
||||
|
||||
interface DevelopmentServerInit {
|
||||
apiURL: string
|
||||
listenAddress?: { host: string; port: number }
|
||||
}
|
||||
|
||||
async function startDevProxyServer({
|
||||
apiURL,
|
||||
listenAddress = { host: '127.0.0.1', port: SOURCEGRAPH_HTTP_PORT },
|
||||
}: DevelopmentServerInit): Promise<void> {
|
||||
const { proxyRoutes, ...proxyMiddlewareOptions } = getAPIProxySettings({
|
||||
apiURL,
|
||||
getLocalIndexHTML(jsContextScript) {
|
||||
return getIndexHTML({ manifest: getWebBuildManifest(), jsContextScript })
|
||||
},
|
||||
})
|
||||
|
||||
const proxyServer = express()
|
||||
proxyServer.use(createProxyMiddleware(proxyRoutes, proxyMiddlewareOptions))
|
||||
return new Promise<void>((_resolve, reject) => {
|
||||
proxyServer
|
||||
.listen(listenAddress)
|
||||
.once('listening', () => {
|
||||
printSuccessBanner(['✱ Sourcegraph is really ready now!', `Click here: ${HTTPS_WEB_SERVER_URL}`])
|
||||
})
|
||||
.once('error', error => reject(error))
|
||||
})
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
signale.start('Starting dev server.', ENVIRONMENT_CONFIG)
|
||||
|
||||
if (!SOURCEGRAPH_API_URL) {
|
||||
throw new Error(
|
||||
'development.server.ts only supports *web-standalone* usage (must set SOURCEGRAPH_API_URL env var)'
|
||||
)
|
||||
}
|
||||
|
||||
startDevProxyServer({
|
||||
apiURL: SOURCEGRAPH_API_URL,
|
||||
}).catch(error => {
|
||||
signale.error(error)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
41
client/web/dev/server/development.server.ts
Normal file
41
client/web/dev/server/development.server.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { createProxyMiddleware } from 'http-proxy-middleware'
|
||||
import signale from 'signale'
|
||||
|
||||
import { esbuildDevelopmentServer } from '../esbuild/server'
|
||||
import { ENVIRONMENT_CONFIG, getAPIProxySettings, getIndexHTML, getWebBuildManifest } from '../utils'
|
||||
|
||||
const { SOURCEGRAPH_API_URL, SOURCEGRAPH_HTTP_PORT } = ENVIRONMENT_CONFIG
|
||||
|
||||
interface DevelopmentServerInit {
|
||||
apiURL: string
|
||||
}
|
||||
|
||||
async function startDevelopmentServer(): Promise<void> {
|
||||
signale.start('Starting dev server.', ENVIRONMENT_CONFIG)
|
||||
|
||||
if (!SOURCEGRAPH_API_URL) {
|
||||
throw new Error('development.server.ts only supports *web-standalone* usage')
|
||||
}
|
||||
|
||||
await startEsbuildDevelopmentServer({
|
||||
apiURL: SOURCEGRAPH_API_URL,
|
||||
})
|
||||
}
|
||||
|
||||
async function startEsbuildDevelopmentServer({ apiURL }: DevelopmentServerInit): Promise<void> {
|
||||
const { proxyRoutes, ...proxyMiddlewareOptions } = getAPIProxySettings({
|
||||
apiURL,
|
||||
getLocalIndexHTML(jsContextScript) {
|
||||
return getIndexHTML({ manifestFile: getWebBuildManifest(), jsContextScript })
|
||||
},
|
||||
})
|
||||
|
||||
await esbuildDevelopmentServer({ host: '0.0.0.0', port: SOURCEGRAPH_HTTP_PORT }, app => {
|
||||
app.use(createProxyMiddleware(proxyRoutes, proxyMiddlewareOptions))
|
||||
app.get(/.*/, (_request, response) => {
|
||||
response.send(getIndexHTML({ manifestFile: getWebBuildManifest() }))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
startDevelopmentServer().catch(error => signale.error(error))
|
||||
64
client/web/dev/server/production.server.ts
Normal file
64
client/web/dev/server/production.server.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import chalk from 'chalk'
|
||||
import historyApiFallback from 'connect-history-api-fallback'
|
||||
import express, { type RequestHandler } from 'express'
|
||||
import expressStaticGzip from 'express-static-gzip'
|
||||
import { createProxyMiddleware } from 'http-proxy-middleware'
|
||||
import signale from 'signale'
|
||||
|
||||
import {
|
||||
getAPIProxySettings,
|
||||
ENVIRONMENT_CONFIG,
|
||||
HTTP_WEB_SERVER_URL,
|
||||
HTTPS_WEB_SERVER_URL,
|
||||
getWebBuildManifest,
|
||||
STATIC_INDEX_PATH,
|
||||
getIndexHTML,
|
||||
} from '../utils'
|
||||
|
||||
const { SOURCEGRAPH_API_URL, SOURCEGRAPH_HTTP_PORT, STATIC_ASSETS_PATH } = ENVIRONMENT_CONFIG
|
||||
|
||||
function startProductionServer(): void {
|
||||
if (!SOURCEGRAPH_API_URL) {
|
||||
throw new Error('production.server.ts only supports *web-standalone* usage')
|
||||
}
|
||||
|
||||
signale.await('Starting production server', ENVIRONMENT_CONFIG)
|
||||
|
||||
const app = express()
|
||||
|
||||
// Serve index.html in place of any 404 responses.
|
||||
app.use(historyApiFallback() as RequestHandler)
|
||||
|
||||
// Serve build artifacts.
|
||||
app.use(
|
||||
'/.assets',
|
||||
expressStaticGzip(STATIC_ASSETS_PATH, {
|
||||
enableBrotli: true,
|
||||
orderPreference: ['br', 'gz'],
|
||||
index: false,
|
||||
})
|
||||
)
|
||||
|
||||
const { proxyRoutes, ...proxyConfig } = getAPIProxySettings({
|
||||
apiURL: SOURCEGRAPH_API_URL,
|
||||
...(ENVIRONMENT_CONFIG.WEB_BUILDER_SERVE_INDEX && {
|
||||
getLocalIndexHTML(jsContextScript) {
|
||||
const manifestFile = getWebBuildManifest()
|
||||
return getIndexHTML({ manifestFile, jsContextScript })
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
||||
// Proxy API requests to the `process.env.SOURCEGRAPH_API_URL`.
|
||||
app.use(proxyRoutes, createProxyMiddleware(proxyConfig))
|
||||
|
||||
// Redirect remaining routes to index.html
|
||||
app.get('/*', (_request, response) => response.sendFile(STATIC_INDEX_PATH))
|
||||
|
||||
app.listen(SOURCEGRAPH_HTTP_PORT, () => {
|
||||
signale.info(`Production HTTP server is ready at ${chalk.blue.bold(HTTP_WEB_SERVER_URL)}`)
|
||||
signale.success(`Production HTTPS server is ready at ${chalk.blue.bold(HTTPS_WEB_SERVER_URL)}`)
|
||||
})
|
||||
}
|
||||
|
||||
startProductionServer()
|
||||
@ -3,6 +3,6 @@
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
},
|
||||
"include": ["vite", "server", "utils", "../src/jscontext.ts", "../src/graphql-operations.ts"],
|
||||
"include": ["esbuild", "server", "utils", "../src/jscontext.ts", "../src/graphql-operations.ts"],
|
||||
"exclude": ["vitest.config.ts"],
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ import path from 'path'
|
||||
|
||||
import { ROOT_PATH } from '@sourcegraph/build-config'
|
||||
|
||||
export const DEV_SERVER_LISTEN_ADDR = { host: '127.0.0.1', port: 3080 } as const
|
||||
export const DEV_SERVER_PROXY_TARGET_ADDR = { host: '127.0.0.1', port: 3081 } as const
|
||||
export const DEFAULT_SITE_CONFIG_PATH = path.resolve(ROOT_PATH, '../dev-private/enterprise/dev/site-config.json')
|
||||
export const assetPathPrefix = '/.assets'
|
||||
|
||||
export const WEB_BUILD_MANIFEST_FILENAME = 'vite-manifest.json'
|
||||
|
||||
@ -3,20 +3,19 @@ import * as zlib from 'zlib'
|
||||
|
||||
import { type Options, responseInterceptor } from 'http-proxy-middleware'
|
||||
|
||||
import { ENVIRONMENT_CONFIG, HTTPS_WEB_SERVER_URL } from '../utils/environment-config'
|
||||
import { STREAMING_ENDPOINTS } from '../utils/should-compress-response'
|
||||
import { ENVIRONMENT_CONFIG, HTTPS_WEB_SERVER_URL } from './environment-config'
|
||||
import { STREAMING_ENDPOINTS } from './should-compress-response'
|
||||
|
||||
// One of the API routes: "/-/sign-in".
|
||||
const PROXY_ROUTES = ['/.api', '/search/stream', '/-', '/.auth']
|
||||
|
||||
interface GetAPIProxySettingsOptions {
|
||||
apiURL: string
|
||||
|
||||
/**
|
||||
* Use the remote `window.context` as the basis for our local `window.context`, so that most
|
||||
* parts of the remote site's config are applied here.
|
||||
* If provided, the server will proxy requests to index.html
|
||||
* and inject the `window.context` defined there into the local template.
|
||||
*/
|
||||
getLocalIndexHTML: (jsContextScript?: string) => string
|
||||
getLocalIndexHTML?: (jsContextScript?: string) => string
|
||||
}
|
||||
|
||||
interface ProxySettings extends Options {
|
||||
@ -27,8 +26,8 @@ export function getAPIProxySettings(options: GetAPIProxySettingsOptions): ProxyS
|
||||
const { apiURL, getLocalIndexHTML } = options
|
||||
|
||||
return {
|
||||
// Proxy '' (for index.html).
|
||||
proxyRoutes: [...PROXY_ROUTES, ''],
|
||||
// Enable index.html proxy if `getLocalIndexHTML` is provided.
|
||||
proxyRoutes: [...PROXY_ROUTES, ...(getLocalIndexHTML ? [''] : [])],
|
||||
target: apiURL,
|
||||
// Do not SSL certificate.
|
||||
secure: false,
|
||||
@ -53,6 +52,7 @@ export function getAPIProxySettings(options: GetAPIProxySettingsOptions): ProxyS
|
||||
// Extract remote `window.context` from the HTML response and inject it into
|
||||
// the index.html generated by `getLocalIndexHTML`.
|
||||
if (
|
||||
getLocalIndexHTML &&
|
||||
// router.go is not up to date with client routes and still serves index.html with 404
|
||||
(proxyRes.statusCode === 200 || proxyRes.statusCode === 404) &&
|
||||
proxyRes.headers['content-type'] &&
|
||||
@ -76,7 +76,7 @@ export function getAPIProxySettings(options: GetAPIProxySettingsOptions): ProxyS
|
||||
// Don't log proxy errors, these usually just contain
|
||||
// ECONNRESET errors caused by the browser cancelling
|
||||
// requests. This should not be needed to actually debug something.
|
||||
logLevel: 'debug',
|
||||
logLevel: 'silent',
|
||||
onProxyReqWs: (_proxyRequest, _request, socket) =>
|
||||
socket.on('error', error => console.error('WebSocket proxy error:', error)),
|
||||
}
|
||||
@ -142,7 +142,6 @@ function conditionalResponseInterceptor(
|
||||
res.setHeader('content-type', 'text/event-stream')
|
||||
const _proxyRes = decompress(proxyRes, proxyRes.headers['content-encoding'])
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
_proxyRes.on('data', (chunk: any) => res.write(chunk))
|
||||
_proxyRes.on('end', () => {
|
||||
res.end()
|
||||
@ -2,11 +2,9 @@ import { readFileSync } from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import type { SourcegraphContext } from '../../src/jscontext'
|
||||
import { assetPathPrefix, WEB_BUILD_MANIFEST_FILENAME, type WebBuildManifest } from '../esbuild/manifest'
|
||||
|
||||
import { WEB_BUILD_MANIFEST_FILENAME, assetPathPrefix } from './constants'
|
||||
import { createJsContext } from './create-js-context'
|
||||
import { ENVIRONMENT_CONFIG, HTTPS_WEB_SERVER_URL } from './environment-config'
|
||||
import type { WebBuildManifest } from './webBuildManifest'
|
||||
import { createJsContext, ENVIRONMENT_CONFIG, HTTPS_WEB_SERVER_URL } from '.'
|
||||
|
||||
const { STATIC_ASSETS_PATH } = ENVIRONMENT_CONFIG
|
||||
|
||||
@ -17,7 +15,7 @@ export const getWebBuildManifest = (): WebBuildManifest =>
|
||||
JSON.parse(readFileSync(WEB_BUILD_MANIFEST_PATH, 'utf-8')) as WebBuildManifest
|
||||
|
||||
interface GetHTMLPageOptions {
|
||||
manifest: WebBuildManifest
|
||||
manifestFile: WebBuildManifest
|
||||
/**
|
||||
* Used to inject dummy `window.context` in integration tests.
|
||||
*/
|
||||
@ -35,10 +33,11 @@ interface GetHTMLPageOptions {
|
||||
* Note: This page should be kept as close as possible to `app.html` to avoid any inconsistencies
|
||||
* between our development server and the actual production server.
|
||||
*/
|
||||
export function getIndexHTML({ manifest, jsContext, jsContextScript }: GetHTMLPageOptions): string {
|
||||
if (!manifest.assets['src/enterprise/main']) {
|
||||
throw new Error('entrypoint asset not found')
|
||||
}
|
||||
export function getIndexHTML(options: GetHTMLPageOptions): string {
|
||||
const { manifestFile, jsContext, jsContextScript } = options
|
||||
|
||||
const { 'main.js': mainJS, 'main.css': mainCSS } = manifestFile
|
||||
|
||||
return `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
@ -48,19 +47,14 @@ export function getIndexHTML({ manifest, jsContext, jsContextScript }: GetHTMLPa
|
||||
<meta name="viewport" content="width=device-width, viewport-fit=cover" />
|
||||
<meta name="referrer" content="origin-when-cross-origin"/>
|
||||
<meta name="color-scheme" content="light dark"/>
|
||||
<link rel="stylesheet" href="${assetPathPrefix}/${mainCSS}">
|
||||
${
|
||||
ENVIRONMENT_CONFIG.SOURCEGRAPHDOTCOM_MODE
|
||||
? '<script src="https://js.sentry-cdn.com/ae2f74442b154faf90b5ff0f7cd1c618.min.js" crossorigin="anonymous"></script>'
|
||||
: ''
|
||||
}
|
||||
${
|
||||
manifest.assets['src/enterprise/main']?.css
|
||||
? `<link rel="stylesheet" href="${assetPathPrefix}/${manifest.assets['src/enterprise/main']?.css}">`
|
||||
: ''
|
||||
}
|
||||
</head>
|
||||
<body>
|
||||
${manifest.devInjectHTML ?? ''}
|
||||
<div id="root"></div>
|
||||
<script>
|
||||
${
|
||||
@ -74,7 +68,7 @@ export function getIndexHTML({ manifest, jsContext, jsContextScript }: GetHTMLPa
|
||||
}
|
||||
</script>
|
||||
|
||||
<script src="${assetPathPrefix}/${manifest.assets['src/enterprise/main'].js}" type="module"></script>
|
||||
<script src="${assetPathPrefix}/${mainJS}" type="module"></script>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
7
client/web/dev/utils/index.ts
Normal file
7
client/web/dev/utils/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export * from './constants'
|
||||
export * from './create-js-context'
|
||||
export * from './environment-config'
|
||||
export * from './get-api-proxy-settings'
|
||||
export * from './get-index-html'
|
||||
export * from './should-compress-response'
|
||||
export * from './success-banner'
|
||||
@ -1,19 +0,0 @@
|
||||
type Entry = 'src/enterprise/main' | 'src/enterprise/embed/embedMain' | 'src/enterprise/app/main'
|
||||
|
||||
export function isEntry(value: string): value is Entry {
|
||||
return ['src/enterprise/main', 'src/enterprise/embed/embedMain', 'src/enterprise/app/main'].includes(value)
|
||||
}
|
||||
|
||||
export interface WebBuildManifest {
|
||||
/** Base URL for asset paths. */
|
||||
url?: string
|
||||
|
||||
/**
|
||||
* A map of entrypoint (such as "src/enterprise/main" with no extension) to its JavaScript and
|
||||
* CSS assets.
|
||||
*/
|
||||
assets: Partial<Record<Entry, { js: string; css?: string }>>
|
||||
|
||||
/** Additional HTML <script> tags to inject in dev mode. */
|
||||
devInjectHTML?: string
|
||||
}
|
||||
@ -1,159 +0,0 @@
|
||||
import { writeFileSync } from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import os from 'os'
|
||||
|
||||
import { Plugin, normalizePath } from 'vite'
|
||||
|
||||
import { WebBuildManifest, isEntry } from '../utils/webBuildManifest'
|
||||
|
||||
export interface ManifestPluginConfig {
|
||||
fileName: string
|
||||
}
|
||||
|
||||
function createSimplifyPath(root: string, base: string): (path: string) => string {
|
||||
return path => {
|
||||
path = normalizePath(path)
|
||||
|
||||
if (root !== '/' && path.startsWith(root)) {
|
||||
path = path.slice(root.length)
|
||||
}
|
||||
|
||||
if (path.startsWith(base)) {
|
||||
path = path.slice(base.length)
|
||||
}
|
||||
|
||||
if (path[0] === '/') {
|
||||
path = path.slice(1)
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Vite plugin that writes a JSON manifest with the JavaScript and CSS output filenames for each
|
||||
* entrypoint. This JSON manifest is read by our backend to inject the right scripts and styles into
|
||||
* the page.
|
||||
*/
|
||||
export function manifestPlugin(pluginConfig: ManifestPluginConfig): Plugin {
|
||||
let root: string | undefined
|
||||
|
||||
return {
|
||||
name: 'manifest',
|
||||
enforce: 'post',
|
||||
configResolved(config): void {
|
||||
root = config.root
|
||||
},
|
||||
|
||||
// Run in dev mode.
|
||||
configureServer({ config, httpServer }): void {
|
||||
httpServer?.once('listening', () => {
|
||||
// Resolve URL.
|
||||
const { root: _root, base } = config
|
||||
const root = normalizePath(_root)
|
||||
const protocol = config.server.https ? 'https' : 'http'
|
||||
const host = resolveHost(config.server.host)
|
||||
const port = config.server.port
|
||||
const url = `${protocol}://${host}:${port}${base}`
|
||||
config.server.origin = `${protocol}://${host}:${port}`
|
||||
|
||||
// Resolve inputs.
|
||||
const simplifyPath = createSimplifyPath(root, base)
|
||||
const inputOptions = config.build.rollupOptions?.input ?? {}
|
||||
const inputs =
|
||||
typeof inputOptions === 'string'
|
||||
? { [inputOptions]: inputOptions }
|
||||
: Array.isArray(inputOptions)
|
||||
? Object.fromEntries(inputOptions.map(path => [path, path]))
|
||||
: inputOptions
|
||||
|
||||
const manifest: WebBuildManifest = {
|
||||
url: url,
|
||||
assets: {},
|
||||
devInjectHTML: `
|
||||
<script type="module">
|
||||
import RefreshRuntime from "${url}@react-refresh"
|
||||
RefreshRuntime.injectIntoGlobalHook(window)
|
||||
window.$RefreshReg$ = () => {}
|
||||
window.$RefreshSig$ = () => (type) => type
|
||||
window.__vite_plugin_react_preamble_installed__ = true
|
||||
</script>
|
||||
<script type="module" src="${url}@vite/client"></script>`,
|
||||
}
|
||||
for (const [entryAlias, entryPath] of Object.entries(inputs)) {
|
||||
const relativeEntryAlias = noExt(normalizePath(path.relative(root, entryAlias)))
|
||||
if (isEntry(relativeEntryAlias)) {
|
||||
manifest.assets[relativeEntryAlias] = {
|
||||
js: simplifyPath(entryPath),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const outputDir = path.resolve(config.root, config.build.outDir)
|
||||
writeFileSync(path.resolve(outputDir, pluginConfig.fileName), JSON.stringify(manifest, null, 2))
|
||||
})
|
||||
},
|
||||
|
||||
// Run when generating the production bundle.
|
||||
generateBundle(_options, bundle): void {
|
||||
if (root === undefined) {
|
||||
throw new Error('no config')
|
||||
}
|
||||
|
||||
const manifest: WebBuildManifest = { assets: {} }
|
||||
for (const chunk of Object.values(bundle)) {
|
||||
if (chunk.type === 'chunk' && chunk.isEntry && chunk.facadeModuleId) {
|
||||
let entryAlias = noExt(normalizePath(path.relative(root, chunk.facadeModuleId)))
|
||||
const css = chunk.viteMetadata ? Array.from(chunk.viteMetadata?.importedCss.values()) : []
|
||||
if (css.length >= 2) {
|
||||
throw new Error('multiple CSS asset files not supported')
|
||||
}
|
||||
|
||||
if (isEntry(entryAlias)) {
|
||||
manifest.assets[entryAlias] = {
|
||||
js: chunk.fileName,
|
||||
css: css.length === 1 ? css[0] : undefined,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.emitFile({ fileName: pluginConfig.fileName, type: 'asset', source: JSON.stringify(manifest, null, 2) })
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function noExt(path: string): string {
|
||||
return path.replace(/\.(tsx|js)$/, '')
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve host if is passed as `true`
|
||||
*
|
||||
* Copied from https://github.com/vitejs/vite/blob/d4dcdd1ffaea79ecf8a9fc78cdbe311f0d801fb5/packages/vite/src/node/logger.ts#L197
|
||||
*/
|
||||
function resolveHost(host?: string | boolean): string {
|
||||
if (!host) return 'localhost'
|
||||
|
||||
if (host === true) {
|
||||
const nInterface = Object.values(os.networkInterfaces())
|
||||
.flatMap(nInterface => nInterface ?? [])
|
||||
.filter(
|
||||
detail =>
|
||||
detail &&
|
||||
detail.address &&
|
||||
// Node < v18
|
||||
((typeof detail.family === 'string' && detail.family === 'IPv4') ||
|
||||
// Node >= v18
|
||||
(typeof detail.family === 'number' && (detail as any).family === 4))
|
||||
)
|
||||
.filter(detail => {
|
||||
return detail.address !== '127.0.0.1'
|
||||
})[0]
|
||||
|
||||
if (!nInterface) return 'localhost'
|
||||
|
||||
return nInterface.address
|
||||
}
|
||||
|
||||
return host
|
||||
}
|
||||
@ -1,128 +0,0 @@
|
||||
import path from 'path'
|
||||
|
||||
import react from '@vitejs/plugin-react'
|
||||
import { UserConfig, defineConfig, mergeConfig } from 'vite'
|
||||
|
||||
import { ENVIRONMENT_CONFIG } from '../utils/environment-config'
|
||||
|
||||
import { manifestPlugin } from './manifestPlugin'
|
||||
|
||||
/** Whether we're running in Bazel. */
|
||||
const BAZEL = !!process.env.BAZEL_BINDIR
|
||||
|
||||
const repoRoot = BAZEL ? process.cwd() : path.join(__dirname, '../../../..')
|
||||
const clientWebRoot = path.join(repoRoot, 'client/web')
|
||||
|
||||
export default defineConfig(() => {
|
||||
let config: UserConfig = {
|
||||
plugins: [react(), manifestPlugin({ fileName: 'vite-manifest.json' })],
|
||||
build: {
|
||||
rollupOptions: {
|
||||
input: ENVIRONMENT_CONFIG.CODY_APP
|
||||
? ['src/enterprise/app/main.tsx']
|
||||
: ['src/enterprise/main.tsx', 'src/enterprise/embed/embedMain.tsx']
|
||||
.map(BAZEL ? toJSExtension : String)
|
||||
.map(p => path.join(clientWebRoot, p)),
|
||||
},
|
||||
sourcemap: true,
|
||||
|
||||
// modulepreload is supported widely enough now (https://caniuse.com/link-rel-modulepreload)
|
||||
// and is only relevant for local dev.
|
||||
modulePreload: { polyfill: false },
|
||||
|
||||
emptyOutDir: false, // client/web/dist has static assets checked in
|
||||
},
|
||||
base: '/.assets',
|
||||
root: clientWebRoot,
|
||||
publicDir: 'dist',
|
||||
assetsInclude: ['**/*.yaml'],
|
||||
define: {
|
||||
...Object.fromEntries(
|
||||
Object.entries({ ...ENVIRONMENT_CONFIG, SOURCEGRAPH_API_URL: undefined }).map(([key, value]) => [
|
||||
`process.env.${key}`,
|
||||
JSON.stringify(value === undefined ? null : value),
|
||||
])
|
||||
),
|
||||
},
|
||||
optimizeDeps: {
|
||||
exclude: [
|
||||
// Without addings this Vite throws an error
|
||||
'linguist-languages',
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
path: require.resolve('path-browserify'),
|
||||
},
|
||||
mainFields: ['browser', 'module', 'main'],
|
||||
},
|
||||
css: {
|
||||
devSourcemap: true,
|
||||
preprocessorOptions: {
|
||||
scss: {
|
||||
includePaths: [
|
||||
// Our scss files and scss files in client/* often import global styles via @import 'wildcard/src/...'
|
||||
// Adding '..' as load path causes scss to look for these imports in the client folder.
|
||||
// (without it scss @import paths are always relative to the importing file)
|
||||
path.join(clientWebRoot, '..'),
|
||||
],
|
||||
},
|
||||
},
|
||||
modules: {
|
||||
localsConvention: 'camelCaseOnly',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if (BAZEL) {
|
||||
// TODO(sqs): dedupe with client/web-sveltekit
|
||||
|
||||
// Merge settings necessary to make the build work with bazel
|
||||
config = mergeConfig(config, {
|
||||
resolve: {
|
||||
alias: [
|
||||
// When using Bazel, @sourcegraph/* dependencies will refer to the built packages.
|
||||
// These do not contain the source *.module.scss files but still contain import statements
|
||||
// that reference *.scss files. Processing them with vite throws an error unless we
|
||||
// update the imports to reference the corresponding *.css files instead.
|
||||
// Additionally our own source files might reference *.module.scss files, which we also want
|
||||
// to rewrite.
|
||||
{
|
||||
find: /^(.+)\.module\.scss$/,
|
||||
replacement: '$1.module.css',
|
||||
customResolver(source, importer, options) {
|
||||
// The this.resolve(...) part is taken from the @rollup/plugin-alias implementation. Without
|
||||
// it it appears the bundler tries to resolve relative module IDs to the current working
|
||||
// directory.
|
||||
return source.includes('@sourcegraph') || importer?.includes('@sourcegraph/')
|
||||
? this.resolve(source, importer, { skipSelf: true, ...options }).then(
|
||||
resolved => resolved || { id: source }
|
||||
)
|
||||
: null
|
||||
},
|
||||
},
|
||||
|
||||
// Assume all other *.scss files have been built.
|
||||
{
|
||||
find: /^(.+)\.scss(\?.*)?$/,
|
||||
replacement: '$1.css$2',
|
||||
},
|
||||
],
|
||||
},
|
||||
ssr: {
|
||||
// By default vite treats dependencies that are links to other packages in the monorepo as source code
|
||||
// and processes them as well.
|
||||
// In a bazel sandbox however all @sourcegraph/* dependencies are built packages and thus not processed
|
||||
// by vite without this additional setting.
|
||||
// We have to process those files to apply certain "fixes", such as aliases defined in svelte.config.js.
|
||||
noExternal: [/@sourcegraph\/.*/],
|
||||
},
|
||||
} satisfies UserConfig)
|
||||
}
|
||||
|
||||
return config
|
||||
})
|
||||
|
||||
function toJSExtension(path: string): string {
|
||||
return path.replace(/\.ts$/, '.js').replace(/\.tsx$/, '.js')
|
||||
}
|
||||
17
client/web/dist/assets.go
vendored
17
client/web/dist/assets.go
vendored
@ -17,17 +17,15 @@ import (
|
||||
//
|
||||
//go:embed all:*
|
||||
var assetsFS embed.FS
|
||||
var afs fs.FS = assetsFS
|
||||
|
||||
var (
|
||||
afs fs.FS = assetsFS
|
||||
assetsHTTPFS http.FileSystem
|
||||
)
|
||||
var Assets http.FileSystem
|
||||
|
||||
var (
|
||||
webBuildManifestOnce sync.Once
|
||||
assetsOnce sync.Once
|
||||
webBuildManifest *assets.WebBuildManifest
|
||||
webBuildManifestErr error
|
||||
assetsOnce sync.Once
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -39,7 +37,7 @@ type Provider struct{}
|
||||
|
||||
func (p Provider) LoadWebBuildManifest() (*assets.WebBuildManifest, error) {
|
||||
webBuildManifestOnce.Do(func() {
|
||||
f, err := afs.Open("vite-manifest.json")
|
||||
f, err := afs.Open("web.manifest.json")
|
||||
if err != nil {
|
||||
webBuildManifestErr = errors.Wrap(err, "read manifest file")
|
||||
return
|
||||
@ -66,7 +64,7 @@ func (p Provider) Assets() http.FileSystem {
|
||||
// it's already containing other files known to Bazel. So instead we put those into the dist folder.
|
||||
// If we do detect a dist folder when running this code, we immediately substitute the root to that dist folder.
|
||||
//
|
||||
// Therefore, this code works with both the traditional build approach and when built with Bazel.
|
||||
// Therefore, this code works with both the traditionnal build approach and when built with Bazel.
|
||||
if _, err := assetsFS.ReadDir("dist"); err == nil {
|
||||
var err error
|
||||
afs, err = fs.Sub(assetsFS, "dist")
|
||||
@ -74,7 +72,8 @@ func (p Provider) Assets() http.FileSystem {
|
||||
panic("incorrect embed")
|
||||
}
|
||||
}
|
||||
assetsHTTPFS = http.FS(afs)
|
||||
Assets = http.FS(afs)
|
||||
})
|
||||
return assetsHTTPFS
|
||||
|
||||
return Assets
|
||||
}
|
||||
|
||||
@ -16,10 +16,11 @@
|
||||
"test:regression:onboarding": "pnpm task:mocha ./src/regression/onboarding.test.ts",
|
||||
"test:regression:search": "pnpm task:mocha ./src/regression/search.test.ts",
|
||||
"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/devProxyServer.ts",
|
||||
"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",
|
||||
"generate": "pnpm -w run generate",
|
||||
"dev": "ts-node -T ../../node_modules/vite/bin/vite.js dev --config vite.config.ts",
|
||||
"build": "pnpm run generate && ts-node -T ../../node_modules/vite/bin/vite.js build --config vite.config.ts",
|
||||
"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)'",
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
.dialog {
|
||||
top: 3rem;
|
||||
transform: translate(-50%, 0);
|
||||
max-height: calc(100vh - 6rem);
|
||||
width: 48rem;
|
||||
max-width: 95%;
|
||||
overflow: hidden;
|
||||
width: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@ -2,10 +2,6 @@ import React, { useCallback, useMemo, useState } from 'react'
|
||||
|
||||
import classNames from 'classnames'
|
||||
import { getYear, parseISO } from 'date-fns'
|
||||
|
||||
// for polyfill
|
||||
import 'events'
|
||||
|
||||
import {
|
||||
Area,
|
||||
ComposedChart,
|
||||
|
||||
@ -37,3 +37,9 @@ window.addEventListener('DOMContentLoaded', async () => {
|
||||
logger.error('Failed to initialize the app shell', error)
|
||||
}
|
||||
})
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
new EventSource('/.assets/esbuild').addEventListener('change', () => {
|
||||
location.reload()
|
||||
})
|
||||
}
|
||||
|
||||
@ -70,7 +70,7 @@ export const createWebIntegrationTestContext = async ({
|
||||
.intercept((request, response) => {
|
||||
response.type('text/html').send(
|
||||
getIndexHTML({
|
||||
manifest: getWebBuildManifest(),
|
||||
manifestFile: getWebBuildManifest(),
|
||||
jsContext: { ...jsContext, ...customContext },
|
||||
})
|
||||
)
|
||||
|
||||
@ -2,13 +2,7 @@
|
||||
// Don't remove the empty lines between these imports.
|
||||
import './initZones'
|
||||
|
||||
/**
|
||||
* The @opentelemetry/context-zone import enables zone.js which patches global web API
|
||||
* modules. You can find a list of the patched modules here:
|
||||
* https://github.com/angular/angular/blob/main/packages/zone.js/MODULE.md
|
||||
*/
|
||||
|
||||
import { ZoneContextManager } from '@opentelemetry/context-zone'
|
||||
import type { ZoneContextManager } from '@opentelemetry/context-zone'
|
||||
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'
|
||||
import { type InstrumentationOption, registerInstrumentations } from '@opentelemetry/instrumentation'
|
||||
import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch'
|
||||
@ -60,6 +54,17 @@ export function initOpenTelemetry(): void {
|
||||
provider.addSpanProcessor(new BatchSpanProcessor(consoleExporter))
|
||||
}
|
||||
|
||||
/**
|
||||
* This import enables zone.js which patches global web API modules.
|
||||
* You can find a list of the patched modules here:
|
||||
* https://github.com/angular/angular/blob/main/packages/zone.js/MODULE.md
|
||||
*
|
||||
* It's added with the `require` statement to avoid polluting stack traces in
|
||||
* the development environment when OpenTelemetry is disabled.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
|
||||
const ZoneContextManager = require('@opentelemetry/context-zone').ZoneContextManager
|
||||
|
||||
provider.register({
|
||||
contextManager: new ZoneContextManager() as ZoneContextManager,
|
||||
})
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
.logo {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
margin: 0 !important;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.divider {
|
||||
|
||||
@ -361,36 +361,14 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
|
||||
// Manually configure the MonacoEnvironment for the Monaco editor.
|
||||
if (!window.MonacoEnvironment) {
|
||||
window.MonacoEnvironment = {
|
||||
// @ts-ignore
|
||||
async getWorker(_, label) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// In dev mode, we need to use a blob URL and a module worker because (1) the worker
|
||||
// is loaded cross-origin and (2) the worker is not bundled and only module workers
|
||||
// support `import` statements.
|
||||
const workerModule =
|
||||
label === 'json'
|
||||
? new URL('monaco-editor/esm/vs/language/json/json.worker.js', import.meta.url)
|
||||
: new URL('monaco-editor/esm/vs/editor/editor.worker.js', import.meta.url)
|
||||
const source = `import ${JSON.stringify(workerModule.toString())}`
|
||||
const workerBlobUrl = URL.createObjectURL(new Blob([source], { type: 'text/javascript' }))
|
||||
return new Worker(workerBlobUrl, { type: 'module' })
|
||||
}
|
||||
|
||||
let worker: any
|
||||
getWorkerUrl(_moduleId: string, label: string): string {
|
||||
if (label === 'json') {
|
||||
// @ts-ignore
|
||||
worker = await import('monaco-editor/esm/vs/language/json/json.worker?worker')
|
||||
} else {
|
||||
// @ts-ignore
|
||||
worker = await import('monaco-editor/esm/vs/editor/editor.worker?worker')
|
||||
return window.context.assetsRoot + '/scripts/json.worker.bundle.js'
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
||||
return new worker.default()
|
||||
return window.context.assetsRoot + '/scripts/editor.worker.bundle.js'
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,7 +51,6 @@
|
||||
"include": ["src", "scripts", "__mocks__", "./src/**/*.json"],
|
||||
"exclude": [
|
||||
"vitest.config.ts",
|
||||
"vite.config.ts",
|
||||
"dev",
|
||||
"../../node_modules",
|
||||
"./node_modules",
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
import viteConfig from './dev/vite/vite.config'
|
||||
|
||||
export default viteConfig
|
||||
@ -28,7 +28,7 @@
|
||||
{{end}}
|
||||
{{end}}
|
||||
<title>{{.Title}}</title>
|
||||
{{if .Manifest.Assets.Main.CSS}}<link rel="stylesheet" href="{{assetURL (printf "%s%s" .Manifest.URL .Manifest.Assets.Main.CSS)}}">{{end}}
|
||||
{{if .Manifest.MainCSSBundlePath}}<link rel="stylesheet" href="{{assetURL .Manifest.MainCSSBundlePath}}">{{end}}
|
||||
<link id='sourcegraph-chrome-webstore-item' rel="chrome-webstore-item" href="https://chrome.google.com/webstore/detail/dgjhfomjieaadpoljlnidmbgkdffpack">
|
||||
<link rel="search" href="/opensearch.xml" type="application/opensearchdescription+xml" title="Sourcegraph Search">
|
||||
{{if .PreloadedAssets}}
|
||||
@ -86,7 +86,6 @@
|
||||
|
||||
{{ end }}
|
||||
{{.Injected.BodyTop}}
|
||||
{{.ManifestDevInjectHTML}}
|
||||
<div id="root">
|
||||
{{ if .Context.RedirectUnsupportedBrowser }}
|
||||
<script ignore-csp>
|
||||
@ -108,7 +107,7 @@
|
||||
<br>
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
<script src="{{assetURL (printf "%s%s" .Manifest.URL .Manifest.Assets.Main.JS)}}" type="module"></script>
|
||||
<script src="{{assetURL .Manifest.MainJSBundlePath}}" type="module"></script>
|
||||
{{.Injected.BodyBottom}}
|
||||
</body>
|
||||
|
||||
|
||||
@ -86,8 +86,7 @@ type Common struct {
|
||||
|
||||
PreloadedAssets *[]PreloadedAsset
|
||||
|
||||
Manifest *assets.WebBuildManifest
|
||||
ManifestDevInjectHTML template.HTML
|
||||
Manifest *assets.WebBuildManifest
|
||||
|
||||
WebBuilderDevServer bool // whether the web builder dev server is running (WEB_BUILDER_DEV_SERVER env var)
|
||||
|
||||
@ -183,10 +182,6 @@ func newCommon(w http.ResponseWriter, r *http.Request, db database.DB, title str
|
||||
WebBuilderDevServer: webBuilderDevServer,
|
||||
}
|
||||
|
||||
if env.InsecureDev && manifest.DevInjectHTML != "" {
|
||||
common.ManifestDevInjectHTML = template.HTML(manifest.DevInjectHTML)
|
||||
}
|
||||
|
||||
if enableHTMLInject != "true" {
|
||||
common.Injected = InjectedHTML{}
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/cmd/frontend/internal/app/assetsutil"
|
||||
@ -39,9 +38,6 @@ var (
|
||||
// Functions that are exposed to templates.
|
||||
var funcMap = template.FuncMap{
|
||||
"assetURL": func(filePath string) string {
|
||||
if strings.HasPrefix(filePath, "http://") {
|
||||
return filePath
|
||||
}
|
||||
return assetsutil.URL(filePath).String()
|
||||
},
|
||||
"version": func(fp string) (string, error) {
|
||||
|
||||
@ -1,11 +1,20 @@
|
||||
{
|
||||
http_port 3081
|
||||
auto_https disable_redirects
|
||||
}
|
||||
|
||||
# Caddy (tls :3443) -> sourcegraph-frontend (:3080)
|
||||
# A bit of monstrosity, since we need to reverse proxy via the web builder dev server which then
|
||||
# reverse proxies to us on HTTP.
|
||||
#
|
||||
# Caddy (tls :3443) -> web builder dev server (:3080) -> Caddy (:3081) -> sourcegraph-frontend (:3082)
|
||||
{$SOURCEGRAPH_HTTPS_DOMAIN}:{$SOURCEGRAPH_HTTPS_PORT} {
|
||||
tls internal
|
||||
reverse_proxy 127.0.0.1:3080 {
|
||||
lb_try_duration 60s
|
||||
}
|
||||
}
|
||||
|
||||
# Caddy (:3081) -> sourcegraph-frontend (:3082)
|
||||
:3081 {
|
||||
reverse_proxy 127.0.0.1:3082
|
||||
}
|
||||
|
||||
19
dev/esbuild.bzl
Normal file
19
dev/esbuild.bzl
Normal file
@ -0,0 +1,19 @@
|
||||
load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory")
|
||||
load("@aspect_rules_esbuild//esbuild:defs.bzl", "esbuild")
|
||||
|
||||
def esbuild_web_app(name, **kwargs):
|
||||
bundle_name = "%s_bundle" % name
|
||||
|
||||
esbuild(
|
||||
name = bundle_name,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
copy_to_directory(
|
||||
name = name,
|
||||
# flatten static assets
|
||||
# https://docs.aspect.build/rules/aspect_bazel_lib/docs/copy_to_directory/#root_paths
|
||||
root_paths = ["client/web/dist", "client/web/%s" % bundle_name],
|
||||
srcs = ["//client/web/dist/img:img", ":%s" % bundle_name],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
@ -1,225 +0,0 @@
|
||||
"Vite rule"
|
||||
|
||||
load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_file_to_bin_action", "copy_files_to_bin_actions")
|
||||
load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory")
|
||||
load("@aspect_bazel_lib//lib:directory_path.bzl", "directory_path")
|
||||
load("@aspect_rules_js//js:defs.bzl", "js_binary")
|
||||
load("@aspect_rules_js//js:libs.bzl", "js_lib_helpers")
|
||||
load("@aspect_rules_js//js:providers.bzl", "JsInfo", "js_info")
|
||||
load("@bazel_skylib//lib:paths.bzl", "paths")
|
||||
|
||||
_ATTRS = {
|
||||
"config": attr.label(
|
||||
mandatory = True,
|
||||
allow_single_file = True,
|
||||
doc = """Configuration file used for Vite""",
|
||||
),
|
||||
"data": js_lib_helpers.JS_LIBRARY_DATA_ATTR,
|
||||
"deps": attr.label_list(
|
||||
default = [],
|
||||
doc = "A list of direct dependencies that are required to build the bundle",
|
||||
providers = [JsInfo],
|
||||
),
|
||||
"entry_points": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = """The bundle's entry points""",
|
||||
),
|
||||
"srcs": attr.label_list(
|
||||
allow_files = True,
|
||||
default = [],
|
||||
doc = """Source files to be made available to Vite""",
|
||||
),
|
||||
"tsconfig": attr.label(
|
||||
mandatory = True,
|
||||
allow_single_file = True,
|
||||
doc = """TypeScript configuration file used by Vite""",
|
||||
),
|
||||
"vite_js_bin": attr.label(
|
||||
executable = True,
|
||||
doc = "Override the default vite executable",
|
||||
cfg = "exec",
|
||||
),
|
||||
"env": attr.string_dict(),
|
||||
}
|
||||
|
||||
def _bin_relative_path(ctx, file):
|
||||
prefix = ctx.bin_dir.path + "/"
|
||||
if file.path.startswith(prefix):
|
||||
return file.path[len(prefix):]
|
||||
|
||||
# Since file.path is relative to execroot, go up with ".." starting from
|
||||
# ctx.bin_dir until we reach execroot, then join that with the file path.
|
||||
up = "/".join([".." for _ in ctx.bin_dir.path.split("/")])
|
||||
return up + "/" + file.path
|
||||
|
||||
def _output_relative_path(f):
|
||||
"Give the path from bazel-out/[arch]/bin to the given File object"
|
||||
if f.short_path.startswith("../"):
|
||||
return "external/" + f.short_path[3:]
|
||||
return f.short_path
|
||||
|
||||
def _filter_js(files):
|
||||
return [f for f in files if f.extension == "js" or f.extension == "mjs"]
|
||||
|
||||
def _vite_project_impl(ctx):
|
||||
input_sources = copy_files_to_bin_actions(ctx, ctx.files.srcs)
|
||||
entry_points = copy_files_to_bin_actions(ctx, _filter_js(ctx.files.entry_points))
|
||||
inputs = entry_points + input_sources + ctx.files.deps
|
||||
|
||||
args = ctx.actions.args()
|
||||
|
||||
output_sources = [getattr(ctx.outputs, o) for o in dir(ctx.outputs)]
|
||||
output_sources.append(ctx.actions.declare_directory(ctx.label.name))
|
||||
args.add_all(["--outDir", output_sources[0].basename])
|
||||
|
||||
config_file = copy_file_to_bin_action(ctx, ctx.file.config)
|
||||
args.add_all(["--config", _output_relative_path(config_file)])
|
||||
inputs.append(config_file)
|
||||
|
||||
env = {
|
||||
"BAZEL_BINDIR": ctx.bin_dir.path,
|
||||
}
|
||||
for (key, value) in ctx.attr.env.items():
|
||||
env[key] = value
|
||||
|
||||
args.add("build")
|
||||
|
||||
ctx.actions.run(
|
||||
executable = ctx.executable.vite_js_bin,
|
||||
arguments = [args],
|
||||
inputs = depset(
|
||||
inputs,
|
||||
transitive = [js_lib_helpers.gather_files_from_js_providers(
|
||||
targets = ctx.attr.srcs + ctx.attr.deps,
|
||||
include_transitive_sources = True,
|
||||
include_declarations = False,
|
||||
include_npm_linked_packages = True,
|
||||
)],
|
||||
),
|
||||
outputs = output_sources,
|
||||
progress_message = "Building Vite project %s" % (" ".join([_bin_relative_path(ctx, entry_point) for entry_point in entry_points])),
|
||||
mnemonic = "Vite",
|
||||
env = env,
|
||||
)
|
||||
|
||||
npm_linked_packages = js_lib_helpers.gather_npm_linked_packages(
|
||||
srcs = ctx.attr.srcs,
|
||||
deps = [],
|
||||
)
|
||||
|
||||
npm_package_store_deps = js_lib_helpers.gather_npm_package_store_deps(
|
||||
# Since we're bundling, only propagate `data` npm packages to the direct dependencies of
|
||||
# downstream linked `npm_package` targets instead of the common `data` and `deps` pattern.
|
||||
targets = ctx.attr.data,
|
||||
)
|
||||
|
||||
output_sources_depset = depset(output_sources)
|
||||
|
||||
runfiles = js_lib_helpers.gather_runfiles(
|
||||
ctx = ctx,
|
||||
sources = output_sources_depset,
|
||||
data = ctx.attr.data,
|
||||
# Since we're bundling, we don't propagate any transitive runfiles from dependencies
|
||||
deps = [],
|
||||
)
|
||||
|
||||
return [
|
||||
DefaultInfo(
|
||||
files = output_sources_depset,
|
||||
runfiles = runfiles,
|
||||
),
|
||||
js_info(
|
||||
npm_linked_package_files = npm_linked_packages.direct_files,
|
||||
npm_linked_packages = npm_linked_packages.direct,
|
||||
npm_package_store_deps = npm_package_store_deps,
|
||||
sources = output_sources_depset,
|
||||
# Since we're bundling, we don't propagate linked npm packages from dependencies since
|
||||
# they are bundled and the dependencies are dropped. If a subset of linked npm
|
||||
# dependencies are not bundled it is up the the user to re-specify these in `data` if
|
||||
# they are runtime dependencies to progagate to binary rules or `srcs` if they are to be
|
||||
# propagated to downstream build targets.
|
||||
transitive_npm_linked_package_files = npm_linked_packages.direct_files,
|
||||
transitive_npm_linked_packages = npm_linked_packages.direct,
|
||||
# Since we're bundling, we don't propagate any transitive sources from dependencies
|
||||
transitive_sources = output_sources_depset,
|
||||
),
|
||||
]
|
||||
|
||||
lib = struct(
|
||||
attrs = _ATTRS,
|
||||
implementation = _vite_project_impl,
|
||||
toolchains = [
|
||||
"@rules_nodejs//nodejs:toolchain_type",
|
||||
],
|
||||
)
|
||||
|
||||
_vite_project = rule(
|
||||
implementation = _vite_project_impl,
|
||||
attrs = _ATTRS,
|
||||
toolchains = lib.toolchains,
|
||||
doc = """\
|
||||
Runs Vite in Bazel
|
||||
""",
|
||||
)
|
||||
|
||||
def vite_project(name, config, data = [], deps = [], entry_points = [], srcs = [], env = {}, **kwargs):
|
||||
"""Runs Vite in Bazel.
|
||||
|
||||
Args:
|
||||
|
||||
name: A unique name for this rule.
|
||||
|
||||
config: The Vite config file.
|
||||
|
||||
data: Runtime dependencies that are passed to the Vite build.
|
||||
|
||||
deps: Other npm dependencies that are passed to the Vite build.
|
||||
|
||||
entry_points: The entry points to build.
|
||||
|
||||
srcs: Other sources that are passed to the Vite build.
|
||||
|
||||
env: Environment variables to pass to the Vite build.
|
||||
|
||||
**kwargs: Additional arguments
|
||||
"""
|
||||
vite_js_entry_point = "_{}_vite_js_entry_point".format(name)
|
||||
node_modules = "//:node_modules"
|
||||
directory_path(
|
||||
name = vite_js_entry_point,
|
||||
directory = "{}/vite/dir".format(node_modules),
|
||||
path = "bin/vite.js",
|
||||
)
|
||||
|
||||
vite_js_bin = "_{}_vite_js_bin".format(name)
|
||||
js_binary(
|
||||
name = vite_js_bin,
|
||||
data = ["%s/vite" % node_modules],
|
||||
entry_point = vite_js_entry_point,
|
||||
)
|
||||
|
||||
_vite_project(
|
||||
name = name,
|
||||
config = config,
|
||||
data = data,
|
||||
deps = deps,
|
||||
entry_points = entry_points,
|
||||
srcs = srcs,
|
||||
vite_js_bin = vite_js_bin,
|
||||
env = env,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def vite_web_app(name, **kwargs):
|
||||
bundle_name = "%s_bundle" % name
|
||||
|
||||
vite_project(name = bundle_name, **kwargs)
|
||||
|
||||
copy_to_directory(
|
||||
name = name,
|
||||
# flatten static assets
|
||||
# https://docs.aspect.build/rules/aspect_bazel_lib/docs/copy_to_directory/#root_paths
|
||||
root_paths = ["client/web/dist", "client/web/%s" % bundle_name],
|
||||
srcs = ["//client/web/dist/img:img", ":%s" % bundle_name],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
@ -55,6 +55,7 @@ Available commandsets in `sg.config.yaml`:
|
||||
* qdrant
|
||||
* single-program
|
||||
* web-standalone
|
||||
* web-standalone-prod
|
||||
* web-sveltekit-standalone
|
||||
|
||||
```sh
|
||||
@ -141,6 +142,7 @@ Available commands in `sg.config.yaml`:
|
||||
* telemetry-gateway
|
||||
* web-integration-build-prod: Build production web application for integration tests
|
||||
* web-integration-build: Build development web application for integration tests
|
||||
* web-standalone-http-prod: Standalone web frontend (production) with API proxy to a configurable URL
|
||||
* web-standalone-http: Standalone web frontend (dev) with API proxy to a configurable URL
|
||||
* web-sveltekit-prod-watch: Builds the prod version of the SvelteKit web app and rebuilds on changes
|
||||
* web-sveltekit-standalone: Standalone SvelteKit web frontend (dev) with API proxy to a configurable URL
|
||||
|
||||
@ -176,7 +176,7 @@
|
||||
"@types/uuid": "8.0.1",
|
||||
"@types/whatwg-url": "^11.0.3",
|
||||
"@types/yauzl": "^2.9.2",
|
||||
"@vitejs/plugin-react": "^4.1.0",
|
||||
"@vitejs/plugin-react": "^3.1.0",
|
||||
"abort-controller": "^3.0.0",
|
||||
"autoprefixer": "^10.2.1",
|
||||
"axe-core": "^4.4.1",
|
||||
@ -260,7 +260,7 @@
|
||||
"typed-scss-modules": "^4.1.1",
|
||||
"typescript": "^5.0.2",
|
||||
"utc-version": "^2.0.2",
|
||||
"vite": "^4.5.0",
|
||||
"vite": "^4.1.4",
|
||||
"vite-plugin-turbosnap": "^1.0.3",
|
||||
"vitest": "1.0.0-beta.4",
|
||||
"vitest-fetch-mock": "^0.2.2",
|
||||
|
||||
150
pnpm-lock.yaml
150
pnpm-lock.yaml
@ -574,7 +574,7 @@ importers:
|
||||
version: 7.4.6(react-dom@18.1.0)(react@18.1.0)
|
||||
'@storybook/builder-vite':
|
||||
specifier: ^7.4.6
|
||||
version: 7.4.6(typescript@5.2.2)(vite@4.5.0)
|
||||
version: 7.4.6(typescript@5.2.2)(vite@4.4.7)
|
||||
'@storybook/cli':
|
||||
specifier: ^7.4.6
|
||||
version: 7.4.6
|
||||
@ -595,7 +595,7 @@ importers:
|
||||
version: 7.4.6(react-dom@18.1.0)(react@18.1.0)(typescript@5.2.2)
|
||||
'@storybook/react-vite':
|
||||
specifier: ^7.4.6
|
||||
version: 7.4.6(react-dom@18.1.0)(react@18.1.0)(typescript@5.2.2)(vite@4.5.0)
|
||||
version: 7.4.6(react-dom@18.1.0)(react@18.1.0)(typescript@5.2.2)(vite@4.4.7)
|
||||
'@storybook/theming':
|
||||
specifier: ^7.4.6
|
||||
version: 7.4.6(react-dom@18.1.0)(react@18.1.0)
|
||||
@ -798,8 +798,8 @@ importers:
|
||||
specifier: ^2.9.2
|
||||
version: 2.10.0
|
||||
'@vitejs/plugin-react':
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0(vite@4.5.0)
|
||||
specifier: ^3.1.0
|
||||
version: 3.1.0(vite@4.4.7)
|
||||
abort-controller:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
@ -1047,8 +1047,8 @@ importers:
|
||||
specifier: ^2.0.2
|
||||
version: 2.0.2
|
||||
vite:
|
||||
specifier: ^4.5.0
|
||||
version: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
specifier: ^4.1.4
|
||||
version: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite-plugin-turbosnap:
|
||||
specifier: ^1.0.3
|
||||
version: 1.0.3
|
||||
@ -1486,7 +1486,7 @@ importers:
|
||||
version: 7.4.6(react-dom@18.2.0)(react@18.2.0)
|
||||
'@storybook/addon-svelte-csf':
|
||||
specifier: ^3.0.7
|
||||
version: 3.0.7(@storybook/svelte@7.2.0)(@storybook/theming@7.4.6)(@sveltejs/vite-plugin-svelte@2.4.2)(svelte@4.1.1)(vite@4.5.0)
|
||||
version: 3.0.7(@storybook/svelte@7.2.0)(@storybook/theming@7.4.6)(@sveltejs/vite-plugin-svelte@2.4.2)(svelte@4.1.1)(vite@4.4.7)
|
||||
'@storybook/blocks':
|
||||
specifier: ^7.2.0
|
||||
version: 7.4.6(@types/react-dom@18.0.2)(@types/react@18.0.8)(react-dom@18.2.0)(react@18.2.0)
|
||||
@ -1495,7 +1495,7 @@ importers:
|
||||
version: 7.2.0(svelte@4.1.1)
|
||||
'@storybook/sveltekit':
|
||||
specifier: ^7.2.0
|
||||
version: 7.2.0(svelte@4.1.1)(typescript@5.2.2)(vite@4.5.0)
|
||||
version: 7.2.0(svelte@4.1.1)(typescript@5.2.2)(vite@4.4.7)
|
||||
'@storybook/testing-library':
|
||||
specifier: 0.2.0
|
||||
version: 0.2.0
|
||||
@ -1507,7 +1507,7 @@ importers:
|
||||
version: 2.0.3(@sveltejs/kit@1.22.3)
|
||||
'@sveltejs/kit':
|
||||
specifier: ^1.22.3
|
||||
version: 1.22.3(svelte@4.1.1)(vite@4.5.0)
|
||||
version: 1.22.3(svelte@4.1.1)(vite@4.4.7)
|
||||
'@testing-library/svelte':
|
||||
specifier: ^4.0.3
|
||||
version: 4.0.3(svelte@4.1.1)
|
||||
@ -1570,10 +1570,10 @@ importers:
|
||||
version: 2.1.0
|
||||
vite:
|
||||
specifier: ^4.4.7
|
||||
version: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
version: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite-plugin-inspect:
|
||||
specifier: ^0.7.35
|
||||
version: 0.7.35(vite@4.5.0)
|
||||
version: 0.7.35(vite@4.4.7)
|
||||
vitest:
|
||||
specifier: ^0.33.0
|
||||
version: 0.33.0(happy-dom@12.10.1)(jsdom@22.1.0)(sass@1.32.4)
|
||||
@ -5228,7 +5228,7 @@ packages:
|
||||
'@types/yargs': 17.0.23
|
||||
chalk: 4.1.2
|
||||
|
||||
/@joshwooding/vite-plugin-react-docgen-typescript@0.2.1(typescript@5.2.2)(vite@4.5.0):
|
||||
/@joshwooding/vite-plugin-react-docgen-typescript@0.2.1(typescript@5.2.2)(vite@4.4.7):
|
||||
resolution: {integrity: sha512-ou4ZJSXMMWHqGS4g8uNRbC5TiTWxAgQZiVucoUrOCWuPrTbkpJbmVyIi9jU72SBry7gQtuMEDp4YR8EEXAg7VQ==}
|
||||
peerDependencies:
|
||||
typescript: '>= 4.3.x'
|
||||
@ -5242,7 +5242,7 @@ packages:
|
||||
magic-string: 0.27.0
|
||||
react-docgen-typescript: 2.2.2(typescript@5.2.2)
|
||||
typescript: 5.2.2
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
dev: true
|
||||
|
||||
/@jridgewell/gen-mapping@0.3.3:
|
||||
@ -6253,6 +6253,7 @@ packages:
|
||||
/@playwright/test@1.25.0:
|
||||
resolution: {integrity: sha512-j4EZhTTQI3dBeWblE21EV//swwmBtOpIrLdOIJIRv4uqsLdHgBg1z+JtTg+AeC5o2bAXIE26kDNW5A0TimG8Bg==}
|
||||
engines: {node: '>=14'}
|
||||
deprecated: Please update to the latest version of Playwright to test up-to-date browsers.
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@types/node': 20.8.0
|
||||
@ -9105,7 +9106,7 @@ packages:
|
||||
- '@types/react-dom'
|
||||
dev: true
|
||||
|
||||
/@storybook/addon-svelte-csf@3.0.7(@storybook/svelte@7.2.0)(@storybook/theming@7.4.6)(@sveltejs/vite-plugin-svelte@2.4.2)(svelte@4.1.1)(vite@4.5.0):
|
||||
/@storybook/addon-svelte-csf@3.0.7(@storybook/svelte@7.2.0)(@storybook/theming@7.4.6)(@sveltejs/vite-plugin-svelte@2.4.2)(svelte@4.1.1)(vite@4.4.7):
|
||||
resolution: {integrity: sha512-T7KYWlhIs3G2N4r0UPawCCnHnYUWyg2rUMIfi/HLVYODsnqG7rJmK3ZAvtEgd1sFST0gRNBu13NIyH3YYUnA7A==}
|
||||
peerDependencies:
|
||||
'@storybook/svelte': ^7.0.0
|
||||
@ -9125,12 +9126,12 @@ packages:
|
||||
'@babel/runtime': 7.23.1
|
||||
'@storybook/svelte': 7.2.0(svelte@4.1.1)
|
||||
'@storybook/theming': 7.4.6(react-dom@18.2.0)(react@18.2.0)
|
||||
'@sveltejs/vite-plugin-svelte': 2.4.2(svelte@4.1.1)(vite@4.5.0)
|
||||
'@sveltejs/vite-plugin-svelte': 2.4.2(svelte@4.1.1)(vite@4.4.7)
|
||||
dedent: 1.5.1
|
||||
fs-extra: 11.1.1
|
||||
magic-string: 0.30.5
|
||||
svelte: 4.1.1
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
transitivePeerDependencies:
|
||||
- babel-plugin-macros
|
||||
dev: true
|
||||
@ -9430,7 +9431,7 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@storybook/builder-vite@7.2.0(typescript@5.2.2)(vite@4.5.0):
|
||||
/@storybook/builder-vite@7.2.0(typescript@5.2.2)(vite@4.4.7):
|
||||
resolution: {integrity: sha512-YmTtyIMxWKaFOsJaLU5rGHukvt37LjVvW6QEAEK1Clbl1f3QUNSEGJwVYLRYO7xQvhymBF4JMa8N5NSc1+xSEQ==}
|
||||
peerDependencies:
|
||||
'@preact/preset-vite': '*'
|
||||
@ -9463,15 +9464,15 @@ packages:
|
||||
magic-string: 0.30.5
|
||||
remark-external-links: 8.0.0
|
||||
remark-slug: 6.1.0
|
||||
rollup: 3.29.4
|
||||
rollup: 3.26.3
|
||||
typescript: 5.2.2
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@storybook/builder-vite@7.4.6(typescript@5.2.2)(vite@4.5.0):
|
||||
/@storybook/builder-vite@7.4.6(typescript@5.2.2)(vite@4.4.7):
|
||||
resolution: {integrity: sha512-xV9STYK+TkqWWTf2ydm6jx+7P70fjD2UPd1XTUw08uKszIjhuuxk+bG/OF5R1E25mPunAKXm6kBFh351AKejBg==}
|
||||
peerDependencies:
|
||||
'@preact/preset-vite': '*'
|
||||
@ -9504,9 +9505,9 @@ packages:
|
||||
magic-string: 0.30.5
|
||||
remark-external-links: 8.0.0
|
||||
remark-slug: 6.1.0
|
||||
rollup: 3.29.4
|
||||
rollup: 3.26.3
|
||||
typescript: 5.2.2
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
@ -10232,7 +10233,7 @@ packages:
|
||||
react-dom: 18.1.0(react@18.1.0)
|
||||
dev: true
|
||||
|
||||
/@storybook/react-vite@7.4.6(react-dom@18.1.0)(react@18.1.0)(typescript@5.2.2)(vite@4.5.0):
|
||||
/@storybook/react-vite@7.4.6(react-dom@18.1.0)(react@18.1.0)(typescript@5.2.2)(vite@4.4.7):
|
||||
resolution: {integrity: sha512-jkjnrf3FxzR5wcmebXRPflrsM4WIDjWyW/NVFJwxi5PeIOk7fE7/QAPrm4NFRUu2Q7DeuH3oLKsw8bigvUI9RA==}
|
||||
engines: {node: '>=16'}
|
||||
peerDependencies:
|
||||
@ -10240,17 +10241,17 @@ packages:
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
vite: ^3.0.0 || ^4.0.0
|
||||
dependencies:
|
||||
'@joshwooding/vite-plugin-react-docgen-typescript': 0.2.1(typescript@5.2.2)(vite@4.5.0)
|
||||
'@joshwooding/vite-plugin-react-docgen-typescript': 0.2.1(typescript@5.2.2)(vite@4.4.7)
|
||||
'@rollup/pluginutils': 5.0.2
|
||||
'@storybook/builder-vite': 7.4.6(typescript@5.2.2)(vite@4.5.0)
|
||||
'@storybook/builder-vite': 7.4.6(typescript@5.2.2)(vite@4.4.7)
|
||||
'@storybook/react': 7.4.6(react-dom@18.1.0)(react@18.1.0)(typescript@5.2.2)
|
||||
'@vitejs/plugin-react': 3.1.0(vite@4.5.0)
|
||||
'@vitejs/plugin-react': 3.1.0(vite@4.4.7)
|
||||
ast-types: 0.14.2
|
||||
magic-string: 0.30.5
|
||||
react: 18.1.0
|
||||
react-docgen: 6.0.0-alpha.3
|
||||
react-dom: 18.1.0(react@18.1.0)
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
transitivePeerDependencies:
|
||||
- '@preact/preset-vite'
|
||||
- encoding
|
||||
@ -10354,22 +10355,22 @@ packages:
|
||||
react-dom: 18.1.0(react@18.1.0)
|
||||
dev: true
|
||||
|
||||
/@storybook/svelte-vite@7.2.0(svelte@4.1.1)(typescript@5.2.2)(vite@4.5.0):
|
||||
/@storybook/svelte-vite@7.2.0(svelte@4.1.1)(typescript@5.2.2)(vite@4.4.7):
|
||||
resolution: {integrity: sha512-iGaaY64xWjMDzECpu+qw82Y0LtwZYD5FimCEmx1gjPLiv0TJDRVcpBvtGNzEf6ztevastRQs8HEDxv1H1xjCkQ==}
|
||||
engines: {node: ^14.18 || >=16}
|
||||
peerDependencies:
|
||||
svelte: ^3.0.0 || ^4.0.0
|
||||
vite: ^3.0.0 || ^4.0.0
|
||||
dependencies:
|
||||
'@storybook/builder-vite': 7.2.0(typescript@5.2.2)(vite@4.5.0)
|
||||
'@storybook/builder-vite': 7.2.0(typescript@5.2.2)(vite@4.4.7)
|
||||
'@storybook/node-logger': 7.2.0
|
||||
'@storybook/svelte': 7.2.0(svelte@4.1.1)
|
||||
'@sveltejs/vite-plugin-svelte': 2.4.2(svelte@4.1.1)(vite@4.5.0)
|
||||
'@sveltejs/vite-plugin-svelte': 2.4.2(svelte@4.1.1)(vite@4.4.7)
|
||||
magic-string: 0.30.5
|
||||
svelte: 4.1.1
|
||||
sveltedoc-parser: 4.2.1
|
||||
ts-dedent: 2.2.0
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
transitivePeerDependencies:
|
||||
- '@preact/preset-vite'
|
||||
- encoding
|
||||
@ -10399,18 +10400,18 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@storybook/sveltekit@7.2.0(svelte@4.1.1)(typescript@5.2.2)(vite@4.5.0):
|
||||
/@storybook/sveltekit@7.2.0(svelte@4.1.1)(typescript@5.2.2)(vite@4.4.7):
|
||||
resolution: {integrity: sha512-JyhRofOywpIElqgpc6NR6xMyBgop5bVSnzeDl9aJk0VTVGFvQOEco85f9FHJmlhhBpFr7g+Nal7hzsqg5vkdPg==}
|
||||
engines: {node: ^14.18 || >=16}
|
||||
peerDependencies:
|
||||
svelte: ^3.0.0 || ^4.0.0
|
||||
vite: ^4.0.0
|
||||
dependencies:
|
||||
'@storybook/builder-vite': 7.2.0(typescript@5.2.2)(vite@4.5.0)
|
||||
'@storybook/builder-vite': 7.2.0(typescript@5.2.2)(vite@4.4.7)
|
||||
'@storybook/svelte': 7.2.0(svelte@4.1.1)
|
||||
'@storybook/svelte-vite': 7.2.0(svelte@4.1.1)(typescript@5.2.2)(vite@4.5.0)
|
||||
'@storybook/svelte-vite': 7.2.0(svelte@4.1.1)(typescript@5.2.2)(vite@4.4.7)
|
||||
svelte: 4.1.1
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
transitivePeerDependencies:
|
||||
- '@preact/preset-vite'
|
||||
- encoding
|
||||
@ -10505,7 +10506,7 @@ packages:
|
||||
resolution: {integrity: sha512-jwoA/TIp+U8Vz868aQT+XfoAw6qFrtn2HbZlTfwNWZsUhPFlMsGrwIVEpWqBWIoe6WITU/lNw3BuRmxul+wvAQ==}
|
||||
dependencies:
|
||||
'@storybook/channels': 7.2.0
|
||||
'@types/babel__core': 7.20.3
|
||||
'@types/babel__core': 7.1.20
|
||||
'@types/express': 4.17.11
|
||||
file-system-cache: 2.3.0
|
||||
dev: true
|
||||
@ -10514,7 +10515,7 @@ packages:
|
||||
resolution: {integrity: sha512-6QLXtMVsFZFpzPkdGWsu/iuc8na9dnS67AMOBKm5qCLPwtUJOYkwhMdFRSSeJthLRpzV7JLAL8Kwvl7MFP3QSw==}
|
||||
dependencies:
|
||||
'@storybook/channels': 7.4.6
|
||||
'@types/babel__core': 7.20.3
|
||||
'@types/babel__core': 7.1.20
|
||||
'@types/express': 4.17.11
|
||||
file-system-cache: 2.3.0
|
||||
dev: true
|
||||
@ -10524,7 +10525,7 @@ packages:
|
||||
peerDependencies:
|
||||
'@sveltejs/kit': ^1.0.0
|
||||
dependencies:
|
||||
'@sveltejs/kit': 1.22.3(svelte@4.1.1)(vite@4.5.0)
|
||||
'@sveltejs/kit': 1.22.3(svelte@4.1.1)(vite@4.4.7)
|
||||
import-meta-resolve: 3.0.0
|
||||
dev: true
|
||||
|
||||
@ -10533,10 +10534,10 @@ packages:
|
||||
peerDependencies:
|
||||
'@sveltejs/kit': ^1.5.0
|
||||
dependencies:
|
||||
'@sveltejs/kit': 1.22.3(svelte@4.1.1)(vite@4.5.0)
|
||||
'@sveltejs/kit': 1.22.3(svelte@4.1.1)(vite@4.4.7)
|
||||
dev: true
|
||||
|
||||
/@sveltejs/kit@1.22.3(svelte@4.1.1)(vite@4.5.0):
|
||||
/@sveltejs/kit@1.22.3(svelte@4.1.1)(vite@4.4.7):
|
||||
resolution: {integrity: sha512-IpHD5wvuoOIHYaHQUBJ1zERD2Iz+fB/rBXhXjl8InKw6X4VKE9BSus+ttHhE7Ke+Ie9ecfilzX8BnWE3FeQyng==}
|
||||
engines: {node: ^16.14 || >=18}
|
||||
hasBin: true
|
||||
@ -10545,7 +10546,7 @@ packages:
|
||||
svelte: ^3.54.0 || ^4.0.0-next.0
|
||||
vite: ^4.0.0
|
||||
dependencies:
|
||||
'@sveltejs/vite-plugin-svelte': 2.4.2(svelte@4.1.1)(vite@4.5.0)
|
||||
'@sveltejs/vite-plugin-svelte': 2.4.2(svelte@4.1.1)(vite@4.4.7)
|
||||
'@types/cookie': 0.5.1
|
||||
cookie: 0.5.0
|
||||
devalue: 4.3.2
|
||||
@ -10558,12 +10559,12 @@ packages:
|
||||
sirv: 2.0.3
|
||||
svelte: 4.1.1
|
||||
undici: 5.22.1
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@sveltejs/vite-plugin-svelte-inspector@1.0.3(@sveltejs/vite-plugin-svelte@2.4.2)(svelte@4.1.1)(vite@4.5.0):
|
||||
/@sveltejs/vite-plugin-svelte-inspector@1.0.3(@sveltejs/vite-plugin-svelte@2.4.2)(svelte@4.1.1)(vite@4.4.7):
|
||||
resolution: {integrity: sha512-Khdl5jmmPN6SUsVuqSXatKpQTMIifoQPDanaxC84m9JxIibWvSABJyHpyys0Z+1yYrxY5TTEQm+6elh0XCMaOA==}
|
||||
engines: {node: ^14.18.0 || >= 16}
|
||||
peerDependencies:
|
||||
@ -10571,30 +10572,30 @@ packages:
|
||||
svelte: ^3.54.0 || ^4.0.0
|
||||
vite: ^4.0.0
|
||||
dependencies:
|
||||
'@sveltejs/vite-plugin-svelte': 2.4.2(svelte@4.1.1)(vite@4.5.0)
|
||||
'@sveltejs/vite-plugin-svelte': 2.4.2(svelte@4.1.1)(vite@4.4.7)
|
||||
debug: 4.3.4
|
||||
svelte: 4.1.1
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@sveltejs/vite-plugin-svelte@2.4.2(svelte@4.1.1)(vite@4.5.0):
|
||||
/@sveltejs/vite-plugin-svelte@2.4.2(svelte@4.1.1)(vite@4.4.7):
|
||||
resolution: {integrity: sha512-ePfcC48ftMKhkT0OFGdOyycYKnnkT6i/buzey+vHRTR/JpQvuPzzhf1PtKqCDQfJRgoPSN2vscXs6gLigx/zGw==}
|
||||
engines: {node: ^14.18.0 || >= 16}
|
||||
peerDependencies:
|
||||
svelte: ^3.54.0 || ^4.0.0
|
||||
vite: ^4.0.0
|
||||
dependencies:
|
||||
'@sveltejs/vite-plugin-svelte-inspector': 1.0.3(@sveltejs/vite-plugin-svelte@2.4.2)(svelte@4.1.1)(vite@4.5.0)
|
||||
'@sveltejs/vite-plugin-svelte-inspector': 1.0.3(@sveltejs/vite-plugin-svelte@2.4.2)(svelte@4.1.1)(vite@4.4.7)
|
||||
debug: 4.3.4
|
||||
deepmerge: 4.3.1
|
||||
kleur: 4.1.5
|
||||
magic-string: 0.30.5
|
||||
svelte: 4.1.1
|
||||
svelte-hmr: 0.15.2(svelte@4.1.1)
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vitefu: 0.2.4(vite@4.5.0)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
vitefu: 0.2.4(vite@4.4.7)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
@ -10883,8 +10884,8 @@ packages:
|
||||
resolution: {integrity: sha512-yzgMaql7aW1by1XuhKhovuhLyK/1A60lapFXDXXBeHmoyRGQFO2T8lkL3g8hAhHoW5PEvqPJFWPd8jvXiRnxeQ==}
|
||||
dev: true
|
||||
|
||||
/@types/babel__core@7.20.3:
|
||||
resolution: {integrity: sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==}
|
||||
/@types/babel__core@7.1.20:
|
||||
resolution: {integrity: sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==}
|
||||
dependencies:
|
||||
'@babel/parser': 7.23.0
|
||||
'@babel/types': 7.23.0
|
||||
@ -12158,7 +12159,7 @@ packages:
|
||||
react: 18.1.0
|
||||
dev: false
|
||||
|
||||
/@vitejs/plugin-react@3.1.0(vite@4.5.0):
|
||||
/@vitejs/plugin-react@3.1.0(vite@4.4.7):
|
||||
resolution: {integrity: sha512-AfgcRL8ZBhAlc3BFdigClmTUMISmmzHn7sB2h9U1odvc5U/MjWXsAaz18b/WoppUTDBzxOJwo2VdClfUcItu9g==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
@ -12169,23 +12170,7 @@ packages:
|
||||
'@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.23.0)
|
||||
magic-string: 0.27.0
|
||||
react-refresh: 0.14.0
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@vitejs/plugin-react@4.1.0(vite@4.5.0):
|
||||
resolution: {integrity: sha512-rM0SqazU9iqPUraQ2JlIvReeaxOoRj6n+PzB1C0cBzIbd8qP336nC39/R9yPi3wVcah7E7j/kdU1uCUqMEU4OQ==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
vite: ^4.2.0
|
||||
dependencies:
|
||||
'@babel/core': 7.23.0
|
||||
'@babel/plugin-transform-react-jsx-self': 7.22.5(@babel/core@7.23.0)
|
||||
'@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.23.0)
|
||||
'@types/babel__core': 7.20.3
|
||||
react-refresh: 0.14.0
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
@ -23022,8 +23007,8 @@ packages:
|
||||
dependencies:
|
||||
glob: 7.2.3
|
||||
|
||||
/rollup@3.29.4:
|
||||
resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==}
|
||||
/rollup@3.26.3:
|
||||
resolution: {integrity: sha512-7Tin0C8l86TkpcMtXvQu6saWH93nhG3dGQ1/+l5V2TDMceTxO7kDiK6GzbfLWNNxqJXm591PcEZUozZm51ogwQ==}
|
||||
engines: {node: '>=14.18.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
optionalDependencies:
|
||||
@ -24724,6 +24709,7 @@ packages:
|
||||
|
||||
/trim@0.0.1:
|
||||
resolution: {integrity: sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==}
|
||||
deprecated: Use String.prototype.trim() instead
|
||||
dev: true
|
||||
|
||||
/ts-api-utils@1.0.3(typescript@5.2.2):
|
||||
@ -25488,7 +25474,7 @@ packages:
|
||||
mlly: 1.4.0
|
||||
pathe: 1.1.1
|
||||
picocolors: 1.0.0
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- less
|
||||
@ -25510,7 +25496,7 @@ packages:
|
||||
mlly: 1.4.0
|
||||
pathe: 1.1.1
|
||||
picocolors: 1.0.0
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- less
|
||||
@ -25522,7 +25508,7 @@ packages:
|
||||
- terser
|
||||
dev: true
|
||||
|
||||
/vite-plugin-inspect@0.7.35(vite@4.5.0):
|
||||
/vite-plugin-inspect@0.7.35(vite@4.4.7):
|
||||
resolution: {integrity: sha512-e5w5dJAj3vDcHTxn8hHbiH+mVqYs17gaW00f3aGuMTXiqUog+T1Lsxr9Jb4WRiip84cpuhR0KFFBT1egtXboiA==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
@ -25539,7 +25525,7 @@ packages:
|
||||
open: 9.1.0
|
||||
picocolors: 1.0.0
|
||||
sirv: 2.0.3
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
transitivePeerDependencies:
|
||||
- rollup
|
||||
- supports-color
|
||||
@ -25549,8 +25535,8 @@ packages:
|
||||
resolution: {integrity: sha512-p4D8CFVhZS412SyQX125qxyzOgIFouwOcvjZWk6bQbNPR1wtaEzFT6jZxAjf1dejlGqa6fqHcuCvQea6EWUkUA==}
|
||||
dev: true
|
||||
|
||||
/vite@4.5.0(@types/node@20.8.0)(sass@1.32.4):
|
||||
resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==}
|
||||
/vite@4.4.7(@types/node@20.8.0)(sass@1.32.4):
|
||||
resolution: {integrity: sha512-6pYf9QJ1mHylfVh39HpuSfMPojPSKVxZvnclX1K1FyZ1PXDOcLBibdq5t1qxJSnL63ca8Wf4zts6mD8u8oc9Fw==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@ -25580,13 +25566,13 @@ packages:
|
||||
'@types/node': 20.8.0
|
||||
esbuild: 0.18.17
|
||||
postcss: 8.4.31
|
||||
rollup: 3.29.4
|
||||
rollup: 3.26.3
|
||||
sass: 1.32.4
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
dev: true
|
||||
|
||||
/vitefu@0.2.4(vite@4.5.0):
|
||||
/vitefu@0.2.4(vite@4.4.7):
|
||||
resolution: {integrity: sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==}
|
||||
peerDependencies:
|
||||
vite: ^3.0.0 || ^4.0.0
|
||||
@ -25594,7 +25580,7 @@ packages:
|
||||
vite:
|
||||
optional: true
|
||||
dependencies:
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
dev: true
|
||||
|
||||
/vitest-fetch-mock@0.2.2(vitest@1.0.0-beta.4):
|
||||
@ -25663,7 +25649,7 @@ packages:
|
||||
strip-literal: 1.0.1
|
||||
tinybench: 2.5.0
|
||||
tinypool: 0.6.0
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite-node: 0.33.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
why-is-node-running: 2.2.2
|
||||
transitivePeerDependencies:
|
||||
@ -25722,7 +25708,7 @@ packages:
|
||||
strip-literal: 1.0.1
|
||||
tinybench: 2.5.0
|
||||
tinypool: 0.8.1
|
||||
vite: 4.5.0(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite: 4.4.7(@types/node@20.8.0)(sass@1.32.4)
|
||||
vite-node: 1.0.0-beta.4(@types/node@20.8.0)(sass@1.32.4)
|
||||
why-is-node-running: 2.2.2
|
||||
transitivePeerDependencies:
|
||||
|
||||
@ -29,6 +29,8 @@ env:
|
||||
|
||||
DEPLOY_TYPE: dev
|
||||
|
||||
SRC_HTTP_ADDR: ':3082'
|
||||
|
||||
# I don't think we even need to set these?
|
||||
SEARCHER_URL: http://127.0.0.1:3181
|
||||
REPO_UPDATER_URL: http://127.0.0.1:3182
|
||||
@ -404,7 +406,7 @@ commands:
|
||||
|
||||
web:
|
||||
description: Enterprise version of the web app
|
||||
cmd: pnpm --filter @sourcegraph/web run dev --clearScreen=false
|
||||
cmd: pnpm --filter @sourcegraph/web dev
|
||||
install: |
|
||||
pnpm install
|
||||
pnpm run generate
|
||||
@ -421,6 +423,15 @@ commands:
|
||||
WEB_BUILDER_SERVE_INDEX: true
|
||||
SOURCEGRAPH_API_URL: https://sourcegraph.sourcegraph.com
|
||||
|
||||
web-standalone-http-prod:
|
||||
description: Standalone web frontend (production) with API proxy to a configurable URL
|
||||
cmd: pnpm --filter @sourcegraph/web serve:prod
|
||||
install: pnpm --filter @sourcegraph/web run build
|
||||
env:
|
||||
NODE_ENV: production
|
||||
WEB_BUILDER_SERVE_INDEX: true
|
||||
SOURCEGRAPH_API_URL: https://k8s.sgdev.org
|
||||
|
||||
web-integration-build:
|
||||
description: Build development web application for integration tests
|
||||
cmd: pnpm --filter @sourcegraph/web run build
|
||||
@ -1505,6 +1516,11 @@ commandsets:
|
||||
env:
|
||||
SK_PORT: 3080
|
||||
|
||||
web-standalone-prod:
|
||||
commands:
|
||||
- web-standalone-http-prod
|
||||
- caddy
|
||||
|
||||
# For testing our OpenTelemetry stack
|
||||
otel:
|
||||
checks:
|
||||
@ -1632,14 +1648,6 @@ tests:
|
||||
export PERCY_TOKEN=$(gcloud secrets versions access latest --secret=PERCY_TOKEN --quiet --project=sourcegraph-ci)
|
||||
bazel test //client/web/src/integration:integration-tests --define=E2E_HEADLESS=false --define=E2E_SOURCEGRAPH_BASE_URL="http://localhost:7080" --define=GH_TOKEN=$GH_TOKEN --define=DISPLAY=$DISPLAY --define=PERCY_TOKEN=$PERCY_TOKEN
|
||||
|
||||
bazel-backend-integration:
|
||||
cmd: |
|
||||
export GHE_GITHUB_TOKEN=$(gcloud secrets versions access latest --secret=GHE_GITHUB_TOKEN --quiet --project=sourcegraph-ci)
|
||||
export GH_TOKEN=$(gcloud secrets versions access latest --secret=GITHUB_TOKEN --quiet --project=sourcegraph-ci)
|
||||
export SOURCEGRAPH_LICENSE_KEY=$(gcloud secrets versions access latest --secret=SOURCEGRAPH_LICENSE_KEY --quiet --project=sourcegraph-ci)
|
||||
export SOURCEGRAPH_LICENSE_GENERATION_KEY=$(gcloud secrets versions access latest --secret=SOURCEGRAPH_LICENSE_GENERATION_KEY --quiet --project=sourcegraph-ci)
|
||||
bazel test //testing:backend_integration_test --define=GHE_GITHUB_TOKEN=$GHE_GITHUB_TOKEN
|
||||
|
||||
backend-integration:
|
||||
cmd: cd dev/gqltest && go test -long -base-url $BASE_URL -email $EMAIL -username $USERNAME -password $PASSWORD ./gqltest
|
||||
env:
|
||||
|
||||
@ -42,7 +42,7 @@ func loadWebBuildManifest() (m *WebBuildManifest, err error) {
|
||||
return MockLoadWebBuildManifest()
|
||||
}
|
||||
|
||||
manifestContent, err := os.ReadFile(filepath.Join(assetsDir, "vite-manifest.json"))
|
||||
manifestContent, err := os.ReadFile(filepath.Join(assetsDir, "web.manifest.json"))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "loading web build manifest file from disk")
|
||||
}
|
||||
|
||||
@ -1,23 +1,8 @@
|
||||
package assets
|
||||
|
||||
// WebBuildManifest describes the web build and is produced by Vite. Keep it in sync with `interface
|
||||
// WebBuildManifest`.
|
||||
type WebBuildManifest struct {
|
||||
// URL is the base URL for asset paths.
|
||||
URL string `json:"url,omitempty"`
|
||||
|
||||
// Assets is a map of entrypoint (such as "src/enterprise/main.tsx") to its JavaScript and CSS assets.
|
||||
Assets struct {
|
||||
Main *entryAssets `json:"src/enterprise/main"`
|
||||
EmbedMain *entryAssets `json:"src/enterprise/embed/embedMain"`
|
||||
AppMain *entryAssets `json:"src/enterprise/app/main"`
|
||||
} `json:"assets"`
|
||||
|
||||
// DevInjectHTML contains additional HTML <script> tags to inject in dev mode.
|
||||
DevInjectHTML string `json:"devInjectHTML,omitempty"`
|
||||
}
|
||||
|
||||
type entryAssets struct {
|
||||
JS string `json:"js,omitempty"`
|
||||
CSS string `json:"css,omitempty"`
|
||||
MainJSBundlePath string `json:"main.js"`
|
||||
MainCSSBundlePath string `json:"main.css"`
|
||||
EmbedJSBundlePath string `json:"embed.js"`
|
||||
EmbedCSSBundlePath string `json:"embed.css"`
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user