@liquidmetal-ai/drizzle 0.0.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.
Files changed (76) hide show
  1. package/.changeset/README.md +4 -0
  2. package/.changeset/config.json +11 -0
  3. package/.changeset/odd-plums-dress.md +7 -0
  4. package/.turbo/turbo-build.log +6 -0
  5. package/dist/appify/build.d.ts +130 -0
  6. package/dist/appify/build.d.ts.map +1 -0
  7. package/dist/appify/build.js +703 -0
  8. package/dist/appify/build.test.d.ts +2 -0
  9. package/dist/appify/build.test.d.ts.map +1 -0
  10. package/dist/appify/build.test.js +111 -0
  11. package/dist/appify/index.d.ts +8 -0
  12. package/dist/appify/index.d.ts.map +1 -0
  13. package/dist/appify/index.js +28 -0
  14. package/dist/appify/index.test.d.ts +2 -0
  15. package/dist/appify/index.test.d.ts.map +1 -0
  16. package/dist/appify/index.test.js +40 -0
  17. package/dist/appify/parse.d.ts +151 -0
  18. package/dist/appify/parse.d.ts.map +1 -0
  19. package/dist/appify/parse.js +579 -0
  20. package/dist/appify/parse.test.d.ts +2 -0
  21. package/dist/appify/parse.test.d.ts.map +1 -0
  22. package/dist/appify/parse.test.js +319 -0
  23. package/dist/appify/validate.d.ts +22 -0
  24. package/dist/appify/validate.d.ts.map +1 -0
  25. package/dist/appify/validate.js +346 -0
  26. package/dist/appify/validate.test.d.ts +2 -0
  27. package/dist/appify/validate.test.d.ts.map +1 -0
  28. package/dist/appify/validate.test.js +327 -0
  29. package/dist/codestore.d.ts +34 -0
  30. package/dist/codestore.d.ts.map +1 -0
  31. package/dist/codestore.js +54 -0
  32. package/dist/codestore.test.d.ts +2 -0
  33. package/dist/codestore.test.d.ts.map +1 -0
  34. package/dist/codestore.test.js +84 -0
  35. package/dist/liquidmetal/v1alpha1/catalog_connect.d.ts +147 -0
  36. package/dist/liquidmetal/v1alpha1/catalog_connect.d.ts.map +1 -0
  37. package/dist/liquidmetal/v1alpha1/catalog_connect.js +150 -0
  38. package/dist/liquidmetal/v1alpha1/catalog_pb.d.ts +965 -0
  39. package/dist/liquidmetal/v1alpha1/catalog_pb.d.ts.map +1 -0
  40. package/dist/liquidmetal/v1alpha1/catalog_pb.js +1486 -0
  41. package/dist/liquidmetal/v1alpha1/rainbow_auth_connect.d.ts +49 -0
  42. package/dist/liquidmetal/v1alpha1/rainbow_auth_connect.d.ts.map +1 -0
  43. package/dist/liquidmetal/v1alpha1/rainbow_auth_connect.js +52 -0
  44. package/dist/liquidmetal/v1alpha1/rainbow_auth_pb.d.ts +271 -0
  45. package/dist/liquidmetal/v1alpha1/rainbow_auth_pb.d.ts.map +1 -0
  46. package/dist/liquidmetal/v1alpha1/rainbow_auth_pb.js +381 -0
  47. package/dist/liquidmetal/v1alpha1/raindrop_pb.d.ts +38 -0
  48. package/dist/liquidmetal/v1alpha1/raindrop_pb.d.ts.map +1 -0
  49. package/dist/liquidmetal/v1alpha1/raindrop_pb.js +52 -0
  50. package/dist/unsafe/codestore.d.ts +10 -0
  51. package/dist/unsafe/codestore.d.ts.map +1 -0
  52. package/dist/unsafe/codestore.js +23 -0
  53. package/dist/unsafe/codestore.test.d.ts +2 -0
  54. package/dist/unsafe/codestore.test.d.ts.map +1 -0
  55. package/dist/unsafe/codestore.test.js +27 -0
  56. package/eslint.config.mjs +4 -0
  57. package/package.json +45 -0
  58. package/src/appify/build.test.ts +116 -0
  59. package/src/appify/build.ts +783 -0
  60. package/src/appify/index.test.ts +43 -0
  61. package/src/appify/index.ts +33 -0
  62. package/src/appify/parse.test.ts +337 -0
  63. package/src/appify/parse.ts +744 -0
  64. package/src/appify/validate.test.ts +341 -0
  65. package/src/appify/validate.ts +435 -0
  66. package/src/codestore.test.ts +98 -0
  67. package/src/codestore.ts +93 -0
  68. package/src/liquidmetal/v1alpha1/catalog_connect.ts +153 -0
  69. package/src/liquidmetal/v1alpha1/catalog_pb.ts +1827 -0
  70. package/src/liquidmetal/v1alpha1/rainbow_auth_connect.ts +55 -0
  71. package/src/liquidmetal/v1alpha1/rainbow_auth_pb.ts +476 -0
  72. package/src/liquidmetal/v1alpha1/raindrop_pb.ts +63 -0
  73. package/src/unsafe/codestore.test.ts +34 -0
  74. package/src/unsafe/codestore.ts +29 -0
  75. package/tsconfig.json +31 -0
  76. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,43 @@
1
+ import { expect, test } from 'vitest';
2
+ import { valueOf } from './build.js';
3
+ import { ManifestError, mustManifestFromString } from './index.js';
4
+
5
+ test('mustManifestFromString no errors', async () => {
6
+ const manifest = `
7
+ application "app" {
8
+ service "svc" {}
9
+ }
10
+ `;
11
+ const apps = await mustManifestFromString(manifest);
12
+ expect(apps).toHaveLength(1);
13
+ expect(valueOf(apps[0]!.name)).toBe('app');
14
+ expect(apps[0]!.service).toHaveLength(1);
15
+ expect(valueOf(apps[0]!.service[0]!.name)).toBe('svc');
16
+ });
17
+
18
+ test('mustManifestFromString with errors', async () => {
19
+ const manifest = `
20
+ application "app" {
21
+ service "my-svc" {}
22
+ service "my-svc" {}
23
+ }
24
+ `;
25
+ expect(mustManifestFromString(manifest)).rejects.toThrowError(ManifestError);
26
+ });
27
+
28
+ test('mustManifestFromString with warnings', async () => {
29
+ const manifest = `
30
+ application "app" {
31
+ service "svc" {
32
+ domain {
33
+ fqdn = "bad_domain_name"
34
+ }
35
+ }
36
+ }
37
+ `;
38
+ const apps = await mustManifestFromString(manifest);
39
+ expect(apps).toHaveLength(1);
40
+ expect(valueOf(apps[0]!.name)).toBe('app');
41
+ expect(apps[0]!.service).toHaveLength(1);
42
+ expect(valueOf(apps[0]!.service[0]!.name)).toBe('svc');
43
+ });
@@ -0,0 +1,33 @@
1
+ import { Application, buildManifest, ConfigError } from '@liquidmetal-ai/drizzle/appify/build';
2
+ import { Parser, Tokenizer } from '@liquidmetal-ai/drizzle/appify/parse';
3
+ import { validate, VALIDATORS } from '@liquidmetal-ai/drizzle/appify/validate';
4
+
5
+ export class ManifestError extends Error {
6
+ errors: ConfigError[];
7
+
8
+ constructor(errors: ConfigError[]) {
9
+ const message = errors.map((e) => `${e.line}:${e.column} - ${e.message}`).join('\n');
10
+ super(message);
11
+ this.errors = errors;
12
+ }
13
+ }
14
+
15
+ export async function manifestFromString(manifestString: string): Promise<[Application[], ConfigError[]]> {
16
+ const tokenizer = new Tokenizer(manifestString);
17
+ const parser = new Parser(tokenizer);
18
+ const ast = parser.parse();
19
+ const parseErrors = parser.errors;
20
+ const [apps, buildErrors] = buildManifest(ast);
21
+ const validationErrors = await validate(apps, VALIDATORS);
22
+
23
+ return [apps, [...parseErrors, ...buildErrors, ...validationErrors]];
24
+ }
25
+
26
+ // MUST load without errors, but ignores warnings.
27
+ export async function mustManifestFromString(manifestString: string): Promise<Application[]> {
28
+ const [apps, errors] = await manifestFromString(manifestString);
29
+ if (errors.length > 0 && !errors.every((e) => 'severity' in e && e.severity === 'warning')) {
30
+ throw new ManifestError(errors);
31
+ }
32
+ return apps;
33
+ }
@@ -0,0 +1,337 @@
1
+ import { expect, test } from 'vitest';
2
+ import { JSONTranslator, Parser, Tokenizer, fmt } from './parse.js';
3
+
4
+ const CONFIG = `
5
+ application "my-app" {
6
+ service "my-service" {
7
+ domain {
8
+ fqdn = "testymctestface.com"
9
+ }
10
+
11
+ binding {
12
+ // This is a binding of foo to "bar".
13
+ foo = "bar" // this is a comment
14
+ }
15
+
16
+ // comment
17
+ env "API_KEY" {
18
+ secret = true
19
+ }
20
+
21
+ env "API_URL" {
22
+ // Empty but has a comment.
23
+ }
24
+ env "API_PATH" {
25
+ }
26
+ }
27
+ observer "my-observer" {
28
+ source {
29
+ bucket = "my-bucket"
30
+ rule {
31
+ actions = ['PutObject', 'DeleteObject']
32
+ }
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
38
+ `;
39
+
40
+ const CONFIG_FORMATTED = `
41
+ application "my-app" {
42
+ service "my-service" {
43
+ domain {
44
+ fqdn = "testymctestface.com"
45
+ }
46
+
47
+ binding {
48
+ // This is a binding of foo to "bar".
49
+ foo = "bar" // this is a comment
50
+ }
51
+
52
+ // comment
53
+ env "API_KEY" {
54
+ secret = true
55
+ }
56
+
57
+ env "API_URL" {
58
+ // Empty but has a comment.
59
+ }
60
+ env "API_PATH" {}
61
+ }
62
+ observer "my-observer" {
63
+ source {
64
+ bucket = "my-bucket"
65
+ rule {
66
+ actions = ['PutObject', 'DeleteObject']
67
+ }
68
+ }
69
+ }
70
+ }
71
+ `;
72
+
73
+ test('parser', () => {
74
+ const tokenizer = new Tokenizer(CONFIG);
75
+ const parser = new Parser(tokenizer);
76
+ const translator = new JSONTranslator();
77
+ const ast = parser.parse();
78
+ expect(parser.errors).toEqual([]);
79
+ expect(translator.translate(ast)).toEqual({
80
+ application: [
81
+ {
82
+ name: 'my-app',
83
+ observer: [
84
+ {
85
+ name: 'my-observer',
86
+ source: [
87
+ {
88
+ bucket: 'my-bucket',
89
+ rule: [
90
+ {
91
+ actions: ['PutObject', 'DeleteObject'],
92
+ },
93
+ ],
94
+ },
95
+ ],
96
+ },
97
+ ],
98
+ service: [
99
+ {
100
+ name: 'my-service',
101
+ domain: [
102
+ {
103
+ fqdn: 'testymctestface.com',
104
+ },
105
+ ],
106
+ binding: [
107
+ {
108
+ foo: 'bar',
109
+ },
110
+ ],
111
+ env: [
112
+ {
113
+ name: 'API_KEY',
114
+ secret: true,
115
+ },
116
+ {
117
+ name: 'API_URL',
118
+ },
119
+ {
120
+ name: 'API_PATH',
121
+ },
122
+ ],
123
+ },
124
+ ],
125
+ },
126
+ ],
127
+ });
128
+ });
129
+
130
+ test('fmt', () => {
131
+ const tokenizer = new Tokenizer(CONFIG);
132
+ const parser = new Parser(tokenizer);
133
+ const ast = parser.parse();
134
+ expect(fmt(ast)).toEqual(CONFIG_FORMATTED);
135
+ });
136
+
137
+ test('parser errors', () => {
138
+ const tokenizer = new Tokenizer(`
139
+ application "my-app" }
140
+ `);
141
+ const parser = new Parser(tokenizer);
142
+ parser.parse();
143
+ expect(parser.errors).toHaveLength(1);
144
+
145
+ const tokenizer2 = new Tokenizer(`
146
+ application "my-app" {
147
+ service "my-service" {
148
+ domain {
149
+ fqdn = "testymctestface.com"
150
+ }
151
+ }
152
+ `);
153
+ const parser2 = new Parser(tokenizer2);
154
+ parser2.parse();
155
+ expect(parser2.errors).toHaveLength(1);
156
+ });
157
+
158
+ test('wrong curly brace', () => {
159
+ const tokenizer = new Tokenizer(`
160
+ application "my-app" {
161
+ service "my-service" {
162
+ domain {
163
+ fqdn = "testymctestface.com"
164
+ }
165
+ {
166
+ }
167
+ `);
168
+ const parser = new Parser(tokenizer);
169
+ parser.parse();
170
+ expect(parser.errors).toHaveLength(2);
171
+ });
172
+
173
+ test('root parse runs into something unexpected', () => {
174
+ const tokenizer = new Tokenizer(` "foo" `);
175
+ const parser = new Parser(tokenizer);
176
+ parser.parse();
177
+ expect(parser.errors).toHaveLength(1);
178
+ });
179
+
180
+ test('empty is valid (just borring)', () => {
181
+ const tokenizer = new Tokenizer(` `);
182
+ const parser = new Parser(tokenizer);
183
+ parser.parse();
184
+ expect(parser.errors).toHaveLength(0);
185
+ });
186
+
187
+ test('identifier followed by not {, string, number, boolean, operator', () => {
188
+ const tokenizer = new Tokenizer(`
189
+ application "my-app" {
190
+ service "my-service" {
191
+ domain {
192
+ fqdn = "testymctestface.com"
193
+ }
194
+ foo
195
+ }
196
+ }
197
+ `);
198
+ const parser = new Parser(tokenizer);
199
+ parser.parse();
200
+ expect(parser.errors).toHaveLength(1);
201
+ });
202
+
203
+ test("stanza doesn't have string, number, boolean arguments", () => {
204
+ const tokenizer = new Tokenizer(`
205
+ application "my-app" {
206
+ service "my-service" indentifier {
207
+ domain {
208
+ fqdn = "testymctestface.com"
209
+ }
210
+ }
211
+ }
212
+ `);
213
+ const parser = new Parser(tokenizer);
214
+ parser.parse();
215
+ expect(parser.errors).toHaveLength(1);
216
+ });
217
+
218
+ test('unexpected newline in expression', () => {
219
+ const tokenizer = new Tokenizer(`
220
+ application "my-app" {
221
+ service "my-service" {
222
+ domain {
223
+ fqdn = "testymctestface.com"
224
+ }
225
+ foo =
226
+ }
227
+ }
228
+ `);
229
+ const parser = new Parser(tokenizer);
230
+ parser.parse();
231
+ expect(parser.errors).toHaveLength(1);
232
+ });
233
+
234
+ test('unexpected trash in an array', () => {
235
+ const tokenizer = new Tokenizer(`
236
+ application "my-app" {
237
+ service "my-service" {
238
+ domain {
239
+ fqdn = "testymctestface.com"
240
+ }
241
+ foo = [1, 2, 3, } ]
242
+ }
243
+ }
244
+ `);
245
+ const parser = new Parser(tokenizer);
246
+ parser.parse();
247
+ expect(parser.errors).toHaveLength(1);
248
+ });
249
+
250
+ test('unclosed array', () => {
251
+ const tokenizer = new Tokenizer(`
252
+ application "my-app" {
253
+ service "my-service" {
254
+ domain {
255
+ fqdn = "testymctestface.com"
256
+ }
257
+ foo = [1, 2, 3, }
258
+ }
259
+ }
260
+ `);
261
+ const parser = new Parser(tokenizer);
262
+ parser.parse();
263
+ expect(parser.errors).toHaveLength(2); // unexpecte curly and expected ]
264
+ });
265
+
266
+ test('parse object', () => {
267
+ const tokenizer = new Tokenizer(`
268
+ application "my-app" {
269
+ service "my-service" {
270
+ domain {
271
+ fqdn = "testymctestface.com"
272
+ }
273
+ foo = {
274
+ bar = "baz"
275
+ }
276
+ }
277
+ }
278
+ `);
279
+ const parser = new Parser(tokenizer);
280
+ parser.parse();
281
+ console.log(parser.errors);
282
+ expect(parser.errors).toHaveLength(0);
283
+ });
284
+
285
+ test('parse object with trash', () => {
286
+ const tokenizer = new Tokenizer(`
287
+ application "my-app" {
288
+ service "my-service" {
289
+ domain {
290
+ fqdn = "testymctestface.com"
291
+ }
292
+ foo = {
293
+ bar = "baz"
294
+ baz
295
+ }
296
+ }
297
+ }
298
+ `);
299
+ const parser = new Parser(tokenizer);
300
+ parser.parse();
301
+ expect(parser.errors).toHaveLength(2); // missing = and expression
302
+ });
303
+
304
+ test('parse object with more trash', () => {
305
+ const tokenizer = new Tokenizer(`
306
+ application "my-app" {
307
+ service "my-service" {
308
+ domain {
309
+ fqdn = "testymctestface.com"
310
+ }
311
+ foo = {
312
+ bar = "baz"
313
+ true = false
314
+ }
315
+ }
316
+ }
317
+ `);
318
+ const parser = new Parser(tokenizer);
319
+ parser.parse();
320
+ expect(parser.errors).toHaveLength(3);
321
+ });
322
+
323
+ test('parse object that EOFs', () => {
324
+ const tokenizer = new Tokenizer(`
325
+ application "my-app" {
326
+ service "my-service" {
327
+ domain {
328
+ fqdn = "testymctestface.com"
329
+ }
330
+ foo = {
331
+ bar = "baz"
332
+ `);
333
+ const parser = new Parser(tokenizer);
334
+ parser.parse();
335
+ // Failed to close 3 curly braces.
336
+ expect(parser.errors).toHaveLength(3);
337
+ });