Skip to content

Commit fc298f2

Browse files
authored
settings schema.json (#1874)
Adds schema.json support to the settings file to provide type hints and other eventual details. This also adds a system to easily add more schema files for other type of configurations.
1 parent 1a70c83 commit fc298f2

File tree

10 files changed

+468
-43
lines changed

10 files changed

+468
-43
lines changed

Taskfile.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,18 @@ tasks:
114114
- task: build:server
115115
- task: build:wsh
116116

117+
build:schema:
118+
desc: Build the schema for configuration.
119+
sources:
120+
- "cmd/generateschema/*.go"
121+
- "pkg/wconfig/*.go"
122+
generates:
123+
- "dist/schema/**/*"
124+
cmds:
125+
- go run cmd/generateschema/main-generateschema.go
126+
- '{{.RMRF}} "dist/schema"'
127+
- task: copyfiles:'schema':'dist/schema'
128+
117129
build:server:
118130
desc: Build the wavesrv component.
119131
cmds:
@@ -243,6 +255,8 @@ tasks:
243255
cmds:
244256
- go run cmd/generatets/main-generatets.go
245257
- go run cmd/generatego/main-generatego.go
258+
deps:
259+
- build:schema
246260
sources:
247261
- "cmd/generatego/*.go"
248262
- "cmd/generatets/*.go"
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2025, Command Line Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package main
5+
6+
import (
7+
"encoding/json"
8+
"fmt"
9+
"log"
10+
"os"
11+
12+
"github.com/invopop/jsonschema"
13+
"github.com/wavetermdev/waveterm/pkg/util/utilfn"
14+
"github.com/wavetermdev/waveterm/pkg/wconfig"
15+
)
16+
17+
const WaveSchemaSettingsFileName = "schema/settings.json"
18+
19+
func main() {
20+
settingsSchema := jsonschema.Reflect(&wconfig.SettingsType{})
21+
22+
jsonSettingsSchema, err := json.MarshalIndent(settingsSchema, "", " ")
23+
if err != nil {
24+
log.Fatalf("failed to parse local schema: %v", err)
25+
}
26+
/*
27+
err = os.MkdirAll(WaveSchemaSettingsFileName, 0755)
28+
if err != nil {
29+
log.Fatalf("failed to create schema dir: %v", err)
30+
}
31+
*/
32+
written, err := utilfn.WriteFileIfDifferent(WaveSchemaSettingsFileName, jsonSettingsSchema)
33+
if !written {
34+
fmt.Fprintf(os.Stderr, "no changes to %s\n", WaveSchemaSettingsFileName)
35+
}
36+
if err != nil {
37+
log.Fatalf("failed to write local schema: %v", err)
38+
}
39+
}

frontend/app/view/codeeditor/codeeditor.tsx

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@ import type * as MonacoTypes from "monaco-editor/esm/vs/editor/editor.api";
99
import { configureMonacoYaml } from "monaco-yaml";
1010
import React, { useMemo, useRef } from "react";
1111

12+
import { RpcApi } from "@/app/store/wshclientapi";
13+
import { TabRpcClient } from "@/app/store/wshrpcutil";
14+
import { makeConnRoute } from "@/util/util";
1215
import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker";
1316
import cssWorker from "monaco-editor/esm/vs/language/css/css.worker?worker";
1417
import htmlWorker from "monaco-editor/esm/vs/language/html/html.worker?worker";
1518
import jsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker";
1619
import tsWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker";
20+
import { SchemaEndpoints, getSchemaEndpointInfo } from "./schemaendpoints";
1721
import ymlWorker from "./yamlworker?worker";
1822

1923
import "./codeeditor.scss";
@@ -42,48 +46,45 @@ window.MonacoEnvironment = {
4246
},
4347
};
4448

45-
export function loadMonaco() {
49+
export async function loadMonaco() {
4650
loader.config({ paths: { vs: "monaco" } });
47-
loader
48-
.init()
49-
.then(() => {
50-
monaco.editor.defineTheme("wave-theme-dark", {
51-
base: "vs-dark",
52-
inherit: true,
53-
rules: [],
54-
colors: {
55-
"editor.background": "#00000000",
56-
"editorStickyScroll.background": "#00000055",
57-
"minimap.background": "#00000077",
58-
focusBorder: "#00000000",
59-
},
60-
});
61-
monaco.editor.defineTheme("wave-theme-light", {
62-
base: "vs",
63-
inherit: true,
64-
rules: [],
65-
colors: {
66-
"editor.background": "#fefefe",
67-
focusBorder: "#00000000",
68-
},
69-
});
70-
configureMonacoYaml(monaco, {
71-
validate: true,
72-
schemas: [],
73-
});
74-
// Disable default validation errors for typescript and javascript
75-
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
76-
noSemanticValidation: true,
77-
});
78-
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
79-
validate: true,
80-
allowComments: false, // Set to true if you want to allow comments in JSON
81-
schemas: [], // You can specify JSON schemas here if needed
82-
});
83-
})
84-
.catch((e) => {
85-
console.error("error loading monaco", e);
86-
});
51+
await loader.init();
52+
53+
monaco.editor.defineTheme("wave-theme-dark", {
54+
base: "vs-dark",
55+
inherit: true,
56+
rules: [],
57+
colors: {
58+
"editor.background": "#00000000",
59+
"editorStickyScroll.background": "#00000055",
60+
"minimap.background": "#00000077",
61+
focusBorder: "#00000000",
62+
},
63+
});
64+
monaco.editor.defineTheme("wave-theme-light", {
65+
base: "vs",
66+
inherit: true,
67+
rules: [],
68+
colors: {
69+
"editor.background": "#fefefe",
70+
focusBorder: "#00000000",
71+
},
72+
});
73+
configureMonacoYaml(monaco, {
74+
validate: true,
75+
schemas: [],
76+
});
77+
// Disable default validation errors for typescript and javascript
78+
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
79+
noSemanticValidation: true,
80+
});
81+
const schemas = await Promise.all(SchemaEndpoints.map((endpoint) => getSchemaEndpointInfo(endpoint)));
82+
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
83+
validate: true,
84+
allowComments: false, // Set to true if you want to allow comments in JSON
85+
enableSchemaRequest: true,
86+
schemas,
87+
});
8788
}
8889

8990
function defaultEditorOptions(): MonacoTypes.editor.IEditorOptions {
@@ -125,6 +126,7 @@ export function CodeEditor({ blockId, text, language, filename, meta, onChange,
125126
const wordWrap = useOverrideConfigAtom(blockId, "editor:wordwrap") ?? false;
126127
const fontSize = boundNumber(useOverrideConfigAtom(blockId, "editor:fontsize"), 6, 64);
127128
const theme = "wave-theme-dark";
129+
const [absPath, setAbsPath] = React.useState("");
128130

129131
React.useEffect(() => {
130132
return () => {
@@ -135,6 +137,24 @@ export function CodeEditor({ blockId, text, language, filename, meta, onChange,
135137
};
136138
}, []);
137139

140+
React.useEffect(() => {
141+
const inner = async () => {
142+
try {
143+
const fileInfo = await RpcApi.RemoteFileJoinCommand(TabRpcClient, [filename], {
144+
route: makeConnRoute(meta.connection ?? ""),
145+
});
146+
setAbsPath(`${fileInfo.dir}/${fileInfo.name}`);
147+
} catch (e) {
148+
setAbsPath(filename);
149+
}
150+
};
151+
inner();
152+
}, [filename]);
153+
154+
React.useEffect(() => {
155+
console.log("abspath is", absPath);
156+
}, [absPath]);
157+
138158
function handleEditorChange(text: string, ev: MonacoTypes.editor.IModelContentChangedEvent) {
139159
if (onChange) {
140160
onChange(text);
@@ -165,7 +185,7 @@ export function CodeEditor({ blockId, text, language, filename, meta, onChange,
165185
options={editorOpts}
166186
onChange={handleEditorChange}
167187
onMount={handleEditorOnMount}
168-
path={filename}
188+
path={absPath}
169189
language={language}
170190
/>
171191
</div>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2025, Command Line Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { getApi } from "@/app/store/global";
5+
import { getWebServerEndpoint } from "@/util/endpoints";
6+
7+
type EndpointInfo = {
8+
uri: string;
9+
fileMatch: Array<string>;
10+
schema: object;
11+
};
12+
13+
const allFilepaths: Map<string, Array<string>> = new Map();
14+
allFilepaths.set(`${getWebServerEndpoint()}/schema/settings.json`, [`${getApi().getConfigDir()}/settings.json`]);
15+
16+
async function getSchemaEndpointInfo(endpoint: string): Promise<EndpointInfo> {
17+
let schema: Object;
18+
try {
19+
const data = await fetch(endpoint);
20+
const fullSchema: object = await data.json();
21+
const schemaRef: string = fullSchema?.["$ref"];
22+
schema = fullSchema?.[schemaRef];
23+
} catch (e) {
24+
console.log("cannot find schema:", e);
25+
schema = {};
26+
}
27+
const fileMatch = allFilepaths.get(endpoint) ?? [];
28+
29+
return {
30+
uri: endpoint,
31+
fileMatch,
32+
schema,
33+
};
34+
}
35+
36+
const SchemaEndpoints = Array.from(allFilepaths.keys());
37+
38+
export { getSchemaEndpointInfo, SchemaEndpoints };

frontend/wave.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ async function initWave(initOpts: WaveInitOpts) {
183183
registerGlobalKeys();
184184
registerElectronReinjectKeyHandler();
185185
registerControlShiftStateUpdateHandler();
186-
setTimeout(loadMonaco, 30);
186+
await loadMonaco();
187187
const fullConfig = await RpcApi.GetFullConfigCommand(TabRpcClient);
188188
console.log("fullconfig", fullConfig);
189189
globalStore.set(atoms.fullConfigAtom, fullConfig);

go.mod

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ require (
1818
github.com/gorilla/handlers v1.5.2
1919
github.com/gorilla/mux v1.8.1
2020
github.com/gorilla/websocket v1.5.3
21+
github.com/invopop/jsonschema v0.13.0
2122
github.com/jmoiron/sqlx v1.4.0
2223
github.com/kevinburke/ssh_config v1.2.0
2324
github.com/mattn/go-sqlite3 v1.14.24
@@ -59,6 +60,8 @@ require (
5960
github.com/aws/aws-sdk-go-v2/service/sso v1.24.13 // indirect
6061
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.12 // indirect
6162
github.com/aws/aws-sdk-go-v2/service/sts v1.33.11 // indirect
63+
github.com/bahlo/generic-list-go v0.2.0 // indirect
64+
github.com/buger/jsonparser v1.1.1 // indirect
6265
github.com/ebitengine/purego v0.8.1 // indirect
6366
github.com/felixge/httpsnoop v1.0.4 // indirect
6467
github.com/go-logr/logr v1.4.2 // indirect
@@ -71,12 +74,14 @@ require (
7174
github.com/hashicorp/go-multierror v1.1.1 // indirect
7275
github.com/inconshreveable/mousetrap v1.1.0 // indirect
7376
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
77+
github.com/mailru/easyjson v0.7.7 // indirect
7478
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
7579
github.com/sirupsen/logrus v1.9.3 // indirect
7680
github.com/spf13/pflag v1.0.5 // indirect
7781
github.com/tklauser/go-sysconf v0.3.12 // indirect
7882
github.com/tklauser/numcpus v0.6.1 // indirect
7983
github.com/ubuntu/decorate v0.0.0-20230125165522-2d5b0a9bb117 // indirect
84+
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
8085
github.com/yusufpapurcu/wmi v1.2.4 // indirect
8186
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect
8287
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
@@ -93,6 +98,7 @@ require (
9398
google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47 // indirect
9499
google.golang.org/grpc v1.70.0 // indirect
95100
google.golang.org/protobuf v1.36.4 // indirect
101+
gopkg.in/yaml.v3 v3.0.1 // indirect
96102
)
97103

98104
replace github.com/kevinburke/ssh_config => github.com/wavetermdev/ssh_config v0.0.0-20241219203747-6409e4292f34

go.sum

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.33.11 h1:RIXOjp7Dp4siCYJRwBHUcBdVgOW
5252
github.com/aws/aws-sdk-go-v2/service/sts v1.33.11/go.mod h1:ZR17k9bPKPR8u0IkyA6xVsjr56doNQ4ZB1fs7abYBfE=
5353
github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
5454
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
55+
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
56+
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
57+
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
58+
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
5559
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
5660
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5761
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -105,12 +109,21 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
105109
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
106110
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
107111
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
112+
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
113+
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
108114
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
109115
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
116+
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
117+
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
118+
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
119+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
120+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
110121
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
111122
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
112123
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
113124
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
125+
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
126+
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
114127
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
115128
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
116129
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
@@ -122,6 +135,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
122135
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
123136
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
124137
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
138+
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
139+
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
125140
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
126141
github.com/sashabaranov/go-openai v1.36.1 h1:EVfRXwIlW2rUzpx6vR+aeIKCK/xylSrVYAx1TMTSX3g=
127142
github.com/sashabaranov/go-openai v1.36.1/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
@@ -157,6 +172,8 @@ github.com/wavetermdev/htmltoken v0.2.0 h1:sFVPPemlDv7/jg7n4Hx1AEF2m9MVAFjFpELWf
157172
github.com/wavetermdev/htmltoken v0.2.0/go.mod h1:5FM0XV6zNYiNza2iaTcFGj+hnMtgqumFHO31Z8euquk=
158173
github.com/wavetermdev/ssh_config v0.0.0-20241219203747-6409e4292f34 h1:I8VZVTZEXhnzfN7jB9a7TZYpzNO48sCUWMRXHM9XWSA=
159174
github.com/wavetermdev/ssh_config v0.0.0-20241219203747-6409e4292f34/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
175+
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
176+
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
160177
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
161178
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
162179
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc=
@@ -212,6 +229,8 @@ google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40Rmc
212229
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
213230
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
214231
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
232+
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
233+
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
215234
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
216235
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
217236
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

0 commit comments

Comments
 (0)