@deephaven-enterprise/query-utils 1.20240723.62-alpha-fix-dependencies.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.
@@ -0,0 +1,76 @@
1
+ import { QueryScheduler } from './QueryScheduler';
2
+ /**
3
+ * Validation for Query Scheduler
4
+ */
5
+ export declare class QuerySchedulerValidation {
6
+ static VALIDATORS: Readonly<{
7
+ dailyDays: typeof QuerySchedulerValidation.validateDailyDays;
8
+ businessDays: typeof QuerySchedulerValidation.validateDailyDays;
9
+ months: typeof QuerySchedulerValidation.validateMonths;
10
+ firstBusinessDay: typeof QuerySchedulerValidation.validateMonthlyDays;
11
+ lastBusinessDay: typeof QuerySchedulerValidation.validateMonthlyDays;
12
+ specificDays: typeof QuerySchedulerValidation.validateMonthlyDays;
13
+ monthlyDays: typeof QuerySchedulerValidation.validateMonthlyDays;
14
+ dependentOnQuerySerials: typeof QuerySchedulerValidation.validateDependentOnQuerySerials;
15
+ schedulingDisabled: typeof QuerySchedulerValidation.validateSchedulingDisabled;
16
+ startTime: typeof QuerySchedulerValidation.validateStartTime;
17
+ stopTime: typeof QuerySchedulerValidation.validateStopTime;
18
+ overnight: typeof QuerySchedulerValidation.validateOvernight;
19
+ stopTimeDisabled: typeof QuerySchedulerValidation.validateStopTimeDisabled;
20
+ repeatEnabled: typeof QuerySchedulerValidation.validateRepeat;
21
+ temporaryDependentOnQuerySerials: typeof QuerySchedulerValidation.validateTemporaryDependentOnQuerySerials;
22
+ expirationTimeMillis: typeof QuerySchedulerValidation.validateExpirationTime;
23
+ repeatInterval: typeof QuerySchedulerValidation.validateRepeatInterval;
24
+ restartDelayMinutes: typeof QuerySchedulerValidation.validateRestartDelayMinutes;
25
+ startDateTime: typeof QuerySchedulerValidation.validateStartDateTime;
26
+ stopDateTime: typeof QuerySchedulerValidation.validateStopDateTime;
27
+ }>;
28
+ /**
29
+ * Validates a field. Returns an error message if the value is invalid. Returns null if it is valid.
30
+ *
31
+ * @param field the field to validate
32
+ * @param scheduler the scheduler
33
+ * @param timeout the timeout from query
34
+ * @param stopTimeRequired if a stop time is required
35
+ * @param dependentQuerySerials available dependent query serials, skip check if undefined
36
+ * @param temporaryQuerySerials available temporary query serials, skip check if undefined
37
+ * @return an error message for an invalid value, null if it is valid
38
+ */
39
+ static validate(field: string, scheduler: QueryScheduler, timeout?: number, stopTimeRequired?: boolean, dependentQuerySerials?: string[], temporaryQuerySerials?: string[]): string | null;
40
+ /**
41
+ * Runs all validators on a scheduler.
42
+ *
43
+ * @param scheduler the scheduler to validate
44
+ * @param timeout the timeout from query
45
+ * @param stopTimeRequired if a stop time is required
46
+ * @param dependentQuerySerials available dependent query serials, skip check if undefined
47
+ * @param temporaryQuerySerials available temporary query serials, skip check if undefined
48
+ * @return a map containing any errors
49
+ */
50
+ static validateAll(scheduler: QueryScheduler, timeout?: number, stopTimeRequired?: boolean, dependentQuerySerials?: string[], temporaryQuerySerials?: string[]): Map<string, string>;
51
+ /**
52
+ * Many scheduler validations involved multiple fields and are displayed in a banner.
53
+ * This is a helper method to get an error message to display. Returns null if there is no error
54
+ * message or if the error message is for only one field.
55
+ *
56
+ * @param errorMap the map of error message from a validate all call
57
+ */
58
+ static getErrorMessage(errorMap: Map<string, string>): string | null | undefined;
59
+ static validateStartTime(scheduler: QueryScheduler): string | null;
60
+ static validateStopTime(scheduler: QueryScheduler): string | null;
61
+ static validateOvernight(scheduler: QueryScheduler): string | null;
62
+ static validateStopTimeDisabled(scheduler: QueryScheduler, timeout: number, stopTimeRequired: boolean): string | null;
63
+ static validateRepeat(scheduler: QueryScheduler): string | null;
64
+ static validateDailyDays(scheduler: QueryScheduler): string | null;
65
+ static validateMonthlyDays(scheduler: QueryScheduler): string | null;
66
+ static validateMonths(scheduler: QueryScheduler): string | null;
67
+ static validateDependentOnQuerySerials(scheduler: QueryScheduler, timeout: number, stopTimeRequired: boolean, dependentQuerySerials: string[]): string | null;
68
+ static validateSchedulingDisabled(scheduler: QueryScheduler): string | null;
69
+ static validateTemporaryDependentOnQuerySerials(scheduler: QueryScheduler, timeout: number, stopTimeRequired: boolean, dependentQuerySerials: string[], temporaryQuerySerials: string[]): string | null;
70
+ static validateExpirationTime(scheduler: QueryScheduler): string | null;
71
+ static validateRepeatInterval(scheduler: QueryScheduler, timeout: number): string | null;
72
+ static validateRestartDelayMinutes(scheduler: QueryScheduler): string | null;
73
+ static validateStartDateTime(scheduler: QueryScheduler): string | null;
74
+ static validateStopDateTime(scheduler: QueryScheduler): string | null;
75
+ }
76
+ export default QuerySchedulerValidation;
@@ -0,0 +1,306 @@
1
+ import { QueryScheduler } from './QueryScheduler';
2
+ /**
3
+ * Validation for Query Scheduler
4
+ */
5
+ export class QuerySchedulerValidation {
6
+ /**
7
+ * Validates a field. Returns an error message if the value is invalid. Returns null if it is valid.
8
+ *
9
+ * @param field the field to validate
10
+ * @param scheduler the scheduler
11
+ * @param timeout the timeout from query
12
+ * @param stopTimeRequired if a stop time is required
13
+ * @param dependentQuerySerials available dependent query serials, skip check if undefined
14
+ * @param temporaryQuerySerials available temporary query serials, skip check if undefined
15
+ * @return an error message for an invalid value, null if it is valid
16
+ */
17
+ static validate(field, scheduler, timeout = 0, stopTimeRequired = true, dependentQuerySerials, temporaryQuerySerials) {
18
+ // @ts-expect-error we are checking if field is a valid key
19
+ const validator = QuerySchedulerValidation.VALIDATORS[field];
20
+ if (validator != null) {
21
+ return validator(scheduler, timeout, stopTimeRequired, dependentQuerySerials, temporaryQuerySerials);
22
+ }
23
+ return null;
24
+ }
25
+ /**
26
+ * Runs all validators on a scheduler.
27
+ *
28
+ * @param scheduler the scheduler to validate
29
+ * @param timeout the timeout from query
30
+ * @param stopTimeRequired if a stop time is required
31
+ * @param dependentQuerySerials available dependent query serials, skip check if undefined
32
+ * @param temporaryQuerySerials available temporary query serials, skip check if undefined
33
+ * @return a map containing any errors
34
+ */
35
+ static validateAll(scheduler, timeout = 0, stopTimeRequired = true, dependentQuerySerials, temporaryQuerySerials) {
36
+ const keys = Object.keys(QuerySchedulerValidation.VALIDATORS);
37
+ const result = new Map();
38
+ keys.forEach(key => {
39
+ const validationError = QuerySchedulerValidation.validate(key, scheduler, timeout, stopTimeRequired, dependentQuerySerials, temporaryQuerySerials);
40
+ if (validationError != null) {
41
+ result.set(key, validationError);
42
+ }
43
+ });
44
+ return result;
45
+ }
46
+ /**
47
+ * Many scheduler validations involved multiple fields and are displayed in a banner.
48
+ * This is a helper method to get an error message to display. Returns null if there is no error
49
+ * message or if the error message is for only one field.
50
+ *
51
+ * @param errorMap the map of error message from a validate all call
52
+ */
53
+ static getErrorMessage(errorMap) {
54
+ if (errorMap.size === 0) {
55
+ return null;
56
+ }
57
+ const firstKey = errorMap.keys().next().value;
58
+ if (firstKey === QueryScheduler.FIELDS.MONTHS ||
59
+ firstKey === QueryScheduler.FIELDS.SCHEDULING_DISABLED) {
60
+ return null;
61
+ }
62
+ return errorMap.get(firstKey);
63
+ }
64
+ static validateStartTime(scheduler) {
65
+ if (scheduler.type === QueryScheduler.TYPES.CONTINUOUS ||
66
+ scheduler.type === QueryScheduler.TYPES.TEMPORARY ||
67
+ scheduler.type === QueryScheduler.TYPES.RANGE) {
68
+ return null;
69
+ }
70
+ const { startTime } = scheduler;
71
+ if (startTime === undefined) {
72
+ return 'Schedule must have a start time';
73
+ }
74
+ // This will check if the times have the correct order
75
+ return QuerySchedulerValidation.validateStopTime(scheduler);
76
+ }
77
+ static validateStopTime(scheduler) {
78
+ if (scheduler.type === QueryScheduler.TYPES.CONTINUOUS ||
79
+ scheduler.type === QueryScheduler.TYPES.TEMPORARY ||
80
+ scheduler.type === QueryScheduler.TYPES.RANGE) {
81
+ return null;
82
+ }
83
+ if (scheduler.type === QueryScheduler.TYPES.DEPENDENT &&
84
+ !scheduler.useMinStartTime) {
85
+ return null;
86
+ }
87
+ const { stopTime, stopTimeDisabled, repeatEnabled, overnight, startTime } = scheduler;
88
+ if (stopTime !== undefined && (!stopTimeDisabled || repeatEnabled)) {
89
+ if (stopTime === startTime) {
90
+ return 'Start time and stop time cannot be the same';
91
+ }
92
+ if (!overnight && stopTime < startTime) {
93
+ return 'Stop time must be later than start time or select overnight';
94
+ }
95
+ if (overnight && startTime < stopTime) {
96
+ return 'Stop time must be earlier than start time or deselect overnight';
97
+ }
98
+ }
99
+ return null;
100
+ }
101
+ static validateOvernight(scheduler) {
102
+ const { type, overnight, stopTimeDisabled } = scheduler;
103
+ if (overnight && stopTimeDisabled) {
104
+ return 'Overnight cannot be set if stop time is disabled';
105
+ }
106
+ if (type === QueryScheduler.TYPES.TEMPORARY && overnight) {
107
+ return 'Temporary schedules do not support overnight';
108
+ }
109
+ return null;
110
+ }
111
+ static validateStopTimeDisabled(scheduler, timeout, stopTimeRequired) {
112
+ const { type, overnight, stopTimeDisabled } = scheduler;
113
+ if (!stopTimeRequired && type === QueryScheduler.TYPES.CONTINUOUS) {
114
+ return 'Continuous schedule is not supported for this query type. Please select a schedule type';
115
+ }
116
+ if (stopTimeRequired && type === QueryScheduler.TYPES.TEMPORARY) {
117
+ return 'Temporary schedule is not supported for this query type. Please select a schedule type';
118
+ }
119
+ if (overnight && stopTimeDisabled) {
120
+ return 'Stop time cannot be disabled on an overnight query';
121
+ }
122
+ if (stopTimeDisabled && timeout <= 0) {
123
+ if (type === QueryScheduler.TYPES.CONTINUOUS) {
124
+ return 'Query types without an end time must have a non-zero Initialization Timeout';
125
+ }
126
+ return 'Query types without an end time must have a non-zero Max Execution Time';
127
+ }
128
+ return null;
129
+ }
130
+ static validateRepeat(scheduler) {
131
+ const { repeatEnabled, repeatInterval } = scheduler;
132
+ if (repeatEnabled && repeatInterval <= 0) {
133
+ return `Set repeat interval greater than 0 or disable interval repeat`;
134
+ }
135
+ return null;
136
+ }
137
+ static validateDailyDays(scheduler) {
138
+ const { type, schedulingDisabled, businessDays, dailyDays } = scheduler;
139
+ if (!schedulingDisabled) {
140
+ if (type === QueryScheduler.TYPES.DAILY &&
141
+ !businessDays &&
142
+ !dailyDays.includes(true)) {
143
+ return 'Select a day of the week or Business Days';
144
+ }
145
+ }
146
+ return null;
147
+ }
148
+ static validateMonthlyDays(scheduler) {
149
+ const { type, schedulingDisabled, monthlyDays, specificDays, firstBusinessDay, lastBusinessDay, } = scheduler;
150
+ if (!schedulingDisabled) {
151
+ if (type === QueryScheduler.TYPES.MONTHLY &&
152
+ !firstBusinessDay &&
153
+ !lastBusinessDay &&
154
+ (!specificDays || !monthlyDays.includes(true))) {
155
+ return 'Select First Business Day, Last Business Day, or at least one Specific Day';
156
+ }
157
+ }
158
+ return null;
159
+ }
160
+ static validateMonths(scheduler) {
161
+ const { type, schedulingDisabled, months } = scheduler;
162
+ if (!schedulingDisabled &&
163
+ type === QueryScheduler.TYPES.MONTHLY &&
164
+ !months.includes(true)) {
165
+ return 'Select at least one month';
166
+ }
167
+ return null;
168
+ }
169
+ static validateDependentOnQuerySerials(scheduler, timeout, stopTimeRequired, dependentQuerySerials) {
170
+ const { type, schedulingDisabled, dependentOnQuerySerials } = scheduler;
171
+ if (!schedulingDisabled && type === QueryScheduler.TYPES.DEPENDENT) {
172
+ if (dependentOnQuerySerials == null ||
173
+ dependentOnQuerySerials.length === 0) {
174
+ return 'Must have one dependent-on query';
175
+ }
176
+ if (dependentOnQuerySerials.includes(QueryScheduler.INVALID_SERIAL)) {
177
+ return 'Select a query or delete empty query dependencies';
178
+ }
179
+ if (dependentQuerySerials !== undefined &&
180
+ dependentOnQuerySerials.some(serial => !dependentQuerySerials.includes(serial))) {
181
+ return 'Select a different query or delete invalid query dependencies';
182
+ }
183
+ }
184
+ return null;
185
+ }
186
+ static validateSchedulingDisabled(scheduler) {
187
+ const { type, schedulingDisabled } = scheduler;
188
+ if (type === QueryScheduler.TYPES.TEMPORARY && schedulingDisabled) {
189
+ return 'Temporary schedules cannot be disabled';
190
+ }
191
+ return null;
192
+ }
193
+ static validateTemporaryDependentOnQuerySerials(scheduler, timeout, stopTimeRequired, dependentQuerySerials, temporaryQuerySerials) {
194
+ const { type, schedulingDisabled, temporaryDependentOnQuerySerials } = scheduler;
195
+ if (!schedulingDisabled && type === QueryScheduler.TYPES.TEMPORARY) {
196
+ if (temporaryDependentOnQuerySerials.includes(QueryScheduler.INVALID_SERIAL)) {
197
+ return 'Select temporary query or delete empty query dependencies';
198
+ }
199
+ if (temporaryQuerySerials !== undefined &&
200
+ temporaryDependentOnQuerySerials.some(serial => !temporaryQuerySerials.includes(serial))) {
201
+ return 'Select a different query or delete invalid query dependencies';
202
+ }
203
+ }
204
+ return null;
205
+ }
206
+ static validateExpirationTime(scheduler) {
207
+ const { type, schedulingDisabled, expirationTimeMillis } = scheduler;
208
+ if (!schedulingDisabled &&
209
+ type === QueryScheduler.TYPES.TEMPORARY &&
210
+ expirationTimeMillis <= 0) {
211
+ return 'Temporary schedules must have a deletion delay';
212
+ }
213
+ return null;
214
+ }
215
+ static validateRepeatInterval(scheduler, timeout) {
216
+ const { type, schedulingDisabled, stopTimeDisabled, repeatEnabled, repeatInterval, } = scheduler;
217
+ if (!schedulingDisabled &&
218
+ (type === QueryScheduler.TYPES.DAILY ||
219
+ type === QueryScheduler.TYPES.MONTHLY ||
220
+ type === QueryScheduler.TYPES.RANGE) &&
221
+ stopTimeDisabled &&
222
+ repeatEnabled &&
223
+ repeatInterval * 60 * 1000 <= timeout) {
224
+ return 'Max Execution Time must be less than Repeat Interval';
225
+ }
226
+ return null;
227
+ }
228
+ static validateRestartDelayMinutes(scheduler) {
229
+ const { restartDelayMinutes, restartErrorCount } = scheduler;
230
+ if (restartErrorCount > 0) {
231
+ if (restartDelayMinutes === null) {
232
+ return 'must not be empty';
233
+ }
234
+ const number = Number(restartDelayMinutes);
235
+ if (Number.isNaN(number)) {
236
+ return 'must be a number';
237
+ }
238
+ if (number < 0) {
239
+ return 'must not be negative';
240
+ }
241
+ if (String(restartDelayMinutes).includes('.')) {
242
+ return 'must be an integer';
243
+ }
244
+ }
245
+ return null;
246
+ }
247
+ static validateStartDateTime(scheduler) {
248
+ const { type, startDateTime, stopDateTime, repeatEnabled } = scheduler;
249
+ if (type !== QueryScheduler.TYPES.RANGE) {
250
+ return null;
251
+ }
252
+ if (startDateTime === null && stopDateTime === null) {
253
+ return 'At least one date is required';
254
+ }
255
+ if (repeatEnabled && startDateTime === null) {
256
+ return 'Start date is required if repeat is enabled';
257
+ }
258
+ if (startDateTime !== null && stopDateTime !== null) {
259
+ if (startDateTime.compare(stopDateTime) >= 0) {
260
+ return 'Start date must be before stop date';
261
+ }
262
+ }
263
+ return null;
264
+ }
265
+ static validateStopDateTime(scheduler) {
266
+ const { type, startDateTime, stopDateTime, repeatEnabled } = scheduler;
267
+ if (type !== QueryScheduler.TYPES.RANGE) {
268
+ return null;
269
+ }
270
+ if (startDateTime === null && stopDateTime === null) {
271
+ return 'At least one date is required';
272
+ }
273
+ if (repeatEnabled && stopDateTime === null) {
274
+ return 'Stop date is required if repeat is enabled';
275
+ }
276
+ if (startDateTime !== null && stopDateTime !== null) {
277
+ if (startDateTime.compare(stopDateTime) >= 0) {
278
+ return 'Stop date must be after start date';
279
+ }
280
+ }
281
+ return null;
282
+ }
283
+ }
284
+ QuerySchedulerValidation.VALIDATORS = Object.freeze({
285
+ [QueryScheduler.FIELDS.DAILY_DAYS]: QuerySchedulerValidation.validateDailyDays,
286
+ [QueryScheduler.FIELDS.BUSINESS_DAYS]: QuerySchedulerValidation.validateDailyDays,
287
+ [QueryScheduler.FIELDS.MONTHS]: QuerySchedulerValidation.validateMonths,
288
+ [QueryScheduler.FIELDS.FIRST_BUSINESS_DAY]: QuerySchedulerValidation.validateMonthlyDays,
289
+ [QueryScheduler.FIELDS.LAST_BUSINESS_DAY]: QuerySchedulerValidation.validateMonthlyDays,
290
+ [QueryScheduler.FIELDS.SPECIFIC_DAYS]: QuerySchedulerValidation.validateMonthlyDays,
291
+ [QueryScheduler.FIELDS.MONTHLY_DAYS]: QuerySchedulerValidation.validateMonthlyDays,
292
+ [QueryScheduler.FIELDS.DEPENDENT_ON_QUERY_SERIALS]: QuerySchedulerValidation.validateDependentOnQuerySerials,
293
+ [QueryScheduler.FIELDS.SCHEDULING_DISABLED]: QuerySchedulerValidation.validateSchedulingDisabled,
294
+ [QueryScheduler.FIELDS.START_TIME]: QuerySchedulerValidation.validateStartTime,
295
+ [QueryScheduler.FIELDS.STOP_TIME]: QuerySchedulerValidation.validateStopTime,
296
+ [QueryScheduler.FIELDS.OVERNIGHT]: QuerySchedulerValidation.validateOvernight,
297
+ [QueryScheduler.FIELDS.STOP_TIME_DISABLED]: QuerySchedulerValidation.validateStopTimeDisabled,
298
+ [QueryScheduler.FIELDS.REPEAT_ENABLED]: QuerySchedulerValidation.validateRepeat,
299
+ [QueryScheduler.FIELDS.TEMPORARY_DEPENDENT_ON_QUERY_SERIALS]: QuerySchedulerValidation.validateTemporaryDependentOnQuerySerials,
300
+ [QueryScheduler.FIELDS.EXPIRATION_TIME_MILLIS]: QuerySchedulerValidation.validateExpirationTime,
301
+ [QueryScheduler.FIELDS.REPEAT_INTERVAL]: QuerySchedulerValidation.validateRepeatInterval,
302
+ [QueryScheduler.FIELDS.RESTART_DELAY_MINUTES]: QuerySchedulerValidation.validateRestartDelayMinutes,
303
+ [QueryScheduler.FIELDS.START_DATE_TIME]: QuerySchedulerValidation.validateStartDateTime,
304
+ [QueryScheduler.FIELDS.STOP_DATE_TIME]: QuerySchedulerValidation.validateStopDateTime,
305
+ });
306
+ export default QuerySchedulerValidation;
@@ -0,0 +1,12 @@
1
+ export declare enum QueryType {
2
+ CSV_IMPORT = "CsvImport",
3
+ JDBC_IMPORT = "JdbcImport",
4
+ DATA_MERGE = "Merge",
5
+ DATA_VALIDATE = "Validate",
6
+ INTERACTIVE_CONSOLE = "InteractiveConsole",
7
+ REPLAY_SCRIPT = "ReplayScript",
8
+ RUN_AND_DONE = "RunAndDone",
9
+ RUN_AND_DONE_IMPORT = "RunAndDoneImport",
10
+ SCRIPT = "Script",
11
+ SCRIPT_MERGE_SERVER = "ScriptMergeServer"
12
+ }
@@ -0,0 +1,13 @@
1
+ export var QueryType;
2
+ (function (QueryType) {
3
+ QueryType["CSV_IMPORT"] = "CsvImport";
4
+ QueryType["JDBC_IMPORT"] = "JdbcImport";
5
+ QueryType["DATA_MERGE"] = "Merge";
6
+ QueryType["DATA_VALIDATE"] = "Validate";
7
+ QueryType["INTERACTIVE_CONSOLE"] = "InteractiveConsole";
8
+ QueryType["REPLAY_SCRIPT"] = "ReplayScript";
9
+ QueryType["RUN_AND_DONE"] = "RunAndDone";
10
+ QueryType["RUN_AND_DONE_IMPORT"] = "RunAndDoneImport";
11
+ QueryType["SCRIPT"] = "Script";
12
+ QueryType["SCRIPT_MERGE_SERVER"] = "ScriptMergeServer";
13
+ })(QueryType || (QueryType = {}));
@@ -0,0 +1,5 @@
1
+ export * from './DraftQuery';
2
+ export * from './QueryColumns';
3
+ export * from './QueryScheduler';
4
+ export * from './QuerySchedulerValidation';
5
+ export * from './QueryType';
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from './DraftQuery';
2
+ export * from './QueryColumns';
3
+ export * from './QueryScheduler';
4
+ export * from './QuerySchedulerValidation';
5
+ export * from './QueryType';
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@deephaven-enterprise/query-utils",
3
+ "version": "1.20240723.62-alpha-fix-dependencies.1",
4
+ "description": "Deephaven Enterprise Query Utils",
5
+ "author": "Deephaven Data Labs LLC",
6
+ "license": "SEE LICENSE IN LICENSE.md",
7
+ "type": "module",
8
+ "private": false,
9
+ "source": "src/index.ts",
10
+ "main": "dist/index.js",
11
+ "types": "dist/index.d.ts",
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "sideEffects": false,
16
+ "scripts": {
17
+ "build": "tsc --build"
18
+ },
19
+ "dependencies": {
20
+ "@deephaven/jsapi-types": "^1.0.0-dev0.34.3",
21
+ "@deephaven/log": "^0.95.0",
22
+ "@deephaven/utils": "^0.95.0",
23
+ "@internationalized/date": "^3.5.5",
24
+ "shortid": "^2.2.16"
25
+ },
26
+ "devDependencies": {
27
+ "@types/shortid": "^0.0.32"
28
+ },
29
+ "publishConfig": {
30
+ "access": "public"
31
+ }
32
+ }