1+ import * as fs from "fs-extra"
2+ import yaml from "js-yaml"
13import * as path from "path"
24import { field , logger , Level } from "@coder/logger"
35import { Args as VsArgs } from "../../lib/vscode/src/vs/server/ipc"
46import { AuthType } from "./http"
57import { xdgLocalDir } from "./util"
8+ import xdgBasedir from "xdg-basedir"
69
710export class Optional < T > {
811 public constructor ( public readonly value ?: T ) { }
@@ -19,6 +22,7 @@ export enum LogLevel {
1922export class OptionalString extends Optional < string > { }
2023
2124export interface Args extends VsArgs {
25+ readonly config ?: string
2226 readonly auth ?: AuthType
2327 readonly cert ?: OptionalString
2428 readonly "cert-key" ?: string
@@ -95,6 +99,8 @@ const options: Options<Required<Args>> = {
9599
96100 "bind-addr" : { type : "string" , description : "Address to bind to in host:port." } ,
97101
102+ config : { type : "string" , description : "Path to yaml config file." } ,
103+
98104 // These two have been deprecated by bindAddr.
99105 host : { type : "string" , description : "" } ,
100106 port : { type : "number" , description : "" } ,
@@ -275,3 +281,47 @@ export const parse = (argv: string[]): Args => {
275281
276282 return args
277283}
284+
285+ // readConfigFile reads the config file specified in the config flag
286+ // and loads it's configuration.
287+ //
288+ // Flags set on the CLI take priority.
289+ //
290+ // The config file can also be passed via $CODE_SERVER_CONFIG and defaults
291+ // to ~/.config/code-server/config.yaml.
292+ export async function readConfigFile ( args : Args ) : Promise < Args > {
293+ const configPath = getConfigPath ( args )
294+ if ( configPath === undefined ) {
295+ return args
296+ }
297+
298+ if ( ! ( await fs . pathExists ( configPath ) ) ) {
299+ await fs . outputFile ( configPath , `default: hello` )
300+ }
301+
302+ const configFile = await fs . readFile ( configPath )
303+ const config = yaml . safeLoad ( configFile . toString ( ) , {
304+ filename : args . config ,
305+ } )
306+
307+ // We convert the config file into a set of flags.
308+ // This is a temporary measure until we add a proper CLI library.
309+ const configFileArgv = Object . entries ( config ) . map ( ( [ optName , opt ] ) => `--${ optName } =${ opt } ` )
310+ const configFileArgs = parse ( configFileArgv )
311+
312+ // This prioritizes the flags set in args over the ones in the config file.
313+ return Object . assign ( configFileArgs , args )
314+ }
315+
316+ function getConfigPath ( args : Args ) : string | undefined {
317+ if ( args . config !== undefined ) {
318+ return args . config
319+ }
320+ if ( process . env . CODE_SERVER_CONFIG !== undefined ) {
321+ return process . env . CODE_SERVER_CONFIG
322+ }
323+ if ( xdgBasedir . config !== undefined ) {
324+ return `${ xdgBasedir . config } /code-server/config.yaml`
325+ }
326+ return undefined
327+ }
0 commit comments