Skip to content

Commit fa01008

Browse files
committed
fix: let user choice 'standard' vs 'aws'
Let the user choose between cron format (since help is different)
1 parent 8754d62 commit fa01008

File tree

4 files changed

+57
-22
lines changed

4 files changed

+57
-22
lines changed

components.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,18 @@ declare module '@vue/runtime-core' {
135135
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
136136
NDivider: typeof import('naive-ui')['NDivider']
137137
NEllipsis: typeof import('naive-ui')['NEllipsis']
138+
NForm: typeof import('naive-ui')['NForm']
139+
NFormItem: typeof import('naive-ui')['NFormItem']
138140
NH1: typeof import('naive-ui')['NH1']
139141
NH3: typeof import('naive-ui')['NH3']
140142
NIcon: typeof import('naive-ui')['NIcon']
141143
NLayout: typeof import('naive-ui')['NLayout']
142144
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
143145
NMenu: typeof import('naive-ui')['NMenu']
146+
NRadio: typeof import('naive-ui')['NRadio']
147+
NRadioGroup: typeof import('naive-ui')['NRadioGroup']
144148
NSpace: typeof import('naive-ui')['NSpace']
149+
NSwitch: typeof import('naive-ui')['NSwitch']
145150
NTable: typeof import('naive-ui')['NTable']
146151
NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default']
147152
OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default']

src/tools/crontab-generator/crontab-generator.service.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,32 @@ import { getCronType, getLastExecutionTimes, isCronValid } from './crontab-gener
44
describe('crontab-generator', () => {
55
describe('isCronValid', () => {
66
it('should return true for all valid formats', () => {
7+
// standard format
78
expect(isCronValid('0 0 * * 1-5')).toBe(true);
89
expect(isCronValid('23 0-20/2 * * *')).toBe(true);
910

1011
// AWS formats
1112
expect(isCronValid('0 11-22 ? * MON-FRI *')).toBe(true);
1213
expect(isCronValid('0 0 ? * 1 *')).toBe(true);
1314
});
15+
it('should check standard format', () => {
16+
// standard format
17+
expect(isCronValid('0 0 * * 1-5', 'standard')).toBe(true);
18+
expect(isCronValid('23 0-20/2 * * *', 'standard')).toBe(true);
19+
20+
// AWS format
21+
expect(isCronValid('0 11-22 ? * MON-FRI *', 'standard')).toBe(false);
22+
expect(isCronValid('0 0 ? * 1 *', 'standard')).toBe(false);
23+
});
24+
it('should check aws format', () => {
25+
// standard format
26+
expect(isCronValid('0 0 * * 1-5', 'aws')).toBe(false);
27+
expect(isCronValid('23 0-20/2 * * *', 'aws')).toBe(false);
28+
29+
// AWS format
30+
expect(isCronValid('0 11-22 ? * MON-FRI *', 'aws')).toBe(true);
31+
expect(isCronValid('0 0 ? * 1 *', 'aws')).toBe(true);
32+
});
1433
it('should return false for all invalid formats', () => {
1534
expect(isCronValid('aert')).toBe(false);
1635
expect(isCronValid('40 *')).toBe(false);

src/tools/crontab-generator/crontab-generator.service.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { parseExpression } from 'cron-parser';
22
import EventCronParser from 'event-cron-parser';
33

4+
export type CronType = 'standard' | 'aws';
5+
46
export function getLastExecutionTimes(cronExpression: string, tz: string | undefined = undefined, count: number = 5) {
57
if (getCronType(cronExpression) === 'standard') {
68
const interval = parseExpression(cronExpression, { tz });
@@ -22,18 +24,19 @@ export function getLastExecutionTimes(cronExpression: string, tz: string | undef
2224
return [];
2325
}
2426

25-
export function isCronValid(v: string) {
26-
return !!getCronType(v);
27+
export function isCronValid(cronExpression: string, cronType: CronType | 'any' = 'any') {
28+
const expressionCronType = getCronType(cronExpression);
29+
return cronType === 'any' ? !!expressionCronType : expressionCronType === cronType;
2730
}
2831

29-
export function getCronType(v: string) {
32+
export function getCronType(cronExpression: string) {
3033
try {
31-
parseExpression(v);
34+
parseExpression(cronExpression);
3235
return 'standard';
3336
}
3437
catch (_) {
3538
try {
36-
const parsed = new EventCronParser(v);
39+
const parsed = new EventCronParser(cronExpression);
3740
parsed.validate();
3841
return 'aws';
3942
}

src/tools/crontab-generator/crontab-generator.vue

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import cronstrue from 'cronstrue';
33
import ctz from 'countries-and-timezones';
44
import getTimezoneOffset from 'get-timezone-offset';
5-
import { getCronType, getLastExecutionTimes, isCronValid } from './crontab-generator.service';
5+
import { type CronType, getLastExecutionTimes, isCronValid } from './crontab-generator.service';
66
import { useStyleStore } from '@/stores/style.store';
77
import { useQueryParamOrStorage } from '@/composable/queryParams';
88
@@ -20,10 +20,13 @@ const cronstrueConfig = reactive({
2020
2121
// getTimezoneOffset(tz.name, now) / 60
2222
const browserTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
23-
const allTimezones = Object.values(ctz.getAllTimezones()).map(tz => ({
24-
value: tz.name,
25-
label: `${tz.name === browserTimezone ? 'Browser TZ - ' : ''}${tz.name} (${tz.utcOffset === tz.dstOffset ? tz.utcOffsetStr : `${tz.utcOffsetStr}/${tz.dstOffsetStr}`})`,
26-
}));
23+
const allTimezones = Object.values(ctz.getAllTimezones()).map((tz) => {
24+
const timezoneUTCDSTOffset = tz.utcOffset === tz.dstOffset ? tz.utcOffsetStr : `${tz.utcOffsetStr}/${tz.dstOffsetStr}`;
25+
return {
26+
value: tz.name,
27+
label: `${tz.name === browserTimezone ? 'Browser TZ - ' : ''}${tz.name} (${timezoneUTCDSTOffset})`,
28+
};
29+
});
2730
const currentTimezone = useQueryParamOrStorage({ name: 'tz', storageName: 'crongen:tz', defaultValue: browserTimezone });
2831
watchEffect(() => {
2932
cronstrueConfig.tzOffset = -getTimezoneOffset(currentTimezone.value, new Date()) / 60;
@@ -136,19 +139,24 @@ const awsHelpers = [
136139
},
137140
];
138141
139-
const cronType = computed({
140-
get() {
141-
return getCronType(cron.value);
142-
},
143-
set(newCronType) {
142+
const defaultAWSCronExpression = '0 0 ? * 1 *';
143+
const defaultStandardCronExpression = '40 * * * *';
144+
const cronType = ref<CronType>('standard');
145+
watch(cronType,
146+
(newCronType) => {
144147
if (newCronType === 'aws') {
145-
cron.value = '0 0 ? * 1 *';
148+
if (!cron.value || cron.value === defaultStandardCronExpression) {
149+
cron.value = defaultAWSCronExpression;
150+
}
146151
}
147-
else {
148-
cron.value = '40 * * * *';
152+
else if (newCronType === 'standard') {
153+
if (!cron.value || cron.value === defaultAWSCronExpression) {
154+
cron.value = defaultStandardCronExpression;
155+
}
149156
}
150157
},
151-
});
158+
);
159+
152160
const getHelpers = computed(() => {
153161
if (cronType.value === 'aws') {
154162
return awsHelpers;
@@ -165,7 +173,7 @@ const cronString = computed(() => {
165173
166174
const cronValidationRules = [
167175
{
168-
validator: (value: string) => isCronValid(value),
176+
validator: (value: string) => isCronValid(value, cronType.value),
169177
message: 'This cron is invalid',
170178
},
171179
];
@@ -245,7 +253,7 @@ const executionTimesString = computed(() => {
245253
</c-card>
246254
<c-card>
247255
<pre v-if="cronType === 'standard'">
248-
-- Standard CRON Syntax --
256+
-- Standard CRON Syntax --
249257
┌──────────── [optional] seconds (0 - 59)
250258
| ┌────────── minute (0 - 59)
251259
| | ┌──────── hour (0 - 23)
@@ -256,7 +264,7 @@ const executionTimesString = computed(() => {
256264
* * * * * * command</pre>
257265

258266
<pre v-if="cronType === 'aws'">
259-
-- AWS CRON Syntax --
267+
-- AWS CRON Syntax --
260268
┌──────────── minute (0 - 59)
261269
| ┌────────── hour (0 - 23)
262270
| | ┌──────── day of month (1 - 31) OR ? OR L OR W

0 commit comments

Comments
 (0)