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/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-DH561Z1u.mjs";
3
- import { n as readStdin, t as promptForValue } from "./prompt-BrfcK2Ry.mjs";
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("utf8");
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, "utf8")).session;
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: "utf8",
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 data = await requestGraphql(context, `${options.baseUrl}/graphql`, {
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: { label: options.label }
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 = (resolvedToken) => {
1017
- const userId = resolvedToken.user?.id ?? null;
1018
- if (!(typeof userId === "string" && userId.length > 0)) throw new CliError("Could not determine user id from auth token", EXIT_CODES.AUTH_REQUIRED);
1019
- return userId;
1020
- };
1021
- //#endregion
1022
- //#region src/output.ts
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 runCreate = async (context, label) => {
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: resolveApiBaseUrl(context),
1304
+ baseUrl,
1305
+ expiresAt,
1230
1306
  label,
1231
- token
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
- token: key.token
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
- writeInfo(context, `${key.keyPrefix}... ${key.label} ${lastUsed}${status} [${key.id}]`);
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, _options, command) => {
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]+/g, "-").replaceAll(/^-+|-+$/g, "").replaceAll(/-{2,}/g, "-").slice(0, 50);
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-D0Z9vbaU.mjs");
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, "utf8")).digest();
2214
- const bytes = Uint8Array.from(hash.subarray(0, 16));
2215
- const versionByte = bytes[6];
2216
- const variantByte = bytes[8];
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 & PACKED_DATE_DAY_MASK,
2260
- month: packed >> PACKED_DATE_MONTH_SHIFT & PACKED_DATE_MONTH_MASK,
2261
- year: packed >> PACKED_DATE_YEAR_SHIFT
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>`).exec(xml);
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>/g)) {
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]+/g;
2524
- const WHITESPACE_SPLIT_PATTERN = /\s+/;
2525
- const NON_ALPHANUMERIC_STRICT_PATTERN = /[^A-Z0-9]/g;
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]/g, "").slice(-4);
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("utf8");
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+.-]*:/i;
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("utf8").trim();
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.resolvedToken);
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, "utf8");
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: "utf8",
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]+/g, "-").replaceAll(/^-|-$/g, "").slice(0, 39);
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-FRvfbinv.mjs");
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.resolvedToken);
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}$/i;
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.resolvedToken);
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
- const config = resolveSupabaseConfig();
6271
- const resolvedToken = await resolveAuthToken(context, config);
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 getSupabaseUser(config.url, config.publishableKey, resolvedToken.token);
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=(.+)$/i;
9762
+ const WORKSPACE_PREFIX_REGEX = /^workspace=(.+)$/iu;
6650
9763
  const extractWorkspaceTarget = (argv) => {
6651
9764
  const processedArgv = [...argv];
6652
- const [, , firstArg] = processedArgv;
9765
+ const firstArg = processedArgv[2];
6653
9766
  if (firstArg) {
6654
9767
  const match = WORKSPACE_PREFIX_REGEX.exec(firstArg);
6655
9768
  if (match?.[1]) {