kayvee 3.18.0 → 4.0.0

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 (58) hide show
  1. package/README.md +147 -202
  2. package/dist/index.d.ts +4 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +29 -0
  5. package/dist/kayvee.d.ts +12 -0
  6. package/dist/kayvee.d.ts.map +1 -0
  7. package/{build/lib → dist}/kayvee.js +17 -30
  8. package/dist/logger/logger.d.ts +49 -0
  9. package/dist/logger/logger.d.ts.map +1 -0
  10. package/{build/lib → dist}/logger/logger.js +91 -83
  11. package/dist/middleware.d.ts +23 -0
  12. package/dist/middleware.d.ts.map +1 -0
  13. package/dist/middleware.js +196 -0
  14. package/dist/package.json +89 -0
  15. package/dist/router/index.d.ts +23 -0
  16. package/dist/router/index.d.ts.map +1 -0
  17. package/{build/lib → dist}/router/index.js +33 -45
  18. package/package.json +63 -27
  19. package/.circleci/config.yml +0 -25
  20. package/.eslintrc.js +0 -124
  21. package/.github/workflows/notify-ci-status.yml +0 -20
  22. package/.nvmrc +0 -1
  23. package/.prettierrc.json +0 -1
  24. package/Makefile +0 -55
  25. package/benchmarks/data/.keep +0 -1
  26. package/benchmarks/data/corpus-basic.json +0 -22
  27. package/benchmarks/data/corpus-pathological.json +0 -22
  28. package/benchmarks/data/corpus-realistic.json +0 -22
  29. package/benchmarks/data/kvconfig-basic.yml +0 -7
  30. package/benchmarks/data/kvconfig-pathological.yml +0 -222
  31. package/benchmarks/data/kvconfig-realistic.yml +0 -39
  32. package/benchmarks/routing.js +0 -116
  33. package/build/lib/logger/helpers.js +0 -0
  34. package/build/lib/middleware.js +0 -274
  35. package/build/package.json +0 -53
  36. package/build/test/context_logger.js +0 -69
  37. package/build/test/kayvee.js +0 -36
  38. package/build/test/logger_test.js +0 -345
  39. package/build/test/middleware.js +0 -556
  40. package/build/test/router.js +0 -451
  41. package/index.js +0 -7
  42. package/lib/kayvee.ts +0 -73
  43. package/lib/logger/helpers.ts +0 -0
  44. package/lib/logger/logger.ts +0 -312
  45. package/lib/middleware.ts +0 -317
  46. package/lib/router/index.ts +0 -234
  47. package/lib/router/schema_definitions.json +0 -158
  48. package/test/context_logger.ts +0 -76
  49. package/test/kayvee.ts +0 -50
  50. package/test/kvconfig.yml +0 -14
  51. package/test/logger_test.ts +0 -378
  52. package/test/middleware.ts +0 -632
  53. package/test/router.ts +0 -558
  54. package/test/static/empty.css +0 -0
  55. package/test/static/js/empty.js +0 -0
  56. package/test/tests.json +0 -100
  57. package/tsconfig.json +0 -10
  58. /package/{build/lib → dist}/router/schema_definitions.json +0 -0
package/test/router.ts DELETED
@@ -1,558 +0,0 @@
1
- var assert = require("assert");
2
- var router = require("../lib/router");
3
-
4
- describe("router.Router", () => {
5
- describe("constructor", () => {
6
- it("parses well formatted configs", () => {
7
- process.env.SCHOOL = "Hogwarts";
8
- const conf = `
9
- routes:
10
- rule-one:
11
- matchers:
12
- title: ["authorize-app"]
13
- output:
14
- type: "notifications"
15
- channel: "%{foo.bar}"
16
- icon: ":rocket:"
17
- message: "authorized %{foo.bar} in \${SCHOOL}"
18
- user: "@fishman"
19
- rule-two:
20
- matchers:
21
- foo.bar: ["multiple", "matches"]
22
- baz: ["whatever"]
23
- output:
24
- type: "alerts"
25
- series: "other-series"
26
- dimensions: ["baz"]
27
- stat_type: "gauge"
28
- rule-three:
29
- matchers:
30
- foo.bar: ["multiple", "matches"]
31
- baz: ["whatever"]
32
- output:
33
- type: "alerts"
34
- series: "other-series"
35
- dimensions: ["baz"]
36
- stat_type: "gauge"
37
- value_field: "hello"
38
- rule-four:
39
- matchers:
40
- foo.bar: ["multiple", "matches"]
41
- baz: ["whatever"]
42
- output:
43
- type: "alerts"
44
- series: "other-series"
45
- dimensions: []
46
- stat_type: "gauge"
47
- rule-five:
48
- matchers:
49
- foo.bar: [true]
50
- baz: [false]
51
- output:
52
- type: "alerts"
53
- series: "other-series"
54
- dimensions: []
55
- stat_type: "gauge"
56
- `;
57
- const expected = [
58
- new router.Rule(
59
- "rule-one",
60
- { title: ["authorize-app"] },
61
- {
62
- type: "notifications",
63
- channel: "%{foo.bar}",
64
- icon: ":rocket:",
65
- message: "authorized %{foo.bar} in Hogwarts",
66
- user: "@fishman",
67
- },
68
- ),
69
- new router.Rule(
70
- "rule-two",
71
- { "foo.bar": ["multiple", "matches"], baz: ["whatever"] },
72
- {
73
- type: "alerts",
74
- series: "other-series",
75
- dimensions: ["baz"],
76
- stat_type: "gauge",
77
- value_field: "value",
78
- },
79
- ),
80
- new router.Rule(
81
- "rule-three",
82
- { "foo.bar": ["multiple", "matches"], baz: ["whatever"] },
83
- {
84
- type: "alerts",
85
- series: "other-series",
86
- dimensions: ["baz"],
87
- stat_type: "gauge",
88
- value_field: "hello",
89
- },
90
- ),
91
- new router.Rule(
92
- "rule-four",
93
- { "foo.bar": ["multiple", "matches"], baz: ["whatever"] },
94
- {
95
- type: "alerts",
96
- series: "other-series",
97
- dimensions: [],
98
- stat_type: "gauge",
99
- value_field: "value",
100
- },
101
- ),
102
- new router.Rule(
103
- "rule-five",
104
- { "foo.bar": [true], baz: [false] },
105
- {
106
- type: "alerts",
107
- series: "other-series",
108
- dimensions: [],
109
- stat_type: "gauge",
110
- value_field: "value",
111
- },
112
- ),
113
- ];
114
- const actual = new router.Router();
115
- actual._loadConfigString(conf);
116
- assert.deepEqual(actual.rules, expected);
117
- });
118
-
119
- it("rejects specials in matchers", () => {
120
- const confTmpl = (v) => `
121
- routes:
122
- non-string-values:
123
- matchers:
124
- no-numbers: [${v}]
125
- output:
126
- type: "analytics"
127
- series: "fun"
128
- `;
129
-
130
- // Make sure the template works
131
- const conf = confTmpl('"valid"');
132
- const actual = new router.Router();
133
- assert.doesNotThrow(() => actual._loadConfigString(conf));
134
-
135
- for (const invalidVal of ["5", "[]", "{}"]) {
136
- const invalidConf = confTmpl(invalidVal);
137
- assert.throws(() => actual._loadConfigString(invalidConf));
138
- }
139
- assert.throws(() => actual._loadConfigString(confTmpl('""')));
140
- return;
141
- });
142
-
143
- it("rejects duplicates in matchers", () => {
144
- const confTmpl = (v) => `
145
- routes:
146
- sloppy:
147
- matchers:
148
- title: [${v}]
149
- output:
150
- type: "analytics"
151
- series: "fun"
152
- `;
153
-
154
- const actual = new router.Router();
155
- const validConf = confTmpl('"non-repeated", "name"');
156
- assert.doesNotThrow(() => actual._loadConfigString(validConf));
157
-
158
- const invalidConf = confTmpl('"repeated", "repeated", "name"');
159
- assert.throws(() => actual._loadConfigString(invalidConf));
160
- });
161
-
162
- it("requires correct types in outputs", () => {
163
- const confTmpl = (series, dimensions) => `
164
- routes:
165
- wrong:
166
- matchers:
167
- title: ["test"]
168
- output:
169
- type: "alerts"
170
- series: ${series}
171
- dimensions: ${dimensions}
172
- value_field: "hihi"
173
- stat_type: "gauge"
174
- `;
175
-
176
- const actual = new router.Router();
177
- const validConf = confTmpl('"my-series"', '["dim1", "dim2"]');
178
- assert.doesNotThrow(() => actual._loadConfigString(validConf));
179
-
180
- const invalidConf0 = confTmpl('["my-series"]', '["dim1", "dim2"]');
181
- assert.throws(() => actual._loadConfigString(invalidConf0));
182
-
183
- const invalidConf1 = confTmpl('"my-series"', '"dim1"');
184
- assert.throws(() => actual._loadConfigString(invalidConf1));
185
- });
186
-
187
- it("requires all keys in outputs", () => {
188
- const confTmpl = (v) => `
189
- routes:
190
- wrong:
191
- matchers:
192
- title: ["test"]
193
- output:
194
- type: "alerts"${v}
195
- dimensions: ["dim1", "dim2"]
196
- stat_type: "gauge"
197
- `;
198
-
199
- const actual = new router.Router();
200
- const validConf = confTmpl(`
201
- series: "whatever"`);
202
- assert.doesNotThrow(() => actual._loadConfigString(validConf));
203
-
204
- const invalidConf = confTmpl("");
205
- assert.throws(() => actual._loadConfigString(invalidConf));
206
- });
207
-
208
- it("doesn't allow extra keys", () => {
209
- const confTmpl = (v) => `
210
- routes:
211
- wrong:
212
- matchers:
213
- title: ["test"]
214
- output:
215
- type: "metrics"${v}
216
- dimensions: ["dim1", "dim2"]
217
- `;
218
-
219
- const actual = new router.Router();
220
- const validConf = confTmpl(`
221
- series: "whatever"`);
222
- assert.doesNotThrow(() => actual._loadConfigString(validConf));
223
-
224
- const invalidConf = confTmpl(`
225
- series: "whatever"
226
- something-else: "hi there"`);
227
- assert.throws(() => actual._loadConfigString(invalidConf));
228
- });
229
-
230
- it("errors on type-os", () => {
231
- const actual = new router.Router();
232
- let config;
233
-
234
- config = `
235
- route: # Should be routes (plural)
236
- string-values:
237
- matchers:
238
- errors: [ "type-o" ]
239
- output:
240
- type: "analytics"
241
- series: "fun"
242
- `;
243
- assert.throws(() => actual._loadConfigString(config));
244
-
245
- config = `
246
- routes:
247
- string-values:
248
- matcher: # Should be matchers (plural)
249
- errors: [ "type-o" ]
250
- output:
251
- type: "analytics"
252
- series: "fun"
253
- `;
254
- assert.throws(() => actual._loadConfigString(config));
255
-
256
- config = `
257
- routes:
258
- string-values:
259
- matchers:
260
- errors: [ "type-o" ]
261
- outputs: # Should be output (signular)
262
- type: "analytics"
263
- series: "fun"
264
- `;
265
- assert.throws(() => actual._loadConfigString(config));
266
-
267
- config = `
268
- routes:
269
- $invalid-string-values: # Invalid rule name
270
- matchers:
271
- errors: [ "type-o" ]
272
- output:
273
- type: "analytics"
274
- series: "fun"
275
- `;
276
- assert.throws(() => actual._loadConfigString(config));
277
-
278
- config = `
279
- routes:
280
- string-values:
281
- matchers:
282
- errors: [ "type-o" ]
283
- output:
284
- type: "analytic" # Should be analytics (plural)p
285
- series: "fun"
286
- `;
287
- assert.throws(() => actual._loadConfigString(config));
288
-
289
- config = `
290
- routes:
291
- string-values:
292
- matchers:
293
- errors: [ "*", "type-o" ] # A wildcard cannot exist with other matchers
294
- output:
295
- type: "analytics"
296
- series: "fun"
297
- `;
298
- assert.throws(() => actual._loadConfigString(config));
299
- });
300
- });
301
-
302
- describe("route", () => {
303
- it("matches one or more rule and returns appropriate outputs", () => {
304
- const r = new router.Router([
305
- new router.Rule(
306
- "rule-one",
307
- { title: ["hello", "hi"], foo: ["bar", "baz"] },
308
- { channel: "#-%{foo}-", dimensions: ["-%{foo}-"] },
309
- ),
310
- new router.Rule("rule-two", { "bing.bong": ["buzz"] }, { series: "x" }),
311
- ]);
312
-
313
- const msg0 = {
314
- title: "hi",
315
- foo: "bar",
316
- };
317
- const expected0 = [
318
- {
319
- rule: "rule-one",
320
- channel: "#-bar-",
321
- dimensions: ["-bar-"],
322
- },
323
- ];
324
- const actual0 = r.route(msg0).routes;
325
- assert.deepEqual(expected0, actual0);
326
-
327
- const msg1 = {
328
- title: "hi",
329
- bing: {
330
- bong: "buzz",
331
- },
332
- };
333
- const expected1 = [
334
- {
335
- rule: "rule-two",
336
- series: "x",
337
- },
338
- ];
339
- const actual1 = r.route(msg1).routes;
340
- assert.deepEqual(expected1, actual1);
341
-
342
- const msg2 = {
343
- title: "hello",
344
- foo: "baz",
345
- bing: {
346
- bong: "buzz",
347
- },
348
- };
349
- const expected2 = [
350
- {
351
- rule: "rule-one",
352
- channel: "#-baz-",
353
- dimensions: ["-baz-"],
354
- },
355
- {
356
- rule: "rule-two",
357
- series: "x",
358
- },
359
- ];
360
- const actual2 = r.route(msg2).routes;
361
- assert.deepEqual(expected2, actual2);
362
- });
363
- });
364
- });
365
-
366
- describe("router.Rule", () => {
367
- describe("matches", () => {
368
- it("works on simple cases", () => {
369
- const r = new router.Rule("test-rule", { title: ["hello", "hi"], foo: ["bar"] }, {});
370
- assert(
371
- r.matches({
372
- title: "hello",
373
- foo: "bar",
374
- }),
375
- );
376
- assert(
377
- r.matches({
378
- title: "hi",
379
- foo: "bar",
380
- }),
381
- );
382
- assert(
383
- !r.matches({
384
- title: "hi",
385
- foo: "fighters",
386
- }),
387
- );
388
- assert(
389
- !r.matches({
390
- title: "howdy",
391
- foo: "bar",
392
- }),
393
- );
394
- assert(
395
- !r.matches({
396
- "missing-stuff": "indeed",
397
- }),
398
- );
399
- });
400
-
401
- it("works on nested messages", () => {
402
- const r = new router.Rule("test-rule", { "foo.bar": ["hello", "hi"] }, {});
403
- assert(
404
- r.matches({
405
- title: "greeting",
406
- foo: {
407
- bar: "hello",
408
- },
409
- }),
410
- );
411
- assert(
412
- r.matches({
413
- title: "greeting",
414
- foo: {
415
- bar: "hi",
416
- },
417
- }),
418
- );
419
- assert(
420
- !r.matches({
421
- title: "greeting",
422
- foo: {
423
- bar: "howdy",
424
- },
425
- }),
426
- );
427
- assert(
428
- !r.matches({
429
- title: "greeting",
430
- foo: {
431
- baz: "howdy",
432
- },
433
- }),
434
- );
435
- assert(
436
- !r.matches({
437
- title: "greeting",
438
- boo: {
439
- bar: "howdy",
440
- },
441
- }),
442
- );
443
- assert(
444
- !r.matches({
445
- title: "greeting",
446
- foo: "hi",
447
- }),
448
- );
449
- });
450
- it("wild card matching", () => {
451
- const r = new router.Rule("test-rule", { any: ["*"] }, {});
452
- assert(
453
- r.matches({
454
- any: false,
455
- }),
456
- );
457
- assert(
458
- r.matches({
459
- any: 5,
460
- }),
461
- );
462
- assert(
463
- r.matches({
464
- any: "hello",
465
- }),
466
- );
467
- assert(
468
- r.matches({
469
- any: {
470
- bar: "hi",
471
- },
472
- }),
473
- );
474
- assert(
475
- !r.matches({
476
- any: "",
477
- }),
478
- );
479
- assert(
480
- !r.matches({
481
- any: null,
482
- }),
483
- );
484
- assert(
485
- !r.matches({
486
- any: undefined,
487
- }),
488
- );
489
- assert(
490
- !r.matches({
491
- title: "greeting",
492
- foo: {
493
- bar: "howdy",
494
- },
495
- }),
496
- );
497
- });
498
- it("bool matching", () => {
499
- const r = new router.Rule("test-rule", { bull: [true] }, {});
500
- assert(
501
- r.matches({
502
- bull: true,
503
- }),
504
- );
505
- assert(
506
- r.matches({
507
- any: false,
508
- bull: true,
509
- }),
510
- );
511
- assert(
512
- !r.matches({
513
- bull: false,
514
- }),
515
- );
516
- assert(
517
- !r.matches({
518
- bull: "false",
519
- }),
520
- );
521
- assert(
522
- !r.matches({
523
- title: "greeting",
524
- foo: {
525
- bar: "howdy",
526
- },
527
- }),
528
- );
529
- });
530
- });
531
-
532
- describe("outputFor", () => {
533
- it("substitutes kv entries", () => {
534
- const r = new router.Rule(
535
- "myrule",
536
- {},
537
- {
538
- channel: "#-%{foo}-",
539
- dimensions: ["-%{foo}-", "-%{bar.baz}-"],
540
- },
541
- );
542
- const msg = {
543
- title: "greeting",
544
- foo: "partner",
545
- bar: {
546
- baz: "nest egg",
547
- },
548
- };
549
- const expected = {
550
- rule: "myrule",
551
- channel: "#-partner-",
552
- dimensions: ["-partner-", "-nest egg-"],
553
- };
554
- const actual = r.outputFor(msg);
555
- assert.deepEqual(expected, actual);
556
- });
557
- });
558
- });
File without changes
File without changes
package/test/tests.json DELETED
@@ -1,100 +0,0 @@
1
- {
2
- "version": "1.0.0",
3
- "format": [
4
- {
5
- "title": "allows empty data",
6
- "input": {
7
- "data" : {}
8
- },
9
- "output": "{}"
10
- },
11
- {
12
- "title": "maps one data field",
13
- "input": {
14
- "data" : {
15
- "context": "fake_context"
16
- }
17
- },
18
- "output": "{\"context\":\"fake_context\"}"
19
- },
20
- {
21
- "title": "maps multiple data fields",
22
- "input": {
23
- "data" : {
24
- "level": "WARNING",
25
- "context": "fake_context"
26
- }
27
- },
28
- "output": "{\"context\":\"fake_context\",\"level\":\"WARNING\"}"
29
- },
30
- {
31
- "title": "allows nested objects",
32
- "input": {
33
- "data" : {
34
- "baz": {
35
- "nested": "object"
36
- }
37
- }
38
-
39
- },
40
- "output": "{\"baz\":{\"nested\":\"object\"}}"
41
- },
42
- {
43
- "title": "allows spaces",
44
- "input": {
45
- "data" : {
46
- "spaces": " set c"
47
- }
48
- },
49
- "output": "{\"spaces\":\" set c\"}"
50
- },
51
- {
52
- "title": "allows single-quote",
53
- "input": {
54
- "data" : {
55
- "singlequote": "'"
56
- }
57
- },
58
- "output": "{\"singlequote\":\"'\"}"
59
- },
60
- {
61
- "title": "allows double-quote",
62
- "input": {
63
- "data" : {
64
- "doublequote": "\""
65
- }
66
- },
67
- "output": "{\"doublequote\":\"\\\"\"}"
68
- }
69
- ],
70
- "formatLog": [
71
- {
72
- "title": "outputs reserved fields",
73
- "input": {
74
- "source": "SOURCE",
75
- "level": "error",
76
- "title": "BAD_THINGS_HAPPENING",
77
- "data": {}
78
- },
79
- "output": "{\"source\":\"SOURCE\",\"level\":\"error\",\"title\":\"BAD_THINGS_HAPPENING\"}"
80
- },
81
- {
82
- "title": "outputs reserved fields and sorted data",
83
- "input": {
84
- "source": "SOURCE",
85
- "level": "error",
86
- "title": "BAD_THINGS_HAPPENING",
87
- "data": {
88
- "foo": "bar",
89
- "baz": "boo"
90
- }
91
- },
92
- "output": "{\"source\":\"SOURCE\",\"level\":\"error\",\"title\":\"BAD_THINGS_HAPPENING\",\"baz\":\"boo\",\"foo\":\"bar\"}"
93
- },
94
- {
95
- "title": "outputs reserved fields, even if undefined",
96
- "input": {},
97
- "output": "{\"source\":\"\",\"level\":\"\",\"title\":\"\"}"
98
- }
99
- ]
100
- }
package/tsconfig.json DELETED
@@ -1,10 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "module": "commonjs",
4
- "target": "ES2019",
5
- "noImplicitAny": false
6
- },
7
- "exclude": [
8
- "node_modules"
9
- ]
10
- }