@shakerquiz/utilities 4.0.55 → 4.0.56

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@shakerquiz/utilities",
4
- "version": "4.0.55",
4
+ "version": "4.0.56",
5
5
  "author": "yurkimus <yurkimus@gmail.com>",
6
6
  "license": "ISC",
7
7
  "repository": {
@@ -15,7 +15,7 @@
15
15
  "prepublishOnly": "bun scripts/codegen.js && dprint fmt --includes-override source/codegen/autogenerated.js"
16
16
  },
17
17
  "devDependencies": {
18
- "@types/bun": "1.3.6",
18
+ "@types/bun": "1.3.8",
19
19
  "dprint": "0.51.1"
20
20
  }
21
21
  }
@@ -249,31 +249,31 @@ export const RoutePathname = Object.freeze(
249
249
  'themes': 'themes',
250
250
  'themes/search': 'themes/search',
251
251
  'game/search': 'game/:game/search',
252
- 'game/status/search': 'game/:game/status/:status/search',
252
+ 'game/status/search': 'game/:game/status/search',
253
253
  'game/city/search': 'game/:game/city/:city/search',
254
254
  'game/summary/search': 'game/:game/summary/search',
255
255
  'game/theme/search': 'game/:game/theme/:theme/search',
256
256
  'game/theme/cover/search': 'game/:game/theme/:theme/cover/:cover/search',
257
257
  'game/venue/search': 'game/:game/venue/:venue/search',
258
258
  'game/registration': 'game/:game/registration/:registration',
259
- 'game/registration/status': 'game/:game/registration/:registration/status/:status',
259
+ 'game/registration/status': 'game/:game/registration/:registration/status',
260
260
  'game/registration/lineup': 'game/:game/registration/:registration/lineup',
261
261
  'game/registrations': 'game/:game/registrations',
262
- 'game/registrations/status': 'game/:game/registrations/status/:status',
262
+ 'game/registrations/status': 'game/:game/registrations/status',
263
263
  'game/registrations/lineup': 'game/:game/registrations/lineup',
264
264
  'game/summary': 'game/:game/summary',
265
265
  'game/theme': 'game/:game/theme/:theme',
266
266
  'game/theme/cover': 'game/:game/theme/:theme/cover/:cover',
267
267
  'game/venue': 'game/:game/venue/:venue',
268
268
  'games/search': 'games/search',
269
- 'games/status/search': 'games/status/:status/search',
269
+ 'games/status/search': 'games/status/search',
270
270
  'games/city/search': 'games/city/:city/search',
271
271
  'games/summary/search': 'games/summary/search',
272
272
  'games/theme/search': 'games/theme/:theme/search',
273
273
  'games/theme/cover/search': 'games/theme/:theme/cover/:cover/search',
274
274
  'games/venue/search': 'games/venue/:venue/search',
275
275
  'registration/search': 'registration/:registration/search',
276
- 'registration/status/search': 'registration/:registration/status/:status/search',
276
+ 'registration/status/search': 'registration/:registration/status/search',
277
277
  'registration/creation': 'registration/:registration/creation',
278
278
  'registration/confirmation': 'registration/:registration/confirmation',
279
279
  'registration/cancellation': 'registration/:registration/cancellation',
@@ -286,11 +286,11 @@ export const RoutePathname = Object.freeze(
286
286
  'registration/game/theme/cover/search': 'registration/:registration/game/:game/theme/:theme/cover/:cover/search',
287
287
  'registration/game/venue/search': 'registration/:registration/game/:game/venue/:venue/search',
288
288
  'registrations/search': 'registrations/search',
289
- 'registrations/status/search': 'registrations/status/:status/search',
289
+ 'registrations/status/search': 'registrations/status/search',
290
290
  'registrations/lineup/search': 'registrations/lineup/search',
291
291
  'registrations/city/search': 'registrations/city/:city/search',
292
292
  'registrations/game/search': 'registrations/game/:game/search',
293
- 'registrations/game/status/search': 'registrations/game/:game/status/:status/search',
293
+ 'registrations/game/status/search': 'registrations/game/:game/status/search',
294
294
  'registrations/game/theme/search': 'registrations/game/:game/theme/:theme/search',
295
295
  'registrations/game/venue/search': 'registrations/game/:game/venue/:venue/search',
296
296
  'telegram/webhook': 'telegram/webhook',
@@ -423,7 +423,6 @@ export const RouteParameters = Object.freeze(
423
423
  ],
424
424
  'game/status/search': [
425
425
  ':game',
426
- ':status',
427
426
  ],
428
427
  'game/city/search': [
429
428
  ':game',
@@ -452,7 +451,6 @@ export const RouteParameters = Object.freeze(
452
451
  'game/registration/status': [
453
452
  ':game',
454
453
  ':registration',
455
- ':status',
456
454
  ],
457
455
  'game/registration/lineup': [
458
456
  ':game',
@@ -463,7 +461,6 @@ export const RouteParameters = Object.freeze(
463
461
  ],
464
462
  'game/registrations/status': [
465
463
  ':game',
466
- ':status',
467
464
  ],
468
465
  'game/registrations/lineup': [
469
466
  ':game',
@@ -485,9 +482,7 @@ export const RouteParameters = Object.freeze(
485
482
  ':venue',
486
483
  ],
487
484
  'games/search': [],
488
- 'games/status/search': [
489
- ':status',
490
- ],
485
+ 'games/status/search': [],
491
486
  'games/city/search': [
492
487
  ':city',
493
488
  ],
@@ -507,7 +502,6 @@ export const RouteParameters = Object.freeze(
507
502
  ],
508
503
  'registration/status/search': [
509
504
  ':registration',
510
- ':status',
511
505
  ],
512
506
  'registration/creation': [
513
507
  ':registration',
@@ -552,9 +546,7 @@ export const RouteParameters = Object.freeze(
552
546
  ':venue',
553
547
  ],
554
548
  'registrations/search': [],
555
- 'registrations/status/search': [
556
- ':status',
557
- ],
549
+ 'registrations/status/search': [],
558
550
  'registrations/lineup/search': [],
559
551
  'registrations/city/search': [
560
552
  ':city',
@@ -564,7 +556,6 @@ export const RouteParameters = Object.freeze(
564
556
  ],
565
557
  'registrations/game/status/search': [
566
558
  ':game',
567
- ':status',
568
559
  ],
569
560
  'registrations/game/theme/search': [
570
561
  ':game',
@@ -639,31 +630,31 @@ export const PathnameRoute = Object.freeze(
639
630
  'themes': 'themes',
640
631
  'themes/search': 'themes/search',
641
632
  'game/:game/search': 'game/search',
642
- 'game/:game/status/:status/search': 'game/status/search',
633
+ 'game/:game/status/search': 'game/status/search',
643
634
  'game/:game/city/:city/search': 'game/city/search',
644
635
  'game/:game/summary/search': 'game/summary/search',
645
636
  'game/:game/theme/:theme/search': 'game/theme/search',
646
637
  'game/:game/theme/:theme/cover/:cover/search': 'game/theme/cover/search',
647
638
  'game/:game/venue/:venue/search': 'game/venue/search',
648
639
  'game/:game/registration/:registration': 'game/registration',
649
- 'game/:game/registration/:registration/status/:status': 'game/registration/status',
640
+ 'game/:game/registration/:registration/status': 'game/registration/status',
650
641
  'game/:game/registration/:registration/lineup': 'game/registration/lineup',
651
642
  'game/:game/registrations': 'game/registrations',
652
- 'game/:game/registrations/status/:status': 'game/registrations/status',
643
+ 'game/:game/registrations/status': 'game/registrations/status',
653
644
  'game/:game/registrations/lineup': 'game/registrations/lineup',
654
645
  'game/:game/summary': 'game/summary',
655
646
  'game/:game/theme/:theme': 'game/theme',
656
647
  'game/:game/theme/:theme/cover/:cover': 'game/theme/cover',
657
648
  'game/:game/venue/:venue': 'game/venue',
658
649
  'games/search': 'games/search',
659
- 'games/status/:status/search': 'games/status/search',
650
+ 'games/status/search': 'games/status/search',
660
651
  'games/city/:city/search': 'games/city/search',
661
652
  'games/summary/search': 'games/summary/search',
662
653
  'games/theme/:theme/search': 'games/theme/search',
663
654
  'games/theme/:theme/cover/:cover/search': 'games/theme/cover/search',
664
655
  'games/venue/:venue/search': 'games/venue/search',
665
656
  'registration/:registration/search': 'registration/search',
666
- 'registration/:registration/status/:status/search': 'registration/status/search',
657
+ 'registration/:registration/status/search': 'registration/status/search',
667
658
  'registration/:registration/creation': 'registration/creation',
668
659
  'registration/:registration/confirmation': 'registration/confirmation',
669
660
  'registration/:registration/cancellation': 'registration/cancellation',
@@ -676,11 +667,11 @@ export const PathnameRoute = Object.freeze(
676
667
  'registration/:registration/game/:game/theme/:theme/cover/:cover/search': 'registration/game/theme/cover/search',
677
668
  'registration/:registration/game/:game/venue/:venue/search': 'registration/game/venue/search',
678
669
  'registrations/search': 'registrations/search',
679
- 'registrations/status/:status/search': 'registrations/status/search',
670
+ 'registrations/status/search': 'registrations/status/search',
680
671
  'registrations/lineup/search': 'registrations/lineup/search',
681
672
  'registrations/city/:city/search': 'registrations/city/search',
682
673
  'registrations/game/:game/search': 'registrations/game/search',
683
- 'registrations/game/:game/status/:status/search': 'registrations/game/status/search',
674
+ 'registrations/game/:game/status/search': 'registrations/game/status/search',
684
675
  'registrations/game/:game/theme/:theme/search': 'registrations/game/theme/search',
685
676
  'registrations/game/:game/venue/:venue/search': 'registrations/game/venue/search',
686
677
  'telegram/webhook': 'telegram/webhook',
@@ -811,9 +802,8 @@ export const PathnameParameters = Object.freeze(
811
802
  'game/:game/search': [
812
803
  ':game',
813
804
  ],
814
- 'game/:game/status/:status/search': [
805
+ 'game/:game/status/search': [
815
806
  ':game',
816
- ':status',
817
807
  ],
818
808
  'game/:game/city/:city/search': [
819
809
  ':game',
@@ -839,10 +829,9 @@ export const PathnameParameters = Object.freeze(
839
829
  ':game',
840
830
  ':registration',
841
831
  ],
842
- 'game/:game/registration/:registration/status/:status': [
832
+ 'game/:game/registration/:registration/status': [
843
833
  ':game',
844
834
  ':registration',
845
- ':status',
846
835
  ],
847
836
  'game/:game/registration/:registration/lineup': [
848
837
  ':game',
@@ -851,9 +840,8 @@ export const PathnameParameters = Object.freeze(
851
840
  'game/:game/registrations': [
852
841
  ':game',
853
842
  ],
854
- 'game/:game/registrations/status/:status': [
843
+ 'game/:game/registrations/status': [
855
844
  ':game',
856
- ':status',
857
845
  ],
858
846
  'game/:game/registrations/lineup': [
859
847
  ':game',
@@ -875,9 +863,7 @@ export const PathnameParameters = Object.freeze(
875
863
  ':venue',
876
864
  ],
877
865
  'games/search': [],
878
- 'games/status/:status/search': [
879
- ':status',
880
- ],
866
+ 'games/status/search': [],
881
867
  'games/city/:city/search': [
882
868
  ':city',
883
869
  ],
@@ -895,9 +881,8 @@ export const PathnameParameters = Object.freeze(
895
881
  'registration/:registration/search': [
896
882
  ':registration',
897
883
  ],
898
- 'registration/:registration/status/:status/search': [
884
+ 'registration/:registration/status/search': [
899
885
  ':registration',
900
- ':status',
901
886
  ],
902
887
  'registration/:registration/creation': [
903
888
  ':registration',
@@ -942,9 +927,7 @@ export const PathnameParameters = Object.freeze(
942
927
  ':venue',
943
928
  ],
944
929
  'registrations/search': [],
945
- 'registrations/status/:status/search': [
946
- ':status',
947
- ],
930
+ 'registrations/status/search': [],
948
931
  'registrations/lineup/search': [],
949
932
  'registrations/city/:city/search': [
950
933
  ':city',
@@ -952,9 +935,8 @@ export const PathnameParameters = Object.freeze(
952
935
  'registrations/game/:game/search': [
953
936
  ':game',
954
937
  ],
955
- 'registrations/game/:game/status/:status/search': [
938
+ 'registrations/game/:game/status/search': [
956
939
  ':game',
957
- ':status',
958
940
  ],
959
941
  'registrations/game/:game/theme/:theme/search': [
960
942
  ':game',
@@ -995,7 +977,6 @@ export const ParameterPattern = Object.freeze(
995
977
  ':cover': '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}',
996
978
  ':game': '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}',
997
979
  ':registration': '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}',
998
- ':status': '\w+',
999
980
  }),
1000
981
  )
1001
982
 
@@ -11,6 +11,7 @@ export const Segments = Object.freeze(
11
11
  plural: 'checkins',
12
12
  service: Service['Checkin'],
13
13
  pattern: null,
14
+ kind: 'Operation',
14
15
  }),
15
16
  ),
16
17
  Object.freeze(
@@ -21,6 +22,7 @@ export const Segments = Object.freeze(
21
22
  plural: 'users',
22
23
  service: Service['Users'],
23
24
  pattern: Pattern.UUID.source,
25
+ kind: 'Entity',
24
26
  }),
25
27
  ),
26
28
  Object.freeze(
@@ -31,6 +33,7 @@ export const Segments = Object.freeze(
31
33
  plural: 'users',
32
34
  service: Service['Users'],
33
35
  pattern: null,
36
+ kind: 'Entity',
34
37
  }),
35
38
  ),
36
39
  Object.freeze(
@@ -41,6 +44,7 @@ export const Segments = Object.freeze(
41
44
  plural: 'roles',
42
45
  service: Service['Roles'],
43
46
  pattern: Pattern.UUID.source,
47
+ kind: 'Entity',
44
48
  }),
45
49
  ),
46
50
  Object.freeze(
@@ -51,6 +55,7 @@ export const Segments = Object.freeze(
51
55
  plural: 'roles',
52
56
  service: Service['Roles'],
53
57
  pattern: null,
58
+ kind: 'Entity',
54
59
  }),
55
60
  ),
56
61
  Object.freeze(
@@ -61,6 +66,7 @@ export const Segments = Object.freeze(
61
66
  plural: 'countries',
62
67
  service: Service['Locations'],
63
68
  pattern: Pattern.COUNTRY_CODE.source,
69
+ kind: 'Entity',
64
70
  }),
65
71
  ),
66
72
  Object.freeze(
@@ -71,6 +77,7 @@ export const Segments = Object.freeze(
71
77
  plural: 'countries',
72
78
  service: Service['Locations'],
73
79
  pattern: null,
80
+ kind: 'Entity',
74
81
  }),
75
82
  ),
76
83
  Object.freeze(
@@ -81,6 +88,7 @@ export const Segments = Object.freeze(
81
88
  plural: 'currencies',
82
89
  service: Service['Locations'],
83
90
  pattern: Pattern.CURRENCY_CODE.source,
91
+ kind: 'Entity',
84
92
  }),
85
93
  ),
86
94
  Object.freeze(
@@ -91,6 +99,7 @@ export const Segments = Object.freeze(
91
99
  plural: 'currencies',
92
100
  service: Service['Locations'],
93
101
  pattern: null,
102
+ kind: 'Entity',
94
103
  }),
95
104
  ),
96
105
  Object.freeze(
@@ -101,6 +110,7 @@ export const Segments = Object.freeze(
101
110
  plural: 'timezones',
102
111
  service: Service['Locations'],
103
112
  pattern: Pattern.TIMEZONE_NAME.source,
113
+ kind: 'Entity',
104
114
  }),
105
115
  ),
106
116
  Object.freeze(
@@ -111,6 +121,7 @@ export const Segments = Object.freeze(
111
121
  plural: 'timezones',
112
122
  service: Service['Locations'],
113
123
  pattern: null,
124
+ kind: 'Entity',
114
125
  }),
115
126
  ),
116
127
  Object.freeze(
@@ -121,6 +132,7 @@ export const Segments = Object.freeze(
121
132
  plural: 'cities',
122
133
  service: Service['Cities'],
123
134
  pattern: Pattern.UUID.source,
135
+ kind: 'Entity',
124
136
  }),
125
137
  ),
126
138
  Object.freeze(
@@ -131,6 +143,7 @@ export const Segments = Object.freeze(
131
143
  plural: 'cities',
132
144
  service: Service['Cities'],
133
145
  pattern: null,
146
+ kind: 'Entity',
134
147
  }),
135
148
  ),
136
149
  Object.freeze(
@@ -141,6 +154,7 @@ export const Segments = Object.freeze(
141
154
  plural: 'venues',
142
155
  service: Service['Venues'],
143
156
  pattern: Pattern.UUID.source,
157
+ kind: 'Entity',
144
158
  }),
145
159
  ),
146
160
  Object.freeze(
@@ -151,6 +165,7 @@ export const Segments = Object.freeze(
151
165
  plural: 'venues',
152
166
  service: Service['Venues'],
153
167
  pattern: null,
168
+ kind: 'Entity',
154
169
  }),
155
170
  ),
156
171
  Object.freeze(
@@ -161,6 +176,7 @@ export const Segments = Object.freeze(
161
176
  plural: 'themes',
162
177
  service: Service['Themes'],
163
178
  pattern: Pattern.UUID.source,
179
+ kind: 'Entity',
164
180
  }),
165
181
  ),
166
182
  Object.freeze(
@@ -171,6 +187,7 @@ export const Segments = Object.freeze(
171
187
  plural: 'themes',
172
188
  service: Service['Themes'],
173
189
  pattern: null,
190
+ kind: 'Entity',
174
191
  }),
175
192
  ),
176
193
  Object.freeze(
@@ -181,6 +198,7 @@ export const Segments = Object.freeze(
181
198
  plural: 'covers',
182
199
  service: Service['Minio'],
183
200
  pattern: Pattern.UUID.source,
201
+ kind: 'Entity',
184
202
  }),
185
203
  ),
186
204
  Object.freeze(
@@ -191,6 +209,7 @@ export const Segments = Object.freeze(
191
209
  plural: 'covers',
192
210
  service: Service['Minio'],
193
211
  pattern: null,
212
+ kind: 'Entity',
194
213
  }),
195
214
  ),
196
215
  Object.freeze(
@@ -201,6 +220,7 @@ export const Segments = Object.freeze(
201
220
  plural: 'games',
202
221
  service: Service['Games'],
203
222
  pattern: Pattern.UUID.source,
223
+ kind: 'Entity',
204
224
  }),
205
225
  ),
206
226
  Object.freeze(
@@ -211,6 +231,7 @@ export const Segments = Object.freeze(
211
231
  plural: 'games',
212
232
  service: Service['Games'],
213
233
  pattern: null,
234
+ kind: 'Entity',
214
235
  }),
215
236
  ),
216
237
  Object.freeze(
@@ -221,6 +242,7 @@ export const Segments = Object.freeze(
221
242
  plural: 'registrations',
222
243
  service: Service['Registrations'],
223
244
  pattern: Pattern.UUID.source,
245
+ kind: 'Entity',
224
246
  }),
225
247
  ),
226
248
  Object.freeze(
@@ -231,6 +253,7 @@ export const Segments = Object.freeze(
231
253
  plural: 'registrations',
232
254
  service: Service['Registrations'],
233
255
  pattern: null,
256
+ kind: 'Entity',
234
257
  }),
235
258
  ),
236
259
  Object.freeze(
@@ -240,7 +263,8 @@ export const Segments = Object.freeze(
240
263
  singular: 'status',
241
264
  plural: 'statuses',
242
265
  service: null,
243
- pattern: Pattern.STRING.source,
266
+ pattern: null,
267
+ kind: 'Property',
244
268
  }),
245
269
  ),
246
270
  Object.freeze(
@@ -251,6 +275,7 @@ export const Segments = Object.freeze(
251
275
  plural: 'statuses',
252
276
  service: null,
253
277
  pattern: null,
278
+ kind: 'Property',
254
279
  }),
255
280
  ),
256
281
  Object.freeze(
@@ -261,6 +286,7 @@ export const Segments = Object.freeze(
261
286
  plural: 'lineups',
262
287
  service: null,
263
288
  pattern: null,
289
+ kind: 'Property',
264
290
  }),
265
291
  ),
266
292
  Object.freeze(
@@ -271,6 +297,7 @@ export const Segments = Object.freeze(
271
297
  plural: 'lineups',
272
298
  service: null,
273
299
  pattern: null,
300
+ kind: 'Property',
274
301
  }),
275
302
  ),
276
303
  Object.freeze(
@@ -281,6 +308,7 @@ export const Segments = Object.freeze(
281
308
  plural: 'telegrams',
282
309
  service: Service['Telegram'],
283
310
  pattern: null,
311
+ kind: 'Integration',
284
312
  }),
285
313
  ),
286
314
  Object.freeze(
@@ -291,6 +319,7 @@ export const Segments = Object.freeze(
291
319
  plural: 'chatapps',
292
320
  service: Service['Chatapp'],
293
321
  pattern: null,
322
+ kind: 'Integration',
294
323
  }),
295
324
  ),
296
325
  Object.freeze(
@@ -301,6 +330,7 @@ export const Segments = Object.freeze(
301
330
  plural: 'bitrixes',
302
331
  service: Service['Bitrix'],
303
332
  pattern: null,
333
+ kind: 'Integration',
304
334
  }),
305
335
  ),
306
336
  Object.freeze(
@@ -311,6 +341,7 @@ export const Segments = Object.freeze(
311
341
  plural: 'webhooks',
312
342
  service: null,
313
343
  pattern: null,
344
+ kind: 'Integration',
314
345
  }),
315
346
  ),
316
347
  Object.freeze(
@@ -321,6 +352,7 @@ export const Segments = Object.freeze(
321
352
  plural: 'sources',
322
353
  service: Service['Updates'],
323
354
  pattern: null,
355
+ kind: 'Integration',
324
356
  }),
325
357
  ),
326
358
  Object.freeze(
@@ -331,6 +363,7 @@ export const Segments = Object.freeze(
331
363
  plural: 'searches',
332
364
  service: null,
333
365
  pattern: null,
366
+ kind: 'Integration',
334
367
  }),
335
368
  ),
336
369
  Object.freeze(
@@ -341,6 +374,7 @@ export const Segments = Object.freeze(
341
374
  plural: 'exports',
342
375
  service: null,
343
376
  pattern: null,
377
+ kind: 'Operation',
344
378
  }),
345
379
  ),
346
380
  Object.freeze(
@@ -351,6 +385,7 @@ export const Segments = Object.freeze(
351
385
  plural: 'passwords',
352
386
  service: null,
353
387
  pattern: null,
388
+ kind: 'Property',
354
389
  }),
355
390
  ),
356
391
  Object.freeze(
@@ -361,6 +396,7 @@ export const Segments = Object.freeze(
361
396
  plural: 'vk_group_tokens',
362
397
  service: null,
363
398
  pattern: null,
399
+ kind: 'Property',
364
400
  }),
365
401
  ),
366
402
  Object.freeze(
@@ -371,6 +407,7 @@ export const Segments = Object.freeze(
371
407
  plural: 'summaries',
372
408
  service: null,
373
409
  pattern: null,
410
+ kind: 'Aggregation',
374
411
  }),
375
412
  ),
376
413
  Object.freeze(
@@ -381,6 +418,7 @@ export const Segments = Object.freeze(
381
418
  plural: 'mailings',
382
419
  service: null,
383
420
  pattern: null,
421
+ kind: 'Entity',
384
422
  }),
385
423
  ),
386
424
  Object.freeze(
@@ -391,6 +429,7 @@ export const Segments = Object.freeze(
391
429
  plural: 'channels',
392
430
  service: null,
393
431
  pattern: null,
432
+ kind: 'Property',
394
433
  }),
395
434
  ),
396
435
  Object.freeze(
@@ -401,6 +440,7 @@ export const Segments = Object.freeze(
401
440
  plural: 'creations',
402
441
  service: null,
403
442
  pattern: null,
443
+ kind: 'Operation',
404
444
  }),
405
445
  ),
406
446
  Object.freeze(
@@ -411,6 +451,7 @@ export const Segments = Object.freeze(
411
451
  plural: 'confirmations',
412
452
  service: null,
413
453
  pattern: null,
454
+ kind: 'Operation',
414
455
  }),
415
456
  ),
416
457
  Object.freeze(
@@ -421,6 +462,7 @@ export const Segments = Object.freeze(
421
462
  plural: 'cancellations',
422
463
  service: null,
423
464
  pattern: null,
465
+ kind: 'Operation',
424
466
  }),
425
467
  ),
426
468
  ]),
@@ -23,6 +23,26 @@ export const route = maybeString => {
23
23
  return segments.join('/')
24
24
  }
25
25
 
26
+ /**
27
+ * @param {string} maybeRoute
28
+ *
29
+ * @example
30
+ * routeBreakdown('users/role') // ['role']
31
+ * routeBreakdown('games/search') // ['game']
32
+ */
33
+ export const routeBreakdown = maybeRoute => {
34
+ let singulars = route(maybeRoute)
35
+ .split('/')
36
+ .filter(segment => ['Entity', 'Property', 'Aggregation', 'Operation'].includes(Segment[segment].kind))
37
+ .map(segment => Segment[segment].singular)
38
+
39
+ let lastIndex = singulars.findLastIndex(segment => Segment[segment].kind === 'Entity')
40
+
41
+ return singulars
42
+ .slice(lastIndex, singulars.length)
43
+ .join('/')
44
+ }
45
+
26
46
  /**
27
47
  * @param {string} segment
28
48
  *