@teamkeel/wasm 0.329.0 → 0.330.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/keel.wasm +0 -0
- package/dist/wasm.js +1 -1
- package/index.d.ts +16 -14
- package/index.test.ts +95 -9
- package/lib/main.go +70 -17
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
export function format(schema: string): Promise<string>;
|
|
2
2
|
|
|
3
|
-
export function validate(
|
|
4
|
-
schemaString: string,
|
|
5
|
-
configFile: string
|
|
6
|
-
): Promise<ValidationResult>;
|
|
3
|
+
export function validate(req: ValidateRequest): Promise<ValidationResult>;
|
|
7
4
|
|
|
8
5
|
export function completions(
|
|
9
|
-
|
|
10
|
-
position: SimplePosition,
|
|
11
|
-
configFile: string
|
|
6
|
+
req: GetCompletionsRequest
|
|
12
7
|
): Promise<CompletionResult>;
|
|
13
8
|
|
|
14
9
|
export function getDefinition(
|
|
@@ -24,24 +19,31 @@ export interface SchemaDefinition {
|
|
|
24
19
|
schema: SchemaDefinition;
|
|
25
20
|
}
|
|
26
21
|
|
|
22
|
+
export interface GetCompletionsRequest {
|
|
23
|
+
position: Position;
|
|
24
|
+
schemaFiles: SchemaFile[];
|
|
25
|
+
config?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
27
28
|
export interface GetDefinitionRequest {
|
|
28
29
|
position: Position;
|
|
29
30
|
schemaFiles: SchemaFile[];
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
export interface ValidateRequest {
|
|
34
|
+
schemaFiles: SchemaFile[];
|
|
35
|
+
config?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
32
38
|
export interface SchemaFile {
|
|
33
39
|
filename: string;
|
|
34
40
|
contents: string;
|
|
35
41
|
}
|
|
36
42
|
|
|
37
|
-
export interface
|
|
38
|
-
column: number;
|
|
39
|
-
line: number;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface Position extends SimplePosition {
|
|
43
|
+
export interface Position {
|
|
43
44
|
filename: string;
|
|
44
|
-
|
|
45
|
+
line: number;
|
|
46
|
+
column: number;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
export interface CompletionItem {
|
package/index.test.ts
CHANGED
|
@@ -40,33 +40,121 @@ test("completions", async () => {
|
|
|
40
40
|
name Te
|
|
41
41
|
}
|
|
42
42
|
}`;
|
|
43
|
-
const result = await completions(
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
const result = await completions({
|
|
44
|
+
schemaFiles: [
|
|
45
|
+
{
|
|
46
|
+
filename: "schema.keel",
|
|
47
|
+
contents: schema,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
position: {
|
|
51
|
+
filename: "schema.keel",
|
|
46
52
|
line: 3,
|
|
47
53
|
column: 16,
|
|
48
54
|
},
|
|
49
|
-
|
|
50
|
-
);
|
|
55
|
+
});
|
|
51
56
|
|
|
52
57
|
expect(result.completions.map((x) => x.label)).toContain("Text");
|
|
53
58
|
});
|
|
54
59
|
|
|
60
|
+
test("completions - multi file", async () => {
|
|
61
|
+
const result = await completions({
|
|
62
|
+
schemaFiles: [
|
|
63
|
+
{
|
|
64
|
+
filename: "schema.keel",
|
|
65
|
+
contents: `
|
|
66
|
+
model Person {
|
|
67
|
+
fields {
|
|
68
|
+
name
|
|
69
|
+
}
|
|
70
|
+
}`,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
filename: "other.keel",
|
|
74
|
+
contents: `
|
|
75
|
+
enum Category {
|
|
76
|
+
Sport
|
|
77
|
+
Finance
|
|
78
|
+
}
|
|
79
|
+
`,
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
position: {
|
|
83
|
+
filename: "schema.keel",
|
|
84
|
+
line: 4,
|
|
85
|
+
column: 10,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
expect(result.completions.map((x) => x.label)).toContain("Category");
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test("completions - with config", async () => {
|
|
93
|
+
const result = await completions({
|
|
94
|
+
schemaFiles: [
|
|
95
|
+
{
|
|
96
|
+
filename: "schema.keel",
|
|
97
|
+
contents: `
|
|
98
|
+
model Person {
|
|
99
|
+
@permission(
|
|
100
|
+
expression: ctx.secrets.
|
|
101
|
+
)
|
|
102
|
+
}`,
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
position: {
|
|
106
|
+
filename: "schema.keel",
|
|
107
|
+
line: 4,
|
|
108
|
+
column: 29,
|
|
109
|
+
},
|
|
110
|
+
config: configFile,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
expect(result.completions.map((x) => x.label)).toContain("API_KEY");
|
|
114
|
+
});
|
|
115
|
+
|
|
55
116
|
test("validate", async () => {
|
|
56
117
|
const schema = `model Person {
|
|
57
118
|
fields {
|
|
58
119
|
name Foo
|
|
59
120
|
}
|
|
60
121
|
}`;
|
|
61
|
-
const { errors } = await validate(
|
|
122
|
+
const { errors } = await validate({
|
|
123
|
+
schemaFiles: [{ filename: "schema.keel", contents: schema }],
|
|
124
|
+
config: configFile,
|
|
125
|
+
});
|
|
62
126
|
|
|
63
127
|
expect(errors[0].message).toEqual("field name has an unsupported type Foo");
|
|
64
128
|
});
|
|
65
129
|
|
|
130
|
+
test("validate - multi file", async () => {
|
|
131
|
+
const schemaA = `model Customer {
|
|
132
|
+
fields {
|
|
133
|
+
orders Order[]
|
|
134
|
+
}
|
|
135
|
+
}`;
|
|
136
|
+
const schemaB = `model Order {
|
|
137
|
+
fields {
|
|
138
|
+
customer Customer
|
|
139
|
+
}
|
|
140
|
+
}`;
|
|
141
|
+
const { errors } = await validate({
|
|
142
|
+
schemaFiles: [
|
|
143
|
+
{ filename: "customer.keel", contents: schemaA },
|
|
144
|
+
{ filename: "hobby.keel", contents: schemaB },
|
|
145
|
+
],
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
expect(errors.length).toEqual(0);
|
|
149
|
+
});
|
|
150
|
+
|
|
66
151
|
test("validate - invalid schema", async () => {
|
|
67
152
|
const schema = `model Person {
|
|
68
153
|
fields {`;
|
|
69
|
-
const { errors } = await validate(
|
|
154
|
+
const { errors } = await validate({
|
|
155
|
+
schemaFiles: [{ filename: "schema.keel", contents: schema }],
|
|
156
|
+
config: configFile,
|
|
157
|
+
});
|
|
70
158
|
|
|
71
159
|
expect(errors[0].code).toEqual("E025");
|
|
72
160
|
expect(errors[0].message).toEqual(` unexpected token "<EOF>" (expected "}")`);
|
|
@@ -77,7 +165,6 @@ test("getDefinition", async () => {
|
|
|
77
165
|
position: {
|
|
78
166
|
line: 7,
|
|
79
167
|
column: 21,
|
|
80
|
-
offset: 0,
|
|
81
168
|
filename: "myschema.keel",
|
|
82
169
|
},
|
|
83
170
|
schemaFiles: [
|
|
@@ -112,7 +199,6 @@ test("getDefinition - no result", async () => {
|
|
|
112
199
|
position: {
|
|
113
200
|
line: 1,
|
|
114
201
|
column: 1,
|
|
115
|
-
offset: 0,
|
|
116
202
|
filename: "myschema.keel",
|
|
117
203
|
},
|
|
118
204
|
schemaFiles: [
|
package/lib/main.go
CHANGED
|
@@ -78,15 +78,50 @@ func newPromise(fn func() (any, error)) any {
|
|
|
78
78
|
return promiseConstructor.New(handler)
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
// Expected argument to definitions API:
|
|
82
|
+
//
|
|
83
|
+
// {
|
|
84
|
+
// position: {
|
|
85
|
+
// filename: "",
|
|
86
|
+
// line: 1,
|
|
87
|
+
// column: 1,
|
|
88
|
+
// },
|
|
89
|
+
// schemaFiles: [
|
|
90
|
+
// {
|
|
91
|
+
// filename: "",
|
|
92
|
+
// contents: "",
|
|
93
|
+
// },
|
|
94
|
+
// ],
|
|
95
|
+
// config: "",
|
|
96
|
+
// }
|
|
81
97
|
func provideCompletions(this js.Value, args []js.Value) any {
|
|
82
98
|
return newPromise(func() (any, error) {
|
|
83
|
-
|
|
84
|
-
|
|
99
|
+
positionArg := args[0].Get("position")
|
|
100
|
+
pos := &node.Position{
|
|
101
|
+
Filename: positionArg.Get("filename").String(),
|
|
102
|
+
Line: positionArg.Get("line").Int(),
|
|
103
|
+
Column: positionArg.Get("column").Int(),
|
|
104
|
+
}
|
|
85
105
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
106
|
+
schemaFilesArg := args[0].Get("schemaFiles")
|
|
107
|
+
schemaFiles := []*reader.SchemaFile{}
|
|
108
|
+
for i := 0; i < schemaFilesArg.Length(); i++ {
|
|
109
|
+
f := schemaFilesArg.Index(i)
|
|
110
|
+
schemaFiles = append(schemaFiles, &reader.SchemaFile{
|
|
111
|
+
FileName: f.Get("filename").String(),
|
|
112
|
+
Contents: f.Get("contents").String(),
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
configSrc := args[0].Get("config")
|
|
117
|
+
var cfg *config.ProjectConfig
|
|
118
|
+
if configSrc.Truthy() {
|
|
119
|
+
// We don't care about errors here, if we can get a config object
|
|
120
|
+
// back we'll use it, if not then we'll run validation without it
|
|
121
|
+
cfg, _ = config.LoadFromBytes([]byte(configSrc.String()))
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
completions := completions.Completions(schemaFiles, pos, cfg)
|
|
90
125
|
|
|
91
126
|
untypedCompletions := toUntypedArray(completions)
|
|
92
127
|
|
|
@@ -155,28 +190,46 @@ func formatSchema(this js.Value, args []js.Value) any {
|
|
|
155
190
|
})
|
|
156
191
|
}
|
|
157
192
|
|
|
158
|
-
//
|
|
193
|
+
// Expected argument to validate API:
|
|
159
194
|
//
|
|
160
|
-
//
|
|
195
|
+
// {
|
|
196
|
+
// schemaFiles: [
|
|
197
|
+
// {
|
|
198
|
+
// filename: "",
|
|
199
|
+
// contents: "",
|
|
200
|
+
// },
|
|
201
|
+
// ],
|
|
202
|
+
// config: "<YAML config file>"
|
|
203
|
+
// }
|
|
204
|
+
//
|
|
205
|
+
// The config file source is optional.
|
|
161
206
|
func validate(this js.Value, args []js.Value) any {
|
|
162
207
|
return newPromise(func() (any, error) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
208
|
+
|
|
209
|
+
schemaFilesArg := args[0].Get("schemaFiles")
|
|
210
|
+
schemaFiles := []reader.SchemaFile{}
|
|
211
|
+
for i := 0; i < schemaFilesArg.Length(); i++ {
|
|
212
|
+
f := schemaFilesArg.Index(i)
|
|
213
|
+
schemaFiles = append(schemaFiles, reader.SchemaFile{
|
|
214
|
+
FileName: f.Get("filename").String(),
|
|
215
|
+
Contents: f.Get("contents").String(),
|
|
216
|
+
})
|
|
166
217
|
}
|
|
167
218
|
|
|
168
219
|
builder := schema.Builder{}
|
|
169
220
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if
|
|
173
|
-
|
|
221
|
+
configSrc := args[0].Get("config")
|
|
222
|
+
if configSrc.Truthy() {
|
|
223
|
+
// We don't care about errors here, if we can get a config object
|
|
224
|
+
// back we'll use it, if not then we'll run validation without it
|
|
225
|
+
config, _ := config.LoadFromBytes([]byte(configSrc.String()))
|
|
226
|
+
if config != nil {
|
|
227
|
+
builder.Config = config
|
|
174
228
|
}
|
|
175
|
-
builder.Config = config
|
|
176
229
|
}
|
|
177
230
|
|
|
178
231
|
_, err := builder.MakeFromInputs(&reader.Inputs{
|
|
179
|
-
SchemaFiles:
|
|
232
|
+
SchemaFiles: schemaFiles,
|
|
180
233
|
})
|
|
181
234
|
|
|
182
235
|
if err != nil {
|