donebear 0.3.6 → 0.3.8
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/AGENTS.md +3 -3
- package/dist/cli.mjs +3364 -251
- package/dist/cli.mjs.map +1 -1
- package/dist/context-store-CK4yIl9e.mjs +3 -0
- package/dist/{context-store-DH561Z1u.mjs → context-store-DuCNavgl.mjs} +3 -3
- package/dist/context-store-DuCNavgl.mjs.map +1 -0
- package/dist/prompt-B7mDo4K7.mjs +3 -0
- package/dist/{prompt-BrfcK2Ry.mjs → prompt-GfcWO85b.mjs} +2 -2
- package/dist/prompt-GfcWO85b.mjs.map +1 -0
- package/package.json +8 -12
- package/dist/context-store-D0Z9vbaU.mjs +0 -3
- package/dist/context-store-DH561Z1u.mjs.map +0 -1
- package/dist/prompt-BrfcK2Ry.mjs.map +0 -1
- package/dist/prompt-FRvfbinv.mjs +0 -3
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as toCliError, b as DONEBEAR_TOKEN_ENV, d as DEFAULT_OAUTH_CALLBACK_PATH, f as DEFAULT_OAUTH_CALLBACK_PORT, i as EXIT_CODES, l as CONFIG_DIR, n as setCurrentWorkspace, o as AUTH_FILE_PATH, r as CliError, s as CLI_NAME, t as ensureLocalContext } from "./context-store-
|
|
3
|
-
import { n as readStdin, t as promptForValue } from "./prompt-
|
|
2
|
+
import { a as toCliError, b as DONEBEAR_TOKEN_ENV, d as DEFAULT_OAUTH_CALLBACK_PATH, f as DEFAULT_OAUTH_CALLBACK_PORT, i as EXIT_CODES, l as CONFIG_DIR, n as setCurrentWorkspace, o as AUTH_FILE_PATH, r as CliError, s as CLI_NAME, t as ensureLocalContext } from "./context-store-DuCNavgl.mjs";
|
|
3
|
+
import { n as readStdin, t as promptForValue } from "./prompt-GfcWO85b.mjs";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { Command, InvalidArgumentError } from "commander";
|
|
6
6
|
import { homedir } from "node:os";
|
|
@@ -14,15 +14,17 @@ import { styleText } from "node:util";
|
|
|
14
14
|
import jmespath from "jmespath";
|
|
15
15
|
import { stringify } from "yaml";
|
|
16
16
|
import { createServer } from "node:http";
|
|
17
|
-
import rrule from "rrule";
|
|
18
17
|
import { fileURLToPath } from "node:url";
|
|
19
18
|
import Database from "better-sqlite3";
|
|
20
19
|
import { createInterface } from "node:readline";
|
|
20
|
+
//#region \0rolldown/runtime.js
|
|
21
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
22
|
+
//#endregion
|
|
21
23
|
//#region src/jwt.ts
|
|
22
24
|
const parseJwtBase64Url = (input) => {
|
|
23
25
|
const normalized = input.replaceAll("-", "+").replaceAll("_", "/");
|
|
24
26
|
const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "=");
|
|
25
|
-
return Buffer.from(padded, "base64").toString("
|
|
27
|
+
return Buffer.from(padded, "base64").toString("utf-8");
|
|
26
28
|
};
|
|
27
29
|
const parseJwtClaims = (token) => {
|
|
28
30
|
const payloadPart = token.split(".").at(1);
|
|
@@ -113,7 +115,7 @@ const parseAuthFile = (payload) => {
|
|
|
113
115
|
};
|
|
114
116
|
const readStoredAuthSession = async () => {
|
|
115
117
|
try {
|
|
116
|
-
return parseAuthFile(await readFile(AUTH_FILE_PATH, "
|
|
118
|
+
return parseAuthFile(await readFile(AUTH_FILE_PATH, "utf-8")).session;
|
|
117
119
|
} catch (error) {
|
|
118
120
|
if (isRecord(error) && error.code === "ENOENT") return null;
|
|
119
121
|
if (error instanceof CliError) throw error;
|
|
@@ -130,7 +132,7 @@ const writeStoredAuthSession = async (session) => {
|
|
|
130
132
|
recursive: true
|
|
131
133
|
});
|
|
132
134
|
await writeFile(AUTH_FILE_PATH, `${JSON.stringify(payload, null, 2)}\n`, {
|
|
133
|
-
encoding: "
|
|
135
|
+
encoding: "utf-8",
|
|
134
136
|
mode: 384
|
|
135
137
|
});
|
|
136
138
|
};
|
|
@@ -197,19 +199,6 @@ const tokenResponseToStoredSession = (response) => {
|
|
|
197
199
|
} : null
|
|
198
200
|
};
|
|
199
201
|
};
|
|
200
|
-
const getSupabaseUser = async (supabaseUrl, publishableKey, accessToken) => {
|
|
201
|
-
const response = await fetch(`${supabaseUrl}/auth/v1/user`, { headers: {
|
|
202
|
-
apikey: publishableKey,
|
|
203
|
-
authorization: `Bearer ${accessToken}`
|
|
204
|
-
} });
|
|
205
|
-
if (!response.ok) throw new CliError(`Failed to load user (${response.status})`, EXIT_CODES.ERROR);
|
|
206
|
-
const data = await response.json();
|
|
207
|
-
if (typeof data.id !== "string") throw new CliError("No user returned for current token", EXIT_CODES.ERROR);
|
|
208
|
-
return {
|
|
209
|
-
email: typeof data.email === "string" ? data.email : null,
|
|
210
|
-
id: data.id
|
|
211
|
-
};
|
|
212
|
-
};
|
|
213
202
|
//#endregion
|
|
214
203
|
//#region src/auth-session.ts
|
|
215
204
|
const expiryFromClaims = (claims) => {
|
|
@@ -344,8 +333,8 @@ const requestNdjson = async (context, endpoint, options) => {
|
|
|
344
333
|
};
|
|
345
334
|
//#endregion
|
|
346
335
|
//#region src/date-codecs.ts
|
|
347
|
-
const ISO_DATE_ONLY_REGEX = /^(\d{4})-(\d{2})-(\d{2})
|
|
348
|
-
const ISO_INSTANT_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})
|
|
336
|
+
const ISO_DATE_ONLY_REGEX = /^(\d{4})-(\d{2})-(\d{2})$/u;
|
|
337
|
+
const ISO_INSTANT_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/u;
|
|
349
338
|
const pad = (value, length = 2) => String(value).padStart(length, "0");
|
|
350
339
|
const isFiniteEpoch = (value) => typeof value === "number" && Number.isFinite(value);
|
|
351
340
|
const isValidDateOnlyParts = (parts) => {
|
|
@@ -415,6 +404,118 @@ const parseCliDateOnlyToEpoch = (value, fieldLabel) => {
|
|
|
415
404
|
};
|
|
416
405
|
const dateOnlyEpochFromLocalDate = (now = /* @__PURE__ */ new Date()) => Date.UTC(now.getFullYear(), now.getMonth(), now.getDate());
|
|
417
406
|
//#endregion
|
|
407
|
+
//#region src/output.ts
|
|
408
|
+
const writeLine = (stream, message) => {
|
|
409
|
+
stream.write(`${message}\n`);
|
|
410
|
+
};
|
|
411
|
+
const colorize = (context, format, message) => {
|
|
412
|
+
if (!context.color) return message;
|
|
413
|
+
return styleText(format, message);
|
|
414
|
+
};
|
|
415
|
+
const writeJson = (value) => {
|
|
416
|
+
writeLine(process.stdout, JSON.stringify(value, null, 2));
|
|
417
|
+
};
|
|
418
|
+
const writeYaml = (value) => {
|
|
419
|
+
process.stdout.write(stringify(value));
|
|
420
|
+
};
|
|
421
|
+
const writeInfo = (context, message) => {
|
|
422
|
+
writeLine(process.stdout, colorize(context, "cyan", message));
|
|
423
|
+
};
|
|
424
|
+
const writeSuccess = (context, message) => {
|
|
425
|
+
writeLine(process.stdout, colorize(context, "green", message));
|
|
426
|
+
};
|
|
427
|
+
const writeWarning = (context, message) => {
|
|
428
|
+
writeLine(process.stderr, colorize(context, "yellow", message));
|
|
429
|
+
};
|
|
430
|
+
const writeError = (context, message) => {
|
|
431
|
+
writeLine(process.stderr, colorize(context, "red", message));
|
|
432
|
+
};
|
|
433
|
+
const writeDebug = (context, message) => {
|
|
434
|
+
if (!context.debug) return;
|
|
435
|
+
writeLine(process.stderr, colorize(context, "gray", `[debug] ${message}`));
|
|
436
|
+
};
|
|
437
|
+
const writeTotal = (context, count) => {
|
|
438
|
+
writeLine(process.stdout, colorize(context, "cyan", String(count)));
|
|
439
|
+
};
|
|
440
|
+
const escapeCsvField = (value) => {
|
|
441
|
+
if (value.includes(",") || value.includes("\"") || value.includes("\n")) return `"${value.replaceAll("\"", "\"\"")}"`;
|
|
442
|
+
return value;
|
|
443
|
+
};
|
|
444
|
+
const writeCsv = (headers, rows) => {
|
|
445
|
+
writeLine(process.stdout, headers.map(escapeCsvField).join(","));
|
|
446
|
+
for (const row of rows) writeLine(process.stdout, row.map(escapeCsvField).join(","));
|
|
447
|
+
};
|
|
448
|
+
const writeTsv = (headers, rows) => {
|
|
449
|
+
writeLine(process.stdout, headers.join(" "));
|
|
450
|
+
for (const row of rows) writeLine(process.stdout, row.join(" "));
|
|
451
|
+
};
|
|
452
|
+
/**
|
|
453
|
+
* Write structured data to stdout, applying --jq filter and --limit if set.
|
|
454
|
+
* Use this for all JSON/YAML/structured output from commands.
|
|
455
|
+
*/
|
|
456
|
+
const writeOutput = (context, data) => {
|
|
457
|
+
let result = data;
|
|
458
|
+
if (context.jq) try {
|
|
459
|
+
result = jmespath.search(result, context.jq);
|
|
460
|
+
} catch (error) {
|
|
461
|
+
throw new CliError(`Invalid --jq expression: ${error instanceof Error ? error.message : String(error)}`, EXIT_CODES.VALIDATION);
|
|
462
|
+
}
|
|
463
|
+
if (context.limit !== null && Array.isArray(result)) result = result.slice(0, context.limit);
|
|
464
|
+
switch (context.format) {
|
|
465
|
+
case "yaml":
|
|
466
|
+
writeYaml(result);
|
|
467
|
+
break;
|
|
468
|
+
case "json":
|
|
469
|
+
writeJson(result);
|
|
470
|
+
break;
|
|
471
|
+
default:
|
|
472
|
+
writeJson(result);
|
|
473
|
+
break;
|
|
474
|
+
}
|
|
475
|
+
if (context.copy) copyToClipboard(JSON.stringify(result, null, 2));
|
|
476
|
+
};
|
|
477
|
+
/**
|
|
478
|
+
* Handles --total, --format csv, --format tsv, --format yaml output.
|
|
479
|
+
* Returns true if the format was handled; caller renders text mode if false.
|
|
480
|
+
*/
|
|
481
|
+
const writeFormattedRows = (context, totalCount, headers, rows) => {
|
|
482
|
+
if (context.total) {
|
|
483
|
+
writeTotal(context, totalCount);
|
|
484
|
+
return true;
|
|
485
|
+
}
|
|
486
|
+
if (context.format === "yaml") {
|
|
487
|
+
const objects = rows.map((row) => Object.fromEntries(headers.map((h, i) => [h, row[i]])));
|
|
488
|
+
writeYaml(objects);
|
|
489
|
+
if (context.copy) copyToClipboard(stringify(objects));
|
|
490
|
+
return true;
|
|
491
|
+
}
|
|
492
|
+
if (context.format === "csv") {
|
|
493
|
+
writeCsv(headers, rows);
|
|
494
|
+
if (context.copy) copyToClipboard([headers.join(","), ...rows.map((r) => r.join(","))].join("\n"));
|
|
495
|
+
return true;
|
|
496
|
+
}
|
|
497
|
+
if (context.format === "tsv") {
|
|
498
|
+
writeTsv(headers, rows);
|
|
499
|
+
if (context.copy) copyToClipboard([headers.join(" "), ...rows.map((r) => r.join(" "))].join("\n"));
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
return false;
|
|
503
|
+
};
|
|
504
|
+
const copyToClipboard = (text) => {
|
|
505
|
+
try {
|
|
506
|
+
if (process.platform === "darwin") execSync("pbcopy", { input: text });
|
|
507
|
+
else if (process.platform === "win32") execSync("clip", { input: text });
|
|
508
|
+
else try {
|
|
509
|
+
execSync("xclip -selection clipboard", { input: text });
|
|
510
|
+
} catch {
|
|
511
|
+
execSync("xsel --clipboard --input", { input: text });
|
|
512
|
+
}
|
|
513
|
+
return true;
|
|
514
|
+
} catch {
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
//#endregion
|
|
418
519
|
//#region src/manage-api.ts
|
|
419
520
|
const TASK_FIELDS = `
|
|
420
521
|
id
|
|
@@ -567,17 +668,17 @@ const WORKSPACE_HISTORY_QUERY = `
|
|
|
567
668
|
}
|
|
568
669
|
`;
|
|
569
670
|
const API_KEY_CREATE_MUTATION = `
|
|
570
|
-
mutation ApiKeyCreate($label: String!) {
|
|
571
|
-
apiKeyCreate(label: $label) {
|
|
671
|
+
mutation ApiKeyCreate($label: String!, $scopes: [String!], $workspaceIds: [ID!], $expiresAt: DateTime) {
|
|
672
|
+
apiKeyCreate(label: $label, scopes: $scopes, workspaceIds: $workspaceIds, expiresAt: $expiresAt) {
|
|
572
673
|
success lastSyncId
|
|
573
|
-
apiKey { id label keyPrefix createdAt }
|
|
674
|
+
apiKey { id label keyPrefix scopes workspaceIds expiresAt createdAt }
|
|
574
675
|
token
|
|
575
676
|
}
|
|
576
677
|
}
|
|
577
678
|
`;
|
|
578
679
|
const API_KEYS_QUERY = `
|
|
579
680
|
query ApiKeys {
|
|
580
|
-
apiKeys { id label keyPrefix lastUsedAt revokedAt createdAt }
|
|
681
|
+
apiKeys { id label keyPrefix scopes workspaceIds expiresAt lastUsedAt revokedAt createdAt }
|
|
581
682
|
}
|
|
582
683
|
`;
|
|
583
684
|
const API_KEY_REVOKE_MUTATION = `
|
|
@@ -761,11 +862,14 @@ const toWorkspaceHistoryEntryFromGraphqlNode = (node) => ({
|
|
|
761
862
|
});
|
|
762
863
|
const toApiKeyRecordFromGraphqlNode = (node) => ({
|
|
763
864
|
createdAt: node.createdAt,
|
|
865
|
+
expiresAt: node.expiresAt,
|
|
764
866
|
id: node.id,
|
|
765
867
|
keyPrefix: node.keyPrefix,
|
|
766
868
|
label: node.label,
|
|
767
869
|
lastUsedAt: node.lastUsedAt,
|
|
768
|
-
revokedAt: node.revokedAt
|
|
870
|
+
revokedAt: node.revokedAt,
|
|
871
|
+
scopes: node.scopes,
|
|
872
|
+
workspaceIds: node.workspaceIds
|
|
769
873
|
});
|
|
770
874
|
const toChecklistItemRecord = (value) => {
|
|
771
875
|
if (typeof value !== "object" || value === null) return null;
|
|
@@ -789,6 +893,26 @@ const resolveApiBaseUrl = (context) => {
|
|
|
789
893
|
if (fromContext) return normalizeApiUrl(fromContext);
|
|
790
894
|
return normalizeApiUrl(readEnvValue("DONEBEAR_API_URL") ?? "https://api.donebear.com");
|
|
791
895
|
};
|
|
896
|
+
const VIEWER_QUERY = `
|
|
897
|
+
query Viewer {
|
|
898
|
+
viewer {
|
|
899
|
+
id
|
|
900
|
+
email
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
`;
|
|
904
|
+
const loadViewer = async (context, options) => {
|
|
905
|
+
const data = await requestGraphql(context, `${options.baseUrl}/graphql`, {
|
|
906
|
+
query: VIEWER_QUERY,
|
|
907
|
+
token: options.token,
|
|
908
|
+
variables: {}
|
|
909
|
+
});
|
|
910
|
+
if (!data.viewer) throw new CliError("Could not resolve current user. The token may be invalid or revoked.", EXIT_CODES.AUTH_REQUIRED);
|
|
911
|
+
return {
|
|
912
|
+
email: data.viewer.email ?? null,
|
|
913
|
+
id: data.viewer.id
|
|
914
|
+
};
|
|
915
|
+
};
|
|
792
916
|
const listWorkspaces = async (context, options) => {
|
|
793
917
|
return (await requestGraphql(context, `${options.baseUrl}/graphql`, {
|
|
794
918
|
query: MY_WORKSPACES_QUERY,
|
|
@@ -910,6 +1034,19 @@ const loadChecklistItemsByTask = async (context, options) => {
|
|
|
910
1034
|
return results;
|
|
911
1035
|
};
|
|
912
1036
|
const mutateModel = async (context, options) => {
|
|
1037
|
+
if (context.dryRun) {
|
|
1038
|
+
writeWarning(context, "dry run: mutation skipped");
|
|
1039
|
+
writeOutput(context, {
|
|
1040
|
+
dryRun: true,
|
|
1041
|
+
transactions: options.request.transactions.map((tx) => ({
|
|
1042
|
+
action: tx.action,
|
|
1043
|
+
modelId: tx.modelId,
|
|
1044
|
+
modelName: tx.modelName,
|
|
1045
|
+
payload: tx.payload
|
|
1046
|
+
}))
|
|
1047
|
+
});
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
913
1050
|
const response = await requestJson(context, `${options.baseUrl}/sync/mutate`, {
|
|
914
1051
|
body: options.request,
|
|
915
1052
|
method: "POST",
|
|
@@ -962,10 +1099,15 @@ const listWorkspaceHistory = async (context, options) => {
|
|
|
962
1099
|
})).workspaceHistory.map(toWorkspaceHistoryEntryFromGraphqlNode);
|
|
963
1100
|
};
|
|
964
1101
|
const createApiKey = async (context, options) => {
|
|
965
|
-
const
|
|
1102
|
+
const endpoint = `${options.baseUrl}/graphql`;
|
|
1103
|
+
const variables = { label: options.label };
|
|
1104
|
+
if (options.scopes !== void 0) variables.scopes = options.scopes;
|
|
1105
|
+
if (options.workspaceIds !== void 0) variables.workspaceIds = options.workspaceIds;
|
|
1106
|
+
if (options.expiresAt !== void 0) variables.expiresAt = options.expiresAt;
|
|
1107
|
+
const data = await requestGraphql(context, endpoint, {
|
|
966
1108
|
query: API_KEY_CREATE_MUTATION,
|
|
967
1109
|
token: options.token,
|
|
968
|
-
variables
|
|
1110
|
+
variables
|
|
969
1111
|
});
|
|
970
1112
|
return {
|
|
971
1113
|
...toApiKeyRecordFromGraphqlNode(data.apiKeyCreate.apiKey),
|
|
@@ -1013,122 +1155,13 @@ const resolveCommandContext = async (context) => {
|
|
|
1013
1155
|
token
|
|
1014
1156
|
};
|
|
1015
1157
|
};
|
|
1016
|
-
const requireUserId = (
|
|
1017
|
-
const
|
|
1018
|
-
if (
|
|
1019
|
-
return
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
const writeLine = (stream, message) => {
|
|
1024
|
-
stream.write(`${message}\n`);
|
|
1025
|
-
};
|
|
1026
|
-
const colorize = (context, format, message) => {
|
|
1027
|
-
if (!context.color) return message;
|
|
1028
|
-
return styleText(format, message);
|
|
1029
|
-
};
|
|
1030
|
-
const writeJson = (value) => {
|
|
1031
|
-
writeLine(process.stdout, JSON.stringify(value, null, 2));
|
|
1032
|
-
};
|
|
1033
|
-
const writeYaml = (value) => {
|
|
1034
|
-
process.stdout.write(stringify(value));
|
|
1035
|
-
};
|
|
1036
|
-
const writeInfo = (context, message) => {
|
|
1037
|
-
writeLine(process.stdout, colorize(context, "cyan", message));
|
|
1038
|
-
};
|
|
1039
|
-
const writeSuccess = (context, message) => {
|
|
1040
|
-
writeLine(process.stdout, colorize(context, "green", message));
|
|
1041
|
-
};
|
|
1042
|
-
const writeWarning = (context, message) => {
|
|
1043
|
-
writeLine(process.stderr, colorize(context, "yellow", message));
|
|
1044
|
-
};
|
|
1045
|
-
const writeError = (context, message) => {
|
|
1046
|
-
writeLine(process.stderr, colorize(context, "red", message));
|
|
1047
|
-
};
|
|
1048
|
-
const writeDebug = (context, message) => {
|
|
1049
|
-
if (!context.debug) return;
|
|
1050
|
-
writeLine(process.stderr, colorize(context, "gray", `[debug] ${message}`));
|
|
1051
|
-
};
|
|
1052
|
-
const writeTotal = (context, count) => {
|
|
1053
|
-
writeLine(process.stdout, colorize(context, "cyan", String(count)));
|
|
1054
|
-
};
|
|
1055
|
-
const escapeCsvField = (value) => {
|
|
1056
|
-
if (value.includes(",") || value.includes("\"") || value.includes("\n")) return `"${value.replaceAll("\"", "\"\"")}"`;
|
|
1057
|
-
return value;
|
|
1058
|
-
};
|
|
1059
|
-
const writeCsv = (headers, rows) => {
|
|
1060
|
-
writeLine(process.stdout, headers.map(escapeCsvField).join(","));
|
|
1061
|
-
for (const row of rows) writeLine(process.stdout, row.map(escapeCsvField).join(","));
|
|
1062
|
-
};
|
|
1063
|
-
const writeTsv = (headers, rows) => {
|
|
1064
|
-
writeLine(process.stdout, headers.join(" "));
|
|
1065
|
-
for (const row of rows) writeLine(process.stdout, row.join(" "));
|
|
1066
|
-
};
|
|
1067
|
-
/**
|
|
1068
|
-
* Write structured data to stdout, applying --jq filter and --limit if set.
|
|
1069
|
-
* Use this for all JSON/YAML/structured output from commands.
|
|
1070
|
-
*/
|
|
1071
|
-
const writeOutput = (context, data) => {
|
|
1072
|
-
let result = data;
|
|
1073
|
-
if (context.jq) try {
|
|
1074
|
-
result = jmespath.search(result, context.jq);
|
|
1075
|
-
} catch (error) {
|
|
1076
|
-
throw new CliError(`Invalid --jq expression: ${error instanceof Error ? error.message : String(error)}`, EXIT_CODES.VALIDATION);
|
|
1077
|
-
}
|
|
1078
|
-
if (context.limit !== null && Array.isArray(result)) result = result.slice(0, context.limit);
|
|
1079
|
-
switch (context.format) {
|
|
1080
|
-
case "yaml":
|
|
1081
|
-
writeYaml(result);
|
|
1082
|
-
break;
|
|
1083
|
-
case "json":
|
|
1084
|
-
writeJson(result);
|
|
1085
|
-
break;
|
|
1086
|
-
default:
|
|
1087
|
-
writeJson(result);
|
|
1088
|
-
break;
|
|
1089
|
-
}
|
|
1090
|
-
if (context.copy) copyToClipboard(JSON.stringify(result, null, 2));
|
|
1091
|
-
};
|
|
1092
|
-
/**
|
|
1093
|
-
* Handles --total, --format csv, --format tsv, --format yaml output.
|
|
1094
|
-
* Returns true if the format was handled; caller renders text mode if false.
|
|
1095
|
-
*/
|
|
1096
|
-
const writeFormattedRows = (context, totalCount, headers, rows) => {
|
|
1097
|
-
if (context.total) {
|
|
1098
|
-
writeTotal(context, totalCount);
|
|
1099
|
-
return true;
|
|
1100
|
-
}
|
|
1101
|
-
if (context.format === "yaml") {
|
|
1102
|
-
const objects = rows.map((row) => Object.fromEntries(headers.map((h, i) => [h, row[i]])));
|
|
1103
|
-
writeYaml(objects);
|
|
1104
|
-
if (context.copy) copyToClipboard(stringify(objects));
|
|
1105
|
-
return true;
|
|
1106
|
-
}
|
|
1107
|
-
if (context.format === "csv") {
|
|
1108
|
-
writeCsv(headers, rows);
|
|
1109
|
-
if (context.copy) copyToClipboard([headers.join(","), ...rows.map((r) => r.join(","))].join("\n"));
|
|
1110
|
-
return true;
|
|
1111
|
-
}
|
|
1112
|
-
if (context.format === "tsv") {
|
|
1113
|
-
writeTsv(headers, rows);
|
|
1114
|
-
if (context.copy) copyToClipboard([headers.join(" "), ...rows.map((r) => r.join(" "))].join("\n"));
|
|
1115
|
-
return true;
|
|
1116
|
-
}
|
|
1117
|
-
return false;
|
|
1118
|
-
};
|
|
1119
|
-
const copyToClipboard = (text) => {
|
|
1120
|
-
try {
|
|
1121
|
-
if (process.platform === "darwin") execSync("pbcopy", { input: text });
|
|
1122
|
-
else if (process.platform === "win32") execSync("clip", { input: text });
|
|
1123
|
-
else try {
|
|
1124
|
-
execSync("xclip -selection clipboard", { input: text });
|
|
1125
|
-
} catch {
|
|
1126
|
-
execSync("xsel --clipboard --input", { input: text });
|
|
1127
|
-
}
|
|
1128
|
-
return true;
|
|
1129
|
-
} catch {
|
|
1130
|
-
return false;
|
|
1131
|
-
}
|
|
1158
|
+
const requireUserId = async (context, commandContext) => {
|
|
1159
|
+
const claimUserId = commandContext.resolvedToken.user?.id ?? null;
|
|
1160
|
+
if (typeof claimUserId === "string" && claimUserId.length > 0) return claimUserId;
|
|
1161
|
+
return (await loadViewer(context, {
|
|
1162
|
+
baseUrl: commandContext.apiBaseUrl,
|
|
1163
|
+
token: commandContext.token
|
|
1164
|
+
})).id;
|
|
1132
1165
|
};
|
|
1133
1166
|
//#endregion
|
|
1134
1167
|
//#region src/options.ts
|
|
@@ -1223,20 +1256,68 @@ const runWithErrorHandling = async (context, action) => {
|
|
|
1223
1256
|
};
|
|
1224
1257
|
//#endregion
|
|
1225
1258
|
//#region src/commands/api-key.ts
|
|
1226
|
-
const
|
|
1259
|
+
const PERMISSION_SCOPES = {
|
|
1260
|
+
"full-access": [
|
|
1261
|
+
"read",
|
|
1262
|
+
"write",
|
|
1263
|
+
"admin"
|
|
1264
|
+
],
|
|
1265
|
+
"read-only": ["read"]
|
|
1266
|
+
};
|
|
1267
|
+
const parseDuration = (duration) => {
|
|
1268
|
+
const match = duration.match(/^(\d+)(d|y)$/u);
|
|
1269
|
+
if (!match) throw new CliError(`Invalid duration "${duration}". Use a format like "30d", "90d", or "1y".`, EXIT_CODES.VALIDATION);
|
|
1270
|
+
const [, rawAmount, unit] = match;
|
|
1271
|
+
const amount = Number(rawAmount);
|
|
1272
|
+
const now = /* @__PURE__ */ new Date();
|
|
1273
|
+
if (unit === "d") now.setDate(now.getDate() + amount);
|
|
1274
|
+
else now.setDate(now.getDate() + amount * 365);
|
|
1275
|
+
return now;
|
|
1276
|
+
};
|
|
1277
|
+
const runCreate = async (context, label, options) => {
|
|
1227
1278
|
const { token } = await requireAuthToken(context);
|
|
1279
|
+
const baseUrl = resolveApiBaseUrl(context);
|
|
1280
|
+
let scopes;
|
|
1281
|
+
if (options.permissions !== void 0) {
|
|
1282
|
+
const level = options.permissions;
|
|
1283
|
+
if (!PERMISSION_SCOPES[level]) throw new CliError(`Invalid permissions "${options.permissions}". Use "full-access" or "read-only".`, EXIT_CODES.VALIDATION);
|
|
1284
|
+
scopes = PERMISSION_SCOPES[level];
|
|
1285
|
+
}
|
|
1286
|
+
let workspaceIds;
|
|
1287
|
+
if (options.workspaces !== void 0) {
|
|
1288
|
+
const slugs = options.workspaces.split(",").map((s) => s.trim()).filter(Boolean);
|
|
1289
|
+
if (slugs.length === 0) throw new CliError("No workspace slugs provided for --workspaces.", EXIT_CODES.VALIDATION);
|
|
1290
|
+
const allWorkspaces = await listWorkspaces(context, {
|
|
1291
|
+
baseUrl,
|
|
1292
|
+
token
|
|
1293
|
+
});
|
|
1294
|
+
workspaceIds = [];
|
|
1295
|
+
for (const slug of slugs) {
|
|
1296
|
+
const match = allWorkspaces.find((ws) => ws.urlKey === slug || ws.id === slug || ws.name.toLowerCase() === slug.toLowerCase());
|
|
1297
|
+
if (!match) throw new CliError(`Workspace "${slug}" not found. Run \`donebear workspace list\` to see available workspaces.`, EXIT_CODES.VALIDATION);
|
|
1298
|
+
workspaceIds.push(match.id);
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
let expiresAt;
|
|
1302
|
+
if (options.expires !== void 0) expiresAt = parseDuration(options.expires).toISOString();
|
|
1228
1303
|
const key = await createApiKey(context, {
|
|
1229
|
-
baseUrl
|
|
1304
|
+
baseUrl,
|
|
1305
|
+
expiresAt,
|
|
1230
1306
|
label,
|
|
1231
|
-
|
|
1307
|
+
scopes,
|
|
1308
|
+
token,
|
|
1309
|
+
workspaceIds
|
|
1232
1310
|
});
|
|
1233
1311
|
if (context.json) {
|
|
1234
1312
|
writeOutput(context, {
|
|
1235
1313
|
createdAt: key.createdAt,
|
|
1314
|
+
expiresAt: key.expiresAt,
|
|
1236
1315
|
id: key.id,
|
|
1237
1316
|
keyPrefix: key.keyPrefix,
|
|
1238
1317
|
label: key.label,
|
|
1239
|
-
|
|
1318
|
+
scopes: key.scopes,
|
|
1319
|
+
token: key.token,
|
|
1320
|
+
workspaceIds: key.workspaceIds
|
|
1240
1321
|
});
|
|
1241
1322
|
return;
|
|
1242
1323
|
}
|
|
@@ -1244,6 +1325,10 @@ const runCreate = async (context, label) => {
|
|
|
1244
1325
|
writeInfo(context, "");
|
|
1245
1326
|
writeInfo(context, ` ${key.token}`);
|
|
1246
1327
|
writeInfo(context, "");
|
|
1328
|
+
writeInfo(context, ` Scopes: ${key.scopes.join(", ")}`);
|
|
1329
|
+
if (key.workspaceIds && key.workspaceIds.length > 0) writeInfo(context, ` Restricted to workspaces: ${key.workspaceIds.join(", ")}`);
|
|
1330
|
+
if (key.expiresAt) writeInfo(context, ` Expires: ${new Date(key.expiresAt).toLocaleDateString()}`);
|
|
1331
|
+
writeInfo(context, "");
|
|
1247
1332
|
writeWarning(context, "Save this key now — it will not be shown again.");
|
|
1248
1333
|
};
|
|
1249
1334
|
const runList = async (context) => {
|
|
@@ -1263,7 +1348,10 @@ const runList = async (context) => {
|
|
|
1263
1348
|
for (const key of keys) {
|
|
1264
1349
|
const status = key.revokedAt ? " (revoked)" : "";
|
|
1265
1350
|
const lastUsed = key.lastUsedAt ? `Last used: ${new Date(key.lastUsedAt).toLocaleDateString()}` : "Never used";
|
|
1266
|
-
|
|
1351
|
+
const scopeStr = `[${key.scopes.join(",")}]`;
|
|
1352
|
+
const wsStr = key.workspaceIds && key.workspaceIds.length > 0 ? ` ws:${key.workspaceIds.length}` : "";
|
|
1353
|
+
const expStr = key.expiresAt ? ` exp:${new Date(key.expiresAt).toLocaleDateString()}` : "";
|
|
1354
|
+
writeInfo(context, `${key.keyPrefix}... ${key.label} ${scopeStr}${wsStr}${expStr} ${lastUsed}${status} [${key.id}]`);
|
|
1267
1355
|
}
|
|
1268
1356
|
};
|
|
1269
1357
|
const runRevoke = async (context, keyId) => {
|
|
@@ -1286,6 +1374,8 @@ const registerApiKeyCommands = (program) => {
|
|
|
1286
1374
|
const apiKey = program.command("api-key").alias("key").description("Manage personal API keys").addHelpText("after", `
|
|
1287
1375
|
Examples:
|
|
1288
1376
|
donebear api-key create "Raycast"
|
|
1377
|
+
donebear api-key create "CI" --permissions read-only --expires 90d
|
|
1378
|
+
donebear api-key create "Scoped" --workspaces my-org,side-project --expires 1y
|
|
1289
1379
|
donebear api-key list
|
|
1290
1380
|
donebear api-key revoke <key-id>
|
|
1291
1381
|
`).action(async (_options, command) => {
|
|
@@ -1294,10 +1384,10 @@ Examples:
|
|
|
1294
1384
|
await runList(context);
|
|
1295
1385
|
});
|
|
1296
1386
|
});
|
|
1297
|
-
apiKey.command("create <label>").description("Create a new personal API key").action(async (label,
|
|
1387
|
+
apiKey.command("create <label>").description("Create a new personal API key").option("--permissions <value>", "Permission level: \"full-access\" or \"read-only\"", "full-access").option("--workspaces <slugs>", "Comma-separated workspace slugs to restrict the key to").option("--expires <duration>", "Expiration duration, e.g. \"30d\", \"90d\", \"1y\"").action(async (label, options, command) => {
|
|
1298
1388
|
const context = contextFromCommand(command);
|
|
1299
1389
|
await runWithErrorHandling(context, async () => {
|
|
1300
|
-
await runCreate(context, label);
|
|
1390
|
+
await runCreate(context, label, options);
|
|
1301
1391
|
});
|
|
1302
1392
|
});
|
|
1303
1393
|
apiKey.command("list").description("List all personal API keys").action(async (_options, command) => {
|
|
@@ -1654,7 +1744,7 @@ const resolveTaskView = (task) => {
|
|
|
1654
1744
|
const formatEpochDate = (epochMs) => formatInstantEpoch(epochMs);
|
|
1655
1745
|
//#endregion
|
|
1656
1746
|
//#region src/command-helpers.ts
|
|
1657
|
-
const SHORT_ID_SUFFIX_PATTERN = /-([a-f0-9]{8})
|
|
1747
|
+
const SHORT_ID_SUFFIX_PATTERN = /-([a-f0-9]{8})$/u;
|
|
1658
1748
|
/**
|
|
1659
1749
|
* Find a record by reference: exact ID, key, ID prefix, slug shortId, or name.
|
|
1660
1750
|
* Works for any entity with id, key, and name fields.
|
|
@@ -1708,7 +1798,7 @@ const taskListLines = (tasks) => tasks.map((task) => {
|
|
|
1708
1798
|
});
|
|
1709
1799
|
//#endregion
|
|
1710
1800
|
//#region src/workspace-context.ts
|
|
1711
|
-
const WORKSPACE_URL_KEY_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)
|
|
1801
|
+
const WORKSPACE_URL_KEY_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
|
|
1712
1802
|
const fetchWorkspaces = async (context, options) => {
|
|
1713
1803
|
const workspaces = await listWorkspaces(context, {
|
|
1714
1804
|
baseUrl: options.apiBaseUrl,
|
|
@@ -1767,7 +1857,7 @@ const byReference = (workspaces, reference) => {
|
|
|
1767
1857
|
return null;
|
|
1768
1858
|
};
|
|
1769
1859
|
const toWorkspaceUrlKey = (name) => {
|
|
1770
|
-
return name.trim().toLowerCase().replaceAll(/[^a-z0-9]+/
|
|
1860
|
+
return name.trim().toLowerCase().replaceAll(/[^a-z0-9]+/gu, "-").replaceAll(/^-+|-+$/gu, "").replaceAll(/-{2,}/gu, "-").slice(0, 50);
|
|
1771
1861
|
};
|
|
1772
1862
|
const isValidWorkspaceUrlKey = (value) => WORKSPACE_URL_KEY_REGEX.test(value) && value.length >= 3;
|
|
1773
1863
|
const resolveWorkspace = async (context, options) => {
|
|
@@ -1978,7 +2068,7 @@ const checkAuth = async (context) => {
|
|
|
1978
2068
|
};
|
|
1979
2069
|
const checkWorkspace = async () => {
|
|
1980
2070
|
try {
|
|
1981
|
-
const { ensureLocalContext } = await import("./context-store-
|
|
2071
|
+
const { ensureLocalContext } = await import("./context-store-CK4yIl9e.mjs");
|
|
1982
2072
|
const localContext = await ensureLocalContext();
|
|
1983
2073
|
if (!localContext.workspaceId) return {
|
|
1984
2074
|
message: "No workspace selected (run `donebear workspace use`)",
|
|
@@ -2169,70 +2259,2825 @@ Examples:
|
|
|
2169
2259
|
await runHistory(context, workspaceOverride, options);
|
|
2170
2260
|
});
|
|
2171
2261
|
});
|
|
2172
|
-
};
|
|
2173
|
-
//#endregion
|
|
2174
|
-
//#region src/import/things-output.ts
|
|
2175
|
-
const summarizeThingsImportResult = (result) => {
|
|
2176
|
-
const infoLines = [
|
|
2177
|
-
`workspace: ${result.workspace.name}`,
|
|
2178
|
-
`database: ${result.databasePath}`,
|
|
2179
|
-
`source: ${result.counts.source.tasks} tasks, ${result.counts.source.projects} projects, ${result.counts.source.headings} headings, ${result.counts.source.areas} areas, ${result.counts.source.tags} tags, ${result.counts.source.checklistItems} checklist items`,
|
|
2180
|
-
`planned: ${result.counts.planned.teams ?? 0} teams, ${result.counts.planned.labels ?? 0} labels, ${result.counts.planned.projects ?? 0} projects, ${result.counts.planned.teamProjects ?? 0} team-project links, ${result.counts.planned.headings ?? 0} headings, ${result.counts.planned.tasks ?? 0} tasks, ${result.counts.planned.taskLabels ?? 0} task-label links, ${result.counts.planned.checklistItems ?? 0} checklist items`
|
|
2181
|
-
];
|
|
2182
|
-
if (result.dryRun) infoLines.push("dry run: no mutations sent");
|
|
2183
|
-
else infoLines.push(`mutations: ${result.execution.inserted} inserted, ${result.execution.updated} updated, ${result.execution.skipped} skipped across ${result.execution.batches} batch(es)`);
|
|
2184
|
-
return {
|
|
2185
|
-
infoLines,
|
|
2186
|
-
successMessage: result.dryRun ? "Things 3 import dry run complete" : "Things 3 import complete"
|
|
2187
|
-
};
|
|
2188
|
-
};
|
|
2189
|
-
//#endregion
|
|
2190
|
-
//#region src/import/things-labels.ts
|
|
2191
|
-
const normalizeThingsLabelLookupKey = (value) => value.trim().toLocaleLowerCase();
|
|
2192
|
-
//#endregion
|
|
2193
|
-
//#region src/import/model-id.ts
|
|
2194
|
-
const IMPORT_ID_NAMESPACE = "b1f9f0ac-9f76-54ed-8eb0-7d6d3a0a0a31";
|
|
2195
|
-
const SYNC_COMPOSITE_ID_NAMESPACE = "92a73695-d772-4b43-9fb4-d79f5fbef300";
|
|
2196
|
-
const uuidToBytes = (uuid) => {
|
|
2197
|
-
const normalized = uuid.replaceAll("-", "");
|
|
2198
|
-
if (normalized.length !== 32) throw new Error(`Invalid UUID namespace: ${uuid}`);
|
|
2199
|
-
return Uint8Array.from(Buffer.from(normalized, "hex"));
|
|
2200
|
-
};
|
|
2201
|
-
const bytesToUuid = (bytes) => {
|
|
2202
|
-
const hex = Buffer.from(bytes).toString("hex");
|
|
2203
|
-
return [
|
|
2204
|
-
hex.slice(0, 8),
|
|
2205
|
-
hex.slice(8, 12),
|
|
2206
|
-
hex.slice(12, 16),
|
|
2207
|
-
hex.slice(16, 20),
|
|
2208
|
-
hex.slice(20, 32)
|
|
2209
|
-
].join("-");
|
|
2210
|
-
};
|
|
2211
|
-
const createUuidV5 = (name, namespace) => {
|
|
2212
|
-
const namespaceBytes = uuidToBytes(namespace);
|
|
2213
|
-
const hash = createHash("sha1").update(namespaceBytes).update(Buffer.from(name, "
|
|
2214
|
-
const bytes = Uint8Array.from(hash.subarray(0, 16));
|
|
2215
|
-
const versionByte = bytes
|
|
2216
|
-
const variantByte = bytes
|
|
2217
|
-
if (typeof versionByte !== "number" || typeof variantByte !== "number") throw new TypeError("Failed to generate a deterministic UUID.");
|
|
2218
|
-
bytes[6] = versionByte & 15 | 80;
|
|
2219
|
-
bytes[8] = variantByte & 63 | 128;
|
|
2220
|
-
return bytesToUuid(bytes);
|
|
2221
|
-
};
|
|
2222
|
-
const createCompositeSyncId = (model, parts) => createUuidV5(`${model}:${JSON.stringify(parts)}`, SYNC_COMPOSITE_ID_NAMESPACE);
|
|
2223
|
-
const createDeterministicImportId = (params) => createUuidV5(`things:${params.workspaceId}:${params.modelName}:${params.sourceId}`, IMPORT_ID_NAMESPACE);
|
|
2224
|
-
const createTaskLabelId = (params) => createCompositeSyncId("TaskLabel", [
|
|
2225
|
-
params.workspaceId,
|
|
2226
|
-
params.taskId,
|
|
2227
|
-
params.labelId
|
|
2228
|
-
]);
|
|
2229
|
-
const createTeamProjectId = (params) => createCompositeSyncId("TeamProject", [
|
|
2230
|
-
params.workspaceId,
|
|
2231
|
-
params.teamId,
|
|
2232
|
-
params.projectId
|
|
2233
|
-
]);
|
|
2234
|
-
//#endregion
|
|
2235
|
-
//#region src/import/things-values.ts
|
|
2262
|
+
};
|
|
2263
|
+
//#endregion
|
|
2264
|
+
//#region src/import/things-output.ts
|
|
2265
|
+
const summarizeThingsImportResult = (result) => {
|
|
2266
|
+
const infoLines = [
|
|
2267
|
+
`workspace: ${result.workspace.name}`,
|
|
2268
|
+
`database: ${result.databasePath}`,
|
|
2269
|
+
`source: ${result.counts.source.tasks} tasks, ${result.counts.source.projects} projects, ${result.counts.source.headings} headings, ${result.counts.source.areas} areas, ${result.counts.source.tags} tags, ${result.counts.source.checklistItems} checklist items`,
|
|
2270
|
+
`planned: ${result.counts.planned.teams ?? 0} teams, ${result.counts.planned.labels ?? 0} labels, ${result.counts.planned.projects ?? 0} projects, ${result.counts.planned.teamProjects ?? 0} team-project links, ${result.counts.planned.headings ?? 0} headings, ${result.counts.planned.tasks ?? 0} tasks, ${result.counts.planned.taskLabels ?? 0} task-label links, ${result.counts.planned.checklistItems ?? 0} checklist items`
|
|
2271
|
+
];
|
|
2272
|
+
if (result.dryRun) infoLines.push("dry run: no mutations sent");
|
|
2273
|
+
else infoLines.push(`mutations: ${result.execution.inserted} inserted, ${result.execution.updated} updated, ${result.execution.skipped} skipped across ${result.execution.batches} batch(es)`);
|
|
2274
|
+
return {
|
|
2275
|
+
infoLines,
|
|
2276
|
+
successMessage: result.dryRun ? "Things 3 import dry run complete" : "Things 3 import complete"
|
|
2277
|
+
};
|
|
2278
|
+
};
|
|
2279
|
+
//#endregion
|
|
2280
|
+
//#region src/import/things-labels.ts
|
|
2281
|
+
const normalizeThingsLabelLookupKey = (value) => value.trim().toLocaleLowerCase();
|
|
2282
|
+
//#endregion
|
|
2283
|
+
//#region src/import/model-id.ts
|
|
2284
|
+
const IMPORT_ID_NAMESPACE = "b1f9f0ac-9f76-54ed-8eb0-7d6d3a0a0a31";
|
|
2285
|
+
const SYNC_COMPOSITE_ID_NAMESPACE = "92a73695-d772-4b43-9fb4-d79f5fbef300";
|
|
2286
|
+
const uuidToBytes = (uuid) => {
|
|
2287
|
+
const normalized = uuid.replaceAll("-", "");
|
|
2288
|
+
if (normalized.length !== 32) throw new Error(`Invalid UUID namespace: ${uuid}`);
|
|
2289
|
+
return Uint8Array.from(Buffer.from(normalized, "hex"));
|
|
2290
|
+
};
|
|
2291
|
+
const bytesToUuid = (bytes) => {
|
|
2292
|
+
const hex = Buffer.from(bytes).toString("hex");
|
|
2293
|
+
return [
|
|
2294
|
+
hex.slice(0, 8),
|
|
2295
|
+
hex.slice(8, 12),
|
|
2296
|
+
hex.slice(12, 16),
|
|
2297
|
+
hex.slice(16, 20),
|
|
2298
|
+
hex.slice(20, 32)
|
|
2299
|
+
].join("-");
|
|
2300
|
+
};
|
|
2301
|
+
const createUuidV5 = (name, namespace) => {
|
|
2302
|
+
const namespaceBytes = uuidToBytes(namespace);
|
|
2303
|
+
const hash = createHash("sha1").update(namespaceBytes).update(Buffer.from(name, "utf-8")).digest();
|
|
2304
|
+
const bytes = Uint8Array.from(hash.subarray(0, 16));
|
|
2305
|
+
const versionByte = bytes.at(6);
|
|
2306
|
+
const variantByte = bytes.at(8);
|
|
2307
|
+
if (typeof versionByte !== "number" || typeof variantByte !== "number") throw new TypeError("Failed to generate a deterministic UUID.");
|
|
2308
|
+
bytes[6] = versionByte & 15 | 80;
|
|
2309
|
+
bytes[8] = variantByte & 63 | 128;
|
|
2310
|
+
return bytesToUuid(bytes);
|
|
2311
|
+
};
|
|
2312
|
+
const createCompositeSyncId = (model, parts) => createUuidV5(`${model}:${JSON.stringify(parts)}`, SYNC_COMPOSITE_ID_NAMESPACE);
|
|
2313
|
+
const createDeterministicImportId = (params) => createUuidV5(`things:${params.workspaceId}:${params.modelName}:${params.sourceId}`, IMPORT_ID_NAMESPACE);
|
|
2314
|
+
const createTaskLabelId = (params) => createCompositeSyncId("TaskLabel", [
|
|
2315
|
+
params.workspaceId,
|
|
2316
|
+
params.taskId,
|
|
2317
|
+
params.labelId
|
|
2318
|
+
]);
|
|
2319
|
+
const createTeamProjectId = (params) => createCompositeSyncId("TeamProject", [
|
|
2320
|
+
params.workspaceId,
|
|
2321
|
+
params.teamId,
|
|
2322
|
+
params.projectId
|
|
2323
|
+
]);
|
|
2324
|
+
//#endregion
|
|
2325
|
+
//#region src/import/things-values.ts
|
|
2326
|
+
var import_rrule = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2327
|
+
(function webpackUniversalModuleDefinition(root, factory) {
|
|
2328
|
+
if (typeof exports === "object" && typeof module === "object") module.exports = factory();
|
|
2329
|
+
else if (typeof define === "function" && define.amd) define([], factory);
|
|
2330
|
+
else if (typeof exports === "object") exports["rrule"] = factory();
|
|
2331
|
+
else root["rrule"] = factory();
|
|
2332
|
+
})(typeof self !== "undefined" ? self : exports, () => {
|
|
2333
|
+
return (() => {
|
|
2334
|
+
"use strict";
|
|
2335
|
+
var __webpack_require__ = {};
|
|
2336
|
+
__webpack_require__.d = (exports$1, definition) => {
|
|
2337
|
+
for (var key in definition) if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports$1, key)) Object.defineProperty(exports$1, key, {
|
|
2338
|
+
enumerable: true,
|
|
2339
|
+
get: definition[key]
|
|
2340
|
+
});
|
|
2341
|
+
};
|
|
2342
|
+
__webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
|
|
2343
|
+
__webpack_require__.r = (exports$2) => {
|
|
2344
|
+
if (typeof Symbol !== "undefined" && Symbol.toStringTag) Object.defineProperty(exports$2, Symbol.toStringTag, { value: "Module" });
|
|
2345
|
+
Object.defineProperty(exports$2, "__esModule", { value: true });
|
|
2346
|
+
};
|
|
2347
|
+
var __webpack_exports__ = {};
|
|
2348
|
+
__webpack_require__.r(__webpack_exports__);
|
|
2349
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
2350
|
+
"ALL_WEEKDAYS": () => ALL_WEEKDAYS,
|
|
2351
|
+
"Frequency": () => Frequency,
|
|
2352
|
+
"RRule": () => RRule,
|
|
2353
|
+
"RRuleSet": () => RRuleSet,
|
|
2354
|
+
"Weekday": () => Weekday,
|
|
2355
|
+
"datetime": () => datetime,
|
|
2356
|
+
"rrulestr": () => rrulestr
|
|
2357
|
+
});
|
|
2358
|
+
var ALL_WEEKDAYS = [
|
|
2359
|
+
"MO",
|
|
2360
|
+
"TU",
|
|
2361
|
+
"WE",
|
|
2362
|
+
"TH",
|
|
2363
|
+
"FR",
|
|
2364
|
+
"SA",
|
|
2365
|
+
"SU"
|
|
2366
|
+
];
|
|
2367
|
+
var Weekday = function() {
|
|
2368
|
+
function Weekday(weekday, n) {
|
|
2369
|
+
if (n === 0) throw new Error("Can't create weekday with n == 0");
|
|
2370
|
+
this.weekday = weekday;
|
|
2371
|
+
this.n = n;
|
|
2372
|
+
}
|
|
2373
|
+
Weekday.fromStr = function(str) {
|
|
2374
|
+
return new Weekday(ALL_WEEKDAYS.indexOf(str));
|
|
2375
|
+
};
|
|
2376
|
+
Weekday.prototype.nth = function(n) {
|
|
2377
|
+
return this.n === n ? this : new Weekday(this.weekday, n);
|
|
2378
|
+
};
|
|
2379
|
+
Weekday.prototype.equals = function(other) {
|
|
2380
|
+
return this.weekday === other.weekday && this.n === other.n;
|
|
2381
|
+
};
|
|
2382
|
+
Weekday.prototype.toString = function() {
|
|
2383
|
+
var s = ALL_WEEKDAYS[this.weekday];
|
|
2384
|
+
if (this.n) s = (this.n > 0 ? "+" : "") + String(this.n) + s;
|
|
2385
|
+
return s;
|
|
2386
|
+
};
|
|
2387
|
+
Weekday.prototype.getJsWeekday = function() {
|
|
2388
|
+
return this.weekday === 6 ? 0 : this.weekday + 1;
|
|
2389
|
+
};
|
|
2390
|
+
return Weekday;
|
|
2391
|
+
}();
|
|
2392
|
+
var isPresent = function(value) {
|
|
2393
|
+
return value !== null && value !== void 0;
|
|
2394
|
+
};
|
|
2395
|
+
var isNumber = function(value) {
|
|
2396
|
+
return typeof value === "number";
|
|
2397
|
+
};
|
|
2398
|
+
var isWeekdayStr = function(value) {
|
|
2399
|
+
return typeof value === "string" && ALL_WEEKDAYS.includes(value);
|
|
2400
|
+
};
|
|
2401
|
+
var isArray = Array.isArray;
|
|
2402
|
+
/**
|
|
2403
|
+
* Simplified version of python's range()
|
|
2404
|
+
*/
|
|
2405
|
+
var range = function(start, end) {
|
|
2406
|
+
if (end === void 0) end = start;
|
|
2407
|
+
if (arguments.length === 1) {
|
|
2408
|
+
end = start;
|
|
2409
|
+
start = 0;
|
|
2410
|
+
}
|
|
2411
|
+
var rang = [];
|
|
2412
|
+
for (var i = start; i < end; i++) rang.push(i);
|
|
2413
|
+
return rang;
|
|
2414
|
+
};
|
|
2415
|
+
var repeat = function(value, times) {
|
|
2416
|
+
var i = 0;
|
|
2417
|
+
var array = [];
|
|
2418
|
+
if (isArray(value)) for (; i < times; i++) array[i] = [].concat(value);
|
|
2419
|
+
else for (; i < times; i++) array[i] = value;
|
|
2420
|
+
return array;
|
|
2421
|
+
};
|
|
2422
|
+
var toArray = function(item) {
|
|
2423
|
+
if (isArray(item)) return item;
|
|
2424
|
+
return [item];
|
|
2425
|
+
};
|
|
2426
|
+
function padStart(item, targetLength, padString) {
|
|
2427
|
+
if (padString === void 0) padString = " ";
|
|
2428
|
+
var str = String(item);
|
|
2429
|
+
targetLength = targetLength >> 0;
|
|
2430
|
+
if (str.length > targetLength) return String(str);
|
|
2431
|
+
targetLength = targetLength - str.length;
|
|
2432
|
+
if (targetLength > padString.length) padString += repeat(padString, targetLength / padString.length);
|
|
2433
|
+
return padString.slice(0, targetLength) + String(str);
|
|
2434
|
+
}
|
|
2435
|
+
/**
|
|
2436
|
+
* Python like split
|
|
2437
|
+
*/
|
|
2438
|
+
var split = function(str, sep, num) {
|
|
2439
|
+
var splits = str.split(sep);
|
|
2440
|
+
return num ? splits.slice(0, num).concat([splits.slice(num).join(sep)]) : splits;
|
|
2441
|
+
};
|
|
2442
|
+
/**
|
|
2443
|
+
* closure/goog/math/math.js:modulo
|
|
2444
|
+
* Copyright 2006 The Closure Library Authors.
|
|
2445
|
+
* The % operator in JavaScript returns the remainder of a / b, but differs from
|
|
2446
|
+
* some other languages in that the result will have the same sign as the
|
|
2447
|
+
* dividend. For example, -1 % 8 == -1, whereas in some other languages
|
|
2448
|
+
* (such as Python) the result would be 7. This function emulates the more
|
|
2449
|
+
* correct modulo behavior, which is useful for certain applications such as
|
|
2450
|
+
* calculating an offset index in a circular list.
|
|
2451
|
+
*
|
|
2452
|
+
* @param {number} a The dividend.
|
|
2453
|
+
* @param {number} b The divisor.
|
|
2454
|
+
* @return {number} a % b where the result is between 0 and b (either 0 <= x < b
|
|
2455
|
+
* or b < x <= 0, depending on the sign of b).
|
|
2456
|
+
*/
|
|
2457
|
+
var pymod = function(a, b) {
|
|
2458
|
+
var r = a % b;
|
|
2459
|
+
return r * b < 0 ? r + b : r;
|
|
2460
|
+
};
|
|
2461
|
+
/**
|
|
2462
|
+
* @see: <http://docs.python.org/library/functions.html#divmod>
|
|
2463
|
+
*/
|
|
2464
|
+
var divmod = function(a, b) {
|
|
2465
|
+
return {
|
|
2466
|
+
div: Math.floor(a / b),
|
|
2467
|
+
mod: pymod(a, b)
|
|
2468
|
+
};
|
|
2469
|
+
};
|
|
2470
|
+
var empty = function(obj) {
|
|
2471
|
+
return !isPresent(obj) || obj.length === 0;
|
|
2472
|
+
};
|
|
2473
|
+
/**
|
|
2474
|
+
* Python-like boolean
|
|
2475
|
+
*
|
|
2476
|
+
* @return {Boolean} value of an object/primitive, taking into account
|
|
2477
|
+
* the fact that in Python an empty list's/tuple's
|
|
2478
|
+
* boolean value is False, whereas in JS it's true
|
|
2479
|
+
*/
|
|
2480
|
+
var notEmpty = function(obj) {
|
|
2481
|
+
return !empty(obj);
|
|
2482
|
+
};
|
|
2483
|
+
/**
|
|
2484
|
+
* Return true if a value is in an array
|
|
2485
|
+
*/
|
|
2486
|
+
var includes = function(arr, val) {
|
|
2487
|
+
return notEmpty(arr) && arr.indexOf(val) !== -1;
|
|
2488
|
+
};
|
|
2489
|
+
var datetime = function(y, m, d, h, i, s) {
|
|
2490
|
+
if (h === void 0) h = 0;
|
|
2491
|
+
if (i === void 0) i = 0;
|
|
2492
|
+
if (s === void 0) s = 0;
|
|
2493
|
+
return new Date(Date.UTC(y, m - 1, d, h, i, s));
|
|
2494
|
+
};
|
|
2495
|
+
/**
|
|
2496
|
+
* General date-related utilities.
|
|
2497
|
+
* Also handles several incompatibilities between JavaScript and Python
|
|
2498
|
+
*
|
|
2499
|
+
*/
|
|
2500
|
+
var MONTH_DAYS = [
|
|
2501
|
+
31,
|
|
2502
|
+
28,
|
|
2503
|
+
31,
|
|
2504
|
+
30,
|
|
2505
|
+
31,
|
|
2506
|
+
30,
|
|
2507
|
+
31,
|
|
2508
|
+
31,
|
|
2509
|
+
30,
|
|
2510
|
+
31,
|
|
2511
|
+
30,
|
|
2512
|
+
31
|
|
2513
|
+
];
|
|
2514
|
+
/**
|
|
2515
|
+
* Number of milliseconds of one day
|
|
2516
|
+
*/
|
|
2517
|
+
var ONE_DAY = 1e3 * 60 * 60 * 24;
|
|
2518
|
+
/**
|
|
2519
|
+
* @see: <http://docs.python.org/library/datetime.html#datetime.MAXYEAR>
|
|
2520
|
+
*/
|
|
2521
|
+
var MAXYEAR = 9999;
|
|
2522
|
+
/**
|
|
2523
|
+
* Python uses 1-Jan-1 as the base for calculating ordinals but we don't
|
|
2524
|
+
* want to confuse the JS engine with milliseconds > Number.MAX_NUMBER,
|
|
2525
|
+
* therefore we use 1-Jan-1970 instead
|
|
2526
|
+
*/
|
|
2527
|
+
var ORDINAL_BASE = datetime(1970, 1, 1);
|
|
2528
|
+
/**
|
|
2529
|
+
* Python: MO-SU: 0 - 6
|
|
2530
|
+
* JS: SU-SAT 0 - 6
|
|
2531
|
+
*/
|
|
2532
|
+
var PY_WEEKDAYS = [
|
|
2533
|
+
6,
|
|
2534
|
+
0,
|
|
2535
|
+
1,
|
|
2536
|
+
2,
|
|
2537
|
+
3,
|
|
2538
|
+
4,
|
|
2539
|
+
5
|
|
2540
|
+
];
|
|
2541
|
+
var isLeapYear = function(year) {
|
|
2542
|
+
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
|
|
2543
|
+
};
|
|
2544
|
+
var isDate = function(value) {
|
|
2545
|
+
return value instanceof Date;
|
|
2546
|
+
};
|
|
2547
|
+
var isValidDate = function(value) {
|
|
2548
|
+
return isDate(value) && !isNaN(value.getTime());
|
|
2549
|
+
};
|
|
2550
|
+
/**
|
|
2551
|
+
* @see: <http://www.mcfedries.com/JavaScript/DaysBetween.asp>
|
|
2552
|
+
*/
|
|
2553
|
+
var daysBetween = function(date1, date2) {
|
|
2554
|
+
var differencems = date1.getTime() - date2.getTime();
|
|
2555
|
+
return Math.round(differencems / ONE_DAY);
|
|
2556
|
+
};
|
|
2557
|
+
/**
|
|
2558
|
+
* @see: <http://docs.python.org/library/datetime.html#datetime.date.toordinal>
|
|
2559
|
+
*/
|
|
2560
|
+
var toOrdinal = function(date) {
|
|
2561
|
+
return daysBetween(date, ORDINAL_BASE);
|
|
2562
|
+
};
|
|
2563
|
+
/**
|
|
2564
|
+
* @see - <http://docs.python.org/library/datetime.html#datetime.date.fromordinal>
|
|
2565
|
+
*/
|
|
2566
|
+
var fromOrdinal = function(ordinal) {
|
|
2567
|
+
return new Date(ORDINAL_BASE.getTime() + ordinal * ONE_DAY);
|
|
2568
|
+
};
|
|
2569
|
+
var getMonthDays = function(date) {
|
|
2570
|
+
var month = date.getUTCMonth();
|
|
2571
|
+
return month === 1 && isLeapYear(date.getUTCFullYear()) ? 29 : MONTH_DAYS[month];
|
|
2572
|
+
};
|
|
2573
|
+
/**
|
|
2574
|
+
* @return {Number} python-like weekday
|
|
2575
|
+
*/
|
|
2576
|
+
var getWeekday = function(date) {
|
|
2577
|
+
return PY_WEEKDAYS[date.getUTCDay()];
|
|
2578
|
+
};
|
|
2579
|
+
/**
|
|
2580
|
+
* @see: <http://docs.python.org/library/calendar.html#calendar.monthrange>
|
|
2581
|
+
*/
|
|
2582
|
+
var monthRange = function(year, month) {
|
|
2583
|
+
var date = datetime(year, month + 1, 1);
|
|
2584
|
+
return [getWeekday(date), getMonthDays(date)];
|
|
2585
|
+
};
|
|
2586
|
+
/**
|
|
2587
|
+
* @see: <http://docs.python.org/library/datetime.html#datetime.datetime.combine>
|
|
2588
|
+
*/
|
|
2589
|
+
var combine = function(date, time) {
|
|
2590
|
+
time = time || date;
|
|
2591
|
+
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds()));
|
|
2592
|
+
};
|
|
2593
|
+
var dateutil_clone = function(date) {
|
|
2594
|
+
return new Date(date.getTime());
|
|
2595
|
+
};
|
|
2596
|
+
var cloneDates = function(dates) {
|
|
2597
|
+
var clones = [];
|
|
2598
|
+
for (var i = 0; i < dates.length; i++) clones.push(dateutil_clone(dates[i]));
|
|
2599
|
+
return clones;
|
|
2600
|
+
};
|
|
2601
|
+
/**
|
|
2602
|
+
* Sorts an array of Date or Time objects
|
|
2603
|
+
*/
|
|
2604
|
+
var sort = function(dates) {
|
|
2605
|
+
dates.sort(function(a, b) {
|
|
2606
|
+
return a.getTime() - b.getTime();
|
|
2607
|
+
});
|
|
2608
|
+
};
|
|
2609
|
+
var timeToUntilString = function(time, utc) {
|
|
2610
|
+
if (utc === void 0) utc = true;
|
|
2611
|
+
var date = new Date(time);
|
|
2612
|
+
return [
|
|
2613
|
+
padStart(date.getUTCFullYear().toString(), 4, "0"),
|
|
2614
|
+
padStart(date.getUTCMonth() + 1, 2, "0"),
|
|
2615
|
+
padStart(date.getUTCDate(), 2, "0"),
|
|
2616
|
+
"T",
|
|
2617
|
+
padStart(date.getUTCHours(), 2, "0"),
|
|
2618
|
+
padStart(date.getUTCMinutes(), 2, "0"),
|
|
2619
|
+
padStart(date.getUTCSeconds(), 2, "0"),
|
|
2620
|
+
utc ? "Z" : ""
|
|
2621
|
+
].join("");
|
|
2622
|
+
};
|
|
2623
|
+
var untilStringToDate = function(until) {
|
|
2624
|
+
var bits = /^(\d{4})(\d{2})(\d{2})(T(\d{2})(\d{2})(\d{2})Z?)?$/.exec(until);
|
|
2625
|
+
if (!bits) throw new Error("Invalid UNTIL value: ".concat(until));
|
|
2626
|
+
return new Date(Date.UTC(parseInt(bits[1], 10), parseInt(bits[2], 10) - 1, parseInt(bits[3], 10), parseInt(bits[5], 10) || 0, parseInt(bits[6], 10) || 0, parseInt(bits[7], 10) || 0));
|
|
2627
|
+
};
|
|
2628
|
+
var dateTZtoISO8601 = function(date, timeZone) {
|
|
2629
|
+
return date.toLocaleString("sv-SE", { timeZone }).replace(" ", "T") + "Z";
|
|
2630
|
+
};
|
|
2631
|
+
var dateInTimeZone = function(date, timeZone) {
|
|
2632
|
+
var localTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
2633
|
+
var dateInLocalTZ = new Date(dateTZtoISO8601(date, localTimeZone));
|
|
2634
|
+
var tzOffset = new Date(dateTZtoISO8601(date, timeZone !== null && timeZone !== void 0 ? timeZone : "UTC")).getTime() - dateInLocalTZ.getTime();
|
|
2635
|
+
return new Date(date.getTime() - tzOffset);
|
|
2636
|
+
};
|
|
2637
|
+
const iterresult = function() {
|
|
2638
|
+
function IterResult(method, args) {
|
|
2639
|
+
this.minDate = null;
|
|
2640
|
+
this.maxDate = null;
|
|
2641
|
+
this._result = [];
|
|
2642
|
+
this.total = 0;
|
|
2643
|
+
this.method = method;
|
|
2644
|
+
this.args = args;
|
|
2645
|
+
if (method === "between") {
|
|
2646
|
+
this.maxDate = args.inc ? args.before : /* @__PURE__ */ new Date(args.before.getTime() - 1);
|
|
2647
|
+
this.minDate = args.inc ? args.after : new Date(args.after.getTime() + 1);
|
|
2648
|
+
} else if (method === "before") this.maxDate = args.inc ? args.dt : /* @__PURE__ */ new Date(args.dt.getTime() - 1);
|
|
2649
|
+
else if (method === "after") this.minDate = args.inc ? args.dt : new Date(args.dt.getTime() + 1);
|
|
2650
|
+
}
|
|
2651
|
+
/**
|
|
2652
|
+
* Possibly adds a date into the result.
|
|
2653
|
+
*
|
|
2654
|
+
* @param {Date} date - the date isn't necessarly added to the result
|
|
2655
|
+
* list (if it is too late/too early)
|
|
2656
|
+
* @return {Boolean} true if it makes sense to continue the iteration
|
|
2657
|
+
* false if we're done.
|
|
2658
|
+
*/
|
|
2659
|
+
IterResult.prototype.accept = function(date) {
|
|
2660
|
+
++this.total;
|
|
2661
|
+
var tooEarly = this.minDate && date < this.minDate;
|
|
2662
|
+
var tooLate = this.maxDate && date > this.maxDate;
|
|
2663
|
+
if (this.method === "between") {
|
|
2664
|
+
if (tooEarly) return true;
|
|
2665
|
+
if (tooLate) return false;
|
|
2666
|
+
} else if (this.method === "before") {
|
|
2667
|
+
if (tooLate) return false;
|
|
2668
|
+
} else if (this.method === "after") {
|
|
2669
|
+
if (tooEarly) return true;
|
|
2670
|
+
this.add(date);
|
|
2671
|
+
return false;
|
|
2672
|
+
}
|
|
2673
|
+
return this.add(date);
|
|
2674
|
+
};
|
|
2675
|
+
/**
|
|
2676
|
+
*
|
|
2677
|
+
* @param {Date} date that is part of the result.
|
|
2678
|
+
* @return {Boolean} whether we are interested in more values.
|
|
2679
|
+
*/
|
|
2680
|
+
IterResult.prototype.add = function(date) {
|
|
2681
|
+
this._result.push(date);
|
|
2682
|
+
return true;
|
|
2683
|
+
};
|
|
2684
|
+
/**
|
|
2685
|
+
* 'before' and 'after' return only one date, whereas 'all'
|
|
2686
|
+
* and 'between' an array.
|
|
2687
|
+
*
|
|
2688
|
+
* @return {Date,Array?}
|
|
2689
|
+
*/
|
|
2690
|
+
IterResult.prototype.getValue = function() {
|
|
2691
|
+
var res = this._result;
|
|
2692
|
+
switch (this.method) {
|
|
2693
|
+
case "all":
|
|
2694
|
+
case "between": return res;
|
|
2695
|
+
default: return res.length ? res[res.length - 1] : null;
|
|
2696
|
+
}
|
|
2697
|
+
};
|
|
2698
|
+
IterResult.prototype.clone = function() {
|
|
2699
|
+
return new IterResult(this.method, this.args);
|
|
2700
|
+
};
|
|
2701
|
+
return IterResult;
|
|
2702
|
+
}();
|
|
2703
|
+
/******************************************************************************
|
|
2704
|
+
Copyright (c) Microsoft Corporation.
|
|
2705
|
+
|
|
2706
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
2707
|
+
purpose with or without fee is hereby granted.
|
|
2708
|
+
|
|
2709
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
2710
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
2711
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
2712
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
2713
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
2714
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
2715
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
2716
|
+
***************************************************************************** */
|
|
2717
|
+
var extendStatics = function(d, b) {
|
|
2718
|
+
extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d, b) {
|
|
2719
|
+
d.__proto__ = b;
|
|
2720
|
+
} || function(d, b) {
|
|
2721
|
+
for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
|
|
2722
|
+
};
|
|
2723
|
+
return extendStatics(d, b);
|
|
2724
|
+
};
|
|
2725
|
+
function __extends(d, b) {
|
|
2726
|
+
if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
2727
|
+
extendStatics(d, b);
|
|
2728
|
+
function __() {
|
|
2729
|
+
this.constructor = d;
|
|
2730
|
+
}
|
|
2731
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
2732
|
+
}
|
|
2733
|
+
var __assign = function() {
|
|
2734
|
+
__assign = Object.assign || function __assign(t) {
|
|
2735
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
2736
|
+
s = arguments[i];
|
|
2737
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
2738
|
+
}
|
|
2739
|
+
return t;
|
|
2740
|
+
};
|
|
2741
|
+
return __assign.apply(this, arguments);
|
|
2742
|
+
};
|
|
2743
|
+
function __spreadArray(to, from, pack) {
|
|
2744
|
+
if (pack || arguments.length === 2) {
|
|
2745
|
+
for (var i = 0, l = from.length, ar; i < l; i++) if (ar || !(i in from)) {
|
|
2746
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
2747
|
+
ar[i] = from[i];
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2750
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
2751
|
+
}
|
|
2752
|
+
function __await(v) {
|
|
2753
|
+
return this instanceof __await ? (this.v = v, this) : new __await(v);
|
|
2754
|
+
}
|
|
2755
|
+
const callbackiterresult = function(_super) {
|
|
2756
|
+
__extends(CallbackIterResult, _super);
|
|
2757
|
+
function CallbackIterResult(method, args, iterator) {
|
|
2758
|
+
var _this = _super.call(this, method, args) || this;
|
|
2759
|
+
_this.iterator = iterator;
|
|
2760
|
+
return _this;
|
|
2761
|
+
}
|
|
2762
|
+
CallbackIterResult.prototype.add = function(date) {
|
|
2763
|
+
if (this.iterator(date, this._result.length)) {
|
|
2764
|
+
this._result.push(date);
|
|
2765
|
+
return true;
|
|
2766
|
+
}
|
|
2767
|
+
return false;
|
|
2768
|
+
};
|
|
2769
|
+
return CallbackIterResult;
|
|
2770
|
+
}(iterresult);
|
|
2771
|
+
const i18n = {
|
|
2772
|
+
dayNames: [
|
|
2773
|
+
"Sunday",
|
|
2774
|
+
"Monday",
|
|
2775
|
+
"Tuesday",
|
|
2776
|
+
"Wednesday",
|
|
2777
|
+
"Thursday",
|
|
2778
|
+
"Friday",
|
|
2779
|
+
"Saturday"
|
|
2780
|
+
],
|
|
2781
|
+
monthNames: [
|
|
2782
|
+
"January",
|
|
2783
|
+
"February",
|
|
2784
|
+
"March",
|
|
2785
|
+
"April",
|
|
2786
|
+
"May",
|
|
2787
|
+
"June",
|
|
2788
|
+
"July",
|
|
2789
|
+
"August",
|
|
2790
|
+
"September",
|
|
2791
|
+
"October",
|
|
2792
|
+
"November",
|
|
2793
|
+
"December"
|
|
2794
|
+
],
|
|
2795
|
+
tokens: {
|
|
2796
|
+
SKIP: /^[ \r\n\t]+|^\.$/,
|
|
2797
|
+
number: /^[1-9][0-9]*/,
|
|
2798
|
+
numberAsText: /^(one|two|three)/i,
|
|
2799
|
+
every: /^every/i,
|
|
2800
|
+
"day(s)": /^days?/i,
|
|
2801
|
+
"weekday(s)": /^weekdays?/i,
|
|
2802
|
+
"week(s)": /^weeks?/i,
|
|
2803
|
+
"hour(s)": /^hours?/i,
|
|
2804
|
+
"minute(s)": /^minutes?/i,
|
|
2805
|
+
"month(s)": /^months?/i,
|
|
2806
|
+
"year(s)": /^years?/i,
|
|
2807
|
+
on: /^(on|in)/i,
|
|
2808
|
+
at: /^(at)/i,
|
|
2809
|
+
the: /^the/i,
|
|
2810
|
+
first: /^first/i,
|
|
2811
|
+
second: /^second/i,
|
|
2812
|
+
third: /^third/i,
|
|
2813
|
+
nth: /^([1-9][0-9]*)(\.|th|nd|rd|st)/i,
|
|
2814
|
+
last: /^last/i,
|
|
2815
|
+
for: /^for/i,
|
|
2816
|
+
"time(s)": /^times?/i,
|
|
2817
|
+
until: /^(un)?til/i,
|
|
2818
|
+
monday: /^mo(n(day)?)?/i,
|
|
2819
|
+
tuesday: /^tu(e(s(day)?)?)?/i,
|
|
2820
|
+
wednesday: /^we(d(n(esday)?)?)?/i,
|
|
2821
|
+
thursday: /^th(u(r(sday)?)?)?/i,
|
|
2822
|
+
friday: /^fr(i(day)?)?/i,
|
|
2823
|
+
saturday: /^sa(t(urday)?)?/i,
|
|
2824
|
+
sunday: /^su(n(day)?)?/i,
|
|
2825
|
+
january: /^jan(uary)?/i,
|
|
2826
|
+
february: /^feb(ruary)?/i,
|
|
2827
|
+
march: /^mar(ch)?/i,
|
|
2828
|
+
april: /^apr(il)?/i,
|
|
2829
|
+
may: /^may/i,
|
|
2830
|
+
june: /^june?/i,
|
|
2831
|
+
july: /^july?/i,
|
|
2832
|
+
august: /^aug(ust)?/i,
|
|
2833
|
+
september: /^sep(t(ember)?)?/i,
|
|
2834
|
+
october: /^oct(ober)?/i,
|
|
2835
|
+
november: /^nov(ember)?/i,
|
|
2836
|
+
december: /^dec(ember)?/i,
|
|
2837
|
+
comma: /^(,\s*|(and|or)\s*)+/i
|
|
2838
|
+
}
|
|
2839
|
+
};
|
|
2840
|
+
/**
|
|
2841
|
+
* Return true if a value is in an array
|
|
2842
|
+
*/
|
|
2843
|
+
var contains = function(arr, val) {
|
|
2844
|
+
return arr.indexOf(val) !== -1;
|
|
2845
|
+
};
|
|
2846
|
+
var defaultGetText = function(id) {
|
|
2847
|
+
return id.toString();
|
|
2848
|
+
};
|
|
2849
|
+
var defaultDateFormatter = function(year, month, day) {
|
|
2850
|
+
return "".concat(month, " ").concat(day, ", ").concat(year);
|
|
2851
|
+
};
|
|
2852
|
+
const totext = function() {
|
|
2853
|
+
function ToText(rrule, gettext, language, dateFormatter) {
|
|
2854
|
+
if (gettext === void 0) gettext = defaultGetText;
|
|
2855
|
+
if (language === void 0) language = i18n;
|
|
2856
|
+
if (dateFormatter === void 0) dateFormatter = defaultDateFormatter;
|
|
2857
|
+
this.text = [];
|
|
2858
|
+
this.language = language || i18n;
|
|
2859
|
+
this.gettext = gettext;
|
|
2860
|
+
this.dateFormatter = dateFormatter;
|
|
2861
|
+
this.rrule = rrule;
|
|
2862
|
+
this.options = rrule.options;
|
|
2863
|
+
this.origOptions = rrule.origOptions;
|
|
2864
|
+
if (this.origOptions.bymonthday) {
|
|
2865
|
+
var bymonthday = [].concat(this.options.bymonthday);
|
|
2866
|
+
var bynmonthday = [].concat(this.options.bynmonthday);
|
|
2867
|
+
bymonthday.sort(function(a, b) {
|
|
2868
|
+
return a - b;
|
|
2869
|
+
});
|
|
2870
|
+
bynmonthday.sort(function(a, b) {
|
|
2871
|
+
return b - a;
|
|
2872
|
+
});
|
|
2873
|
+
this.bymonthday = bymonthday.concat(bynmonthday);
|
|
2874
|
+
if (!this.bymonthday.length) this.bymonthday = null;
|
|
2875
|
+
}
|
|
2876
|
+
if (isPresent(this.origOptions.byweekday)) {
|
|
2877
|
+
var byweekday = !isArray(this.origOptions.byweekday) ? [this.origOptions.byweekday] : this.origOptions.byweekday;
|
|
2878
|
+
var days = String(byweekday);
|
|
2879
|
+
this.byweekday = {
|
|
2880
|
+
allWeeks: byweekday.filter(function(weekday) {
|
|
2881
|
+
return !weekday.n;
|
|
2882
|
+
}),
|
|
2883
|
+
someWeeks: byweekday.filter(function(weekday) {
|
|
2884
|
+
return Boolean(weekday.n);
|
|
2885
|
+
}),
|
|
2886
|
+
isWeekdays: days.indexOf("MO") !== -1 && days.indexOf("TU") !== -1 && days.indexOf("WE") !== -1 && days.indexOf("TH") !== -1 && days.indexOf("FR") !== -1 && days.indexOf("SA") === -1 && days.indexOf("SU") === -1,
|
|
2887
|
+
isEveryDay: days.indexOf("MO") !== -1 && days.indexOf("TU") !== -1 && days.indexOf("WE") !== -1 && days.indexOf("TH") !== -1 && days.indexOf("FR") !== -1 && days.indexOf("SA") !== -1 && days.indexOf("SU") !== -1
|
|
2888
|
+
};
|
|
2889
|
+
var sortWeekDays = function(a, b) {
|
|
2890
|
+
return a.weekday - b.weekday;
|
|
2891
|
+
};
|
|
2892
|
+
this.byweekday.allWeeks.sort(sortWeekDays);
|
|
2893
|
+
this.byweekday.someWeeks.sort(sortWeekDays);
|
|
2894
|
+
if (!this.byweekday.allWeeks.length) this.byweekday.allWeeks = null;
|
|
2895
|
+
if (!this.byweekday.someWeeks.length) this.byweekday.someWeeks = null;
|
|
2896
|
+
} else this.byweekday = null;
|
|
2897
|
+
}
|
|
2898
|
+
/**
|
|
2899
|
+
* Test whether the rrule can be fully converted to text.
|
|
2900
|
+
*
|
|
2901
|
+
* @param {RRule} rrule
|
|
2902
|
+
* @return {Boolean}
|
|
2903
|
+
*/
|
|
2904
|
+
ToText.isFullyConvertible = function(rrule) {
|
|
2905
|
+
var canConvert = true;
|
|
2906
|
+
if (!(rrule.options.freq in ToText.IMPLEMENTED)) return false;
|
|
2907
|
+
if (rrule.origOptions.until && rrule.origOptions.count) return false;
|
|
2908
|
+
for (var key in rrule.origOptions) {
|
|
2909
|
+
if (contains([
|
|
2910
|
+
"dtstart",
|
|
2911
|
+
"tzid",
|
|
2912
|
+
"wkst",
|
|
2913
|
+
"freq"
|
|
2914
|
+
], key)) return true;
|
|
2915
|
+
if (!contains(ToText.IMPLEMENTED[rrule.options.freq], key)) return false;
|
|
2916
|
+
}
|
|
2917
|
+
return canConvert;
|
|
2918
|
+
};
|
|
2919
|
+
ToText.prototype.isFullyConvertible = function() {
|
|
2920
|
+
return ToText.isFullyConvertible(this.rrule);
|
|
2921
|
+
};
|
|
2922
|
+
/**
|
|
2923
|
+
* Perform the conversion. Only some of the frequencies are supported.
|
|
2924
|
+
* If some of the rrule's options aren't supported, they'll
|
|
2925
|
+
* be omitted from the output an "(~ approximate)" will be appended.
|
|
2926
|
+
*
|
|
2927
|
+
* @return {*}
|
|
2928
|
+
*/
|
|
2929
|
+
ToText.prototype.toString = function() {
|
|
2930
|
+
var gettext = this.gettext;
|
|
2931
|
+
if (!(this.options.freq in ToText.IMPLEMENTED)) return gettext("RRule error: Unable to fully convert this rrule to text");
|
|
2932
|
+
this.text = [gettext("every")];
|
|
2933
|
+
this[RRule.FREQUENCIES[this.options.freq]]();
|
|
2934
|
+
if (this.options.until) {
|
|
2935
|
+
this.add(gettext("until"));
|
|
2936
|
+
var until = this.options.until;
|
|
2937
|
+
this.add(this.dateFormatter(until.getUTCFullYear(), this.language.monthNames[until.getUTCMonth()], until.getUTCDate()));
|
|
2938
|
+
} else if (this.options.count) this.add(gettext("for")).add(this.options.count.toString()).add(this.plural(this.options.count) ? gettext("times") : gettext("time"));
|
|
2939
|
+
if (!this.isFullyConvertible()) this.add(gettext("(~ approximate)"));
|
|
2940
|
+
return this.text.join("");
|
|
2941
|
+
};
|
|
2942
|
+
ToText.prototype.HOURLY = function() {
|
|
2943
|
+
var gettext = this.gettext;
|
|
2944
|
+
if (this.options.interval !== 1) this.add(this.options.interval.toString());
|
|
2945
|
+
this.add(this.plural(this.options.interval) ? gettext("hours") : gettext("hour"));
|
|
2946
|
+
};
|
|
2947
|
+
ToText.prototype.MINUTELY = function() {
|
|
2948
|
+
var gettext = this.gettext;
|
|
2949
|
+
if (this.options.interval !== 1) this.add(this.options.interval.toString());
|
|
2950
|
+
this.add(this.plural(this.options.interval) ? gettext("minutes") : gettext("minute"));
|
|
2951
|
+
};
|
|
2952
|
+
ToText.prototype.DAILY = function() {
|
|
2953
|
+
var gettext = this.gettext;
|
|
2954
|
+
if (this.options.interval !== 1) this.add(this.options.interval.toString());
|
|
2955
|
+
if (this.byweekday && this.byweekday.isWeekdays) this.add(this.plural(this.options.interval) ? gettext("weekdays") : gettext("weekday"));
|
|
2956
|
+
else this.add(this.plural(this.options.interval) ? gettext("days") : gettext("day"));
|
|
2957
|
+
if (this.origOptions.bymonth) {
|
|
2958
|
+
this.add(gettext("in"));
|
|
2959
|
+
this._bymonth();
|
|
2960
|
+
}
|
|
2961
|
+
if (this.bymonthday) this._bymonthday();
|
|
2962
|
+
else if (this.byweekday) this._byweekday();
|
|
2963
|
+
else if (this.origOptions.byhour) this._byhour();
|
|
2964
|
+
};
|
|
2965
|
+
ToText.prototype.WEEKLY = function() {
|
|
2966
|
+
var gettext = this.gettext;
|
|
2967
|
+
if (this.options.interval !== 1) this.add(this.options.interval.toString()).add(this.plural(this.options.interval) ? gettext("weeks") : gettext("week"));
|
|
2968
|
+
if (this.byweekday && this.byweekday.isWeekdays) if (this.options.interval === 1) this.add(this.plural(this.options.interval) ? gettext("weekdays") : gettext("weekday"));
|
|
2969
|
+
else this.add(gettext("on")).add(gettext("weekdays"));
|
|
2970
|
+
else if (this.byweekday && this.byweekday.isEveryDay) this.add(this.plural(this.options.interval) ? gettext("days") : gettext("day"));
|
|
2971
|
+
else {
|
|
2972
|
+
if (this.options.interval === 1) this.add(gettext("week"));
|
|
2973
|
+
if (this.origOptions.bymonth) {
|
|
2974
|
+
this.add(gettext("in"));
|
|
2975
|
+
this._bymonth();
|
|
2976
|
+
}
|
|
2977
|
+
if (this.bymonthday) this._bymonthday();
|
|
2978
|
+
else if (this.byweekday) this._byweekday();
|
|
2979
|
+
if (this.origOptions.byhour) this._byhour();
|
|
2980
|
+
}
|
|
2981
|
+
};
|
|
2982
|
+
ToText.prototype.MONTHLY = function() {
|
|
2983
|
+
var gettext = this.gettext;
|
|
2984
|
+
if (this.origOptions.bymonth) {
|
|
2985
|
+
if (this.options.interval !== 1) {
|
|
2986
|
+
this.add(this.options.interval.toString()).add(gettext("months"));
|
|
2987
|
+
if (this.plural(this.options.interval)) this.add(gettext("in"));
|
|
2988
|
+
}
|
|
2989
|
+
this._bymonth();
|
|
2990
|
+
} else {
|
|
2991
|
+
if (this.options.interval !== 1) this.add(this.options.interval.toString());
|
|
2992
|
+
this.add(this.plural(this.options.interval) ? gettext("months") : gettext("month"));
|
|
2993
|
+
}
|
|
2994
|
+
if (this.bymonthday) this._bymonthday();
|
|
2995
|
+
else if (this.byweekday && this.byweekday.isWeekdays) this.add(gettext("on")).add(gettext("weekdays"));
|
|
2996
|
+
else if (this.byweekday) this._byweekday();
|
|
2997
|
+
};
|
|
2998
|
+
ToText.prototype.YEARLY = function() {
|
|
2999
|
+
var gettext = this.gettext;
|
|
3000
|
+
if (this.origOptions.bymonth) {
|
|
3001
|
+
if (this.options.interval !== 1) {
|
|
3002
|
+
this.add(this.options.interval.toString());
|
|
3003
|
+
this.add(gettext("years"));
|
|
3004
|
+
}
|
|
3005
|
+
this._bymonth();
|
|
3006
|
+
} else {
|
|
3007
|
+
if (this.options.interval !== 1) this.add(this.options.interval.toString());
|
|
3008
|
+
this.add(this.plural(this.options.interval) ? gettext("years") : gettext("year"));
|
|
3009
|
+
}
|
|
3010
|
+
if (this.bymonthday) this._bymonthday();
|
|
3011
|
+
else if (this.byweekday) this._byweekday();
|
|
3012
|
+
if (this.options.byyearday) this.add(gettext("on the")).add(this.list(this.options.byyearday, this.nth, gettext("and"))).add(gettext("day"));
|
|
3013
|
+
if (this.options.byweekno) this.add(gettext("in")).add(this.plural(this.options.byweekno.length) ? gettext("weeks") : gettext("week")).add(this.list(this.options.byweekno, void 0, gettext("and")));
|
|
3014
|
+
};
|
|
3015
|
+
ToText.prototype._bymonthday = function() {
|
|
3016
|
+
var gettext = this.gettext;
|
|
3017
|
+
if (this.byweekday && this.byweekday.allWeeks) this.add(gettext("on")).add(this.list(this.byweekday.allWeeks, this.weekdaytext, gettext("or"))).add(gettext("the")).add(this.list(this.bymonthday, this.nth, gettext("or")));
|
|
3018
|
+
else this.add(gettext("on the")).add(this.list(this.bymonthday, this.nth, gettext("and")));
|
|
3019
|
+
};
|
|
3020
|
+
ToText.prototype._byweekday = function() {
|
|
3021
|
+
var gettext = this.gettext;
|
|
3022
|
+
if (this.byweekday.allWeeks && !this.byweekday.isWeekdays) this.add(gettext("on")).add(this.list(this.byweekday.allWeeks, this.weekdaytext));
|
|
3023
|
+
if (this.byweekday.someWeeks) {
|
|
3024
|
+
if (this.byweekday.allWeeks) this.add(gettext("and"));
|
|
3025
|
+
this.add(gettext("on the")).add(this.list(this.byweekday.someWeeks, this.weekdaytext, gettext("and")));
|
|
3026
|
+
}
|
|
3027
|
+
};
|
|
3028
|
+
ToText.prototype._byhour = function() {
|
|
3029
|
+
var gettext = this.gettext;
|
|
3030
|
+
this.add(gettext("at")).add(this.list(this.origOptions.byhour, void 0, gettext("and")));
|
|
3031
|
+
};
|
|
3032
|
+
ToText.prototype._bymonth = function() {
|
|
3033
|
+
this.add(this.list(this.options.bymonth, this.monthtext, this.gettext("and")));
|
|
3034
|
+
};
|
|
3035
|
+
ToText.prototype.nth = function(n) {
|
|
3036
|
+
n = parseInt(n.toString(), 10);
|
|
3037
|
+
var nth;
|
|
3038
|
+
var gettext = this.gettext;
|
|
3039
|
+
if (n === -1) return gettext("last");
|
|
3040
|
+
var npos = Math.abs(n);
|
|
3041
|
+
switch (npos) {
|
|
3042
|
+
case 1:
|
|
3043
|
+
case 21:
|
|
3044
|
+
case 31:
|
|
3045
|
+
nth = npos + gettext("st");
|
|
3046
|
+
break;
|
|
3047
|
+
case 2:
|
|
3048
|
+
case 22:
|
|
3049
|
+
nth = npos + gettext("nd");
|
|
3050
|
+
break;
|
|
3051
|
+
case 3:
|
|
3052
|
+
case 23:
|
|
3053
|
+
nth = npos + gettext("rd");
|
|
3054
|
+
break;
|
|
3055
|
+
default: nth = npos + gettext("th");
|
|
3056
|
+
}
|
|
3057
|
+
return n < 0 ? nth + " " + gettext("last") : nth;
|
|
3058
|
+
};
|
|
3059
|
+
ToText.prototype.monthtext = function(m) {
|
|
3060
|
+
return this.language.monthNames[m - 1];
|
|
3061
|
+
};
|
|
3062
|
+
ToText.prototype.weekdaytext = function(wday) {
|
|
3063
|
+
var weekday = isNumber(wday) ? (wday + 1) % 7 : wday.getJsWeekday();
|
|
3064
|
+
return (wday.n ? this.nth(wday.n) + " " : "") + this.language.dayNames[weekday];
|
|
3065
|
+
};
|
|
3066
|
+
ToText.prototype.plural = function(n) {
|
|
3067
|
+
return n % 100 !== 1;
|
|
3068
|
+
};
|
|
3069
|
+
ToText.prototype.add = function(s) {
|
|
3070
|
+
this.text.push(" ");
|
|
3071
|
+
this.text.push(s);
|
|
3072
|
+
return this;
|
|
3073
|
+
};
|
|
3074
|
+
ToText.prototype.list = function(arr, callback, finalDelim, delim) {
|
|
3075
|
+
var _this = this;
|
|
3076
|
+
if (delim === void 0) delim = ",";
|
|
3077
|
+
if (!isArray(arr)) arr = [arr];
|
|
3078
|
+
var delimJoin = function(array, delimiter, finalDelimiter) {
|
|
3079
|
+
var list = "";
|
|
3080
|
+
for (var i = 0; i < array.length; i++) {
|
|
3081
|
+
if (i !== 0) if (i === array.length - 1) list += " " + finalDelimiter + " ";
|
|
3082
|
+
else list += delimiter + " ";
|
|
3083
|
+
list += array[i];
|
|
3084
|
+
}
|
|
3085
|
+
return list;
|
|
3086
|
+
};
|
|
3087
|
+
callback = callback || function(o) {
|
|
3088
|
+
return o.toString();
|
|
3089
|
+
};
|
|
3090
|
+
var realCallback = function(arg) {
|
|
3091
|
+
return callback && callback.call(_this, arg);
|
|
3092
|
+
};
|
|
3093
|
+
if (finalDelim) return delimJoin(arr.map(realCallback), delim, finalDelim);
|
|
3094
|
+
else return arr.map(realCallback).join(delim + " ");
|
|
3095
|
+
};
|
|
3096
|
+
return ToText;
|
|
3097
|
+
}();
|
|
3098
|
+
var Parser = function() {
|
|
3099
|
+
function Parser(rules) {
|
|
3100
|
+
this.done = true;
|
|
3101
|
+
this.rules = rules;
|
|
3102
|
+
}
|
|
3103
|
+
Parser.prototype.start = function(text) {
|
|
3104
|
+
this.text = text;
|
|
3105
|
+
this.done = false;
|
|
3106
|
+
return this.nextSymbol();
|
|
3107
|
+
};
|
|
3108
|
+
Parser.prototype.isDone = function() {
|
|
3109
|
+
return this.done && this.symbol === null;
|
|
3110
|
+
};
|
|
3111
|
+
Parser.prototype.nextSymbol = function() {
|
|
3112
|
+
var best;
|
|
3113
|
+
var bestSymbol;
|
|
3114
|
+
this.symbol = null;
|
|
3115
|
+
this.value = null;
|
|
3116
|
+
do {
|
|
3117
|
+
if (this.done) return false;
|
|
3118
|
+
var rule = void 0;
|
|
3119
|
+
best = null;
|
|
3120
|
+
for (var name_1 in this.rules) {
|
|
3121
|
+
rule = this.rules[name_1];
|
|
3122
|
+
var match = rule.exec(this.text);
|
|
3123
|
+
if (match) {
|
|
3124
|
+
if (best === null || match[0].length > best[0].length) {
|
|
3125
|
+
best = match;
|
|
3126
|
+
bestSymbol = name_1;
|
|
3127
|
+
}
|
|
3128
|
+
}
|
|
3129
|
+
}
|
|
3130
|
+
if (best != null) {
|
|
3131
|
+
this.text = this.text.substr(best[0].length);
|
|
3132
|
+
if (this.text === "") this.done = true;
|
|
3133
|
+
}
|
|
3134
|
+
if (best == null) {
|
|
3135
|
+
this.done = true;
|
|
3136
|
+
this.symbol = null;
|
|
3137
|
+
this.value = null;
|
|
3138
|
+
return;
|
|
3139
|
+
}
|
|
3140
|
+
} while (bestSymbol === "SKIP");
|
|
3141
|
+
this.symbol = bestSymbol;
|
|
3142
|
+
this.value = best;
|
|
3143
|
+
return true;
|
|
3144
|
+
};
|
|
3145
|
+
Parser.prototype.accept = function(name) {
|
|
3146
|
+
if (this.symbol === name) {
|
|
3147
|
+
if (this.value) {
|
|
3148
|
+
var v = this.value;
|
|
3149
|
+
this.nextSymbol();
|
|
3150
|
+
return v;
|
|
3151
|
+
}
|
|
3152
|
+
this.nextSymbol();
|
|
3153
|
+
return true;
|
|
3154
|
+
}
|
|
3155
|
+
return false;
|
|
3156
|
+
};
|
|
3157
|
+
Parser.prototype.acceptNumber = function() {
|
|
3158
|
+
return this.accept("number");
|
|
3159
|
+
};
|
|
3160
|
+
Parser.prototype.expect = function(name) {
|
|
3161
|
+
if (this.accept(name)) return true;
|
|
3162
|
+
throw new Error("expected " + name + " but found " + this.symbol);
|
|
3163
|
+
};
|
|
3164
|
+
return Parser;
|
|
3165
|
+
}();
|
|
3166
|
+
function parseText(text, language) {
|
|
3167
|
+
if (language === void 0) language = i18n;
|
|
3168
|
+
var options = {};
|
|
3169
|
+
var ttr = new Parser(language.tokens);
|
|
3170
|
+
if (!ttr.start(text)) return null;
|
|
3171
|
+
S();
|
|
3172
|
+
return options;
|
|
3173
|
+
function S() {
|
|
3174
|
+
ttr.expect("every");
|
|
3175
|
+
var n = ttr.acceptNumber();
|
|
3176
|
+
if (n) options.interval = parseInt(n[0], 10);
|
|
3177
|
+
if (ttr.isDone()) throw new Error("Unexpected end");
|
|
3178
|
+
switch (ttr.symbol) {
|
|
3179
|
+
case "day(s)":
|
|
3180
|
+
options.freq = RRule.DAILY;
|
|
3181
|
+
if (ttr.nextSymbol()) {
|
|
3182
|
+
AT();
|
|
3183
|
+
F();
|
|
3184
|
+
}
|
|
3185
|
+
break;
|
|
3186
|
+
case "weekday(s)":
|
|
3187
|
+
options.freq = RRule.WEEKLY;
|
|
3188
|
+
options.byweekday = [
|
|
3189
|
+
RRule.MO,
|
|
3190
|
+
RRule.TU,
|
|
3191
|
+
RRule.WE,
|
|
3192
|
+
RRule.TH,
|
|
3193
|
+
RRule.FR
|
|
3194
|
+
];
|
|
3195
|
+
ttr.nextSymbol();
|
|
3196
|
+
AT();
|
|
3197
|
+
F();
|
|
3198
|
+
break;
|
|
3199
|
+
case "week(s)":
|
|
3200
|
+
options.freq = RRule.WEEKLY;
|
|
3201
|
+
if (ttr.nextSymbol()) {
|
|
3202
|
+
ON();
|
|
3203
|
+
AT();
|
|
3204
|
+
F();
|
|
3205
|
+
}
|
|
3206
|
+
break;
|
|
3207
|
+
case "hour(s)":
|
|
3208
|
+
options.freq = RRule.HOURLY;
|
|
3209
|
+
if (ttr.nextSymbol()) {
|
|
3210
|
+
ON();
|
|
3211
|
+
F();
|
|
3212
|
+
}
|
|
3213
|
+
break;
|
|
3214
|
+
case "minute(s)":
|
|
3215
|
+
options.freq = RRule.MINUTELY;
|
|
3216
|
+
if (ttr.nextSymbol()) {
|
|
3217
|
+
ON();
|
|
3218
|
+
F();
|
|
3219
|
+
}
|
|
3220
|
+
break;
|
|
3221
|
+
case "month(s)":
|
|
3222
|
+
options.freq = RRule.MONTHLY;
|
|
3223
|
+
if (ttr.nextSymbol()) {
|
|
3224
|
+
ON();
|
|
3225
|
+
F();
|
|
3226
|
+
}
|
|
3227
|
+
break;
|
|
3228
|
+
case "year(s)":
|
|
3229
|
+
options.freq = RRule.YEARLY;
|
|
3230
|
+
if (ttr.nextSymbol()) {
|
|
3231
|
+
ON();
|
|
3232
|
+
F();
|
|
3233
|
+
}
|
|
3234
|
+
break;
|
|
3235
|
+
case "monday":
|
|
3236
|
+
case "tuesday":
|
|
3237
|
+
case "wednesday":
|
|
3238
|
+
case "thursday":
|
|
3239
|
+
case "friday":
|
|
3240
|
+
case "saturday":
|
|
3241
|
+
case "sunday":
|
|
3242
|
+
options.freq = RRule.WEEKLY;
|
|
3243
|
+
options.byweekday = [RRule[ttr.symbol.substr(0, 2).toUpperCase()]];
|
|
3244
|
+
if (!ttr.nextSymbol()) return;
|
|
3245
|
+
while (ttr.accept("comma")) {
|
|
3246
|
+
if (ttr.isDone()) throw new Error("Unexpected end");
|
|
3247
|
+
var wkd = decodeWKD();
|
|
3248
|
+
if (!wkd) throw new Error("Unexpected symbol " + ttr.symbol + ", expected weekday");
|
|
3249
|
+
options.byweekday.push(RRule[wkd]);
|
|
3250
|
+
ttr.nextSymbol();
|
|
3251
|
+
}
|
|
3252
|
+
AT();
|
|
3253
|
+
MDAYs();
|
|
3254
|
+
F();
|
|
3255
|
+
break;
|
|
3256
|
+
case "january":
|
|
3257
|
+
case "february":
|
|
3258
|
+
case "march":
|
|
3259
|
+
case "april":
|
|
3260
|
+
case "may":
|
|
3261
|
+
case "june":
|
|
3262
|
+
case "july":
|
|
3263
|
+
case "august":
|
|
3264
|
+
case "september":
|
|
3265
|
+
case "october":
|
|
3266
|
+
case "november":
|
|
3267
|
+
case "december":
|
|
3268
|
+
options.freq = RRule.YEARLY;
|
|
3269
|
+
options.bymonth = [decodeM()];
|
|
3270
|
+
if (!ttr.nextSymbol()) return;
|
|
3271
|
+
while (ttr.accept("comma")) {
|
|
3272
|
+
if (ttr.isDone()) throw new Error("Unexpected end");
|
|
3273
|
+
var m = decodeM();
|
|
3274
|
+
if (!m) throw new Error("Unexpected symbol " + ttr.symbol + ", expected month");
|
|
3275
|
+
options.bymonth.push(m);
|
|
3276
|
+
ttr.nextSymbol();
|
|
3277
|
+
}
|
|
3278
|
+
ON();
|
|
3279
|
+
F();
|
|
3280
|
+
break;
|
|
3281
|
+
default: throw new Error("Unknown symbol");
|
|
3282
|
+
}
|
|
3283
|
+
}
|
|
3284
|
+
function ON() {
|
|
3285
|
+
var on = ttr.accept("on");
|
|
3286
|
+
var the = ttr.accept("the");
|
|
3287
|
+
if (!(on || the)) return;
|
|
3288
|
+
do {
|
|
3289
|
+
var nth = decodeNTH();
|
|
3290
|
+
var wkd = decodeWKD();
|
|
3291
|
+
var m = decodeM();
|
|
3292
|
+
if (nth) if (wkd) {
|
|
3293
|
+
ttr.nextSymbol();
|
|
3294
|
+
if (!options.byweekday) options.byweekday = [];
|
|
3295
|
+
options.byweekday.push(RRule[wkd].nth(nth));
|
|
3296
|
+
} else {
|
|
3297
|
+
if (!options.bymonthday) options.bymonthday = [];
|
|
3298
|
+
options.bymonthday.push(nth);
|
|
3299
|
+
ttr.accept("day(s)");
|
|
3300
|
+
}
|
|
3301
|
+
else if (wkd) {
|
|
3302
|
+
ttr.nextSymbol();
|
|
3303
|
+
if (!options.byweekday) options.byweekday = [];
|
|
3304
|
+
options.byweekday.push(RRule[wkd]);
|
|
3305
|
+
} else if (ttr.symbol === "weekday(s)") {
|
|
3306
|
+
ttr.nextSymbol();
|
|
3307
|
+
if (!options.byweekday) options.byweekday = [
|
|
3308
|
+
RRule.MO,
|
|
3309
|
+
RRule.TU,
|
|
3310
|
+
RRule.WE,
|
|
3311
|
+
RRule.TH,
|
|
3312
|
+
RRule.FR
|
|
3313
|
+
];
|
|
3314
|
+
} else if (ttr.symbol === "week(s)") {
|
|
3315
|
+
ttr.nextSymbol();
|
|
3316
|
+
var n = ttr.acceptNumber();
|
|
3317
|
+
if (!n) throw new Error("Unexpected symbol " + ttr.symbol + ", expected week number");
|
|
3318
|
+
options.byweekno = [parseInt(n[0], 10)];
|
|
3319
|
+
while (ttr.accept("comma")) {
|
|
3320
|
+
n = ttr.acceptNumber();
|
|
3321
|
+
if (!n) throw new Error("Unexpected symbol " + ttr.symbol + "; expected monthday");
|
|
3322
|
+
options.byweekno.push(parseInt(n[0], 10));
|
|
3323
|
+
}
|
|
3324
|
+
} else if (m) {
|
|
3325
|
+
ttr.nextSymbol();
|
|
3326
|
+
if (!options.bymonth) options.bymonth = [];
|
|
3327
|
+
options.bymonth.push(m);
|
|
3328
|
+
} else return;
|
|
3329
|
+
} while (ttr.accept("comma") || ttr.accept("the") || ttr.accept("on"));
|
|
3330
|
+
}
|
|
3331
|
+
function AT() {
|
|
3332
|
+
if (!ttr.accept("at")) return;
|
|
3333
|
+
do {
|
|
3334
|
+
var n = ttr.acceptNumber();
|
|
3335
|
+
if (!n) throw new Error("Unexpected symbol " + ttr.symbol + ", expected hour");
|
|
3336
|
+
options.byhour = [parseInt(n[0], 10)];
|
|
3337
|
+
while (ttr.accept("comma")) {
|
|
3338
|
+
n = ttr.acceptNumber();
|
|
3339
|
+
if (!n) throw new Error("Unexpected symbol " + ttr.symbol + "; expected hour");
|
|
3340
|
+
options.byhour.push(parseInt(n[0], 10));
|
|
3341
|
+
}
|
|
3342
|
+
} while (ttr.accept("comma") || ttr.accept("at"));
|
|
3343
|
+
}
|
|
3344
|
+
function decodeM() {
|
|
3345
|
+
switch (ttr.symbol) {
|
|
3346
|
+
case "january": return 1;
|
|
3347
|
+
case "february": return 2;
|
|
3348
|
+
case "march": return 3;
|
|
3349
|
+
case "april": return 4;
|
|
3350
|
+
case "may": return 5;
|
|
3351
|
+
case "june": return 6;
|
|
3352
|
+
case "july": return 7;
|
|
3353
|
+
case "august": return 8;
|
|
3354
|
+
case "september": return 9;
|
|
3355
|
+
case "october": return 10;
|
|
3356
|
+
case "november": return 11;
|
|
3357
|
+
case "december": return 12;
|
|
3358
|
+
default: return false;
|
|
3359
|
+
}
|
|
3360
|
+
}
|
|
3361
|
+
function decodeWKD() {
|
|
3362
|
+
switch (ttr.symbol) {
|
|
3363
|
+
case "monday":
|
|
3364
|
+
case "tuesday":
|
|
3365
|
+
case "wednesday":
|
|
3366
|
+
case "thursday":
|
|
3367
|
+
case "friday":
|
|
3368
|
+
case "saturday":
|
|
3369
|
+
case "sunday": return ttr.symbol.substr(0, 2).toUpperCase();
|
|
3370
|
+
default: return false;
|
|
3371
|
+
}
|
|
3372
|
+
}
|
|
3373
|
+
function decodeNTH() {
|
|
3374
|
+
switch (ttr.symbol) {
|
|
3375
|
+
case "last":
|
|
3376
|
+
ttr.nextSymbol();
|
|
3377
|
+
return -1;
|
|
3378
|
+
case "first":
|
|
3379
|
+
ttr.nextSymbol();
|
|
3380
|
+
return 1;
|
|
3381
|
+
case "second":
|
|
3382
|
+
ttr.nextSymbol();
|
|
3383
|
+
return ttr.accept("last") ? -2 : 2;
|
|
3384
|
+
case "third":
|
|
3385
|
+
ttr.nextSymbol();
|
|
3386
|
+
return ttr.accept("last") ? -3 : 3;
|
|
3387
|
+
case "nth":
|
|
3388
|
+
var v = parseInt(ttr.value[1], 10);
|
|
3389
|
+
if (v < -366 || v > 366) throw new Error("Nth out of range: " + v);
|
|
3390
|
+
ttr.nextSymbol();
|
|
3391
|
+
return ttr.accept("last") ? -v : v;
|
|
3392
|
+
default: return false;
|
|
3393
|
+
}
|
|
3394
|
+
}
|
|
3395
|
+
function MDAYs() {
|
|
3396
|
+
ttr.accept("on");
|
|
3397
|
+
ttr.accept("the");
|
|
3398
|
+
var nth = decodeNTH();
|
|
3399
|
+
if (!nth) return;
|
|
3400
|
+
options.bymonthday = [nth];
|
|
3401
|
+
ttr.nextSymbol();
|
|
3402
|
+
while (ttr.accept("comma")) {
|
|
3403
|
+
nth = decodeNTH();
|
|
3404
|
+
if (!nth) throw new Error("Unexpected symbol " + ttr.symbol + "; expected monthday");
|
|
3405
|
+
options.bymonthday.push(nth);
|
|
3406
|
+
ttr.nextSymbol();
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
function F() {
|
|
3410
|
+
if (ttr.symbol === "until") {
|
|
3411
|
+
var date = Date.parse(ttr.text);
|
|
3412
|
+
if (!date) throw new Error("Cannot parse until date:" + ttr.text);
|
|
3413
|
+
options.until = new Date(date);
|
|
3414
|
+
} else if (ttr.accept("for")) {
|
|
3415
|
+
options.count = parseInt(ttr.value[0], 10);
|
|
3416
|
+
ttr.expect("number");
|
|
3417
|
+
}
|
|
3418
|
+
}
|
|
3419
|
+
}
|
|
3420
|
+
var Frequency;
|
|
3421
|
+
(function(Frequency) {
|
|
3422
|
+
Frequency[Frequency["YEARLY"] = 0] = "YEARLY";
|
|
3423
|
+
Frequency[Frequency["MONTHLY"] = 1] = "MONTHLY";
|
|
3424
|
+
Frequency[Frequency["WEEKLY"] = 2] = "WEEKLY";
|
|
3425
|
+
Frequency[Frequency["DAILY"] = 3] = "DAILY";
|
|
3426
|
+
Frequency[Frequency["HOURLY"] = 4] = "HOURLY";
|
|
3427
|
+
Frequency[Frequency["MINUTELY"] = 5] = "MINUTELY";
|
|
3428
|
+
Frequency[Frequency["SECONDLY"] = 6] = "SECONDLY";
|
|
3429
|
+
})(Frequency || (Frequency = {}));
|
|
3430
|
+
function freqIsDailyOrGreater(freq) {
|
|
3431
|
+
return freq < Frequency.HOURLY;
|
|
3432
|
+
}
|
|
3433
|
+
/**
|
|
3434
|
+
*
|
|
3435
|
+
* Implementation of RRule.fromText() and RRule::toText().
|
|
3436
|
+
*
|
|
3437
|
+
*
|
|
3438
|
+
* On the client side, this file needs to be included
|
|
3439
|
+
* when those functions are used.
|
|
3440
|
+
*
|
|
3441
|
+
*/
|
|
3442
|
+
/**
|
|
3443
|
+
* Will be able to convert some of the below described rules from
|
|
3444
|
+
* text format to a rule object.
|
|
3445
|
+
*
|
|
3446
|
+
*
|
|
3447
|
+
* RULES
|
|
3448
|
+
*
|
|
3449
|
+
* Every ([n])
|
|
3450
|
+
* day(s)
|
|
3451
|
+
* | [weekday], ..., (and) [weekday]
|
|
3452
|
+
* | weekday(s)
|
|
3453
|
+
* | week(s)
|
|
3454
|
+
* | month(s)
|
|
3455
|
+
* | [month], ..., (and) [month]
|
|
3456
|
+
* | year(s)
|
|
3457
|
+
*
|
|
3458
|
+
*
|
|
3459
|
+
* Plus 0, 1, or multiple of these:
|
|
3460
|
+
*
|
|
3461
|
+
* on [weekday], ..., (or) [weekday] the [monthday], [monthday], ... (or) [monthday]
|
|
3462
|
+
*
|
|
3463
|
+
* on [weekday], ..., (and) [weekday]
|
|
3464
|
+
*
|
|
3465
|
+
* on the [monthday], [monthday], ... (and) [monthday] (day of the month)
|
|
3466
|
+
*
|
|
3467
|
+
* on the [nth-weekday], ..., (and) [nth-weekday] (of the month/year)
|
|
3468
|
+
*
|
|
3469
|
+
*
|
|
3470
|
+
* Plus 0 or 1 of these:
|
|
3471
|
+
*
|
|
3472
|
+
* for [n] time(s)
|
|
3473
|
+
*
|
|
3474
|
+
* until [date]
|
|
3475
|
+
*
|
|
3476
|
+
* Plus (.)
|
|
3477
|
+
*
|
|
3478
|
+
*
|
|
3479
|
+
* Definitely no supported for parsing:
|
|
3480
|
+
*
|
|
3481
|
+
* (for year):
|
|
3482
|
+
* in week(s) [n], ..., (and) [n]
|
|
3483
|
+
*
|
|
3484
|
+
* on the [yearday], ..., (and) [n] day of the year
|
|
3485
|
+
* on day [yearday], ..., (and) [n]
|
|
3486
|
+
*
|
|
3487
|
+
*
|
|
3488
|
+
* NON-TERMINALS
|
|
3489
|
+
*
|
|
3490
|
+
* [n]: 1, 2 ..., one, two, three ..
|
|
3491
|
+
* [month]: January, February, March, April, May, ... December
|
|
3492
|
+
* [weekday]: Monday, ... Sunday
|
|
3493
|
+
* [nth-weekday]: first [weekday], 2nd [weekday], ... last [weekday], ...
|
|
3494
|
+
* [monthday]: first, 1., 2., 1st, 2nd, second, ... 31st, last day, 2nd last day, ..
|
|
3495
|
+
* [date]:
|
|
3496
|
+
* - [month] (0-31(,) ([year])),
|
|
3497
|
+
* - (the) 0-31.(1-12.([year])),
|
|
3498
|
+
* - (the) 0-31/(1-12/([year])),
|
|
3499
|
+
* - [weekday]
|
|
3500
|
+
*
|
|
3501
|
+
* [year]: 0000, 0001, ... 01, 02, ..
|
|
3502
|
+
*
|
|
3503
|
+
* Definitely not supported for parsing:
|
|
3504
|
+
*
|
|
3505
|
+
* [yearday]: first, 1., 2., 1st, 2nd, second, ... 366th, last day, 2nd last day, ..
|
|
3506
|
+
*
|
|
3507
|
+
* @param {String} text
|
|
3508
|
+
* @return {Object, Boolean} the rule, or null.
|
|
3509
|
+
*/
|
|
3510
|
+
var fromText = function(text, language) {
|
|
3511
|
+
if (language === void 0) language = i18n;
|
|
3512
|
+
return new RRule(parseText(text, language) || void 0);
|
|
3513
|
+
};
|
|
3514
|
+
var common = [
|
|
3515
|
+
"count",
|
|
3516
|
+
"until",
|
|
3517
|
+
"interval",
|
|
3518
|
+
"byweekday",
|
|
3519
|
+
"bymonthday",
|
|
3520
|
+
"bymonth"
|
|
3521
|
+
];
|
|
3522
|
+
totext.IMPLEMENTED = [];
|
|
3523
|
+
totext.IMPLEMENTED[Frequency.HOURLY] = common;
|
|
3524
|
+
totext.IMPLEMENTED[Frequency.MINUTELY] = common;
|
|
3525
|
+
totext.IMPLEMENTED[Frequency.DAILY] = ["byhour"].concat(common);
|
|
3526
|
+
totext.IMPLEMENTED[Frequency.WEEKLY] = common;
|
|
3527
|
+
totext.IMPLEMENTED[Frequency.MONTHLY] = common;
|
|
3528
|
+
totext.IMPLEMENTED[Frequency.YEARLY] = ["byweekno", "byyearday"].concat(common);
|
|
3529
|
+
var toText = function(rrule, gettext, language, dateFormatter) {
|
|
3530
|
+
return new totext(rrule, gettext, language, dateFormatter).toString();
|
|
3531
|
+
};
|
|
3532
|
+
var isFullyConvertible = totext.isFullyConvertible;
|
|
3533
|
+
var Time = function() {
|
|
3534
|
+
function Time(hour, minute, second, millisecond) {
|
|
3535
|
+
this.hour = hour;
|
|
3536
|
+
this.minute = minute;
|
|
3537
|
+
this.second = second;
|
|
3538
|
+
this.millisecond = millisecond || 0;
|
|
3539
|
+
}
|
|
3540
|
+
Time.prototype.getHours = function() {
|
|
3541
|
+
return this.hour;
|
|
3542
|
+
};
|
|
3543
|
+
Time.prototype.getMinutes = function() {
|
|
3544
|
+
return this.minute;
|
|
3545
|
+
};
|
|
3546
|
+
Time.prototype.getSeconds = function() {
|
|
3547
|
+
return this.second;
|
|
3548
|
+
};
|
|
3549
|
+
Time.prototype.getMilliseconds = function() {
|
|
3550
|
+
return this.millisecond;
|
|
3551
|
+
};
|
|
3552
|
+
Time.prototype.getTime = function() {
|
|
3553
|
+
return (this.hour * 60 * 60 + this.minute * 60 + this.second) * 1e3 + this.millisecond;
|
|
3554
|
+
};
|
|
3555
|
+
return Time;
|
|
3556
|
+
}();
|
|
3557
|
+
var DateTime = function(_super) {
|
|
3558
|
+
__extends(DateTime, _super);
|
|
3559
|
+
function DateTime(year, month, day, hour, minute, second, millisecond) {
|
|
3560
|
+
var _this = _super.call(this, hour, minute, second, millisecond) || this;
|
|
3561
|
+
_this.year = year;
|
|
3562
|
+
_this.month = month;
|
|
3563
|
+
_this.day = day;
|
|
3564
|
+
return _this;
|
|
3565
|
+
}
|
|
3566
|
+
DateTime.fromDate = function(date) {
|
|
3567
|
+
return new this(date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.valueOf() % 1e3);
|
|
3568
|
+
};
|
|
3569
|
+
DateTime.prototype.getWeekday = function() {
|
|
3570
|
+
return getWeekday(new Date(this.getTime()));
|
|
3571
|
+
};
|
|
3572
|
+
DateTime.prototype.getTime = function() {
|
|
3573
|
+
return new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second, this.millisecond)).getTime();
|
|
3574
|
+
};
|
|
3575
|
+
DateTime.prototype.getDay = function() {
|
|
3576
|
+
return this.day;
|
|
3577
|
+
};
|
|
3578
|
+
DateTime.prototype.getMonth = function() {
|
|
3579
|
+
return this.month;
|
|
3580
|
+
};
|
|
3581
|
+
DateTime.prototype.getYear = function() {
|
|
3582
|
+
return this.year;
|
|
3583
|
+
};
|
|
3584
|
+
DateTime.prototype.addYears = function(years) {
|
|
3585
|
+
this.year += years;
|
|
3586
|
+
};
|
|
3587
|
+
DateTime.prototype.addMonths = function(months) {
|
|
3588
|
+
this.month += months;
|
|
3589
|
+
if (this.month > 12) {
|
|
3590
|
+
var yearDiv = Math.floor(this.month / 12);
|
|
3591
|
+
var monthMod = pymod(this.month, 12);
|
|
3592
|
+
this.month = monthMod;
|
|
3593
|
+
this.year += yearDiv;
|
|
3594
|
+
if (this.month === 0) {
|
|
3595
|
+
this.month = 12;
|
|
3596
|
+
--this.year;
|
|
3597
|
+
}
|
|
3598
|
+
}
|
|
3599
|
+
};
|
|
3600
|
+
DateTime.prototype.addWeekly = function(days, wkst) {
|
|
3601
|
+
if (wkst > this.getWeekday()) this.day += -(this.getWeekday() + 1 + (6 - wkst)) + days * 7;
|
|
3602
|
+
else this.day += -(this.getWeekday() - wkst) + days * 7;
|
|
3603
|
+
this.fixDay();
|
|
3604
|
+
};
|
|
3605
|
+
DateTime.prototype.addDaily = function(days) {
|
|
3606
|
+
this.day += days;
|
|
3607
|
+
this.fixDay();
|
|
3608
|
+
};
|
|
3609
|
+
DateTime.prototype.addHours = function(hours, filtered, byhour) {
|
|
3610
|
+
if (filtered) this.hour += Math.floor((23 - this.hour) / hours) * hours;
|
|
3611
|
+
for (;;) {
|
|
3612
|
+
this.hour += hours;
|
|
3613
|
+
var _a = divmod(this.hour, 24), dayDiv = _a.div, hourMod = _a.mod;
|
|
3614
|
+
if (dayDiv) {
|
|
3615
|
+
this.hour = hourMod;
|
|
3616
|
+
this.addDaily(dayDiv);
|
|
3617
|
+
}
|
|
3618
|
+
if (empty(byhour) || includes(byhour, this.hour)) break;
|
|
3619
|
+
}
|
|
3620
|
+
};
|
|
3621
|
+
DateTime.prototype.addMinutes = function(minutes, filtered, byhour, byminute) {
|
|
3622
|
+
if (filtered) this.minute += Math.floor((1439 - (this.hour * 60 + this.minute)) / minutes) * minutes;
|
|
3623
|
+
for (;;) {
|
|
3624
|
+
this.minute += minutes;
|
|
3625
|
+
var _a = divmod(this.minute, 60), hourDiv = _a.div, minuteMod = _a.mod;
|
|
3626
|
+
if (hourDiv) {
|
|
3627
|
+
this.minute = minuteMod;
|
|
3628
|
+
this.addHours(hourDiv, false, byhour);
|
|
3629
|
+
}
|
|
3630
|
+
if ((empty(byhour) || includes(byhour, this.hour)) && (empty(byminute) || includes(byminute, this.minute))) break;
|
|
3631
|
+
}
|
|
3632
|
+
};
|
|
3633
|
+
DateTime.prototype.addSeconds = function(seconds, filtered, byhour, byminute, bysecond) {
|
|
3634
|
+
if (filtered) this.second += Math.floor((86399 - (this.hour * 3600 + this.minute * 60 + this.second)) / seconds) * seconds;
|
|
3635
|
+
for (;;) {
|
|
3636
|
+
this.second += seconds;
|
|
3637
|
+
var _a = divmod(this.second, 60), minuteDiv = _a.div, secondMod = _a.mod;
|
|
3638
|
+
if (minuteDiv) {
|
|
3639
|
+
this.second = secondMod;
|
|
3640
|
+
this.addMinutes(minuteDiv, false, byhour, byminute);
|
|
3641
|
+
}
|
|
3642
|
+
if ((empty(byhour) || includes(byhour, this.hour)) && (empty(byminute) || includes(byminute, this.minute)) && (empty(bysecond) || includes(bysecond, this.second))) break;
|
|
3643
|
+
}
|
|
3644
|
+
};
|
|
3645
|
+
DateTime.prototype.fixDay = function() {
|
|
3646
|
+
if (this.day <= 28) return;
|
|
3647
|
+
var daysinmonth = monthRange(this.year, this.month - 1)[1];
|
|
3648
|
+
if (this.day <= daysinmonth) return;
|
|
3649
|
+
while (this.day > daysinmonth) {
|
|
3650
|
+
this.day -= daysinmonth;
|
|
3651
|
+
++this.month;
|
|
3652
|
+
if (this.month === 13) {
|
|
3653
|
+
this.month = 1;
|
|
3654
|
+
++this.year;
|
|
3655
|
+
if (this.year > MAXYEAR) return;
|
|
3656
|
+
}
|
|
3657
|
+
daysinmonth = monthRange(this.year, this.month - 1)[1];
|
|
3658
|
+
}
|
|
3659
|
+
};
|
|
3660
|
+
DateTime.prototype.add = function(options, filtered) {
|
|
3661
|
+
var freq = options.freq, interval = options.interval, wkst = options.wkst, byhour = options.byhour, byminute = options.byminute, bysecond = options.bysecond;
|
|
3662
|
+
switch (freq) {
|
|
3663
|
+
case Frequency.YEARLY: return this.addYears(interval);
|
|
3664
|
+
case Frequency.MONTHLY: return this.addMonths(interval);
|
|
3665
|
+
case Frequency.WEEKLY: return this.addWeekly(interval, wkst);
|
|
3666
|
+
case Frequency.DAILY: return this.addDaily(interval);
|
|
3667
|
+
case Frequency.HOURLY: return this.addHours(interval, filtered, byhour);
|
|
3668
|
+
case Frequency.MINUTELY: return this.addMinutes(interval, filtered, byhour, byminute);
|
|
3669
|
+
case Frequency.SECONDLY: return this.addSeconds(interval, filtered, byhour, byminute, bysecond);
|
|
3670
|
+
}
|
|
3671
|
+
};
|
|
3672
|
+
return DateTime;
|
|
3673
|
+
}(Time);
|
|
3674
|
+
function initializeOptions(options) {
|
|
3675
|
+
var invalid = [];
|
|
3676
|
+
var keys = Object.keys(options);
|
|
3677
|
+
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
|
|
3678
|
+
var key = keys_1[_i];
|
|
3679
|
+
if (!includes(defaultKeys, key)) invalid.push(key);
|
|
3680
|
+
if (isDate(options[key]) && !isValidDate(options[key])) invalid.push(key);
|
|
3681
|
+
}
|
|
3682
|
+
if (invalid.length) throw new Error("Invalid options: " + invalid.join(", "));
|
|
3683
|
+
return __assign({}, options);
|
|
3684
|
+
}
|
|
3685
|
+
function parseOptions(options) {
|
|
3686
|
+
var opts = __assign(__assign({}, DEFAULT_OPTIONS), initializeOptions(options));
|
|
3687
|
+
if (isPresent(opts.byeaster)) opts.freq = RRule.YEARLY;
|
|
3688
|
+
if (!(isPresent(opts.freq) && RRule.FREQUENCIES[opts.freq])) throw new Error("Invalid frequency: ".concat(opts.freq, " ").concat(options.freq));
|
|
3689
|
+
if (!opts.dtstart) opts.dtstart = new Date((/* @__PURE__ */ new Date()).setMilliseconds(0));
|
|
3690
|
+
if (!isPresent(opts.wkst)) opts.wkst = RRule.MO.weekday;
|
|
3691
|
+
else if (isNumber(opts.wkst)) {} else opts.wkst = opts.wkst.weekday;
|
|
3692
|
+
if (isPresent(opts.bysetpos)) {
|
|
3693
|
+
if (isNumber(opts.bysetpos)) opts.bysetpos = [opts.bysetpos];
|
|
3694
|
+
for (var i = 0; i < opts.bysetpos.length; i++) {
|
|
3695
|
+
var v = opts.bysetpos[i];
|
|
3696
|
+
if (v === 0 || !(v >= -366 && v <= 366)) throw new Error("bysetpos must be between 1 and 366, or between -366 and -1");
|
|
3697
|
+
}
|
|
3698
|
+
}
|
|
3699
|
+
if (!(Boolean(opts.byweekno) || notEmpty(opts.byweekno) || notEmpty(opts.byyearday) || Boolean(opts.bymonthday) || notEmpty(opts.bymonthday) || isPresent(opts.byweekday) || isPresent(opts.byeaster))) switch (opts.freq) {
|
|
3700
|
+
case RRule.YEARLY:
|
|
3701
|
+
if (!opts.bymonth) opts.bymonth = opts.dtstart.getUTCMonth() + 1;
|
|
3702
|
+
opts.bymonthday = opts.dtstart.getUTCDate();
|
|
3703
|
+
break;
|
|
3704
|
+
case RRule.MONTHLY:
|
|
3705
|
+
opts.bymonthday = opts.dtstart.getUTCDate();
|
|
3706
|
+
break;
|
|
3707
|
+
case RRule.WEEKLY:
|
|
3708
|
+
opts.byweekday = [getWeekday(opts.dtstart)];
|
|
3709
|
+
break;
|
|
3710
|
+
}
|
|
3711
|
+
if (isPresent(opts.bymonth) && !isArray(opts.bymonth)) opts.bymonth = [opts.bymonth];
|
|
3712
|
+
if (isPresent(opts.byyearday) && !isArray(opts.byyearday) && isNumber(opts.byyearday)) opts.byyearday = [opts.byyearday];
|
|
3713
|
+
if (!isPresent(opts.bymonthday)) {
|
|
3714
|
+
opts.bymonthday = [];
|
|
3715
|
+
opts.bynmonthday = [];
|
|
3716
|
+
} else if (isArray(opts.bymonthday)) {
|
|
3717
|
+
var bymonthday = [];
|
|
3718
|
+
var bynmonthday = [];
|
|
3719
|
+
for (var i = 0; i < opts.bymonthday.length; i++) {
|
|
3720
|
+
var v = opts.bymonthday[i];
|
|
3721
|
+
if (v > 0) bymonthday.push(v);
|
|
3722
|
+
else if (v < 0) bynmonthday.push(v);
|
|
3723
|
+
}
|
|
3724
|
+
opts.bymonthday = bymonthday;
|
|
3725
|
+
opts.bynmonthday = bynmonthday;
|
|
3726
|
+
} else if (opts.bymonthday < 0) {
|
|
3727
|
+
opts.bynmonthday = [opts.bymonthday];
|
|
3728
|
+
opts.bymonthday = [];
|
|
3729
|
+
} else {
|
|
3730
|
+
opts.bynmonthday = [];
|
|
3731
|
+
opts.bymonthday = [opts.bymonthday];
|
|
3732
|
+
}
|
|
3733
|
+
if (isPresent(opts.byweekno) && !isArray(opts.byweekno)) opts.byweekno = [opts.byweekno];
|
|
3734
|
+
if (!isPresent(opts.byweekday)) opts.bynweekday = null;
|
|
3735
|
+
else if (isNumber(opts.byweekday)) {
|
|
3736
|
+
opts.byweekday = [opts.byweekday];
|
|
3737
|
+
opts.bynweekday = null;
|
|
3738
|
+
} else if (isWeekdayStr(opts.byweekday)) {
|
|
3739
|
+
opts.byweekday = [Weekday.fromStr(opts.byweekday).weekday];
|
|
3740
|
+
opts.bynweekday = null;
|
|
3741
|
+
} else if (opts.byweekday instanceof Weekday) if (!opts.byweekday.n || opts.freq > RRule.MONTHLY) {
|
|
3742
|
+
opts.byweekday = [opts.byweekday.weekday];
|
|
3743
|
+
opts.bynweekday = null;
|
|
3744
|
+
} else {
|
|
3745
|
+
opts.bynweekday = [[opts.byweekday.weekday, opts.byweekday.n]];
|
|
3746
|
+
opts.byweekday = null;
|
|
3747
|
+
}
|
|
3748
|
+
else {
|
|
3749
|
+
var byweekday = [];
|
|
3750
|
+
var bynweekday = [];
|
|
3751
|
+
for (var i = 0; i < opts.byweekday.length; i++) {
|
|
3752
|
+
var wday = opts.byweekday[i];
|
|
3753
|
+
if (isNumber(wday)) {
|
|
3754
|
+
byweekday.push(wday);
|
|
3755
|
+
continue;
|
|
3756
|
+
} else if (isWeekdayStr(wday)) {
|
|
3757
|
+
byweekday.push(Weekday.fromStr(wday).weekday);
|
|
3758
|
+
continue;
|
|
3759
|
+
}
|
|
3760
|
+
if (!wday.n || opts.freq > RRule.MONTHLY) byweekday.push(wday.weekday);
|
|
3761
|
+
else bynweekday.push([wday.weekday, wday.n]);
|
|
3762
|
+
}
|
|
3763
|
+
opts.byweekday = notEmpty(byweekday) ? byweekday : null;
|
|
3764
|
+
opts.bynweekday = notEmpty(bynweekday) ? bynweekday : null;
|
|
3765
|
+
}
|
|
3766
|
+
if (!isPresent(opts.byhour)) opts.byhour = opts.freq < RRule.HOURLY ? [opts.dtstart.getUTCHours()] : null;
|
|
3767
|
+
else if (isNumber(opts.byhour)) opts.byhour = [opts.byhour];
|
|
3768
|
+
if (!isPresent(opts.byminute)) opts.byminute = opts.freq < RRule.MINUTELY ? [opts.dtstart.getUTCMinutes()] : null;
|
|
3769
|
+
else if (isNumber(opts.byminute)) opts.byminute = [opts.byminute];
|
|
3770
|
+
if (!isPresent(opts.bysecond)) opts.bysecond = opts.freq < RRule.SECONDLY ? [opts.dtstart.getUTCSeconds()] : null;
|
|
3771
|
+
else if (isNumber(opts.bysecond)) opts.bysecond = [opts.bysecond];
|
|
3772
|
+
return { parsedOptions: opts };
|
|
3773
|
+
}
|
|
3774
|
+
function buildTimeset(opts) {
|
|
3775
|
+
var millisecondModulo = opts.dtstart.getTime() % 1e3;
|
|
3776
|
+
if (!freqIsDailyOrGreater(opts.freq)) return [];
|
|
3777
|
+
var timeset = [];
|
|
3778
|
+
opts.byhour.forEach(function(hour) {
|
|
3779
|
+
opts.byminute.forEach(function(minute) {
|
|
3780
|
+
opts.bysecond.forEach(function(second) {
|
|
3781
|
+
timeset.push(new Time(hour, minute, second, millisecondModulo));
|
|
3782
|
+
});
|
|
3783
|
+
});
|
|
3784
|
+
});
|
|
3785
|
+
return timeset;
|
|
3786
|
+
}
|
|
3787
|
+
function parseString(rfcString) {
|
|
3788
|
+
var options = rfcString.split("\n").map(parseLine).filter(function(x) {
|
|
3789
|
+
return x !== null;
|
|
3790
|
+
});
|
|
3791
|
+
return __assign(__assign({}, options[0]), options[1]);
|
|
3792
|
+
}
|
|
3793
|
+
function parseDtstart(line) {
|
|
3794
|
+
var options = {};
|
|
3795
|
+
var dtstartWithZone = /DTSTART(?:;TZID=([^:=]+?))?(?::|=)([^;\s]+)/i.exec(line);
|
|
3796
|
+
if (!dtstartWithZone) return options;
|
|
3797
|
+
var tzid = dtstartWithZone[1], dtstart = dtstartWithZone[2];
|
|
3798
|
+
if (tzid) options.tzid = tzid;
|
|
3799
|
+
options.dtstart = untilStringToDate(dtstart);
|
|
3800
|
+
return options;
|
|
3801
|
+
}
|
|
3802
|
+
function parseLine(rfcString) {
|
|
3803
|
+
rfcString = rfcString.replace(/^\s+|\s+$/, "");
|
|
3804
|
+
if (!rfcString.length) return null;
|
|
3805
|
+
var header = /^([A-Z]+?)[:;]/.exec(rfcString.toUpperCase());
|
|
3806
|
+
if (!header) return parseRrule(rfcString);
|
|
3807
|
+
var key = header[1];
|
|
3808
|
+
switch (key.toUpperCase()) {
|
|
3809
|
+
case "RRULE":
|
|
3810
|
+
case "EXRULE": return parseRrule(rfcString);
|
|
3811
|
+
case "DTSTART": return parseDtstart(rfcString);
|
|
3812
|
+
default: throw new Error("Unsupported RFC prop ".concat(key, " in ").concat(rfcString));
|
|
3813
|
+
}
|
|
3814
|
+
}
|
|
3815
|
+
function parseRrule(line) {
|
|
3816
|
+
var options = parseDtstart(line.replace(/^RRULE:/i, ""));
|
|
3817
|
+
line.replace(/^(?:RRULE|EXRULE):/i, "").split(";").forEach(function(attr) {
|
|
3818
|
+
var _a = attr.split("="), key = _a[0], value = _a[1];
|
|
3819
|
+
switch (key.toUpperCase()) {
|
|
3820
|
+
case "FREQ":
|
|
3821
|
+
options.freq = Frequency[value.toUpperCase()];
|
|
3822
|
+
break;
|
|
3823
|
+
case "WKST":
|
|
3824
|
+
options.wkst = Days[value.toUpperCase()];
|
|
3825
|
+
break;
|
|
3826
|
+
case "COUNT":
|
|
3827
|
+
case "INTERVAL":
|
|
3828
|
+
case "BYSETPOS":
|
|
3829
|
+
case "BYMONTH":
|
|
3830
|
+
case "BYMONTHDAY":
|
|
3831
|
+
case "BYYEARDAY":
|
|
3832
|
+
case "BYWEEKNO":
|
|
3833
|
+
case "BYHOUR":
|
|
3834
|
+
case "BYMINUTE":
|
|
3835
|
+
case "BYSECOND":
|
|
3836
|
+
var num = parseNumber(value);
|
|
3837
|
+
var optionKey = key.toLowerCase();
|
|
3838
|
+
options[optionKey] = num;
|
|
3839
|
+
break;
|
|
3840
|
+
case "BYWEEKDAY":
|
|
3841
|
+
case "BYDAY":
|
|
3842
|
+
options.byweekday = parseWeekday(value);
|
|
3843
|
+
break;
|
|
3844
|
+
case "DTSTART":
|
|
3845
|
+
case "TZID":
|
|
3846
|
+
var dtstart = parseDtstart(line);
|
|
3847
|
+
options.tzid = dtstart.tzid;
|
|
3848
|
+
options.dtstart = dtstart.dtstart;
|
|
3849
|
+
break;
|
|
3850
|
+
case "UNTIL":
|
|
3851
|
+
options.until = untilStringToDate(value);
|
|
3852
|
+
break;
|
|
3853
|
+
case "BYEASTER":
|
|
3854
|
+
options.byeaster = Number(value);
|
|
3855
|
+
break;
|
|
3856
|
+
default: throw new Error("Unknown RRULE property '" + key + "'");
|
|
3857
|
+
}
|
|
3858
|
+
});
|
|
3859
|
+
return options;
|
|
3860
|
+
}
|
|
3861
|
+
function parseNumber(value) {
|
|
3862
|
+
if (value.indexOf(",") !== -1) return value.split(",").map(parseIndividualNumber);
|
|
3863
|
+
return parseIndividualNumber(value);
|
|
3864
|
+
}
|
|
3865
|
+
function parseIndividualNumber(value) {
|
|
3866
|
+
if (/^[+-]?\d+$/.test(value)) return Number(value);
|
|
3867
|
+
return value;
|
|
3868
|
+
}
|
|
3869
|
+
function parseWeekday(value) {
|
|
3870
|
+
return value.split(",").map(function(day) {
|
|
3871
|
+
if (day.length === 2) return Days[day];
|
|
3872
|
+
var parts = day.match(/^([+-]?\d{1,2})([A-Z]{2})$/);
|
|
3873
|
+
if (!parts || parts.length < 3) throw new SyntaxError("Invalid weekday string: ".concat(day));
|
|
3874
|
+
var n = Number(parts[1]);
|
|
3875
|
+
var wday = Days[parts[2]].weekday;
|
|
3876
|
+
return new Weekday(wday, n);
|
|
3877
|
+
});
|
|
3878
|
+
}
|
|
3879
|
+
var DateWithZone = function() {
|
|
3880
|
+
function DateWithZone(date, tzid) {
|
|
3881
|
+
if (isNaN(date.getTime())) throw new RangeError("Invalid date passed to DateWithZone");
|
|
3882
|
+
this.date = date;
|
|
3883
|
+
this.tzid = tzid;
|
|
3884
|
+
}
|
|
3885
|
+
Object.defineProperty(DateWithZone.prototype, "isUTC", {
|
|
3886
|
+
get: function() {
|
|
3887
|
+
return !this.tzid || this.tzid.toUpperCase() === "UTC";
|
|
3888
|
+
},
|
|
3889
|
+
enumerable: false,
|
|
3890
|
+
configurable: true
|
|
3891
|
+
});
|
|
3892
|
+
DateWithZone.prototype.toString = function() {
|
|
3893
|
+
var datestr = timeToUntilString(this.date.getTime(), this.isUTC);
|
|
3894
|
+
if (!this.isUTC) return ";TZID=".concat(this.tzid, ":").concat(datestr);
|
|
3895
|
+
return ":".concat(datestr);
|
|
3896
|
+
};
|
|
3897
|
+
DateWithZone.prototype.getTime = function() {
|
|
3898
|
+
return this.date.getTime();
|
|
3899
|
+
};
|
|
3900
|
+
DateWithZone.prototype.rezonedDate = function() {
|
|
3901
|
+
if (this.isUTC) return this.date;
|
|
3902
|
+
return dateInTimeZone(this.date, this.tzid);
|
|
3903
|
+
};
|
|
3904
|
+
return DateWithZone;
|
|
3905
|
+
}();
|
|
3906
|
+
function optionsToString(options) {
|
|
3907
|
+
var rrule = [];
|
|
3908
|
+
var dtstart = "";
|
|
3909
|
+
var keys = Object.keys(options);
|
|
3910
|
+
var defaultKeys = Object.keys(DEFAULT_OPTIONS);
|
|
3911
|
+
for (var i = 0; i < keys.length; i++) {
|
|
3912
|
+
if (keys[i] === "tzid") continue;
|
|
3913
|
+
if (!includes(defaultKeys, keys[i])) continue;
|
|
3914
|
+
var key = keys[i].toUpperCase();
|
|
3915
|
+
var value = options[keys[i]];
|
|
3916
|
+
var outValue = "";
|
|
3917
|
+
if (!isPresent(value) || isArray(value) && !value.length) continue;
|
|
3918
|
+
switch (key) {
|
|
3919
|
+
case "FREQ":
|
|
3920
|
+
outValue = RRule.FREQUENCIES[options.freq];
|
|
3921
|
+
break;
|
|
3922
|
+
case "WKST":
|
|
3923
|
+
if (isNumber(value)) outValue = new Weekday(value).toString();
|
|
3924
|
+
else outValue = value.toString();
|
|
3925
|
+
break;
|
|
3926
|
+
case "BYWEEKDAY":
|
|
3927
|
+
key = "BYDAY";
|
|
3928
|
+
outValue = toArray(value).map(function(wday) {
|
|
3929
|
+
if (wday instanceof Weekday) return wday;
|
|
3930
|
+
if (isArray(wday)) return new Weekday(wday[0], wday[1]);
|
|
3931
|
+
return new Weekday(wday);
|
|
3932
|
+
}).toString();
|
|
3933
|
+
break;
|
|
3934
|
+
case "DTSTART":
|
|
3935
|
+
dtstart = buildDtstart(value, options.tzid);
|
|
3936
|
+
break;
|
|
3937
|
+
case "UNTIL":
|
|
3938
|
+
outValue = timeToUntilString(value, !options.tzid);
|
|
3939
|
+
break;
|
|
3940
|
+
default: if (isArray(value)) {
|
|
3941
|
+
var strValues = [];
|
|
3942
|
+
for (var j = 0; j < value.length; j++) strValues[j] = String(value[j]);
|
|
3943
|
+
outValue = strValues.toString();
|
|
3944
|
+
} else outValue = String(value);
|
|
3945
|
+
}
|
|
3946
|
+
if (outValue) rrule.push([key, outValue]);
|
|
3947
|
+
}
|
|
3948
|
+
var rules = rrule.map(function(_a) {
|
|
3949
|
+
var key = _a[0], value = _a[1];
|
|
3950
|
+
return "".concat(key, "=").concat(value.toString());
|
|
3951
|
+
}).join(";");
|
|
3952
|
+
var ruleString = "";
|
|
3953
|
+
if (rules !== "") ruleString = "RRULE:".concat(rules);
|
|
3954
|
+
return [dtstart, ruleString].filter(function(x) {
|
|
3955
|
+
return !!x;
|
|
3956
|
+
}).join("\n");
|
|
3957
|
+
}
|
|
3958
|
+
function buildDtstart(dtstart, tzid) {
|
|
3959
|
+
if (!dtstart) return "";
|
|
3960
|
+
return "DTSTART" + new DateWithZone(new Date(dtstart), tzid).toString();
|
|
3961
|
+
}
|
|
3962
|
+
function argsMatch(left, right) {
|
|
3963
|
+
if (Array.isArray(left)) {
|
|
3964
|
+
if (!Array.isArray(right)) return false;
|
|
3965
|
+
if (left.length !== right.length) return false;
|
|
3966
|
+
return left.every(function(date, i) {
|
|
3967
|
+
return date.getTime() === right[i].getTime();
|
|
3968
|
+
});
|
|
3969
|
+
}
|
|
3970
|
+
if (left instanceof Date) return right instanceof Date && left.getTime() === right.getTime();
|
|
3971
|
+
return left === right;
|
|
3972
|
+
}
|
|
3973
|
+
var Cache = function() {
|
|
3974
|
+
function Cache() {
|
|
3975
|
+
this.all = false;
|
|
3976
|
+
this.before = [];
|
|
3977
|
+
this.after = [];
|
|
3978
|
+
this.between = [];
|
|
3979
|
+
}
|
|
3980
|
+
/**
|
|
3981
|
+
* @param {String} what - all/before/after/between
|
|
3982
|
+
* @param {Array,Date} value - an array of dates, one date, or null
|
|
3983
|
+
* @param {Object?} args - _iter arguments
|
|
3984
|
+
*/
|
|
3985
|
+
Cache.prototype._cacheAdd = function(what, value, args) {
|
|
3986
|
+
if (value) value = value instanceof Date ? dateutil_clone(value) : cloneDates(value);
|
|
3987
|
+
if (what === "all") this.all = value;
|
|
3988
|
+
else {
|
|
3989
|
+
args._value = value;
|
|
3990
|
+
this[what].push(args);
|
|
3991
|
+
}
|
|
3992
|
+
};
|
|
3993
|
+
/**
|
|
3994
|
+
* @return false - not in the cache
|
|
3995
|
+
* @return null - cached, but zero occurrences (before/after)
|
|
3996
|
+
* @return Date - cached (before/after)
|
|
3997
|
+
* @return [] - cached, but zero occurrences (all/between)
|
|
3998
|
+
* @return [Date1, DateN] - cached (all/between)
|
|
3999
|
+
*/
|
|
4000
|
+
Cache.prototype._cacheGet = function(what, args) {
|
|
4001
|
+
var cached = false;
|
|
4002
|
+
var argsKeys = args ? Object.keys(args) : [];
|
|
4003
|
+
var findCacheDiff = function(item) {
|
|
4004
|
+
for (var i = 0; i < argsKeys.length; i++) {
|
|
4005
|
+
var key = argsKeys[i];
|
|
4006
|
+
if (!argsMatch(args[key], item[key])) return true;
|
|
4007
|
+
}
|
|
4008
|
+
return false;
|
|
4009
|
+
};
|
|
4010
|
+
var cachedObject = this[what];
|
|
4011
|
+
if (what === "all") cached = this.all;
|
|
4012
|
+
else if (isArray(cachedObject)) for (var i = 0; i < cachedObject.length; i++) {
|
|
4013
|
+
var item = cachedObject[i];
|
|
4014
|
+
if (argsKeys.length && findCacheDiff(item)) continue;
|
|
4015
|
+
cached = item._value;
|
|
4016
|
+
break;
|
|
4017
|
+
}
|
|
4018
|
+
if (!cached && this.all) {
|
|
4019
|
+
var iterResult = new iterresult(what, args);
|
|
4020
|
+
for (var i = 0; i < this.all.length; i++) if (!iterResult.accept(this.all[i])) break;
|
|
4021
|
+
cached = iterResult.getValue();
|
|
4022
|
+
this._cacheAdd(what, cached, args);
|
|
4023
|
+
}
|
|
4024
|
+
return isArray(cached) ? cloneDates(cached) : cached instanceof Date ? dateutil_clone(cached) : cached;
|
|
4025
|
+
};
|
|
4026
|
+
return Cache;
|
|
4027
|
+
}();
|
|
4028
|
+
var M365MASK = __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], repeat(1, 31), true), repeat(2, 28), true), repeat(3, 31), true), repeat(4, 30), true), repeat(5, 31), true), repeat(6, 30), true), repeat(7, 31), true), repeat(8, 31), true), repeat(9, 30), true), repeat(10, 31), true), repeat(11, 30), true), repeat(12, 31), true), repeat(1, 7), true);
|
|
4029
|
+
var M366MASK = __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], repeat(1, 31), true), repeat(2, 29), true), repeat(3, 31), true), repeat(4, 30), true), repeat(5, 31), true), repeat(6, 30), true), repeat(7, 31), true), repeat(8, 31), true), repeat(9, 30), true), repeat(10, 31), true), repeat(11, 30), true), repeat(12, 31), true), repeat(1, 7), true);
|
|
4030
|
+
var M28 = range(1, 29);
|
|
4031
|
+
var M29 = range(1, 30);
|
|
4032
|
+
var M30 = range(1, 31);
|
|
4033
|
+
var M31 = range(1, 32);
|
|
4034
|
+
var MDAY366MASK = __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], M31, true), M29, true), M31, true), M30, true), M31, true), M30, true), M31, true), M31, true), M30, true), M31, true), M30, true), M31, true), M31.slice(0, 7), true);
|
|
4035
|
+
var MDAY365MASK = __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], M31, true), M28, true), M31, true), M30, true), M31, true), M30, true), M31, true), M31, true), M30, true), M31, true), M30, true), M31, true), M31.slice(0, 7), true);
|
|
4036
|
+
var NM28 = range(-28, 0);
|
|
4037
|
+
var NM29 = range(-29, 0);
|
|
4038
|
+
var NM30 = range(-30, 0);
|
|
4039
|
+
var NM31 = range(-31, 0);
|
|
4040
|
+
var NMDAY366MASK = __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], NM31, true), NM29, true), NM31, true), NM30, true), NM31, true), NM30, true), NM31, true), NM31, true), NM30, true), NM31, true), NM30, true), NM31, true), NM31.slice(0, 7), true);
|
|
4041
|
+
var NMDAY365MASK = __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], NM31, true), NM28, true), NM31, true), NM30, true), NM31, true), NM30, true), NM31, true), NM31, true), NM30, true), NM31, true), NM30, true), NM31, true), NM31.slice(0, 7), true);
|
|
4042
|
+
var M366RANGE = [
|
|
4043
|
+
0,
|
|
4044
|
+
31,
|
|
4045
|
+
60,
|
|
4046
|
+
91,
|
|
4047
|
+
121,
|
|
4048
|
+
152,
|
|
4049
|
+
182,
|
|
4050
|
+
213,
|
|
4051
|
+
244,
|
|
4052
|
+
274,
|
|
4053
|
+
305,
|
|
4054
|
+
335,
|
|
4055
|
+
366
|
|
4056
|
+
];
|
|
4057
|
+
var M365RANGE = [
|
|
4058
|
+
0,
|
|
4059
|
+
31,
|
|
4060
|
+
59,
|
|
4061
|
+
90,
|
|
4062
|
+
120,
|
|
4063
|
+
151,
|
|
4064
|
+
181,
|
|
4065
|
+
212,
|
|
4066
|
+
243,
|
|
4067
|
+
273,
|
|
4068
|
+
304,
|
|
4069
|
+
334,
|
|
4070
|
+
365
|
|
4071
|
+
];
|
|
4072
|
+
var WDAYMASK = (function() {
|
|
4073
|
+
var wdaymask = [];
|
|
4074
|
+
for (var i = 0; i < 55; i++) wdaymask = wdaymask.concat(range(7));
|
|
4075
|
+
return wdaymask;
|
|
4076
|
+
})();
|
|
4077
|
+
function rebuildYear(year, options) {
|
|
4078
|
+
var firstyday = datetime(year, 1, 1);
|
|
4079
|
+
var yearlen = isLeapYear(year) ? 366 : 365;
|
|
4080
|
+
var nextyearlen = isLeapYear(year + 1) ? 366 : 365;
|
|
4081
|
+
var yearordinal = toOrdinal(firstyday);
|
|
4082
|
+
var yearweekday = getWeekday(firstyday);
|
|
4083
|
+
var result = __assign(__assign({
|
|
4084
|
+
yearlen,
|
|
4085
|
+
nextyearlen,
|
|
4086
|
+
yearordinal,
|
|
4087
|
+
yearweekday
|
|
4088
|
+
}, baseYearMasks(year)), { wnomask: null });
|
|
4089
|
+
if (empty(options.byweekno)) return result;
|
|
4090
|
+
result.wnomask = repeat(0, yearlen + 7);
|
|
4091
|
+
var firstwkst;
|
|
4092
|
+
var wyearlen;
|
|
4093
|
+
var no1wkst = firstwkst = pymod(7 - yearweekday + options.wkst, 7);
|
|
4094
|
+
if (no1wkst >= 4) {
|
|
4095
|
+
no1wkst = 0;
|
|
4096
|
+
wyearlen = result.yearlen + pymod(yearweekday - options.wkst, 7);
|
|
4097
|
+
} else wyearlen = yearlen - no1wkst;
|
|
4098
|
+
var div = Math.floor(wyearlen / 7);
|
|
4099
|
+
var mod = pymod(wyearlen, 7);
|
|
4100
|
+
var numweeks = Math.floor(div + mod / 4);
|
|
4101
|
+
for (var j = 0; j < options.byweekno.length; j++) {
|
|
4102
|
+
var n = options.byweekno[j];
|
|
4103
|
+
if (n < 0) n += numweeks + 1;
|
|
4104
|
+
if (!(n > 0 && n <= numweeks)) continue;
|
|
4105
|
+
var i = void 0;
|
|
4106
|
+
if (n > 1) {
|
|
4107
|
+
i = no1wkst + (n - 1) * 7;
|
|
4108
|
+
if (no1wkst !== firstwkst) i -= 7 - firstwkst;
|
|
4109
|
+
} else i = no1wkst;
|
|
4110
|
+
for (var k = 0; k < 7; k++) {
|
|
4111
|
+
result.wnomask[i] = 1;
|
|
4112
|
+
i++;
|
|
4113
|
+
if (result.wdaymask[i] === options.wkst) break;
|
|
4114
|
+
}
|
|
4115
|
+
}
|
|
4116
|
+
if (includes(options.byweekno, 1)) {
|
|
4117
|
+
var i = no1wkst + numweeks * 7;
|
|
4118
|
+
if (no1wkst !== firstwkst) i -= 7 - firstwkst;
|
|
4119
|
+
if (i < yearlen) for (var j = 0; j < 7; j++) {
|
|
4120
|
+
result.wnomask[i] = 1;
|
|
4121
|
+
i += 1;
|
|
4122
|
+
if (result.wdaymask[i] === options.wkst) break;
|
|
4123
|
+
}
|
|
4124
|
+
}
|
|
4125
|
+
if (no1wkst) {
|
|
4126
|
+
var lnumweeks = void 0;
|
|
4127
|
+
if (!includes(options.byweekno, -1)) {
|
|
4128
|
+
var lyearweekday = getWeekday(datetime(year - 1, 1, 1));
|
|
4129
|
+
var lno1wkst = pymod(7 - lyearweekday.valueOf() + options.wkst, 7);
|
|
4130
|
+
var lyearlen = isLeapYear(year - 1) ? 366 : 365;
|
|
4131
|
+
var weekst = void 0;
|
|
4132
|
+
if (lno1wkst >= 4) {
|
|
4133
|
+
lno1wkst = 0;
|
|
4134
|
+
weekst = lyearlen + pymod(lyearweekday - options.wkst, 7);
|
|
4135
|
+
} else weekst = yearlen - no1wkst;
|
|
4136
|
+
lnumweeks = Math.floor(52 + pymod(weekst, 7) / 4);
|
|
4137
|
+
} else lnumweeks = -1;
|
|
4138
|
+
if (includes(options.byweekno, lnumweeks)) for (var i = 0; i < no1wkst; i++) result.wnomask[i] = 1;
|
|
4139
|
+
}
|
|
4140
|
+
return result;
|
|
4141
|
+
}
|
|
4142
|
+
function baseYearMasks(year) {
|
|
4143
|
+
var yearlen = isLeapYear(year) ? 366 : 365;
|
|
4144
|
+
var wday = getWeekday(datetime(year, 1, 1));
|
|
4145
|
+
if (yearlen === 365) return {
|
|
4146
|
+
mmask: M365MASK,
|
|
4147
|
+
mdaymask: MDAY365MASK,
|
|
4148
|
+
nmdaymask: NMDAY365MASK,
|
|
4149
|
+
wdaymask: WDAYMASK.slice(wday),
|
|
4150
|
+
mrange: M365RANGE
|
|
4151
|
+
};
|
|
4152
|
+
return {
|
|
4153
|
+
mmask: M366MASK,
|
|
4154
|
+
mdaymask: MDAY366MASK,
|
|
4155
|
+
nmdaymask: NMDAY366MASK,
|
|
4156
|
+
wdaymask: WDAYMASK.slice(wday),
|
|
4157
|
+
mrange: M366RANGE
|
|
4158
|
+
};
|
|
4159
|
+
}
|
|
4160
|
+
function rebuildMonth(year, month, yearlen, mrange, wdaymask, options) {
|
|
4161
|
+
var result = {
|
|
4162
|
+
lastyear: year,
|
|
4163
|
+
lastmonth: month,
|
|
4164
|
+
nwdaymask: []
|
|
4165
|
+
};
|
|
4166
|
+
var ranges = [];
|
|
4167
|
+
if (options.freq === RRule.YEARLY) if (empty(options.bymonth)) ranges = [[0, yearlen]];
|
|
4168
|
+
else for (var j = 0; j < options.bymonth.length; j++) {
|
|
4169
|
+
month = options.bymonth[j];
|
|
4170
|
+
ranges.push(mrange.slice(month - 1, month + 1));
|
|
4171
|
+
}
|
|
4172
|
+
else if (options.freq === RRule.MONTHLY) ranges = [mrange.slice(month - 1, month + 1)];
|
|
4173
|
+
if (empty(ranges)) return result;
|
|
4174
|
+
result.nwdaymask = repeat(0, yearlen);
|
|
4175
|
+
for (var j = 0; j < ranges.length; j++) {
|
|
4176
|
+
var rang = ranges[j];
|
|
4177
|
+
var first = rang[0];
|
|
4178
|
+
var last = rang[1] - 1;
|
|
4179
|
+
for (var k = 0; k < options.bynweekday.length; k++) {
|
|
4180
|
+
var i = void 0;
|
|
4181
|
+
var _a = options.bynweekday[k], wday = _a[0], n = _a[1];
|
|
4182
|
+
if (n < 0) {
|
|
4183
|
+
i = last + (n + 1) * 7;
|
|
4184
|
+
i -= pymod(wdaymask[i] - wday, 7);
|
|
4185
|
+
} else {
|
|
4186
|
+
i = first + (n - 1) * 7;
|
|
4187
|
+
i += pymod(7 - wdaymask[i] + wday, 7);
|
|
4188
|
+
}
|
|
4189
|
+
if (first <= i && i <= last) result.nwdaymask[i] = 1;
|
|
4190
|
+
}
|
|
4191
|
+
}
|
|
4192
|
+
return result;
|
|
4193
|
+
}
|
|
4194
|
+
function easter(y, offset) {
|
|
4195
|
+
if (offset === void 0) offset = 0;
|
|
4196
|
+
var a = y % 19;
|
|
4197
|
+
var b = Math.floor(y / 100);
|
|
4198
|
+
var c = y % 100;
|
|
4199
|
+
var d = Math.floor(b / 4);
|
|
4200
|
+
var e = b % 4;
|
|
4201
|
+
var f = Math.floor((b + 8) / 25);
|
|
4202
|
+
var g = Math.floor((b - f + 1) / 3);
|
|
4203
|
+
var h = Math.floor(19 * a + b - d - g + 15) % 30;
|
|
4204
|
+
var i = Math.floor(c / 4);
|
|
4205
|
+
var k = c % 4;
|
|
4206
|
+
var l = Math.floor(32 + 2 * e + 2 * i - h - k) % 7;
|
|
4207
|
+
var m = Math.floor((a + 11 * h + 22 * l) / 451);
|
|
4208
|
+
var month = Math.floor((h + l - 7 * m + 114) / 31);
|
|
4209
|
+
var day = (h + l - 7 * m + 114) % 31 + 1;
|
|
4210
|
+
var date = Date.UTC(y, month - 1, day + offset);
|
|
4211
|
+
return [Math.ceil((date - Date.UTC(y, 0, 1)) / (1e3 * 60 * 60 * 24))];
|
|
4212
|
+
}
|
|
4213
|
+
const iterinfo = function() {
|
|
4214
|
+
function Iterinfo(options) {
|
|
4215
|
+
this.options = options;
|
|
4216
|
+
}
|
|
4217
|
+
Iterinfo.prototype.rebuild = function(year, month) {
|
|
4218
|
+
var options = this.options;
|
|
4219
|
+
if (year !== this.lastyear) this.yearinfo = rebuildYear(year, options);
|
|
4220
|
+
if (notEmpty(options.bynweekday) && (month !== this.lastmonth || year !== this.lastyear)) {
|
|
4221
|
+
var _a = this.yearinfo, yearlen = _a.yearlen, mrange = _a.mrange, wdaymask = _a.wdaymask;
|
|
4222
|
+
this.monthinfo = rebuildMonth(year, month, yearlen, mrange, wdaymask, options);
|
|
4223
|
+
}
|
|
4224
|
+
if (isPresent(options.byeaster)) this.eastermask = easter(year, options.byeaster);
|
|
4225
|
+
};
|
|
4226
|
+
Object.defineProperty(Iterinfo.prototype, "lastyear", {
|
|
4227
|
+
get: function() {
|
|
4228
|
+
return this.monthinfo ? this.monthinfo.lastyear : null;
|
|
4229
|
+
},
|
|
4230
|
+
enumerable: false,
|
|
4231
|
+
configurable: true
|
|
4232
|
+
});
|
|
4233
|
+
Object.defineProperty(Iterinfo.prototype, "lastmonth", {
|
|
4234
|
+
get: function() {
|
|
4235
|
+
return this.monthinfo ? this.monthinfo.lastmonth : null;
|
|
4236
|
+
},
|
|
4237
|
+
enumerable: false,
|
|
4238
|
+
configurable: true
|
|
4239
|
+
});
|
|
4240
|
+
Object.defineProperty(Iterinfo.prototype, "yearlen", {
|
|
4241
|
+
get: function() {
|
|
4242
|
+
return this.yearinfo.yearlen;
|
|
4243
|
+
},
|
|
4244
|
+
enumerable: false,
|
|
4245
|
+
configurable: true
|
|
4246
|
+
});
|
|
4247
|
+
Object.defineProperty(Iterinfo.prototype, "yearordinal", {
|
|
4248
|
+
get: function() {
|
|
4249
|
+
return this.yearinfo.yearordinal;
|
|
4250
|
+
},
|
|
4251
|
+
enumerable: false,
|
|
4252
|
+
configurable: true
|
|
4253
|
+
});
|
|
4254
|
+
Object.defineProperty(Iterinfo.prototype, "mrange", {
|
|
4255
|
+
get: function() {
|
|
4256
|
+
return this.yearinfo.mrange;
|
|
4257
|
+
},
|
|
4258
|
+
enumerable: false,
|
|
4259
|
+
configurable: true
|
|
4260
|
+
});
|
|
4261
|
+
Object.defineProperty(Iterinfo.prototype, "wdaymask", {
|
|
4262
|
+
get: function() {
|
|
4263
|
+
return this.yearinfo.wdaymask;
|
|
4264
|
+
},
|
|
4265
|
+
enumerable: false,
|
|
4266
|
+
configurable: true
|
|
4267
|
+
});
|
|
4268
|
+
Object.defineProperty(Iterinfo.prototype, "mmask", {
|
|
4269
|
+
get: function() {
|
|
4270
|
+
return this.yearinfo.mmask;
|
|
4271
|
+
},
|
|
4272
|
+
enumerable: false,
|
|
4273
|
+
configurable: true
|
|
4274
|
+
});
|
|
4275
|
+
Object.defineProperty(Iterinfo.prototype, "wnomask", {
|
|
4276
|
+
get: function() {
|
|
4277
|
+
return this.yearinfo.wnomask;
|
|
4278
|
+
},
|
|
4279
|
+
enumerable: false,
|
|
4280
|
+
configurable: true
|
|
4281
|
+
});
|
|
4282
|
+
Object.defineProperty(Iterinfo.prototype, "nwdaymask", {
|
|
4283
|
+
get: function() {
|
|
4284
|
+
return this.monthinfo ? this.monthinfo.nwdaymask : [];
|
|
4285
|
+
},
|
|
4286
|
+
enumerable: false,
|
|
4287
|
+
configurable: true
|
|
4288
|
+
});
|
|
4289
|
+
Object.defineProperty(Iterinfo.prototype, "nextyearlen", {
|
|
4290
|
+
get: function() {
|
|
4291
|
+
return this.yearinfo.nextyearlen;
|
|
4292
|
+
},
|
|
4293
|
+
enumerable: false,
|
|
4294
|
+
configurable: true
|
|
4295
|
+
});
|
|
4296
|
+
Object.defineProperty(Iterinfo.prototype, "mdaymask", {
|
|
4297
|
+
get: function() {
|
|
4298
|
+
return this.yearinfo.mdaymask;
|
|
4299
|
+
},
|
|
4300
|
+
enumerable: false,
|
|
4301
|
+
configurable: true
|
|
4302
|
+
});
|
|
4303
|
+
Object.defineProperty(Iterinfo.prototype, "nmdaymask", {
|
|
4304
|
+
get: function() {
|
|
4305
|
+
return this.yearinfo.nmdaymask;
|
|
4306
|
+
},
|
|
4307
|
+
enumerable: false,
|
|
4308
|
+
configurable: true
|
|
4309
|
+
});
|
|
4310
|
+
Iterinfo.prototype.ydayset = function() {
|
|
4311
|
+
return [
|
|
4312
|
+
range(this.yearlen),
|
|
4313
|
+
0,
|
|
4314
|
+
this.yearlen
|
|
4315
|
+
];
|
|
4316
|
+
};
|
|
4317
|
+
Iterinfo.prototype.mdayset = function(_, month) {
|
|
4318
|
+
var start = this.mrange[month - 1];
|
|
4319
|
+
var end = this.mrange[month];
|
|
4320
|
+
var set = repeat(null, this.yearlen);
|
|
4321
|
+
for (var i = start; i < end; i++) set[i] = i;
|
|
4322
|
+
return [
|
|
4323
|
+
set,
|
|
4324
|
+
start,
|
|
4325
|
+
end
|
|
4326
|
+
];
|
|
4327
|
+
};
|
|
4328
|
+
Iterinfo.prototype.wdayset = function(year, month, day) {
|
|
4329
|
+
var set = repeat(null, this.yearlen + 7);
|
|
4330
|
+
var i = toOrdinal(datetime(year, month, day)) - this.yearordinal;
|
|
4331
|
+
var start = i;
|
|
4332
|
+
for (var j = 0; j < 7; j++) {
|
|
4333
|
+
set[i] = i;
|
|
4334
|
+
++i;
|
|
4335
|
+
if (this.wdaymask[i] === this.options.wkst) break;
|
|
4336
|
+
}
|
|
4337
|
+
return [
|
|
4338
|
+
set,
|
|
4339
|
+
start,
|
|
4340
|
+
i
|
|
4341
|
+
];
|
|
4342
|
+
};
|
|
4343
|
+
Iterinfo.prototype.ddayset = function(year, month, day) {
|
|
4344
|
+
var set = repeat(null, this.yearlen);
|
|
4345
|
+
var i = toOrdinal(datetime(year, month, day)) - this.yearordinal;
|
|
4346
|
+
set[i] = i;
|
|
4347
|
+
return [
|
|
4348
|
+
set,
|
|
4349
|
+
i,
|
|
4350
|
+
i + 1
|
|
4351
|
+
];
|
|
4352
|
+
};
|
|
4353
|
+
Iterinfo.prototype.htimeset = function(hour, _, second, millisecond) {
|
|
4354
|
+
var _this = this;
|
|
4355
|
+
var set = [];
|
|
4356
|
+
this.options.byminute.forEach(function(minute) {
|
|
4357
|
+
set = set.concat(_this.mtimeset(hour, minute, second, millisecond));
|
|
4358
|
+
});
|
|
4359
|
+
sort(set);
|
|
4360
|
+
return set;
|
|
4361
|
+
};
|
|
4362
|
+
Iterinfo.prototype.mtimeset = function(hour, minute, _, millisecond) {
|
|
4363
|
+
var set = this.options.bysecond.map(function(second) {
|
|
4364
|
+
return new Time(hour, minute, second, millisecond);
|
|
4365
|
+
});
|
|
4366
|
+
sort(set);
|
|
4367
|
+
return set;
|
|
4368
|
+
};
|
|
4369
|
+
Iterinfo.prototype.stimeset = function(hour, minute, second, millisecond) {
|
|
4370
|
+
return [new Time(hour, minute, second, millisecond)];
|
|
4371
|
+
};
|
|
4372
|
+
Iterinfo.prototype.getdayset = function(freq) {
|
|
4373
|
+
switch (freq) {
|
|
4374
|
+
case Frequency.YEARLY: return this.ydayset.bind(this);
|
|
4375
|
+
case Frequency.MONTHLY: return this.mdayset.bind(this);
|
|
4376
|
+
case Frequency.WEEKLY: return this.wdayset.bind(this);
|
|
4377
|
+
case Frequency.DAILY: return this.ddayset.bind(this);
|
|
4378
|
+
default: return this.ddayset.bind(this);
|
|
4379
|
+
}
|
|
4380
|
+
};
|
|
4381
|
+
Iterinfo.prototype.gettimeset = function(freq) {
|
|
4382
|
+
switch (freq) {
|
|
4383
|
+
case Frequency.HOURLY: return this.htimeset.bind(this);
|
|
4384
|
+
case Frequency.MINUTELY: return this.mtimeset.bind(this);
|
|
4385
|
+
case Frequency.SECONDLY: return this.stimeset.bind(this);
|
|
4386
|
+
}
|
|
4387
|
+
};
|
|
4388
|
+
return Iterinfo;
|
|
4389
|
+
}();
|
|
4390
|
+
function buildPoslist(bysetpos, timeset, start, end, ii, dayset) {
|
|
4391
|
+
var poslist = [];
|
|
4392
|
+
for (var j = 0; j < bysetpos.length; j++) {
|
|
4393
|
+
var daypos = void 0;
|
|
4394
|
+
var timepos = void 0;
|
|
4395
|
+
var pos = bysetpos[j];
|
|
4396
|
+
if (pos < 0) {
|
|
4397
|
+
daypos = Math.floor(pos / timeset.length);
|
|
4398
|
+
timepos = pymod(pos, timeset.length);
|
|
4399
|
+
} else {
|
|
4400
|
+
daypos = Math.floor((pos - 1) / timeset.length);
|
|
4401
|
+
timepos = pymod(pos - 1, timeset.length);
|
|
4402
|
+
}
|
|
4403
|
+
var tmp = [];
|
|
4404
|
+
for (var k = start; k < end; k++) {
|
|
4405
|
+
var val = dayset[k];
|
|
4406
|
+
if (!isPresent(val)) continue;
|
|
4407
|
+
tmp.push(val);
|
|
4408
|
+
}
|
|
4409
|
+
var i = void 0;
|
|
4410
|
+
if (daypos < 0) i = tmp.slice(daypos)[0];
|
|
4411
|
+
else i = tmp[daypos];
|
|
4412
|
+
var time = timeset[timepos];
|
|
4413
|
+
var res = combine(fromOrdinal(ii.yearordinal + i), time);
|
|
4414
|
+
if (!includes(poslist, res)) poslist.push(res);
|
|
4415
|
+
}
|
|
4416
|
+
sort(poslist);
|
|
4417
|
+
return poslist;
|
|
4418
|
+
}
|
|
4419
|
+
function iter(iterResult, options) {
|
|
4420
|
+
var dtstart = options.dtstart, freq = options.freq, interval = options.interval, until = options.until, bysetpos = options.bysetpos;
|
|
4421
|
+
var count = options.count;
|
|
4422
|
+
if (count === 0 || interval === 0) return emitResult(iterResult);
|
|
4423
|
+
var counterDate = DateTime.fromDate(dtstart);
|
|
4424
|
+
var ii = new iterinfo(options);
|
|
4425
|
+
ii.rebuild(counterDate.year, counterDate.month);
|
|
4426
|
+
var timeset = makeTimeset(ii, counterDate, options);
|
|
4427
|
+
for (;;) {
|
|
4428
|
+
var _a = ii.getdayset(freq)(counterDate.year, counterDate.month, counterDate.day), dayset = _a[0], start = _a[1], end = _a[2];
|
|
4429
|
+
var filtered = removeFilteredDays(dayset, start, end, ii, options);
|
|
4430
|
+
if (notEmpty(bysetpos)) {
|
|
4431
|
+
var poslist = buildPoslist(bysetpos, timeset, start, end, ii, dayset);
|
|
4432
|
+
for (var j = 0; j < poslist.length; j++) {
|
|
4433
|
+
var res = poslist[j];
|
|
4434
|
+
if (until && res > until) return emitResult(iterResult);
|
|
4435
|
+
if (res >= dtstart) {
|
|
4436
|
+
var rezonedDate = rezoneIfNeeded(res, options);
|
|
4437
|
+
if (!iterResult.accept(rezonedDate)) return emitResult(iterResult);
|
|
4438
|
+
if (count) {
|
|
4439
|
+
--count;
|
|
4440
|
+
if (!count) return emitResult(iterResult);
|
|
4441
|
+
}
|
|
4442
|
+
}
|
|
4443
|
+
}
|
|
4444
|
+
} else for (var j = start; j < end; j++) {
|
|
4445
|
+
var currentDay = dayset[j];
|
|
4446
|
+
if (!isPresent(currentDay)) continue;
|
|
4447
|
+
var date = fromOrdinal(ii.yearordinal + currentDay);
|
|
4448
|
+
for (var k = 0; k < timeset.length; k++) {
|
|
4449
|
+
var time = timeset[k];
|
|
4450
|
+
var res = combine(date, time);
|
|
4451
|
+
if (until && res > until) return emitResult(iterResult);
|
|
4452
|
+
if (res >= dtstart) {
|
|
4453
|
+
var rezonedDate = rezoneIfNeeded(res, options);
|
|
4454
|
+
if (!iterResult.accept(rezonedDate)) return emitResult(iterResult);
|
|
4455
|
+
if (count) {
|
|
4456
|
+
--count;
|
|
4457
|
+
if (!count) return emitResult(iterResult);
|
|
4458
|
+
}
|
|
4459
|
+
}
|
|
4460
|
+
}
|
|
4461
|
+
}
|
|
4462
|
+
if (options.interval === 0) return emitResult(iterResult);
|
|
4463
|
+
counterDate.add(options, filtered);
|
|
4464
|
+
if (counterDate.year > MAXYEAR) return emitResult(iterResult);
|
|
4465
|
+
if (!freqIsDailyOrGreater(freq)) timeset = ii.gettimeset(freq)(counterDate.hour, counterDate.minute, counterDate.second, 0);
|
|
4466
|
+
ii.rebuild(counterDate.year, counterDate.month);
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4469
|
+
function isFiltered(ii, currentDay, options) {
|
|
4470
|
+
var bymonth = options.bymonth, byweekno = options.byweekno, byweekday = options.byweekday, byeaster = options.byeaster, bymonthday = options.bymonthday, bynmonthday = options.bynmonthday, byyearday = options.byyearday;
|
|
4471
|
+
return notEmpty(bymonth) && !includes(bymonth, ii.mmask[currentDay]) || notEmpty(byweekno) && !ii.wnomask[currentDay] || notEmpty(byweekday) && !includes(byweekday, ii.wdaymask[currentDay]) || notEmpty(ii.nwdaymask) && !ii.nwdaymask[currentDay] || byeaster !== null && !includes(ii.eastermask, currentDay) || (notEmpty(bymonthday) || notEmpty(bynmonthday)) && !includes(bymonthday, ii.mdaymask[currentDay]) && !includes(bynmonthday, ii.nmdaymask[currentDay]) || notEmpty(byyearday) && (currentDay < ii.yearlen && !includes(byyearday, currentDay + 1) && !includes(byyearday, -ii.yearlen + currentDay) || currentDay >= ii.yearlen && !includes(byyearday, currentDay + 1 - ii.yearlen) && !includes(byyearday, -ii.nextyearlen + currentDay - ii.yearlen));
|
|
4472
|
+
}
|
|
4473
|
+
function rezoneIfNeeded(date, options) {
|
|
4474
|
+
return new DateWithZone(date, options.tzid).rezonedDate();
|
|
4475
|
+
}
|
|
4476
|
+
function emitResult(iterResult) {
|
|
4477
|
+
return iterResult.getValue();
|
|
4478
|
+
}
|
|
4479
|
+
function removeFilteredDays(dayset, start, end, ii, options) {
|
|
4480
|
+
var filtered = false;
|
|
4481
|
+
for (var dayCounter = start; dayCounter < end; dayCounter++) {
|
|
4482
|
+
var currentDay = dayset[dayCounter];
|
|
4483
|
+
filtered = isFiltered(ii, currentDay, options);
|
|
4484
|
+
if (filtered) dayset[currentDay] = null;
|
|
4485
|
+
}
|
|
4486
|
+
return filtered;
|
|
4487
|
+
}
|
|
4488
|
+
function makeTimeset(ii, counterDate, options) {
|
|
4489
|
+
var freq = options.freq, byhour = options.byhour, byminute = options.byminute, bysecond = options.bysecond;
|
|
4490
|
+
if (freqIsDailyOrGreater(freq)) return buildTimeset(options);
|
|
4491
|
+
if (freq >= RRule.HOURLY && notEmpty(byhour) && !includes(byhour, counterDate.hour) || freq >= RRule.MINUTELY && notEmpty(byminute) && !includes(byminute, counterDate.minute) || freq >= RRule.SECONDLY && notEmpty(bysecond) && !includes(bysecond, counterDate.second)) return [];
|
|
4492
|
+
return ii.gettimeset(freq)(counterDate.hour, counterDate.minute, counterDate.second, counterDate.millisecond);
|
|
4493
|
+
}
|
|
4494
|
+
var Days = {
|
|
4495
|
+
MO: new Weekday(0),
|
|
4496
|
+
TU: new Weekday(1),
|
|
4497
|
+
WE: new Weekday(2),
|
|
4498
|
+
TH: new Weekday(3),
|
|
4499
|
+
FR: new Weekday(4),
|
|
4500
|
+
SA: new Weekday(5),
|
|
4501
|
+
SU: new Weekday(6)
|
|
4502
|
+
};
|
|
4503
|
+
var DEFAULT_OPTIONS = {
|
|
4504
|
+
freq: Frequency.YEARLY,
|
|
4505
|
+
dtstart: null,
|
|
4506
|
+
interval: 1,
|
|
4507
|
+
wkst: Days.MO,
|
|
4508
|
+
count: null,
|
|
4509
|
+
until: null,
|
|
4510
|
+
tzid: null,
|
|
4511
|
+
bysetpos: null,
|
|
4512
|
+
bymonth: null,
|
|
4513
|
+
bymonthday: null,
|
|
4514
|
+
bynmonthday: null,
|
|
4515
|
+
byyearday: null,
|
|
4516
|
+
byweekno: null,
|
|
4517
|
+
byweekday: null,
|
|
4518
|
+
bynweekday: null,
|
|
4519
|
+
byhour: null,
|
|
4520
|
+
byminute: null,
|
|
4521
|
+
bysecond: null,
|
|
4522
|
+
byeaster: null
|
|
4523
|
+
};
|
|
4524
|
+
var defaultKeys = Object.keys(DEFAULT_OPTIONS);
|
|
4525
|
+
/**
|
|
4526
|
+
*
|
|
4527
|
+
* @param {Options?} options - see <http://labix.org/python-dateutil/#head-cf004ee9a75592797e076752b2a889c10f445418>
|
|
4528
|
+
* - The only required option is `freq`, one of RRule.YEARLY, RRule.MONTHLY, ...
|
|
4529
|
+
* @constructor
|
|
4530
|
+
*/
|
|
4531
|
+
var RRule = function() {
|
|
4532
|
+
function RRule(options, noCache) {
|
|
4533
|
+
if (options === void 0) options = {};
|
|
4534
|
+
if (noCache === void 0) noCache = false;
|
|
4535
|
+
this._cache = noCache ? null : new Cache();
|
|
4536
|
+
this.origOptions = initializeOptions(options);
|
|
4537
|
+
var parsedOptions = parseOptions(options).parsedOptions;
|
|
4538
|
+
this.options = parsedOptions;
|
|
4539
|
+
}
|
|
4540
|
+
RRule.parseText = function(text, language) {
|
|
4541
|
+
return parseText(text, language);
|
|
4542
|
+
};
|
|
4543
|
+
RRule.fromText = function(text, language) {
|
|
4544
|
+
return fromText(text, language);
|
|
4545
|
+
};
|
|
4546
|
+
RRule.fromString = function(str) {
|
|
4547
|
+
return new RRule(RRule.parseString(str) || void 0);
|
|
4548
|
+
};
|
|
4549
|
+
RRule.prototype._iter = function(iterResult) {
|
|
4550
|
+
return iter(iterResult, this.options);
|
|
4551
|
+
};
|
|
4552
|
+
RRule.prototype._cacheGet = function(what, args) {
|
|
4553
|
+
if (!this._cache) return false;
|
|
4554
|
+
return this._cache._cacheGet(what, args);
|
|
4555
|
+
};
|
|
4556
|
+
RRule.prototype._cacheAdd = function(what, value, args) {
|
|
4557
|
+
if (!this._cache) return;
|
|
4558
|
+
return this._cache._cacheAdd(what, value, args);
|
|
4559
|
+
};
|
|
4560
|
+
/**
|
|
4561
|
+
* @param {Function} iterator - optional function that will be called
|
|
4562
|
+
* on each date that is added. It can return false
|
|
4563
|
+
* to stop the iteration.
|
|
4564
|
+
* @return Array containing all recurrences.
|
|
4565
|
+
*/
|
|
4566
|
+
RRule.prototype.all = function(iterator) {
|
|
4567
|
+
if (iterator) return this._iter(new callbackiterresult("all", {}, iterator));
|
|
4568
|
+
var result = this._cacheGet("all");
|
|
4569
|
+
if (result === false) {
|
|
4570
|
+
result = this._iter(new iterresult("all", {}));
|
|
4571
|
+
this._cacheAdd("all", result);
|
|
4572
|
+
}
|
|
4573
|
+
return result;
|
|
4574
|
+
};
|
|
4575
|
+
/**
|
|
4576
|
+
* Returns all the occurrences of the rrule between after and before.
|
|
4577
|
+
* The inc keyword defines what happens if after and/or before are
|
|
4578
|
+
* themselves occurrences. With inc == True, they will be included in the
|
|
4579
|
+
* list, if they are found in the recurrence set.
|
|
4580
|
+
*
|
|
4581
|
+
* @return Array
|
|
4582
|
+
*/
|
|
4583
|
+
RRule.prototype.between = function(after, before, inc, iterator) {
|
|
4584
|
+
if (inc === void 0) inc = false;
|
|
4585
|
+
if (!isValidDate(after) || !isValidDate(before)) throw new Error("Invalid date passed in to RRule.between");
|
|
4586
|
+
var args = {
|
|
4587
|
+
before,
|
|
4588
|
+
after,
|
|
4589
|
+
inc
|
|
4590
|
+
};
|
|
4591
|
+
if (iterator) return this._iter(new callbackiterresult("between", args, iterator));
|
|
4592
|
+
var result = this._cacheGet("between", args);
|
|
4593
|
+
if (result === false) {
|
|
4594
|
+
result = this._iter(new iterresult("between", args));
|
|
4595
|
+
this._cacheAdd("between", result, args);
|
|
4596
|
+
}
|
|
4597
|
+
return result;
|
|
4598
|
+
};
|
|
4599
|
+
/**
|
|
4600
|
+
* Returns the last recurrence before the given datetime instance.
|
|
4601
|
+
* The inc keyword defines what happens if dt is an occurrence.
|
|
4602
|
+
* With inc == True, if dt itself is an occurrence, it will be returned.
|
|
4603
|
+
*
|
|
4604
|
+
* @return Date or null
|
|
4605
|
+
*/
|
|
4606
|
+
RRule.prototype.before = function(dt, inc) {
|
|
4607
|
+
if (inc === void 0) inc = false;
|
|
4608
|
+
if (!isValidDate(dt)) throw new Error("Invalid date passed in to RRule.before");
|
|
4609
|
+
var args = {
|
|
4610
|
+
dt,
|
|
4611
|
+
inc
|
|
4612
|
+
};
|
|
4613
|
+
var result = this._cacheGet("before", args);
|
|
4614
|
+
if (result === false) {
|
|
4615
|
+
result = this._iter(new iterresult("before", args));
|
|
4616
|
+
this._cacheAdd("before", result, args);
|
|
4617
|
+
}
|
|
4618
|
+
return result;
|
|
4619
|
+
};
|
|
4620
|
+
/**
|
|
4621
|
+
* Returns the first recurrence after the given datetime instance.
|
|
4622
|
+
* The inc keyword defines what happens if dt is an occurrence.
|
|
4623
|
+
* With inc == True, if dt itself is an occurrence, it will be returned.
|
|
4624
|
+
*
|
|
4625
|
+
* @return Date or null
|
|
4626
|
+
*/
|
|
4627
|
+
RRule.prototype.after = function(dt, inc) {
|
|
4628
|
+
if (inc === void 0) inc = false;
|
|
4629
|
+
if (!isValidDate(dt)) throw new Error("Invalid date passed in to RRule.after");
|
|
4630
|
+
var args = {
|
|
4631
|
+
dt,
|
|
4632
|
+
inc
|
|
4633
|
+
};
|
|
4634
|
+
var result = this._cacheGet("after", args);
|
|
4635
|
+
if (result === false) {
|
|
4636
|
+
result = this._iter(new iterresult("after", args));
|
|
4637
|
+
this._cacheAdd("after", result, args);
|
|
4638
|
+
}
|
|
4639
|
+
return result;
|
|
4640
|
+
};
|
|
4641
|
+
/**
|
|
4642
|
+
* Returns the number of recurrences in this set. It will have go trough
|
|
4643
|
+
* the whole recurrence, if this hasn't been done before.
|
|
4644
|
+
*/
|
|
4645
|
+
RRule.prototype.count = function() {
|
|
4646
|
+
return this.all().length;
|
|
4647
|
+
};
|
|
4648
|
+
/**
|
|
4649
|
+
* Converts the rrule into its string representation
|
|
4650
|
+
*
|
|
4651
|
+
* @see <http://www.ietf.org/rfc/rfc2445.txt>
|
|
4652
|
+
* @return String
|
|
4653
|
+
*/
|
|
4654
|
+
RRule.prototype.toString = function() {
|
|
4655
|
+
return optionsToString(this.origOptions);
|
|
4656
|
+
};
|
|
4657
|
+
/**
|
|
4658
|
+
* Will convert all rules described in nlp:ToText
|
|
4659
|
+
* to text.
|
|
4660
|
+
*/
|
|
4661
|
+
RRule.prototype.toText = function(gettext, language, dateFormatter) {
|
|
4662
|
+
return toText(this, gettext, language, dateFormatter);
|
|
4663
|
+
};
|
|
4664
|
+
RRule.prototype.isFullyConvertibleToText = function() {
|
|
4665
|
+
return isFullyConvertible(this);
|
|
4666
|
+
};
|
|
4667
|
+
/**
|
|
4668
|
+
* @return a RRule instance with the same freq and options
|
|
4669
|
+
* as this one (cache is not cloned)
|
|
4670
|
+
*/
|
|
4671
|
+
RRule.prototype.clone = function() {
|
|
4672
|
+
return new RRule(this.origOptions);
|
|
4673
|
+
};
|
|
4674
|
+
RRule.FREQUENCIES = [
|
|
4675
|
+
"YEARLY",
|
|
4676
|
+
"MONTHLY",
|
|
4677
|
+
"WEEKLY",
|
|
4678
|
+
"DAILY",
|
|
4679
|
+
"HOURLY",
|
|
4680
|
+
"MINUTELY",
|
|
4681
|
+
"SECONDLY"
|
|
4682
|
+
];
|
|
4683
|
+
RRule.YEARLY = Frequency.YEARLY;
|
|
4684
|
+
RRule.MONTHLY = Frequency.MONTHLY;
|
|
4685
|
+
RRule.WEEKLY = Frequency.WEEKLY;
|
|
4686
|
+
RRule.DAILY = Frequency.DAILY;
|
|
4687
|
+
RRule.HOURLY = Frequency.HOURLY;
|
|
4688
|
+
RRule.MINUTELY = Frequency.MINUTELY;
|
|
4689
|
+
RRule.SECONDLY = Frequency.SECONDLY;
|
|
4690
|
+
RRule.MO = Days.MO;
|
|
4691
|
+
RRule.TU = Days.TU;
|
|
4692
|
+
RRule.WE = Days.WE;
|
|
4693
|
+
RRule.TH = Days.TH;
|
|
4694
|
+
RRule.FR = Days.FR;
|
|
4695
|
+
RRule.SA = Days.SA;
|
|
4696
|
+
RRule.SU = Days.SU;
|
|
4697
|
+
RRule.parseString = parseString;
|
|
4698
|
+
RRule.optionsToString = optionsToString;
|
|
4699
|
+
return RRule;
|
|
4700
|
+
}();
|
|
4701
|
+
function iterSet(iterResult, _rrule, _exrule, _rdate, _exdate, tzid) {
|
|
4702
|
+
var _exdateHash = {};
|
|
4703
|
+
var _accept = iterResult.accept;
|
|
4704
|
+
function evalExdate(after, before) {
|
|
4705
|
+
_exrule.forEach(function(rrule) {
|
|
4706
|
+
rrule.between(after, before, true).forEach(function(date) {
|
|
4707
|
+
_exdateHash[Number(date)] = true;
|
|
4708
|
+
});
|
|
4709
|
+
});
|
|
4710
|
+
}
|
|
4711
|
+
_exdate.forEach(function(date) {
|
|
4712
|
+
var zonedDate = new DateWithZone(date, tzid).rezonedDate();
|
|
4713
|
+
_exdateHash[Number(zonedDate)] = true;
|
|
4714
|
+
});
|
|
4715
|
+
iterResult.accept = function(date) {
|
|
4716
|
+
var dt = Number(date);
|
|
4717
|
+
if (isNaN(dt)) return _accept.call(this, date);
|
|
4718
|
+
if (!_exdateHash[dt]) {
|
|
4719
|
+
evalExdate(/* @__PURE__ */ new Date(dt - 1), new Date(dt + 1));
|
|
4720
|
+
if (!_exdateHash[dt]) {
|
|
4721
|
+
_exdateHash[dt] = true;
|
|
4722
|
+
return _accept.call(this, date);
|
|
4723
|
+
}
|
|
4724
|
+
}
|
|
4725
|
+
return true;
|
|
4726
|
+
};
|
|
4727
|
+
if (iterResult.method === "between") {
|
|
4728
|
+
evalExdate(iterResult.args.after, iterResult.args.before);
|
|
4729
|
+
iterResult.accept = function(date) {
|
|
4730
|
+
var dt = Number(date);
|
|
4731
|
+
if (!_exdateHash[dt]) {
|
|
4732
|
+
_exdateHash[dt] = true;
|
|
4733
|
+
return _accept.call(this, date);
|
|
4734
|
+
}
|
|
4735
|
+
return true;
|
|
4736
|
+
};
|
|
4737
|
+
}
|
|
4738
|
+
for (var i = 0; i < _rdate.length; i++) {
|
|
4739
|
+
var zonedDate = new DateWithZone(_rdate[i], tzid).rezonedDate();
|
|
4740
|
+
if (!iterResult.accept(new Date(zonedDate.getTime()))) break;
|
|
4741
|
+
}
|
|
4742
|
+
_rrule.forEach(function(rrule) {
|
|
4743
|
+
iter(iterResult, rrule.options);
|
|
4744
|
+
});
|
|
4745
|
+
var res = iterResult._result;
|
|
4746
|
+
sort(res);
|
|
4747
|
+
switch (iterResult.method) {
|
|
4748
|
+
case "all":
|
|
4749
|
+
case "between": return res;
|
|
4750
|
+
case "before": return res.length && res[res.length - 1] || null;
|
|
4751
|
+
default: return res.length && res[0] || null;
|
|
4752
|
+
}
|
|
4753
|
+
}
|
|
4754
|
+
/**
|
|
4755
|
+
* RRuleStr
|
|
4756
|
+
* To parse a set of rrule strings
|
|
4757
|
+
*/
|
|
4758
|
+
var rrulestr_DEFAULT_OPTIONS = {
|
|
4759
|
+
dtstart: null,
|
|
4760
|
+
cache: false,
|
|
4761
|
+
unfold: false,
|
|
4762
|
+
forceset: false,
|
|
4763
|
+
compatible: false,
|
|
4764
|
+
tzid: null
|
|
4765
|
+
};
|
|
4766
|
+
function parseInput(s, options) {
|
|
4767
|
+
var rrulevals = [];
|
|
4768
|
+
var rdatevals = [];
|
|
4769
|
+
var exrulevals = [];
|
|
4770
|
+
var exdatevals = [];
|
|
4771
|
+
var parsedDtstart = parseDtstart(s);
|
|
4772
|
+
var dtstart = parsedDtstart.dtstart;
|
|
4773
|
+
var tzid = parsedDtstart.tzid;
|
|
4774
|
+
splitIntoLines(s, options.unfold).forEach(function(line) {
|
|
4775
|
+
var _a;
|
|
4776
|
+
if (!line) return;
|
|
4777
|
+
var _b = breakDownLine(line), name = _b.name, parms = _b.parms, value = _b.value;
|
|
4778
|
+
switch (name.toUpperCase()) {
|
|
4779
|
+
case "RRULE":
|
|
4780
|
+
if (parms.length) throw new Error("unsupported RRULE parm: ".concat(parms.join(",")));
|
|
4781
|
+
rrulevals.push(parseString(line));
|
|
4782
|
+
break;
|
|
4783
|
+
case "RDATE":
|
|
4784
|
+
var rdateTzid = ((_a = /RDATE(?:;TZID=([^:=]+))?/i.exec(line)) !== null && _a !== void 0 ? _a : [])[1];
|
|
4785
|
+
if (rdateTzid && !tzid) tzid = rdateTzid;
|
|
4786
|
+
rdatevals = rdatevals.concat(parseRDate(value, parms));
|
|
4787
|
+
break;
|
|
4788
|
+
case "EXRULE":
|
|
4789
|
+
if (parms.length) throw new Error("unsupported EXRULE parm: ".concat(parms.join(",")));
|
|
4790
|
+
exrulevals.push(parseString(value));
|
|
4791
|
+
break;
|
|
4792
|
+
case "EXDATE":
|
|
4793
|
+
exdatevals = exdatevals.concat(parseRDate(value, parms));
|
|
4794
|
+
break;
|
|
4795
|
+
case "DTSTART": break;
|
|
4796
|
+
default: throw new Error("unsupported property: " + name);
|
|
4797
|
+
}
|
|
4798
|
+
});
|
|
4799
|
+
return {
|
|
4800
|
+
dtstart,
|
|
4801
|
+
tzid,
|
|
4802
|
+
rrulevals,
|
|
4803
|
+
rdatevals,
|
|
4804
|
+
exrulevals,
|
|
4805
|
+
exdatevals
|
|
4806
|
+
};
|
|
4807
|
+
}
|
|
4808
|
+
function buildRule(s, options) {
|
|
4809
|
+
var _a = parseInput(s, options), rrulevals = _a.rrulevals, rdatevals = _a.rdatevals, exrulevals = _a.exrulevals, exdatevals = _a.exdatevals, dtstart = _a.dtstart, tzid = _a.tzid;
|
|
4810
|
+
var noCache = options.cache === false;
|
|
4811
|
+
if (options.compatible) {
|
|
4812
|
+
options.forceset = true;
|
|
4813
|
+
options.unfold = true;
|
|
4814
|
+
}
|
|
4815
|
+
if (options.forceset || rrulevals.length > 1 || rdatevals.length || exrulevals.length || exdatevals.length) {
|
|
4816
|
+
var rset_1 = new RRuleSet(noCache);
|
|
4817
|
+
rset_1.dtstart(dtstart);
|
|
4818
|
+
rset_1.tzid(tzid || void 0);
|
|
4819
|
+
rrulevals.forEach(function(val) {
|
|
4820
|
+
rset_1.rrule(new RRule(groomRruleOptions(val, dtstart, tzid), noCache));
|
|
4821
|
+
});
|
|
4822
|
+
rdatevals.forEach(function(date) {
|
|
4823
|
+
rset_1.rdate(date);
|
|
4824
|
+
});
|
|
4825
|
+
exrulevals.forEach(function(val) {
|
|
4826
|
+
rset_1.exrule(new RRule(groomRruleOptions(val, dtstart, tzid), noCache));
|
|
4827
|
+
});
|
|
4828
|
+
exdatevals.forEach(function(date) {
|
|
4829
|
+
rset_1.exdate(date);
|
|
4830
|
+
});
|
|
4831
|
+
if (options.compatible && options.dtstart) rset_1.rdate(dtstart);
|
|
4832
|
+
return rset_1;
|
|
4833
|
+
}
|
|
4834
|
+
var val = rrulevals[0] || {};
|
|
4835
|
+
return new RRule(groomRruleOptions(val, val.dtstart || options.dtstart || dtstart, val.tzid || options.tzid || tzid), noCache);
|
|
4836
|
+
}
|
|
4837
|
+
function rrulestr(s, options) {
|
|
4838
|
+
if (options === void 0) options = {};
|
|
4839
|
+
return buildRule(s, rrulestr_initializeOptions(options));
|
|
4840
|
+
}
|
|
4841
|
+
function groomRruleOptions(val, dtstart, tzid) {
|
|
4842
|
+
return __assign(__assign({}, val), {
|
|
4843
|
+
dtstart,
|
|
4844
|
+
tzid
|
|
4845
|
+
});
|
|
4846
|
+
}
|
|
4847
|
+
function rrulestr_initializeOptions(options) {
|
|
4848
|
+
var invalid = [];
|
|
4849
|
+
var keys = Object.keys(options);
|
|
4850
|
+
var defaultKeys = Object.keys(rrulestr_DEFAULT_OPTIONS);
|
|
4851
|
+
keys.forEach(function(key) {
|
|
4852
|
+
if (!includes(defaultKeys, key)) invalid.push(key);
|
|
4853
|
+
});
|
|
4854
|
+
if (invalid.length) throw new Error("Invalid options: " + invalid.join(", "));
|
|
4855
|
+
return __assign(__assign({}, rrulestr_DEFAULT_OPTIONS), options);
|
|
4856
|
+
}
|
|
4857
|
+
function extractName(line) {
|
|
4858
|
+
if (line.indexOf(":") === -1) return {
|
|
4859
|
+
name: "RRULE",
|
|
4860
|
+
value: line
|
|
4861
|
+
};
|
|
4862
|
+
var _a = split(line, ":", 1);
|
|
4863
|
+
return {
|
|
4864
|
+
name: _a[0],
|
|
4865
|
+
value: _a[1]
|
|
4866
|
+
};
|
|
4867
|
+
}
|
|
4868
|
+
function breakDownLine(line) {
|
|
4869
|
+
var _a = extractName(line), name = _a.name, value = _a.value;
|
|
4870
|
+
var parms = name.split(";");
|
|
4871
|
+
if (!parms) throw new Error("empty property name");
|
|
4872
|
+
return {
|
|
4873
|
+
name: parms[0].toUpperCase(),
|
|
4874
|
+
parms: parms.slice(1),
|
|
4875
|
+
value
|
|
4876
|
+
};
|
|
4877
|
+
}
|
|
4878
|
+
function splitIntoLines(s, unfold) {
|
|
4879
|
+
if (unfold === void 0) unfold = false;
|
|
4880
|
+
s = s && s.trim();
|
|
4881
|
+
if (!s) throw new Error("Invalid empty string");
|
|
4882
|
+
if (!unfold) return s.split(/\s/);
|
|
4883
|
+
var lines = s.split("\n");
|
|
4884
|
+
var i = 0;
|
|
4885
|
+
while (i < lines.length) {
|
|
4886
|
+
var line = lines[i] = lines[i].replace(/\s+$/g, "");
|
|
4887
|
+
if (!line) lines.splice(i, 1);
|
|
4888
|
+
else if (i > 0 && line[0] === " ") {
|
|
4889
|
+
lines[i - 1] += line.slice(1);
|
|
4890
|
+
lines.splice(i, 1);
|
|
4891
|
+
} else i += 1;
|
|
4892
|
+
}
|
|
4893
|
+
return lines;
|
|
4894
|
+
}
|
|
4895
|
+
function validateDateParm(parms) {
|
|
4896
|
+
parms.forEach(function(parm) {
|
|
4897
|
+
if (!/(VALUE=DATE(-TIME)?)|(TZID=)/.test(parm)) throw new Error("unsupported RDATE/EXDATE parm: " + parm);
|
|
4898
|
+
});
|
|
4899
|
+
}
|
|
4900
|
+
function parseRDate(rdateval, parms) {
|
|
4901
|
+
validateDateParm(parms);
|
|
4902
|
+
return rdateval.split(",").map(function(datestr) {
|
|
4903
|
+
return untilStringToDate(datestr);
|
|
4904
|
+
});
|
|
4905
|
+
}
|
|
4906
|
+
function createGetterSetter(fieldName) {
|
|
4907
|
+
var _this = this;
|
|
4908
|
+
return function(field) {
|
|
4909
|
+
if (field !== void 0) _this["_".concat(fieldName)] = field;
|
|
4910
|
+
if (_this["_".concat(fieldName)] !== void 0) return _this["_".concat(fieldName)];
|
|
4911
|
+
for (var i = 0; i < _this._rrule.length; i++) {
|
|
4912
|
+
var field_1 = _this._rrule[i].origOptions[fieldName];
|
|
4913
|
+
if (field_1) return field_1;
|
|
4914
|
+
}
|
|
4915
|
+
};
|
|
4916
|
+
}
|
|
4917
|
+
var RRuleSet = function(_super) {
|
|
4918
|
+
__extends(RRuleSet, _super);
|
|
4919
|
+
/**
|
|
4920
|
+
*
|
|
4921
|
+
* @param {Boolean?} noCache
|
|
4922
|
+
* The same stratagy as RRule on cache, default to false
|
|
4923
|
+
* @constructor
|
|
4924
|
+
*/
|
|
4925
|
+
function RRuleSet(noCache) {
|
|
4926
|
+
if (noCache === void 0) noCache = false;
|
|
4927
|
+
var _this = _super.call(this, {}, noCache) || this;
|
|
4928
|
+
_this.dtstart = createGetterSetter.apply(_this, ["dtstart"]);
|
|
4929
|
+
_this.tzid = createGetterSetter.apply(_this, ["tzid"]);
|
|
4930
|
+
_this._rrule = [];
|
|
4931
|
+
_this._rdate = [];
|
|
4932
|
+
_this._exrule = [];
|
|
4933
|
+
_this._exdate = [];
|
|
4934
|
+
return _this;
|
|
4935
|
+
}
|
|
4936
|
+
RRuleSet.prototype._iter = function(iterResult) {
|
|
4937
|
+
return iterSet(iterResult, this._rrule, this._exrule, this._rdate, this._exdate, this.tzid());
|
|
4938
|
+
};
|
|
4939
|
+
/**
|
|
4940
|
+
* Adds an RRule to the set
|
|
4941
|
+
*
|
|
4942
|
+
* @param {RRule}
|
|
4943
|
+
*/
|
|
4944
|
+
RRuleSet.prototype.rrule = function(rrule) {
|
|
4945
|
+
_addRule(rrule, this._rrule);
|
|
4946
|
+
};
|
|
4947
|
+
/**
|
|
4948
|
+
* Adds an EXRULE to the set
|
|
4949
|
+
*
|
|
4950
|
+
* @param {RRule}
|
|
4951
|
+
*/
|
|
4952
|
+
RRuleSet.prototype.exrule = function(rrule) {
|
|
4953
|
+
_addRule(rrule, this._exrule);
|
|
4954
|
+
};
|
|
4955
|
+
/**
|
|
4956
|
+
* Adds an RDate to the set
|
|
4957
|
+
*
|
|
4958
|
+
* @param {Date}
|
|
4959
|
+
*/
|
|
4960
|
+
RRuleSet.prototype.rdate = function(date) {
|
|
4961
|
+
_addDate(date, this._rdate);
|
|
4962
|
+
};
|
|
4963
|
+
/**
|
|
4964
|
+
* Adds an EXDATE to the set
|
|
4965
|
+
*
|
|
4966
|
+
* @param {Date}
|
|
4967
|
+
*/
|
|
4968
|
+
RRuleSet.prototype.exdate = function(date) {
|
|
4969
|
+
_addDate(date, this._exdate);
|
|
4970
|
+
};
|
|
4971
|
+
/**
|
|
4972
|
+
* Get list of included rrules in this recurrence set.
|
|
4973
|
+
*
|
|
4974
|
+
* @return List of rrules
|
|
4975
|
+
*/
|
|
4976
|
+
RRuleSet.prototype.rrules = function() {
|
|
4977
|
+
return this._rrule.map(function(e) {
|
|
4978
|
+
return rrulestr(e.toString());
|
|
4979
|
+
});
|
|
4980
|
+
};
|
|
4981
|
+
/**
|
|
4982
|
+
* Get list of excluded rrules in this recurrence set.
|
|
4983
|
+
*
|
|
4984
|
+
* @return List of exrules
|
|
4985
|
+
*/
|
|
4986
|
+
RRuleSet.prototype.exrules = function() {
|
|
4987
|
+
return this._exrule.map(function(e) {
|
|
4988
|
+
return rrulestr(e.toString());
|
|
4989
|
+
});
|
|
4990
|
+
};
|
|
4991
|
+
/**
|
|
4992
|
+
* Get list of included datetimes in this recurrence set.
|
|
4993
|
+
*
|
|
4994
|
+
* @return List of rdates
|
|
4995
|
+
*/
|
|
4996
|
+
RRuleSet.prototype.rdates = function() {
|
|
4997
|
+
return this._rdate.map(function(e) {
|
|
4998
|
+
return new Date(e.getTime());
|
|
4999
|
+
});
|
|
5000
|
+
};
|
|
5001
|
+
/**
|
|
5002
|
+
* Get list of included datetimes in this recurrence set.
|
|
5003
|
+
*
|
|
5004
|
+
* @return List of exdates
|
|
5005
|
+
*/
|
|
5006
|
+
RRuleSet.prototype.exdates = function() {
|
|
5007
|
+
return this._exdate.map(function(e) {
|
|
5008
|
+
return new Date(e.getTime());
|
|
5009
|
+
});
|
|
5010
|
+
};
|
|
5011
|
+
RRuleSet.prototype.valueOf = function() {
|
|
5012
|
+
var result = [];
|
|
5013
|
+
if (!this._rrule.length && this._dtstart) result = result.concat(optionsToString({ dtstart: this._dtstart }));
|
|
5014
|
+
this._rrule.forEach(function(rrule) {
|
|
5015
|
+
result = result.concat(rrule.toString().split("\n"));
|
|
5016
|
+
});
|
|
5017
|
+
this._exrule.forEach(function(exrule) {
|
|
5018
|
+
result = result.concat(exrule.toString().split("\n").map(function(line) {
|
|
5019
|
+
return line.replace(/^RRULE:/, "EXRULE:");
|
|
5020
|
+
}).filter(function(line) {
|
|
5021
|
+
return !/^DTSTART/.test(line);
|
|
5022
|
+
}));
|
|
5023
|
+
});
|
|
5024
|
+
if (this._rdate.length) result.push(rdatesToString("RDATE", this._rdate, this.tzid()));
|
|
5025
|
+
if (this._exdate.length) result.push(rdatesToString("EXDATE", this._exdate, this.tzid()));
|
|
5026
|
+
return result;
|
|
5027
|
+
};
|
|
5028
|
+
/**
|
|
5029
|
+
* to generate recurrence field such as:
|
|
5030
|
+
* DTSTART:19970902T010000Z
|
|
5031
|
+
* RRULE:FREQ=YEARLY;COUNT=2;BYDAY=TU
|
|
5032
|
+
* RRULE:FREQ=YEARLY;COUNT=1;BYDAY=TH
|
|
5033
|
+
*/
|
|
5034
|
+
RRuleSet.prototype.toString = function() {
|
|
5035
|
+
return this.valueOf().join("\n");
|
|
5036
|
+
};
|
|
5037
|
+
/**
|
|
5038
|
+
* Create a new RRuleSet Object completely base on current instance
|
|
5039
|
+
*/
|
|
5040
|
+
RRuleSet.prototype.clone = function() {
|
|
5041
|
+
var rrs = new RRuleSet(!!this._cache);
|
|
5042
|
+
this._rrule.forEach(function(rule) {
|
|
5043
|
+
return rrs.rrule(rule.clone());
|
|
5044
|
+
});
|
|
5045
|
+
this._exrule.forEach(function(rule) {
|
|
5046
|
+
return rrs.exrule(rule.clone());
|
|
5047
|
+
});
|
|
5048
|
+
this._rdate.forEach(function(date) {
|
|
5049
|
+
return rrs.rdate(new Date(date.getTime()));
|
|
5050
|
+
});
|
|
5051
|
+
this._exdate.forEach(function(date) {
|
|
5052
|
+
return rrs.exdate(new Date(date.getTime()));
|
|
5053
|
+
});
|
|
5054
|
+
return rrs;
|
|
5055
|
+
};
|
|
5056
|
+
return RRuleSet;
|
|
5057
|
+
}(RRule);
|
|
5058
|
+
function _addRule(rrule, collection) {
|
|
5059
|
+
if (!(rrule instanceof RRule)) throw new TypeError(String(rrule) + " is not RRule instance");
|
|
5060
|
+
if (!includes(collection.map(String), String(rrule))) collection.push(rrule);
|
|
5061
|
+
}
|
|
5062
|
+
function _addDate(date, collection) {
|
|
5063
|
+
if (!(date instanceof Date)) throw new TypeError(String(date) + " is not Date instance");
|
|
5064
|
+
if (!includes(collection.map(Number), Number(date))) {
|
|
5065
|
+
collection.push(date);
|
|
5066
|
+
sort(collection);
|
|
5067
|
+
}
|
|
5068
|
+
}
|
|
5069
|
+
function rdatesToString(param, rdates, tzid) {
|
|
5070
|
+
var isUTC = !tzid || tzid.toUpperCase() === "UTC";
|
|
5071
|
+
var header = isUTC ? "".concat(param, ":") : "".concat(param, ";TZID=").concat(tzid, ":");
|
|
5072
|
+
var dateString = rdates.map(function(rdate) {
|
|
5073
|
+
return timeToUntilString(rdate.valueOf(), isUTC);
|
|
5074
|
+
}).join(",");
|
|
5075
|
+
return "".concat(header).concat(dateString);
|
|
5076
|
+
}
|
|
5077
|
+
return __webpack_exports__;
|
|
5078
|
+
})();
|
|
5079
|
+
});
|
|
5080
|
+
})))();
|
|
2236
5081
|
const PACKED_DATE_MULTIPLIER = 128;
|
|
2237
5082
|
const PACKED_DATE_DAY_MASK = 31;
|
|
2238
5083
|
const PACKED_DATE_MONTH_MASK = 15;
|
|
@@ -2256,9 +5101,9 @@ const decodeThingsPackedDateParts = (value) => {
|
|
|
2256
5101
|
if (integer <= 0 || integer % PACKED_DATE_MULTIPLIER !== 0) return null;
|
|
2257
5102
|
const packed = integer / PACKED_DATE_MULTIPLIER;
|
|
2258
5103
|
const parts = {
|
|
2259
|
-
day: packed
|
|
2260
|
-
month: packed
|
|
2261
|
-
year: packed
|
|
5104
|
+
day: packed % (PACKED_DATE_DAY_MASK + 1),
|
|
5105
|
+
month: Math.trunc(packed / 2 ** PACKED_DATE_MONTH_SHIFT) % (PACKED_DATE_MONTH_MASK + 1),
|
|
5106
|
+
year: Math.trunc(packed / 2 ** PACKED_DATE_YEAR_SHIFT)
|
|
2262
5107
|
};
|
|
2263
5108
|
return isValidPackedDate(parts) ? parts : null;
|
|
2264
5109
|
};
|
|
@@ -2380,19 +5225,18 @@ const THINGS_WEEKDAY_TO_RRULE = [
|
|
|
2380
5225
|
"FR",
|
|
2381
5226
|
"SA"
|
|
2382
5227
|
];
|
|
2383
|
-
const { RRule, rrulestr } = rrule;
|
|
2384
5228
|
const parseNumericPlistField = (xml, key) => {
|
|
2385
|
-
const match = new RegExp(`<key>${key}</key>\\s*<(integer|real)>([^<]+)</\\1
|
|
5229
|
+
const match = new RegExp(`<key>${key}</key>\\s*<(integer|real)>([^<]+)</\\1>`, "u").exec(xml);
|
|
2386
5230
|
if (!match?.[2]) return null;
|
|
2387
5231
|
const parsed = Number(match[2]);
|
|
2388
5232
|
return Number.isFinite(parsed) ? parsed : null;
|
|
2389
5233
|
};
|
|
2390
|
-
const PLIST_OFFSETS_ARRAY_PATTERN = /<key>of<\/key>\s*<array>([\s\S]*?)<\/array
|
|
5234
|
+
const PLIST_OFFSETS_ARRAY_PATTERN = /<key>of<\/key>\s*<array>([\s\S]*?)<\/array>/u;
|
|
2391
5235
|
const parseOffsets = (xml) => {
|
|
2392
5236
|
const arrayMatch = PLIST_OFFSETS_ARRAY_PATTERN.exec(xml);
|
|
2393
5237
|
if (!arrayMatch?.[1]) return [];
|
|
2394
5238
|
const offsets = [];
|
|
2395
|
-
for (const dictMatch of arrayMatch[1].matchAll(/<dict>([\s\S]*?)<\/dict>/
|
|
5239
|
+
for (const dictMatch of arrayMatch[1].matchAll(/<dict>([\s\S]*?)<\/dict>/gu)) {
|
|
2396
5240
|
const [, fragment] = dictMatch;
|
|
2397
5241
|
if (!fragment) continue;
|
|
2398
5242
|
const weekday = parseNumericPlistField(fragment, "wd");
|
|
@@ -2406,8 +5250,8 @@ const parseOffsets = (xml) => {
|
|
|
2406
5250
|
};
|
|
2407
5251
|
const parseRRule = (rule) => {
|
|
2408
5252
|
try {
|
|
2409
|
-
const parsed = rrulestr(rule);
|
|
2410
|
-
return parsed instanceof RRule ? parsed : null;
|
|
5253
|
+
const parsed = (0, import_rrule.rrulestr)(rule);
|
|
5254
|
+
return parsed instanceof import_rrule.RRule ? parsed : null;
|
|
2411
5255
|
} catch {
|
|
2412
5256
|
return null;
|
|
2413
5257
|
}
|
|
@@ -2520,11 +5364,11 @@ const normalizeTitle = (value, fallback) => {
|
|
|
2520
5364
|
const trimmed = value?.trim();
|
|
2521
5365
|
return trimmed && trimmed.length > 0 ? trimmed : fallback;
|
|
2522
5366
|
};
|
|
2523
|
-
const NON_ALPHANUMERIC_PATTERN = /[^A-Z0-9]+/
|
|
2524
|
-
const WHITESPACE_SPLIT_PATTERN = /\s
|
|
2525
|
-
const NON_ALPHANUMERIC_STRICT_PATTERN = /[^A-Z0-9]/
|
|
5367
|
+
const NON_ALPHANUMERIC_PATTERN = /[^A-Z0-9]+/gu;
|
|
5368
|
+
const WHITESPACE_SPLIT_PATTERN = /\s+/u;
|
|
5369
|
+
const NON_ALPHANUMERIC_STRICT_PATTERN = /[^A-Z0-9]/gu;
|
|
2526
5370
|
const READABLE_TEXT_PATTERN = /^[\t\n\r\u0020-\u007E\u00A0-\uFFFF]*$/u;
|
|
2527
|
-
const EMAIL_SPLIT_PATTERN = /[,\n;]
|
|
5371
|
+
const EMAIL_SPLIT_PATTERN = /[,\n;]/u;
|
|
2528
5372
|
const normalizeKeyBase = (value, fallback) => {
|
|
2529
5373
|
const initials = value.toUpperCase().replace(NON_ALPHANUMERIC_PATTERN, " ").trim().split(WHITESPACE_SPLIT_PATTERN).filter((word) => word.length > 0).map((word) => word[0] ?? "").join("");
|
|
2530
5374
|
const compact = value.toUpperCase().replace(NON_ALPHANUMERIC_STRICT_PATTERN, "");
|
|
@@ -2542,7 +5386,7 @@ const buildUniqueKeys = (items, options) => {
|
|
|
2542
5386
|
const base = normalizeKeyBase(normalizeTitle(item.title, options.fallback), options.fallback).slice(0, options.maxLength);
|
|
2543
5387
|
let candidate = base || options.fallback;
|
|
2544
5388
|
if (used.has(candidate)) {
|
|
2545
|
-
const suffixBase = item.uuid.replaceAll(/[^a-zA-Z0-9]/
|
|
5389
|
+
const suffixBase = item.uuid.replaceAll(/[^a-zA-Z0-9]/gu, "").slice(-4);
|
|
2546
5390
|
const suffix = suffixBase.length > 0 ? suffixBase.toUpperCase() : "X";
|
|
2547
5391
|
const headLength = Math.max(1, options.maxLength - suffix.length - 1);
|
|
2548
5392
|
candidate = `${candidate.slice(0, headLength)}-${suffix}`;
|
|
@@ -2614,7 +5458,7 @@ const pickCompletedAt = (task) => {
|
|
|
2614
5458
|
};
|
|
2615
5459
|
const sortValue = (primary, fallback) => typeof primary === "number" ? primary : fallback;
|
|
2616
5460
|
const sanitizeBuffer = (buffer) => {
|
|
2617
|
-
const asText = buffer.toString("
|
|
5461
|
+
const asText = buffer.toString("utf-8");
|
|
2618
5462
|
if (!asText.includes("�") && READABLE_TEXT_PATTERN.test(asText)) {
|
|
2619
5463
|
const trimmed = asText.trim();
|
|
2620
5464
|
if (trimmed.length > 0) return trimmed;
|
|
@@ -2993,8 +5837,6 @@ const pushTaskMutation = (ctx, tasks, taskLabels, checklistItems, mutationOption
|
|
|
2993
5837
|
creatorId: ctx.creatorId,
|
|
2994
5838
|
deadlineAt: decodeThingsPackedDate(mutationOptions.task.deadline),
|
|
2995
5839
|
deadlineSuppressionAt: decodeThingsPackedDate(mutationOptions.task.deadlineSuppressionDate),
|
|
2996
|
-
delegateId: null,
|
|
2997
|
-
delegatedAt: null,
|
|
2998
5840
|
description: appendMetadataBlock(mutationOptions.task.notes, ctx.metadataMode, buildTaskMetadata(mutationOptions.task, contact, buildChecklistOverflowMetadata(mutationOptions.task, ctx.checklistByTaskId))),
|
|
2999
5841
|
headingId: mutationOptions.task.headingId === null ? null : ctx.headingIdBySourceId.get(mutationOptions.task.headingId) ?? null,
|
|
3000
5842
|
lastReminderInteractionAt: decodeThingsUnixSeconds(mutationOptions.task.lastReminderInteractionDate),
|
|
@@ -3230,7 +6072,7 @@ const THINGS_CONTAINER_PATH = join(homedir(), "Library/Group Containers/JLMPQHK8
|
|
|
3230
6072
|
const THINGS_BUNDLE_NAME = "Things Database.thingsdatabase";
|
|
3231
6073
|
const THINGS_SQLITE_FILE = "main.sqlite";
|
|
3232
6074
|
const LEGACY_THINGS_SQLITE_FILE = "Things.sqlite3";
|
|
3233
|
-
const URL_SCHEME_PATTERN = /^[a-z][a-z0-9+.-]*:/
|
|
6075
|
+
const URL_SCHEME_PATTERN = /^[a-z][a-z0-9+.-]*:/iu;
|
|
3234
6076
|
const isUrlLike = (value) => URL_SCHEME_PATTERN.test(value);
|
|
3235
6077
|
const resolveInputPath = (databaseUrl) => {
|
|
3236
6078
|
if (!isUrlLike(databaseUrl)) return resolve(databaseUrl);
|
|
@@ -3293,7 +6135,7 @@ const toStringValue = (value) => {
|
|
|
3293
6135
|
return trimmed.length > 0 ? trimmed : null;
|
|
3294
6136
|
}
|
|
3295
6137
|
if (Buffer.isBuffer(value)) {
|
|
3296
|
-
const text = value.toString("
|
|
6138
|
+
const text = value.toString("utf-8").trim();
|
|
3297
6139
|
return text.length > 0 ? text : null;
|
|
3298
6140
|
}
|
|
3299
6141
|
return null;
|
|
@@ -3639,7 +6481,7 @@ const parseMetadataMode = (value) => {
|
|
|
3639
6481
|
};
|
|
3640
6482
|
const runThingsImportCommand = async (context, options, workspaceOverride) => {
|
|
3641
6483
|
const commandContext = await resolveCommandContext(context);
|
|
3642
|
-
const creatorId = requireUserId(commandContext
|
|
6484
|
+
const creatorId = await requireUserId(context, commandContext);
|
|
3643
6485
|
const metadataMode = parseMetadataMode(options.metadataMode);
|
|
3644
6486
|
const { workspace, autoSelected } = await resolveWorkspace(context, {
|
|
3645
6487
|
apiBaseUrl: commandContext.apiBaseUrl,
|
|
@@ -3695,7 +6537,7 @@ const isHistoryFile = (value) => {
|
|
|
3695
6537
|
};
|
|
3696
6538
|
const loadHistory = async (historyFile) => {
|
|
3697
6539
|
try {
|
|
3698
|
-
const raw = await readFile(historyFile, "
|
|
6540
|
+
const raw = await readFile(historyFile, "utf-8");
|
|
3699
6541
|
const parsed = JSON.parse(raw);
|
|
3700
6542
|
if (isHistoryFile(parsed)) return parsed.entries;
|
|
3701
6543
|
return [];
|
|
@@ -3770,7 +6612,7 @@ const runInteractiveMode = async (context, program) => {
|
|
|
3770
6612
|
recursive: true
|
|
3771
6613
|
});
|
|
3772
6614
|
await writeFile(HISTORY_FILE, `${JSON.stringify(payload, null, 2)}\n`, {
|
|
3773
|
-
encoding: "
|
|
6615
|
+
encoding: "utf-8",
|
|
3774
6616
|
mode: 384
|
|
3775
6617
|
});
|
|
3776
6618
|
} catch {}
|
|
@@ -3867,12 +6709,173 @@ const runLabelShow = async (context, labelRef, options) => {
|
|
|
3867
6709
|
writeInfo(context, `createdAt: ${formatEpochDate(label.createdAt) ?? "(none)"}`);
|
|
3868
6710
|
writeInfo(context, `updatedAt: ${formatEpochDate(label.updatedAt) ?? "(none)"}`);
|
|
3869
6711
|
};
|
|
6712
|
+
const UUID_REGEX$1 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu;
|
|
6713
|
+
const resolveTaskForLabel = async (context, options) => {
|
|
6714
|
+
const taskRef = options.taskRef.trim();
|
|
6715
|
+
if (!taskRef) throw new Error("Task id is required.");
|
|
6716
|
+
const exact = await loadTaskById(context, {
|
|
6717
|
+
baseUrl: options.commandContext.apiBaseUrl,
|
|
6718
|
+
taskId: taskRef,
|
|
6719
|
+
token: options.commandContext.token
|
|
6720
|
+
});
|
|
6721
|
+
if (exact) return exact;
|
|
6722
|
+
if (UUID_REGEX$1.test(taskRef)) throw new Error(`Task "${taskRef}" not found.`);
|
|
6723
|
+
if (taskRef.length < 4) throw new Error("Task id prefix must be at least 4 characters.");
|
|
6724
|
+
const { workspace } = await resolveWorkspace(context, {
|
|
6725
|
+
apiBaseUrl: options.commandContext.apiBaseUrl,
|
|
6726
|
+
storedWorkspaceId: options.commandContext.localContext.workspaceId,
|
|
6727
|
+
token: options.commandContext.token,
|
|
6728
|
+
workspaceRef: options.workspaceRef
|
|
6729
|
+
});
|
|
6730
|
+
const matches = (await loadTasksByWorkspace(context, {
|
|
6731
|
+
baseUrl: options.commandContext.apiBaseUrl,
|
|
6732
|
+
token: options.commandContext.token,
|
|
6733
|
+
workspaceId: workspace.id
|
|
6734
|
+
})).filter((task) => task.id.startsWith(taskRef));
|
|
6735
|
+
if (matches.length === 0) throw new Error(`Task "${taskRef}" not found.`);
|
|
6736
|
+
if (matches.length === 1) {
|
|
6737
|
+
const [match] = matches;
|
|
6738
|
+
if (!match) throw new Error(`Task "${taskRef}" not found.`);
|
|
6739
|
+
return match;
|
|
6740
|
+
}
|
|
6741
|
+
throw new Error(`Task prefix "${taskRef}" is ambiguous (${matches.length} matches). Use the full id.`);
|
|
6742
|
+
};
|
|
6743
|
+
const runLabelCreate = async (context, title, options) => {
|
|
6744
|
+
const commandContext = await resolveCommandContext(context);
|
|
6745
|
+
const { workspace } = await resolveWorkspace(context, {
|
|
6746
|
+
apiBaseUrl: commandContext.apiBaseUrl,
|
|
6747
|
+
storedWorkspaceId: commandContext.localContext.workspaceId,
|
|
6748
|
+
token: commandContext.token,
|
|
6749
|
+
workspaceRef: normalizeWorkspaceRef(options.workspace)
|
|
6750
|
+
});
|
|
6751
|
+
const labelId = randomUUID();
|
|
6752
|
+
const now = Date.now();
|
|
6753
|
+
await mutateModel(context, {
|
|
6754
|
+
baseUrl: commandContext.apiBaseUrl,
|
|
6755
|
+
request: {
|
|
6756
|
+
batchId: randomUUID(),
|
|
6757
|
+
transactions: [{
|
|
6758
|
+
action: "INSERT",
|
|
6759
|
+
clientId: commandContext.localContext.clientId,
|
|
6760
|
+
clientTxId: randomUUID(),
|
|
6761
|
+
modelId: labelId,
|
|
6762
|
+
modelName: "Label",
|
|
6763
|
+
payload: {
|
|
6764
|
+
createdAt: now,
|
|
6765
|
+
key: labelId.replaceAll("-", "").slice(0, 8),
|
|
6766
|
+
title: title.trim(),
|
|
6767
|
+
updatedAt: now,
|
|
6768
|
+
workspaceId: workspace.id
|
|
6769
|
+
}
|
|
6770
|
+
}]
|
|
6771
|
+
},
|
|
6772
|
+
token: commandContext.token
|
|
6773
|
+
});
|
|
6774
|
+
if (context.json) {
|
|
6775
|
+
writeOutput(context, {
|
|
6776
|
+
created: true,
|
|
6777
|
+
id: labelId,
|
|
6778
|
+
title: title.trim()
|
|
6779
|
+
});
|
|
6780
|
+
return;
|
|
6781
|
+
}
|
|
6782
|
+
writeSuccess(context, `Created label: ${title.trim()}`);
|
|
6783
|
+
};
|
|
6784
|
+
const runLabelAdd = async (context, taskRef, labelRef, options) => {
|
|
6785
|
+
const commandContext = await resolveCommandContext(context);
|
|
6786
|
+
const workspaceRef = normalizeWorkspaceRef(options.workspace);
|
|
6787
|
+
const task = await resolveTaskForLabel(context, {
|
|
6788
|
+
commandContext,
|
|
6789
|
+
taskRef,
|
|
6790
|
+
workspaceRef
|
|
6791
|
+
});
|
|
6792
|
+
const label = await resolveLabel(context, {
|
|
6793
|
+
commandContext,
|
|
6794
|
+
labelRef,
|
|
6795
|
+
workspaceRef
|
|
6796
|
+
});
|
|
6797
|
+
await mutateModel(context, {
|
|
6798
|
+
baseUrl: commandContext.apiBaseUrl,
|
|
6799
|
+
request: {
|
|
6800
|
+
batchId: randomUUID(),
|
|
6801
|
+
transactions: [{
|
|
6802
|
+
action: "INSERT",
|
|
6803
|
+
clientId: commandContext.localContext.clientId,
|
|
6804
|
+
clientTxId: randomUUID(),
|
|
6805
|
+
modelId: `${task.id}:${label.id}`,
|
|
6806
|
+
modelName: "TaskLabel",
|
|
6807
|
+
payload: {
|
|
6808
|
+
createdAt: Date.now(),
|
|
6809
|
+
labelId: label.id,
|
|
6810
|
+
taskId: task.id,
|
|
6811
|
+
workspaceId: task.workspaceId
|
|
6812
|
+
}
|
|
6813
|
+
}]
|
|
6814
|
+
},
|
|
6815
|
+
token: commandContext.token
|
|
6816
|
+
});
|
|
6817
|
+
if (context.json) {
|
|
6818
|
+
writeOutput(context, {
|
|
6819
|
+
added: true,
|
|
6820
|
+
labelId: label.id,
|
|
6821
|
+
labelTitle: label.title,
|
|
6822
|
+
taskId: task.id
|
|
6823
|
+
});
|
|
6824
|
+
return;
|
|
6825
|
+
}
|
|
6826
|
+
writeSuccess(context, `Added label "${label.title}" to task "${task.title}"`);
|
|
6827
|
+
};
|
|
6828
|
+
const runLabelRemove = async (context, taskRef, labelRef, options) => {
|
|
6829
|
+
const commandContext = await resolveCommandContext(context);
|
|
6830
|
+
const workspaceRef = normalizeWorkspaceRef(options.workspace);
|
|
6831
|
+
const task = await resolveTaskForLabel(context, {
|
|
6832
|
+
commandContext,
|
|
6833
|
+
taskRef,
|
|
6834
|
+
workspaceRef
|
|
6835
|
+
});
|
|
6836
|
+
const label = await resolveLabel(context, {
|
|
6837
|
+
commandContext,
|
|
6838
|
+
labelRef,
|
|
6839
|
+
workspaceRef
|
|
6840
|
+
});
|
|
6841
|
+
await mutateModel(context, {
|
|
6842
|
+
baseUrl: commandContext.apiBaseUrl,
|
|
6843
|
+
request: {
|
|
6844
|
+
batchId: randomUUID(),
|
|
6845
|
+
transactions: [{
|
|
6846
|
+
action: "DELETE",
|
|
6847
|
+
clientId: commandContext.localContext.clientId,
|
|
6848
|
+
clientTxId: randomUUID(),
|
|
6849
|
+
modelId: `${task.id}:${label.id}`,
|
|
6850
|
+
modelName: "TaskLabel",
|
|
6851
|
+
payload: {
|
|
6852
|
+
labelId: label.id,
|
|
6853
|
+
taskId: task.id
|
|
6854
|
+
}
|
|
6855
|
+
}]
|
|
6856
|
+
},
|
|
6857
|
+
token: commandContext.token
|
|
6858
|
+
});
|
|
6859
|
+
if (context.json) {
|
|
6860
|
+
writeOutput(context, {
|
|
6861
|
+
labelId: label.id,
|
|
6862
|
+
labelTitle: label.title,
|
|
6863
|
+
removed: true,
|
|
6864
|
+
taskId: task.id
|
|
6865
|
+
});
|
|
6866
|
+
return;
|
|
6867
|
+
}
|
|
6868
|
+
writeSuccess(context, `Removed label "${label.title}" from task "${task.title}"`);
|
|
6869
|
+
};
|
|
3870
6870
|
const registerLabelCommands = (program, workspaceOverride) => {
|
|
3871
6871
|
const label = program.command("label").alias("labels").description("Manage labels").addHelpText("after", `
|
|
3872
6872
|
Examples:
|
|
3873
6873
|
donebear label
|
|
3874
6874
|
donebear label list --sort alpha
|
|
3875
6875
|
donebear label show bug
|
|
6876
|
+
donebear label create "urgent"
|
|
6877
|
+
donebear label add <task-id> <label>
|
|
6878
|
+
donebear label remove <task-id> <label>
|
|
3876
6879
|
`).action(async (_options, command) => {
|
|
3877
6880
|
const context = contextFromCommand(command);
|
|
3878
6881
|
await runWithErrorHandling(context, async () => {
|
|
@@ -3894,6 +6897,24 @@ Examples:
|
|
|
3894
6897
|
await runLabelShow(context, labelRef, { workspace: workspaceOverride ?? normalizeWorkspaceRef(options.workspace) ?? void 0 });
|
|
3895
6898
|
});
|
|
3896
6899
|
});
|
|
6900
|
+
label.command("create").description("Create a new label").argument("<title>", "Label title").option("-w, --workspace <workspace>", "Workspace id, slug, or exact name").action(async (title, options, command) => {
|
|
6901
|
+
const context = contextFromCommand(command);
|
|
6902
|
+
await runWithErrorHandling(context, async () => {
|
|
6903
|
+
await runLabelCreate(context, title, { workspace: workspaceOverride ?? normalizeWorkspaceRef(options.workspace) ?? void 0 });
|
|
6904
|
+
});
|
|
6905
|
+
});
|
|
6906
|
+
label.command("add").description("Add a label to a task").argument("<task-id>", "Task id or prefix").argument("<label>", "Label id, title, or id prefix").option("-w, --workspace <workspace>", "Workspace id, slug, or exact name").action(async (taskRef, labelRef, options, command) => {
|
|
6907
|
+
const context = contextFromCommand(command);
|
|
6908
|
+
await runWithErrorHandling(context, async () => {
|
|
6909
|
+
await runLabelAdd(context, taskRef, labelRef, { workspace: workspaceOverride ?? normalizeWorkspaceRef(options.workspace) ?? void 0 });
|
|
6910
|
+
});
|
|
6911
|
+
});
|
|
6912
|
+
label.command("remove").alias("rm").description("Remove a label from a task").argument("<task-id>", "Task id or prefix").argument("<label>", "Label id, title, or id prefix").option("-w, --workspace <workspace>", "Workspace id, slug, or exact name").action(async (taskRef, labelRef, options, command) => {
|
|
6913
|
+
const context = contextFromCommand(command);
|
|
6914
|
+
await runWithErrorHandling(context, async () => {
|
|
6915
|
+
await runLabelRemove(context, taskRef, labelRef, { workspace: workspaceOverride ?? normalizeWorkspaceRef(options.workspace) ?? void 0 });
|
|
6916
|
+
});
|
|
6917
|
+
});
|
|
3897
6918
|
};
|
|
3898
6919
|
//#endregion
|
|
3899
6920
|
//#region src/confirm.ts
|
|
@@ -3935,7 +6956,7 @@ const getProjectStatus = (project) => {
|
|
|
3935
6956
|
};
|
|
3936
6957
|
const parseTargetDate = (value) => parseCliDateOnlyToEpoch(value, "target date");
|
|
3937
6958
|
const generateProjectSlug = (name, id) => {
|
|
3938
|
-
const slug = name.toLowerCase().trim().replaceAll(/[^a-z0-9]+/
|
|
6959
|
+
const slug = name.toLowerCase().trim().replaceAll(/[^a-z0-9]+/gu, "-").replaceAll(/^-|-$/gu, "").slice(0, 39);
|
|
3939
6960
|
const shortId = id.replaceAll("-", "").slice(0, 8);
|
|
3940
6961
|
return slug ? `${slug}-${shortId}` : shortId;
|
|
3941
6962
|
};
|
|
@@ -4055,14 +7076,14 @@ const resolveProjectName = async (context, rawName) => {
|
|
|
4055
7076
|
const trimmed = rawName.trim();
|
|
4056
7077
|
if (trimmed.length > 0) return trimmed;
|
|
4057
7078
|
}
|
|
4058
|
-
const { promptForValue } = await import("./prompt-
|
|
7079
|
+
const { promptForValue } = await import("./prompt-B7mDo4K7.mjs");
|
|
4059
7080
|
const prompted = await promptForValue(context, "Project name");
|
|
4060
7081
|
if (prompted) return prompted;
|
|
4061
7082
|
throw new CliError("Project name is required.", EXIT_CODES.VALIDATION, "Provide a name: donebear project add \"My project\"");
|
|
4062
7083
|
};
|
|
4063
7084
|
const runProjectAdd = async (context, name, options) => {
|
|
4064
7085
|
const commandContext = await resolveCommandContext(context);
|
|
4065
|
-
const userId = requireUserId(commandContext
|
|
7086
|
+
const userId = await requireUserId(context, commandContext);
|
|
4066
7087
|
const normalizedName = await resolveProjectName(context, name);
|
|
4067
7088
|
const { workspace, autoSelected } = await resolveWorkspace(context, {
|
|
4068
7089
|
apiBaseUrl: commandContext.apiBaseUrl,
|
|
@@ -4306,7 +7327,7 @@ Agent tip: run "donebear spec project add" for full option reference
|
|
|
4306
7327
|
};
|
|
4307
7328
|
//#endregion
|
|
4308
7329
|
//#region src/commands/task.ts
|
|
4309
|
-
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/
|
|
7330
|
+
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
|
|
4310
7331
|
const DEFAULT_TASK_LIST_LIMIT = 20;
|
|
4311
7332
|
const VALID_TASK_VIEWS = new Set([
|
|
4312
7333
|
"inbox",
|
|
@@ -4470,7 +7491,7 @@ const resolveNotes = async (_context, flagNotes) => {
|
|
|
4470
7491
|
};
|
|
4471
7492
|
const runTaskAdd = async (context, title, options, workspaceOverride) => {
|
|
4472
7493
|
const commandContext = await resolveCommandContext(context);
|
|
4473
|
-
const userId = requireUserId(commandContext
|
|
7494
|
+
const userId = await requireUserId(context, commandContext);
|
|
4474
7495
|
const normalizedTitle = await resolveTitle(context, title);
|
|
4475
7496
|
const notes = await resolveNotes(context, options.notes);
|
|
4476
7497
|
const { workspace, autoSelected } = await resolveWorkspace(context, {
|
|
@@ -4510,6 +7531,7 @@ const runTaskAdd = async (context, title, options, workspaceOverride) => {
|
|
|
4510
7531
|
creatorId: userId,
|
|
4511
7532
|
deadlineAt: deadlineEpoch,
|
|
4512
7533
|
description: notes,
|
|
7534
|
+
key: taskId.replaceAll("-", "").slice(0, 8),
|
|
4513
7535
|
projectId,
|
|
4514
7536
|
sortOrder: 0,
|
|
4515
7537
|
teamId,
|
|
@@ -5213,6 +8235,15 @@ Examples:
|
|
|
5213
8235
|
const OVERVIEW = {
|
|
5214
8236
|
authentication: "Set DONEBEAR_TOKEN env var, or run: donebear auth login",
|
|
5215
8237
|
commands: {
|
|
8238
|
+
"api-key": {
|
|
8239
|
+
description: "Manage personal API keys",
|
|
8240
|
+
quick_example: "donebear api-key list --json",
|
|
8241
|
+
subcommands: [
|
|
8242
|
+
"create",
|
|
8243
|
+
"list",
|
|
8244
|
+
"revoke"
|
|
8245
|
+
]
|
|
8246
|
+
},
|
|
5216
8247
|
auth: {
|
|
5217
8248
|
description: "Authentication",
|
|
5218
8249
|
quick_example: "donebear auth status --json",
|
|
@@ -5328,6 +8359,70 @@ const OVERVIEW = {
|
|
|
5328
8359
|
workspace_targeting: "Prefix any command: donebear workspace=<slug> task list"
|
|
5329
8360
|
};
|
|
5330
8361
|
const COMMAND_SPECS = {
|
|
8362
|
+
"api-key create": {
|
|
8363
|
+
arguments: { label: {
|
|
8364
|
+
description: "Human-readable label for the key",
|
|
8365
|
+
required: true,
|
|
8366
|
+
type: "string"
|
|
8367
|
+
} },
|
|
8368
|
+
command: "api-key create",
|
|
8369
|
+
examples: [
|
|
8370
|
+
"donebear api-key create \"Raycast\" --json",
|
|
8371
|
+
"donebear api-key create \"CI\" --permissions read-only --expires 90d --json",
|
|
8372
|
+
"donebear api-key create \"Scoped\" --workspaces my-org,side-project --expires 1y --json"
|
|
8373
|
+
],
|
|
8374
|
+
json_output: {
|
|
8375
|
+
createdAt: "string",
|
|
8376
|
+
expiresAt: "string | null",
|
|
8377
|
+
id: "string",
|
|
8378
|
+
keyPrefix: "string",
|
|
8379
|
+
label: "string",
|
|
8380
|
+
scopes: "string[]",
|
|
8381
|
+
token: "string",
|
|
8382
|
+
workspaceIds: "string[] | null"
|
|
8383
|
+
},
|
|
8384
|
+
notes: "The full token is only shown once at creation time. Scopes default to full-access (read, write, admin).",
|
|
8385
|
+
options: {
|
|
8386
|
+
"--expires": {
|
|
8387
|
+
description: "Expiration duration, e.g. \"30d\", \"90d\", \"1y\"",
|
|
8388
|
+
type: "string"
|
|
8389
|
+
},
|
|
8390
|
+
"--permissions": {
|
|
8391
|
+
default: "full-access",
|
|
8392
|
+
description: "\"full-access\" (read, write, admin) or \"read-only\" (read only)",
|
|
8393
|
+
enum: ["full-access", "read-only"],
|
|
8394
|
+
type: "string"
|
|
8395
|
+
},
|
|
8396
|
+
"--workspaces": {
|
|
8397
|
+
description: "Comma-separated workspace slugs to restrict the key to",
|
|
8398
|
+
type: "string"
|
|
8399
|
+
}
|
|
8400
|
+
},
|
|
8401
|
+
usage: "donebear api-key create <label> [options]"
|
|
8402
|
+
},
|
|
8403
|
+
"api-key list": {
|
|
8404
|
+
command: "api-key list",
|
|
8405
|
+
examples: ["donebear api-key list --json"],
|
|
8406
|
+
json_output: { keys: "ApiKeyRecord[]" },
|
|
8407
|
+
notes: "Each key includes scopes, workspaceIds, and expiresAt fields.",
|
|
8408
|
+
options: {},
|
|
8409
|
+
usage: "donebear api-key list"
|
|
8410
|
+
},
|
|
8411
|
+
"api-key revoke": {
|
|
8412
|
+
arguments: { "key-id": {
|
|
8413
|
+
description: "The UUID of the API key to revoke",
|
|
8414
|
+
required: true,
|
|
8415
|
+
type: "string"
|
|
8416
|
+
} },
|
|
8417
|
+
command: "api-key revoke",
|
|
8418
|
+
examples: ["donebear api-key revoke abc12345 --json"],
|
|
8419
|
+
json_output: {
|
|
8420
|
+
id: "string",
|
|
8421
|
+
ok: "boolean"
|
|
8422
|
+
},
|
|
8423
|
+
options: {},
|
|
8424
|
+
usage: "donebear api-key revoke <key-id>"
|
|
8425
|
+
},
|
|
5331
8426
|
"auth login": {
|
|
5332
8427
|
command: "auth login",
|
|
5333
8428
|
examples: [
|
|
@@ -5974,6 +9069,16 @@ const COMMAND_SPECS = {
|
|
|
5974
9069
|
}
|
|
5975
9070
|
};
|
|
5976
9071
|
const TOP_LEVEL_SPECS = {
|
|
9072
|
+
"api-key": {
|
|
9073
|
+
command: "api-key",
|
|
9074
|
+
description: "Manage personal API keys",
|
|
9075
|
+
subcommands: {
|
|
9076
|
+
create: "Create a new API key (--permissions, --workspaces, --expires)",
|
|
9077
|
+
list: "List all API keys with scopes and expiration",
|
|
9078
|
+
revoke: "Revoke an API key by id"
|
|
9079
|
+
},
|
|
9080
|
+
tip: "donebear spec api-key create — get full spec for api-key create"
|
|
9081
|
+
},
|
|
5977
9082
|
auth: {
|
|
5978
9083
|
command: "auth",
|
|
5979
9084
|
description: "Authentication",
|
|
@@ -6267,8 +9372,13 @@ Examples:
|
|
|
6267
9372
|
//#endregion
|
|
6268
9373
|
//#region src/commands/whoami.ts
|
|
6269
9374
|
const runWhoAmI = async (context) => {
|
|
6270
|
-
|
|
6271
|
-
|
|
9375
|
+
let supabaseConfig = null;
|
|
9376
|
+
try {
|
|
9377
|
+
supabaseConfig = resolveSupabaseConfig();
|
|
9378
|
+
} catch {
|
|
9379
|
+
supabaseConfig = null;
|
|
9380
|
+
}
|
|
9381
|
+
const resolvedToken = await resolveAuthToken(context, supabaseConfig);
|
|
6272
9382
|
if (!resolvedToken) {
|
|
6273
9383
|
process.exitCode = EXIT_CODES.AUTH_REQUIRED;
|
|
6274
9384
|
if (context.json) {
|
|
@@ -6285,7 +9395,10 @@ const runWhoAmI = async (context) => {
|
|
|
6285
9395
|
writeInfo(context, "Run `donebear auth login`.");
|
|
6286
9396
|
return;
|
|
6287
9397
|
}
|
|
6288
|
-
const user = await
|
|
9398
|
+
const user = await loadViewer(context, {
|
|
9399
|
+
baseUrl: resolveApiBaseUrl(context),
|
|
9400
|
+
token: resolvedToken.token
|
|
9401
|
+
});
|
|
6289
9402
|
if (context.json) {
|
|
6290
9403
|
writeOutput(context, {
|
|
6291
9404
|
ok: true,
|
|
@@ -6646,10 +9759,10 @@ Examples:
|
|
|
6646
9759
|
//#endregion
|
|
6647
9760
|
//#region src/cli.ts
|
|
6648
9761
|
const packageManifest = createRequire(import.meta.url)("../package.json");
|
|
6649
|
-
const WORKSPACE_PREFIX_REGEX = /^workspace=(.+)$/
|
|
9762
|
+
const WORKSPACE_PREFIX_REGEX = /^workspace=(.+)$/iu;
|
|
6650
9763
|
const extractWorkspaceTarget = (argv) => {
|
|
6651
9764
|
const processedArgv = [...argv];
|
|
6652
|
-
const
|
|
9765
|
+
const firstArg = processedArgv[2];
|
|
6653
9766
|
if (firstArg) {
|
|
6654
9767
|
const match = WORKSPACE_PREFIX_REGEX.exec(firstArg);
|
|
6655
9768
|
if (match?.[1]) {
|