@stackframe/stack-shared 2.8.25 → 2.8.27
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/CHANGELOG.md +12 -0
- package/dist/config/format.d.mts +20 -5
- package/dist/config/format.d.ts +20 -5
- package/dist/config/format.js +39 -14
- package/dist/config/format.js.map +1 -1
- package/dist/config/schema.d.mts +795 -317
- package/dist/config/schema.d.ts +795 -317
- package/dist/config/schema.js +471 -84
- package/dist/config/schema.js.map +1 -1
- package/dist/crud.d.mts +1 -0
- package/dist/crud.d.ts +1 -0
- package/dist/esm/config/format.js +37 -14
- package/dist/esm/config/format.js.map +1 -1
- package/dist/esm/config/schema.js +460 -80
- package/dist/esm/config/schema.js.map +1 -1
- package/dist/esm/helpers/emails.js +136 -30
- package/dist/esm/helpers/emails.js.map +1 -1
- package/dist/esm/interface/admin-interface.js +19 -29
- package/dist/esm/interface/admin-interface.js.map +1 -1
- package/dist/esm/known-errors.js +24 -1
- package/dist/esm/known-errors.js.map +1 -1
- package/dist/esm/schema-fields.js +92 -27
- package/dist/esm/schema-fields.js.map +1 -1
- package/dist/esm/utils/currencies.js +52 -0
- package/dist/esm/utils/currencies.js.map +1 -0
- package/dist/esm/utils/dates.js +55 -1
- package/dist/esm/utils/dates.js.map +1 -1
- package/dist/esm/utils/errors.js.map +1 -1
- package/dist/esm/utils/objects.js +2 -0
- package/dist/esm/utils/objects.js.map +1 -1
- package/dist/esm/utils/strings.js +4 -0
- package/dist/esm/utils/strings.js.map +1 -1
- package/dist/esm/utils/types.js +45 -0
- package/dist/esm/utils/types.js.map +1 -1
- package/dist/helpers/emails.d.mts +32 -6
- package/dist/helpers/emails.d.ts +32 -6
- package/dist/helpers/emails.js +138 -30
- package/dist/helpers/emails.js.map +1 -1
- package/dist/helpers/password.d.mts +1 -0
- package/dist/helpers/password.d.ts +1 -0
- package/dist/helpers/production-mode.d.mts +1 -0
- package/dist/helpers/production-mode.d.ts +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/interface/admin-interface.d.mts +8 -8
- package/dist/interface/admin-interface.d.ts +8 -8
- package/dist/interface/admin-interface.js +19 -29
- package/dist/interface/admin-interface.js.map +1 -1
- package/dist/interface/client-interface.d.mts +1 -0
- package/dist/interface/client-interface.d.ts +1 -0
- package/dist/interface/crud/connected-accounts.d.mts +1 -0
- package/dist/interface/crud/connected-accounts.d.ts +1 -0
- package/dist/interface/crud/contact-channels.d.mts +1 -0
- package/dist/interface/crud/contact-channels.d.ts +1 -0
- package/dist/interface/crud/current-user.d.mts +1 -0
- package/dist/interface/crud/current-user.d.ts +1 -0
- package/dist/interface/crud/email-templates.d.mts +1 -0
- package/dist/interface/crud/email-templates.d.ts +1 -0
- package/dist/interface/crud/emails.d.mts +1 -0
- package/dist/interface/crud/emails.d.ts +1 -0
- package/dist/interface/crud/internal-api-keys.d.mts +1 -0
- package/dist/interface/crud/internal-api-keys.d.ts +1 -0
- package/dist/interface/crud/notification-preferences.d.mts +1 -0
- package/dist/interface/crud/notification-preferences.d.ts +1 -0
- package/dist/interface/crud/oauth-providers.d.mts +5 -4
- package/dist/interface/crud/oauth-providers.d.ts +5 -4
- package/dist/interface/crud/project-api-keys.d.mts +3 -2
- package/dist/interface/crud/project-api-keys.d.ts +3 -2
- package/dist/interface/crud/project-permissions.d.mts +1 -0
- package/dist/interface/crud/project-permissions.d.ts +1 -0
- package/dist/interface/crud/projects.d.mts +8 -7
- package/dist/interface/crud/projects.d.ts +8 -7
- package/dist/interface/crud/sessions.d.mts +1 -0
- package/dist/interface/crud/sessions.d.ts +1 -0
- package/dist/interface/crud/svix-token.d.mts +1 -0
- package/dist/interface/crud/svix-token.d.ts +1 -0
- package/dist/interface/crud/team-invitation-details.d.mts +1 -0
- package/dist/interface/crud/team-invitation-details.d.ts +1 -0
- package/dist/interface/crud/team-invitation.d.mts +1 -0
- package/dist/interface/crud/team-invitation.d.ts +1 -0
- package/dist/interface/crud/team-member-profiles.d.mts +1 -0
- package/dist/interface/crud/team-member-profiles.d.ts +1 -0
- package/dist/interface/crud/team-memberships.d.mts +1 -0
- package/dist/interface/crud/team-memberships.d.ts +1 -0
- package/dist/interface/crud/team-permissions.d.mts +1 -0
- package/dist/interface/crud/team-permissions.d.ts +1 -0
- package/dist/interface/crud/teams.d.mts +1 -0
- package/dist/interface/crud/teams.d.ts +1 -0
- package/dist/interface/crud/users.d.mts +1 -0
- package/dist/interface/crud/users.d.ts +1 -0
- package/dist/interface/server-interface.d.mts +1 -0
- package/dist/interface/server-interface.d.ts +1 -0
- package/dist/known-errors.d.mts +6 -0
- package/dist/known-errors.d.ts +6 -0
- package/dist/known-errors.js +24 -1
- package/dist/known-errors.js.map +1 -1
- package/dist/schema-fields.d.mts +39 -8
- package/dist/schema-fields.d.ts +39 -8
- package/dist/schema-fields.js +101 -27
- package/dist/schema-fields.js.map +1 -1
- package/dist/utils/currencies.d.mts +39 -0
- package/dist/utils/currencies.d.ts +39 -0
- package/dist/utils/currencies.js +78 -0
- package/dist/utils/currencies.js.map +1 -0
- package/dist/utils/dates.d.mts +5 -1
- package/dist/utils/dates.d.ts +5 -1
- package/dist/utils/dates.js +58 -2
- package/dist/utils/dates.js.map +1 -1
- package/dist/utils/errors.d.mts +9 -0
- package/dist/utils/errors.d.ts +9 -0
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/objects.d.mts +23 -8
- package/dist/utils/objects.d.ts +23 -8
- package/dist/utils/objects.js +2 -0
- package/dist/utils/objects.js.map +1 -1
- package/dist/utils/strings.d.mts +3 -1
- package/dist/utils/strings.d.ts +3 -1
- package/dist/utils/strings.js +5 -0
- package/dist/utils/strings.js.map +1 -1
- package/dist/utils/types.d.mts +73 -2
- package/dist/utils/types.d.ts +73 -2
- package/dist/utils/types.js +54 -0
- package/dist/utils/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
type Currency = {
|
|
2
|
+
code: Uppercase<string>;
|
|
3
|
+
decimals: number;
|
|
4
|
+
stripeDecimals: number;
|
|
5
|
+
};
|
|
6
|
+
type SupportedCurrency = (typeof SUPPORTED_CURRENCIES)[number];
|
|
7
|
+
declare const SUPPORTED_CURRENCIES: [{
|
|
8
|
+
readonly code: "USD";
|
|
9
|
+
readonly decimals: 2;
|
|
10
|
+
readonly stripeDecimals: 2;
|
|
11
|
+
}, {
|
|
12
|
+
readonly code: "EUR";
|
|
13
|
+
readonly decimals: 2;
|
|
14
|
+
readonly stripeDecimals: 2;
|
|
15
|
+
}, {
|
|
16
|
+
readonly code: "GBP";
|
|
17
|
+
readonly decimals: 2;
|
|
18
|
+
readonly stripeDecimals: 2;
|
|
19
|
+
}, {
|
|
20
|
+
readonly code: "JPY";
|
|
21
|
+
readonly decimals: 0;
|
|
22
|
+
readonly stripeDecimals: 0;
|
|
23
|
+
}, {
|
|
24
|
+
readonly code: "INR";
|
|
25
|
+
readonly decimals: 2;
|
|
26
|
+
readonly stripeDecimals: 2;
|
|
27
|
+
}, {
|
|
28
|
+
readonly code: "AUD";
|
|
29
|
+
readonly decimals: 2;
|
|
30
|
+
readonly stripeDecimals: 2;
|
|
31
|
+
}, {
|
|
32
|
+
readonly code: "CAD";
|
|
33
|
+
readonly decimals: 2;
|
|
34
|
+
readonly stripeDecimals: 2;
|
|
35
|
+
}];
|
|
36
|
+
type MoneyAmount = `${number}` | `${number}.${number}`;
|
|
37
|
+
declare function moneyAmountToStripeUnits(amount: MoneyAmount, currency: Currency): number;
|
|
38
|
+
|
|
39
|
+
export { type Currency, type MoneyAmount, SUPPORTED_CURRENCIES, type SupportedCurrency, moneyAmountToStripeUnits };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/utils/currencies.tsx
|
|
21
|
+
var currencies_exports = {};
|
|
22
|
+
__export(currencies_exports, {
|
|
23
|
+
SUPPORTED_CURRENCIES: () => SUPPORTED_CURRENCIES,
|
|
24
|
+
moneyAmountToStripeUnits: () => moneyAmountToStripeUnits
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(currencies_exports);
|
|
27
|
+
var import_schema_fields = require("../schema-fields.js");
|
|
28
|
+
var import_errors = require("./errors.js");
|
|
29
|
+
var SUPPORTED_CURRENCIES = [
|
|
30
|
+
{
|
|
31
|
+
code: "USD",
|
|
32
|
+
decimals: 2,
|
|
33
|
+
stripeDecimals: 2
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
code: "EUR",
|
|
37
|
+
decimals: 2,
|
|
38
|
+
stripeDecimals: 2
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
code: "GBP",
|
|
42
|
+
decimals: 2,
|
|
43
|
+
stripeDecimals: 2
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
code: "JPY",
|
|
47
|
+
decimals: 0,
|
|
48
|
+
stripeDecimals: 0
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
code: "INR",
|
|
52
|
+
decimals: 2,
|
|
53
|
+
stripeDecimals: 2
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
code: "AUD",
|
|
57
|
+
decimals: 2,
|
|
58
|
+
stripeDecimals: 2
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
code: "CAD",
|
|
62
|
+
decimals: 2,
|
|
63
|
+
stripeDecimals: 2
|
|
64
|
+
}
|
|
65
|
+
];
|
|
66
|
+
function moneyAmountToStripeUnits(amount, currency) {
|
|
67
|
+
const validated = (0, import_schema_fields.moneyAmountSchema)(currency).defined().validateSync(amount);
|
|
68
|
+
if (currency.stripeDecimals !== currency.decimals) {
|
|
69
|
+
throw new import_errors.StackAssertionError("unimplemented: TODO support different decimal configurations");
|
|
70
|
+
}
|
|
71
|
+
return Number.parseInt(validated.replace(".", ""), 10);
|
|
72
|
+
}
|
|
73
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
74
|
+
0 && (module.exports = {
|
|
75
|
+
SUPPORTED_CURRENCIES,
|
|
76
|
+
moneyAmountToStripeUnits
|
|
77
|
+
});
|
|
78
|
+
//# sourceMappingURL=currencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/currencies.tsx"],"sourcesContent":["import { moneyAmountSchema } from \"../schema-fields\";\nimport { StackAssertionError } from \"./errors\";\n\nexport type Currency = {\n code: Uppercase<string>,\n decimals: number,\n stripeDecimals: number,\n};\n\nexport type SupportedCurrency = (typeof SUPPORTED_CURRENCIES)[number];\nexport const SUPPORTED_CURRENCIES = [\n {\n code: 'USD',\n decimals: 2,\n stripeDecimals: 2,\n },\n {\n code: 'EUR',\n decimals: 2,\n stripeDecimals: 2,\n },\n {\n code: 'GBP',\n decimals: 2,\n stripeDecimals: 2,\n },\n {\n code: 'JPY',\n decimals: 0,\n stripeDecimals: 0,\n },\n {\n code: 'INR',\n decimals: 2,\n stripeDecimals: 2,\n },\n {\n code: 'AUD',\n decimals: 2,\n stripeDecimals: 2,\n },\n {\n code: 'CAD',\n decimals: 2,\n stripeDecimals: 2,\n },\n] as const satisfies Currency[];\n\nexport type MoneyAmount = `${number}` | `${number}.${number}`;\n\nexport function moneyAmountToStripeUnits(amount: MoneyAmount, currency: Currency): number {\n const validated = moneyAmountSchema(currency).defined().validateSync(amount);\n if (currency.stripeDecimals !== currency.decimals) {\n throw new StackAssertionError(\"unimplemented: TODO support different decimal configurations\");\n }\n\n return Number.parseInt(validated.replace('.', ''), 10);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAAkC;AAClC,oBAAoC;AAS7B,IAAM,uBAAuB;AAAA,EAClC;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,IACV,gBAAgB;AAAA,EAClB;AACF;AAIO,SAAS,yBAAyB,QAAqB,UAA4B;AACxF,QAAM,gBAAY,wCAAkB,QAAQ,EAAE,QAAQ,EAAE,aAAa,MAAM;AAC3E,MAAI,SAAS,mBAAmB,SAAS,UAAU;AACjD,UAAM,IAAI,kCAAoB,8DAA8D;AAAA,EAC9F;AAEA,SAAO,OAAO,SAAS,UAAU,QAAQ,KAAK,EAAE,GAAG,EAAE;AACvD;","names":[]}
|
package/dist/utils/dates.d.mts
CHANGED
|
@@ -11,5 +11,9 @@ declare function fromNowDetailed(date: Date): {
|
|
|
11
11
|
* Returns a string representation of the given date in the format expected by the `datetime-local` input type.
|
|
12
12
|
*/
|
|
13
13
|
declare function getInputDatetimeLocalString(date: Date): string;
|
|
14
|
+
type Interval = [number, 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year'];
|
|
15
|
+
type DayInterval = [number, 'day' | 'week' | 'month' | 'year'];
|
|
16
|
+
declare function subtractInterval(date: Date, interval: Interval): Date;
|
|
17
|
+
declare function addInterval(date: Date, interval: Interval): Date;
|
|
14
18
|
|
|
15
|
-
export { fromNow, fromNowDetailed, getInputDatetimeLocalString, isWeekend };
|
|
19
|
+
export { type DayInterval, type Interval, addInterval, fromNow, fromNowDetailed, getInputDatetimeLocalString, isWeekend, subtractInterval };
|
package/dist/utils/dates.d.ts
CHANGED
|
@@ -11,5 +11,9 @@ declare function fromNowDetailed(date: Date): {
|
|
|
11
11
|
* Returns a string representation of the given date in the format expected by the `datetime-local` input type.
|
|
12
12
|
*/
|
|
13
13
|
declare function getInputDatetimeLocalString(date: Date): string;
|
|
14
|
+
type Interval = [number, 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year'];
|
|
15
|
+
type DayInterval = [number, 'day' | 'week' | 'month' | 'year'];
|
|
16
|
+
declare function subtractInterval(date: Date, interval: Interval): Date;
|
|
17
|
+
declare function addInterval(date: Date, interval: Interval): Date;
|
|
14
18
|
|
|
15
|
-
export { fromNow, fromNowDetailed, getInputDatetimeLocalString, isWeekend };
|
|
19
|
+
export { type DayInterval, type Interval, addInterval, fromNow, fromNowDetailed, getInputDatetimeLocalString, isWeekend, subtractInterval };
|
package/dist/utils/dates.js
CHANGED
|
@@ -20,12 +20,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/utils/dates.tsx
|
|
21
21
|
var dates_exports = {};
|
|
22
22
|
__export(dates_exports, {
|
|
23
|
+
addInterval: () => addInterval,
|
|
23
24
|
fromNow: () => fromNow,
|
|
24
25
|
fromNowDetailed: () => fromNowDetailed,
|
|
25
26
|
getInputDatetimeLocalString: () => getInputDatetimeLocalString,
|
|
26
|
-
isWeekend: () => isWeekend
|
|
27
|
+
isWeekend: () => isWeekend,
|
|
28
|
+
subtractInterval: () => subtractInterval
|
|
27
29
|
});
|
|
28
30
|
module.exports = __toCommonJS(dates_exports);
|
|
31
|
+
var import_schema_fields = require("../schema-fields.js");
|
|
32
|
+
var import_errors = require("./errors.js");
|
|
29
33
|
var import_math = require("./math.js");
|
|
30
34
|
function isWeekend(date) {
|
|
31
35
|
return date.getDay() === 0 || date.getDay() === 6;
|
|
@@ -82,11 +86,63 @@ function getInputDatetimeLocalString(date) {
|
|
|
82
86
|
date.setMinutes(date.getMinutes() - date.getTimezoneOffset());
|
|
83
87
|
return date.toISOString().slice(0, 19);
|
|
84
88
|
}
|
|
89
|
+
function applyInterval(date, times, interval) {
|
|
90
|
+
if (!import_schema_fields.intervalSchema.isValidSync(interval)) {
|
|
91
|
+
throw new import_errors.StackAssertionError(`Invalid interval`, { interval });
|
|
92
|
+
}
|
|
93
|
+
const [amount, unit] = interval;
|
|
94
|
+
switch (unit) {
|
|
95
|
+
case "millisecond": {
|
|
96
|
+
date.setMilliseconds(date.getMilliseconds() + amount * times);
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
case "second": {
|
|
100
|
+
date.setSeconds(date.getSeconds() + amount * times);
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
case "minute": {
|
|
104
|
+
date.setMinutes(date.getMinutes() + amount * times);
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
case "hour": {
|
|
108
|
+
date.setHours(date.getHours() + amount * times);
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
case "day": {
|
|
112
|
+
date.setDate(date.getDate() + amount * times);
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
case "week": {
|
|
116
|
+
date.setDate(date.getDate() + amount * times * 7);
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
case "month": {
|
|
120
|
+
date.setMonth(date.getMonth() + amount * times);
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
case "year": {
|
|
124
|
+
date.setFullYear(date.getFullYear() + amount * times);
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
default: {
|
|
128
|
+
throw new import_errors.StackAssertionError(`Invalid interval despite schema validation`, { interval });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return date;
|
|
132
|
+
}
|
|
133
|
+
function subtractInterval(date, interval) {
|
|
134
|
+
return applyInterval(date, -1, interval);
|
|
135
|
+
}
|
|
136
|
+
function addInterval(date, interval) {
|
|
137
|
+
return applyInterval(date, 1, interval);
|
|
138
|
+
}
|
|
85
139
|
// Annotate the CommonJS export names for ESM import in node:
|
|
86
140
|
0 && (module.exports = {
|
|
141
|
+
addInterval,
|
|
87
142
|
fromNow,
|
|
88
143
|
fromNowDetailed,
|
|
89
144
|
getInputDatetimeLocalString,
|
|
90
|
-
isWeekend
|
|
145
|
+
isWeekend,
|
|
146
|
+
subtractInterval
|
|
91
147
|
});
|
|
92
148
|
//# sourceMappingURL=dates.js.map
|
package/dist/utils/dates.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/dates.tsx"],"sourcesContent":["import { remainder } from \"./math\";\n\nexport function isWeekend(date: Date): boolean {\n return date.getDay() === 0 || date.getDay() === 6;\n}\n\nundefined?.test(\"isWeekend\", ({ expect }) => {\n // Sunday (day 0)\n expect(isWeekend(new Date(2023, 0, 1))).toBe(true);\n // Saturday (day 6)\n expect(isWeekend(new Date(2023, 0, 7))).toBe(true);\n // Monday (day 1)\n expect(isWeekend(new Date(2023, 0, 2))).toBe(false);\n // Friday (day 5)\n expect(isWeekend(new Date(2023, 0, 6))).toBe(false);\n});\n\nconst agoUnits = [\n [60, 'second'],\n [60, 'minute'],\n [24, 'hour'],\n [7, 'day'],\n [5, 'week'],\n] as const;\n\nexport function fromNow(date: Date): string {\n return fromNowDetailed(date).result;\n}\n\nundefined?.test(\"fromNow\", ({ expect }) => {\n // Set a fixed date for testing\n const fixedDate = new Date(\"2023-01-15T12:00:00.000Z\");\n\n // Use Vitest's fake timers\n undefined?.vi.useFakeTimers();\n undefined?.vi.setSystemTime(fixedDate);\n\n // Test past times\n expect(fromNow(new Date(\"2023-01-15T11:59:50.000Z\"))).toBe(\"just now\");\n expect(fromNow(new Date(\"2023-01-15T11:59:00.000Z\"))).toBe(\"1 minute ago\");\n expect(fromNow(new Date(\"2023-01-15T11:00:00.000Z\"))).toBe(\"1 hour ago\");\n expect(fromNow(new Date(\"2023-01-14T12:00:00.000Z\"))).toBe(\"1 day ago\");\n expect(fromNow(new Date(\"2023-01-08T12:00:00.000Z\"))).toBe(\"1 week ago\");\n\n // Test future times\n expect(fromNow(new Date(\"2023-01-15T12:00:10.000Z\"))).toBe(\"just now\");\n expect(fromNow(new Date(\"2023-01-15T12:01:00.000Z\"))).toBe(\"in 1 minute\");\n expect(fromNow(new Date(\"2023-01-15T13:00:00.000Z\"))).toBe(\"in 1 hour\");\n expect(fromNow(new Date(\"2023-01-16T12:00:00.000Z\"))).toBe(\"in 1 day\");\n expect(fromNow(new Date(\"2023-01-22T12:00:00.000Z\"))).toBe(\"in 1 week\");\n\n // Test very old dates (should use date format)\n expect(fromNow(new Date(\"2022-01-15T12:00:00.000Z\"))).toMatch(/Jan 15, 2022/);\n\n // Restore real timers\n undefined?.vi.useRealTimers();\n});\n\nexport function fromNowDetailed(date: Date): {\n result: string,\n /**\n * May be Infinity if the result will never change.\n */\n secondsUntilChange: number,\n} {\n if (!(date instanceof Date)) {\n throw new Error(`fromNow only accepts Date objects (received: ${date})`);\n }\n\n const now = new Date();\n const elapsed = now.getTime() - date.getTime();\n\n let remainingInUnit = Math.abs(elapsed) / 1000;\n if (remainingInUnit < 15) {\n return {\n result: 'just now',\n secondsUntilChange: 15 - remainingInUnit,\n };\n }\n let unitInSeconds = 1;\n for (const [nextUnitSize, unitName] of agoUnits) {\n const rounded = Math.round(remainingInUnit);\n if (rounded < nextUnitSize) {\n if (elapsed < 0) {\n return {\n result: `in ${rounded} ${unitName}${rounded === 1 ? '' : 's'}`,\n secondsUntilChange: remainder((remainingInUnit - rounded + 0.5) * unitInSeconds, unitInSeconds),\n };\n } else {\n return {\n result: `${rounded} ${unitName}${rounded === 1 ? '' : 's'} ago`,\n secondsUntilChange: remainder((rounded - remainingInUnit - 0.5) * unitInSeconds, unitInSeconds),\n };\n }\n }\n unitInSeconds *= nextUnitSize;\n remainingInUnit /= nextUnitSize;\n }\n\n return {\n result: date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }),\n secondsUntilChange: Infinity,\n };\n}\n\n/**\n * Returns a string representation of the given date in the format expected by the `datetime-local` input type.\n */\nexport function getInputDatetimeLocalString(date: Date): string {\n date = new Date(date);\n date.setMinutes(date.getMinutes() - date.getTimezoneOffset());\n return date.toISOString().slice(0, 19);\n}\n\nundefined?.test(\"getInputDatetimeLocalString\", ({ expect }) => {\n // Use Vitest's fake timers to ensure consistent timezone behavior\n undefined?.vi.useFakeTimers();\n\n // Test with a specific date\n const mockDate = new Date(\"2023-01-15T12:30:45.000Z\");\n const result = getInputDatetimeLocalString(mockDate);\n\n // The result should be in the format YYYY-MM-DDTHH:MM:SS\n expect(result).toMatch(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$/);\n\n // Test with different dates\n const dates = [\n new Date(\"2023-01-01T00:00:00.000Z\"),\n new Date(\"2023-06-15T23:59:59.000Z\"),\n new Date(\"2023-12-31T12:34:56.000Z\"),\n ];\n\n for (const date of dates) {\n const result = getInputDatetimeLocalString(date);\n expect(result).toMatch(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$/);\n }\n\n // Restore real timers\n undefined?.vi.useRealTimers();\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAA0B;AAEnB,SAAS,UAAU,MAAqB;AAC7C,SAAO,KAAK,OAAO,MAAM,KAAK,KAAK,OAAO,MAAM;AAClD;AAaA,IAAM,WAAW;AAAA,EACf,CAAC,IAAI,QAAQ;AAAA,EACb,CAAC,IAAI,QAAQ;AAAA,EACb,CAAC,IAAI,MAAM;AAAA,EACX,CAAC,GAAG,KAAK;AAAA,EACT,CAAC,GAAG,MAAM;AACZ;AAEO,SAAS,QAAQ,MAAoB;AAC1C,SAAO,gBAAgB,IAAI,EAAE;AAC/B;AA+BO,SAAS,gBAAgB,MAM9B;AACA,MAAI,EAAE,gBAAgB,OAAO;AAC3B,UAAM,IAAI,MAAM,gDAAgD,IAAI,GAAG;AAAA,EACzE;AAEA,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,UAAU,IAAI,QAAQ,IAAI,KAAK,QAAQ;AAE7C,MAAI,kBAAkB,KAAK,IAAI,OAAO,IAAI;AAC1C,MAAI,kBAAkB,IAAI;AACxB,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,oBAAoB,KAAK;AAAA,IAC3B;AAAA,EACF;AACA,MAAI,gBAAgB;AACpB,aAAW,CAAC,cAAc,QAAQ,KAAK,UAAU;AAC/C,UAAM,UAAU,KAAK,MAAM,eAAe;AAC1C,QAAI,UAAU,cAAc;AAC1B,UAAI,UAAU,GAAG;AACf,eAAO;AAAA,UACL,QAAQ,MAAM,OAAO,IAAI,QAAQ,GAAG,YAAY,IAAI,KAAK,GAAG;AAAA,UAC5D,wBAAoB,wBAAW,kBAAkB,UAAU,OAAO,eAAe,aAAa;AAAA,QAChG;AAAA,MACF,OAAO;AACL,eAAO;AAAA,UACL,QAAQ,GAAG,OAAO,IAAI,QAAQ,GAAG,YAAY,IAAI,KAAK,GAAG;AAAA,UACzD,wBAAoB,wBAAW,UAAU,kBAAkB,OAAO,eAAe,aAAa;AAAA,QAChG;AAAA,MACF;AAAA,IACF;AACA,qBAAiB;AACjB,uBAAmB;AAAA,EACrB;AAEA,SAAO;AAAA,IACL,QAAQ,KAAK,mBAAmB,SAAS,EAAE,MAAM,WAAW,OAAO,SAAS,KAAK,UAAU,CAAC;AAAA,IAC5F,oBAAoB;AAAA,EACtB;AACF;AAKO,SAAS,4BAA4B,MAAoB;AAC9D,SAAO,IAAI,KAAK,IAAI;AACpB,OAAK,WAAW,KAAK,WAAW,IAAI,KAAK,kBAAkB,CAAC;AAC5D,SAAO,KAAK,YAAY,EAAE,MAAM,GAAG,EAAE;AACvC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/dates.tsx"],"sourcesContent":["import { intervalSchema } from \"../schema-fields\";\nimport { StackAssertionError } from \"./errors\";\nimport { remainder } from \"./math\";\n\nexport function isWeekend(date: Date): boolean {\n return date.getDay() === 0 || date.getDay() === 6;\n}\n\nundefined?.test(\"isWeekend\", ({ expect }) => {\n // Sunday (day 0)\n expect(isWeekend(new Date(2023, 0, 1))).toBe(true);\n // Saturday (day 6)\n expect(isWeekend(new Date(2023, 0, 7))).toBe(true);\n // Monday (day 1)\n expect(isWeekend(new Date(2023, 0, 2))).toBe(false);\n // Friday (day 5)\n expect(isWeekend(new Date(2023, 0, 6))).toBe(false);\n});\n\nconst agoUnits = [\n [60, 'second'],\n [60, 'minute'],\n [24, 'hour'],\n [7, 'day'],\n [5, 'week'],\n] as const;\n\nexport function fromNow(date: Date): string {\n return fromNowDetailed(date).result;\n}\n\nundefined?.test(\"fromNow\", ({ expect }) => {\n // Set a fixed date for testing\n const fixedDate = new Date(\"2023-01-15T12:00:00.000Z\");\n\n // Use Vitest's fake timers\n undefined?.vi.useFakeTimers();\n undefined?.vi.setSystemTime(fixedDate);\n\n // Test past times\n expect(fromNow(new Date(\"2023-01-15T11:59:50.000Z\"))).toBe(\"just now\");\n expect(fromNow(new Date(\"2023-01-15T11:59:00.000Z\"))).toBe(\"1 minute ago\");\n expect(fromNow(new Date(\"2023-01-15T11:00:00.000Z\"))).toBe(\"1 hour ago\");\n expect(fromNow(new Date(\"2023-01-14T12:00:00.000Z\"))).toBe(\"1 day ago\");\n expect(fromNow(new Date(\"2023-01-08T12:00:00.000Z\"))).toBe(\"1 week ago\");\n\n // Test future times\n expect(fromNow(new Date(\"2023-01-15T12:00:10.000Z\"))).toBe(\"just now\");\n expect(fromNow(new Date(\"2023-01-15T12:01:00.000Z\"))).toBe(\"in 1 minute\");\n expect(fromNow(new Date(\"2023-01-15T13:00:00.000Z\"))).toBe(\"in 1 hour\");\n expect(fromNow(new Date(\"2023-01-16T12:00:00.000Z\"))).toBe(\"in 1 day\");\n expect(fromNow(new Date(\"2023-01-22T12:00:00.000Z\"))).toBe(\"in 1 week\");\n\n // Test very old dates (should use date format)\n expect(fromNow(new Date(\"2022-01-15T12:00:00.000Z\"))).toMatch(/Jan 15, 2022/);\n\n // Restore real timers\n undefined?.vi.useRealTimers();\n});\n\nexport function fromNowDetailed(date: Date): {\n result: string,\n /**\n * May be Infinity if the result will never change.\n */\n secondsUntilChange: number,\n} {\n if (!(date instanceof Date)) {\n throw new Error(`fromNow only accepts Date objects (received: ${date})`);\n }\n\n const now = new Date();\n const elapsed = now.getTime() - date.getTime();\n\n let remainingInUnit = Math.abs(elapsed) / 1000;\n if (remainingInUnit < 15) {\n return {\n result: 'just now',\n secondsUntilChange: 15 - remainingInUnit,\n };\n }\n let unitInSeconds = 1;\n for (const [nextUnitSize, unitName] of agoUnits) {\n const rounded = Math.round(remainingInUnit);\n if (rounded < nextUnitSize) {\n if (elapsed < 0) {\n return {\n result: `in ${rounded} ${unitName}${rounded === 1 ? '' : 's'}`,\n secondsUntilChange: remainder((remainingInUnit - rounded + 0.5) * unitInSeconds, unitInSeconds),\n };\n } else {\n return {\n result: `${rounded} ${unitName}${rounded === 1 ? '' : 's'} ago`,\n secondsUntilChange: remainder((rounded - remainingInUnit - 0.5) * unitInSeconds, unitInSeconds),\n };\n }\n }\n unitInSeconds *= nextUnitSize;\n remainingInUnit /= nextUnitSize;\n }\n\n return {\n result: date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }),\n secondsUntilChange: Infinity,\n };\n}\n\n/**\n * Returns a string representation of the given date in the format expected by the `datetime-local` input type.\n */\nexport function getInputDatetimeLocalString(date: Date): string {\n date = new Date(date);\n date.setMinutes(date.getMinutes() - date.getTimezoneOffset());\n return date.toISOString().slice(0, 19);\n}\n\nundefined?.test(\"getInputDatetimeLocalString\", ({ expect }) => {\n // Use Vitest's fake timers to ensure consistent timezone behavior\n undefined?.vi.useFakeTimers();\n\n // Test with a specific date\n const mockDate = new Date(\"2023-01-15T12:30:45.000Z\");\n const result = getInputDatetimeLocalString(mockDate);\n\n // The result should be in the format YYYY-MM-DDTHH:MM:SS\n expect(result).toMatch(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$/);\n\n // Test with different dates\n const dates = [\n new Date(\"2023-01-01T00:00:00.000Z\"),\n new Date(\"2023-06-15T23:59:59.000Z\"),\n new Date(\"2023-12-31T12:34:56.000Z\"),\n ];\n\n for (const date of dates) {\n const result = getInputDatetimeLocalString(date);\n expect(result).toMatch(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$/);\n }\n\n // Restore real timers\n undefined?.vi.useRealTimers();\n});\n\n\nexport type Interval = [number, 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year'];\nexport type DayInterval = [number, 'day' | 'week' | 'month' | 'year'];\n\nfunction applyInterval(date: Date, times: number, interval: Interval): Date {\n if (!intervalSchema.isValidSync(interval)) {\n throw new StackAssertionError(`Invalid interval`, { interval });\n }\n const [amount, unit] = interval;\n switch (unit) {\n case 'millisecond': {\n date.setMilliseconds(date.getMilliseconds() + amount * times);\n break;\n }\n case 'second': {\n date.setSeconds(date.getSeconds() + amount * times);\n break;\n }\n case 'minute': {\n date.setMinutes(date.getMinutes() + amount * times);\n break;\n }\n case 'hour': {\n date.setHours(date.getHours() + amount * times);\n break;\n }\n case 'day': {\n date.setDate(date.getDate() + amount * times);\n break;\n }\n case 'week': {\n date.setDate(date.getDate() + amount * times * 7);\n break;\n }\n case 'month': {\n date.setMonth(date.getMonth() + amount * times);\n break;\n }\n case 'year': {\n date.setFullYear(date.getFullYear() + amount * times);\n break;\n }\n default: {\n throw new StackAssertionError(`Invalid interval despite schema validation`, { interval });\n }\n }\n return date;\n}\n\nexport function subtractInterval(date: Date, interval: Interval): Date {\n return applyInterval(date, -1, interval);\n}\n\nexport function addInterval(date: Date, interval: Interval): Date {\n return applyInterval(date, 1, interval);\n}\n"],"mappings":"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","names":[]}
|
package/dist/utils/errors.d.mts
CHANGED
|
@@ -32,6 +32,15 @@ declare class StackAssertionError extends Error {
|
|
|
32
32
|
}
|
|
33
33
|
declare function errorToNiceString(error: unknown): string;
|
|
34
34
|
declare function registerErrorSink(sink: (location: string, error: unknown) => void): void;
|
|
35
|
+
/**
|
|
36
|
+
* Captures an error and sends it to the error sinks (most notably, Sentry). Errors caught with captureError are
|
|
37
|
+
* supposed to be seen by an engineer, so they should be actionable and important.
|
|
38
|
+
*
|
|
39
|
+
* The location string is a machine-readable ID, and should hence not contain spaces or anything like that. Good
|
|
40
|
+
* examples are: "api-route-handler", "renderPart()", etc.
|
|
41
|
+
*
|
|
42
|
+
* Errors that bubble up to the top of runAsynchronously or a route handler are already captured with captureError.
|
|
43
|
+
*/
|
|
35
44
|
declare function captureError(location: string, error: unknown): void;
|
|
36
45
|
type Status = {
|
|
37
46
|
statusCode: number;
|
package/dist/utils/errors.d.ts
CHANGED
|
@@ -32,6 +32,15 @@ declare class StackAssertionError extends Error {
|
|
|
32
32
|
}
|
|
33
33
|
declare function errorToNiceString(error: unknown): string;
|
|
34
34
|
declare function registerErrorSink(sink: (location: string, error: unknown) => void): void;
|
|
35
|
+
/**
|
|
36
|
+
* Captures an error and sends it to the error sinks (most notably, Sentry). Errors caught with captureError are
|
|
37
|
+
* supposed to be seen by an engineer, so they should be actionable and important.
|
|
38
|
+
*
|
|
39
|
+
* The location string is a machine-readable ID, and should hence not contain spaces or anything like that. Good
|
|
40
|
+
* examples are: "api-route-handler", "renderPart()", etc.
|
|
41
|
+
*
|
|
42
|
+
* Errors that bubble up to the top of runAsynchronously or a route handler are already captured with captureError.
|
|
43
|
+
*/
|
|
35
44
|
declare function captureError(location: string, error: unknown): void;
|
|
36
45
|
type Status = {
|
|
37
46
|
statusCode: number;
|
package/dist/utils/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/errors.tsx"],"sourcesContent":["import { globalVar } from \"./globals\";\nimport { Json } from \"./json\";\nimport { pick } from \"./objects\";\nimport { nicify } from \"./strings\";\n\n\nexport function throwErr(errorMessage: string, extraData?: any): never;\nexport function throwErr(error: Error): never;\nexport function throwErr(...args: StatusErrorConstructorParameters): never;\nexport function throwErr(...args: any[]): never {\n if (typeof args[0] === \"string\") {\n throw new StackAssertionError(args[0], args[1]);\n } else if (args[0] instanceof Error) {\n throw args[0];\n } else {\n // @ts-expect-error\n throw new StatusError(...args);\n }\n}\n\nfunction removeStacktraceNameLine(stack: string): string {\n // some browsers (eg. Chrome) prepend the stack with an extra line with the error name\n const addsNameLine = new Error().stack?.startsWith(\"Error\\n\");\n return stack.split(\"\\n\").slice(addsNameLine ? 1 : 0).join(\"\\n\");\n}\n\n\n/**\n * Concatenates the (original) stacktraces of the given errors onto the first.\n *\n * Useful when you invoke an async function to receive a promise without awaiting it immediately. Browsers are smart\n * enough to keep track of the call stack in async function calls when you invoke `.then` within the same async tick,\n * but if you don't, the stacktrace will be lost.\n *\n * Here's an example of the unwanted behavior:\n *\n * ```tsx\n * async function log() {\n * await wait(0); // simulate an put the task on the event loop\n * console.log(new Error().stack);\n * }\n *\n * async function main() {\n * await log(); // good; prints both \"log\" and \"main\" on the stacktrace\n * log(); // bad; prints only \"log\" on the stacktrace\n * }\n * ```\n */\nexport function concatStacktraces(first: Error, ...errors: Error[]): void {\n // some browsers (eg. Firefox) add an extra empty line at the end\n const addsEmptyLineAtEnd = first.stack?.endsWith(\"\\n\");\n\n\n // Add a reference to this function itself so that we know that stacktraces were concatenated\n // If you are coming here from a stacktrace, please know that the two parts before and after this line are different\n // stacktraces that were concatenated with concatStacktraces\n const separator = removeStacktraceNameLine(new Error().stack ?? \"\").split(\"\\n\")[0];\n\n\n for (const error of errors) {\n const toAppend = removeStacktraceNameLine(error.stack ?? \"\");\n first.stack += (addsEmptyLineAtEnd ? \"\" : \"\\n\") + separator + \"\\n\" + toAppend;\n }\n}\n\n\nexport class StackAssertionError extends Error {\n constructor(message: string, public readonly extraData?: Record<string, any> & ErrorOptions) {\n const disclaimer = `\\n\\nThis is likely an error in Stack. Please make sure you are running the newest version and report it.`;\n super(`${message}${message.endsWith(disclaimer) ? \"\" : disclaimer}`, pick(extraData ?? {}, [\"cause\"]));\n\n Object.defineProperty(this, \"customCaptureExtraArgs\", {\n get() {\n return [this.extraData];\n },\n enumerable: false,\n });\n\n if (process.env.NEXT_PUBLIC_STACK_DEBUGGER_ON_ASSERTION_ERROR === \"true\") {\n debugger;\n }\n }\n}\nStackAssertionError.prototype.name = \"StackAssertionError\";\n\n\nexport function errorToNiceString(error: unknown): string {\n if (!(error instanceof Error)) return `${typeof error}<${nicify(error)}>`;\n return nicify(error, { maxDepth: 8 });\n}\n\n\nconst errorSinks = new Set<(location: string, error: unknown, ...extraArgs: unknown[]) => void>();\nexport function registerErrorSink(sink: (location: string, error: unknown) => void): void {\n if (errorSinks.has(sink)) {\n return;\n }\n errorSinks.add(sink);\n}\nregisterErrorSink((location, error, ...extraArgs) => {\n console.error(\n `\\x1b[41mCaptured error in ${location}:`,\n // HACK: Log a nicified version of the error to get around buggy Next.js pretty-printing\n // https://www.reddit.com/r/nextjs/comments/1gkxdqe/comment/m19kxgn/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button\n errorToNiceString(error),\n ...extraArgs,\n \"\\x1b[0m\",\n );\n});\nregisterErrorSink((location, error, ...extraArgs) => {\n globalVar.stackCapturedErrors = globalVar.stackCapturedErrors ?? [];\n globalVar.stackCapturedErrors.push({ location, error, extraArgs });\n});\n\nexport function captureError(location: string, error: unknown): void {\n for (const sink of errorSinks) {\n sink(\n location,\n error,\n ...error && (typeof error === 'object' || typeof error === 'function') && \"customCaptureExtraArgs\" in error && Array.isArray(error.customCaptureExtraArgs) ? (error.customCaptureExtraArgs as any[]) : [],\n );\n }\n}\n\n\ntype Status = {\n statusCode: number,\n message: string,\n};\n\ntype StatusErrorConstructorParameters =\n| [\n status: Status,\n message?: string\n]\n| [\n statusCode: number | Status,\n message: string,\n];\n\nexport class StatusError extends Error {\n private readonly __stackStatusErrorBrand = \"stack-status-error-brand-sentinel\" as const;\n public name = \"StatusError\";\n public readonly statusCode: number;\n\n public static BadRequest = { statusCode: 400, message: \"Bad Request\" };\n public static Unauthorized = { statusCode: 401, message: \"Unauthorized\" };\n public static PaymentRequired = { statusCode: 402, message: \"Payment Required\" };\n public static Forbidden = { statusCode: 403, message: \"Forbidden\" };\n public static NotFound = { statusCode: 404, message: \"Not Found\" };\n public static MethodNotAllowed = { statusCode: 405, message: \"Method Not Allowed\" };\n public static NotAcceptable = { statusCode: 406, message: \"Not Acceptable\" };\n public static ProxyAuthenticationRequired = { statusCode: 407, message: \"Proxy Authentication Required\" };\n public static RequestTimeout = { statusCode: 408, message: \"Request Timeout\" };\n public static Conflict = { statusCode: 409, message: \"Conflict\" };\n public static Gone = { statusCode: 410, message: \"Gone\" };\n public static LengthRequired = { statusCode: 411, message: \"Length Required\" };\n public static PreconditionFailed = { statusCode: 412, message: \"Precondition Failed\" };\n public static PayloadTooLarge = { statusCode: 413, message: \"Payload Too Large\" };\n public static URITooLong = { statusCode: 414, message: \"URI Too Long\" };\n public static UnsupportedMediaType = { statusCode: 415, message: \"Unsupported Media Type\" };\n public static RangeNotSatisfiable = { statusCode: 416, message: \"Range Not Satisfiable\" };\n public static ExpectationFailed = { statusCode: 417, message: \"Expectation Failed\" };\n public static ImATeapot = { statusCode: 418, message: \"I'm a teapot\" };\n public static MisdirectedRequest = { statusCode: 421, message: \"Misdirected Request\" };\n public static UnprocessableEntity = { statusCode: 422, message: \"Unprocessable Entity\" };\n public static Locked = { statusCode: 423, message: \"Locked\" };\n public static FailedDependency = { statusCode: 424, message: \"Failed Dependency\" };\n public static TooEarly = { statusCode: 425, message: \"Too Early\" };\n public static UpgradeRequired = { statusCode: 426, message: \"Upgrade Required\" };\n public static PreconditionRequired = { statusCode: 428, message: \"Precondition Required\" };\n public static TooManyRequests = { statusCode: 429, message: \"Too Many Requests\" };\n public static RequestHeaderFieldsTooLarge = { statusCode: 431, message: \"Request Header Fields Too Large\" };\n public static UnavailableForLegalReasons = { statusCode: 451, message: \"Unavailable For Legal Reasons\" };\n\n public static InternalServerError = { statusCode: 500, message: \"Internal Server Error\" };\n public static NotImplemented = { statusCode: 501, message: \"Not Implemented\" };\n public static BadGateway = { statusCode: 502, message: \"Bad Gateway\" };\n public static ServiceUnavailable = { statusCode: 503, message: \"Service Unavailable\" };\n public static GatewayTimeout = { statusCode: 504, message: \"Gateway Timeout\" };\n public static HTTPVersionNotSupported = { statusCode: 505, message: \"HTTP Version Not Supported\" };\n public static VariantAlsoNegotiates = { statusCode: 506, message: \"Variant Also Negotiates\" };\n public static InsufficientStorage = { statusCode: 507, message: \"Insufficient Storage\" };\n public static LoopDetected = { statusCode: 508, message: \"Loop Detected\" };\n public static NotExtended = { statusCode: 510, message: \"Not Extended\" };\n public static NetworkAuthenticationRequired = { statusCode: 511, message: \"Network Authentication Required\" };\n\n\n constructor(...args: StatusErrorConstructorParameters);\n constructor(\n status: number | Status,\n message?: string,\n ) {\n if (typeof status === \"object\") {\n message ??= status.message;\n status = status.statusCode;\n }\n super(message);\n this.statusCode = status;\n if (!message) {\n throw new StackAssertionError(\"StatusError always requires a message unless a Status object is passed\", { cause: this });\n }\n }\n\n public static isStatusError(error: unknown): error is StatusError {\n // like instanceof, but also works for errors thrown in other realms or by different versions of the same package\n return typeof error === \"object\" && error !== null && \"__stackStatusErrorBrand\" in error && error.__stackStatusErrorBrand === \"stack-status-error-brand-sentinel\";\n }\n\n public isClientError() {\n return this.statusCode >= 400 && this.statusCode < 500;\n }\n\n public isServerError() {\n return !this.isClientError();\n }\n\n public getStatusCode(): number {\n return this.statusCode;\n }\n\n public getBody(): Uint8Array {\n return new TextEncoder().encode(this.message);\n }\n\n public getHeaders(): Record<string, string[]> {\n return {\n \"Content-Type\": [\"text/plain; charset=utf-8\"],\n };\n }\n\n public toDescriptiveJson(): Json {\n return {\n status_code: this.getStatusCode(),\n message: this.message,\n headers: this.getHeaders(),\n };\n }\n\n /**\n * @deprecated this is not a good way to make status errors human-readable, use toDescriptiveJson instead\n */\n public toHttpJson(): Json {\n return {\n status_code: this.statusCode,\n body: this.message,\n headers: this.getHeaders(),\n };\n }\n}\nStatusError.prototype.name = \"StatusError\";\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/errors.tsx"],"sourcesContent":["import { globalVar } from \"./globals\";\nimport { Json } from \"./json\";\nimport { pick } from \"./objects\";\nimport { nicify } from \"./strings\";\n\n\nexport function throwErr(errorMessage: string, extraData?: any): never;\nexport function throwErr(error: Error): never;\nexport function throwErr(...args: StatusErrorConstructorParameters): never;\nexport function throwErr(...args: any[]): never {\n if (typeof args[0] === \"string\") {\n throw new StackAssertionError(args[0], args[1]);\n } else if (args[0] instanceof Error) {\n throw args[0];\n } else {\n // @ts-expect-error\n throw new StatusError(...args);\n }\n}\n\nfunction removeStacktraceNameLine(stack: string): string {\n // some browsers (eg. Chrome) prepend the stack with an extra line with the error name\n const addsNameLine = new Error().stack?.startsWith(\"Error\\n\");\n return stack.split(\"\\n\").slice(addsNameLine ? 1 : 0).join(\"\\n\");\n}\n\n\n/**\n * Concatenates the (original) stacktraces of the given errors onto the first.\n *\n * Useful when you invoke an async function to receive a promise without awaiting it immediately. Browsers are smart\n * enough to keep track of the call stack in async function calls when you invoke `.then` within the same async tick,\n * but if you don't, the stacktrace will be lost.\n *\n * Here's an example of the unwanted behavior:\n *\n * ```tsx\n * async function log() {\n * await wait(0); // simulate an put the task on the event loop\n * console.log(new Error().stack);\n * }\n *\n * async function main() {\n * await log(); // good; prints both \"log\" and \"main\" on the stacktrace\n * log(); // bad; prints only \"log\" on the stacktrace\n * }\n * ```\n */\nexport function concatStacktraces(first: Error, ...errors: Error[]): void {\n // some browsers (eg. Firefox) add an extra empty line at the end\n const addsEmptyLineAtEnd = first.stack?.endsWith(\"\\n\");\n\n\n // Add a reference to this function itself so that we know that stacktraces were concatenated\n // If you are coming here from a stacktrace, please know that the two parts before and after this line are different\n // stacktraces that were concatenated with concatStacktraces\n const separator = removeStacktraceNameLine(new Error().stack ?? \"\").split(\"\\n\")[0];\n\n\n for (const error of errors) {\n const toAppend = removeStacktraceNameLine(error.stack ?? \"\");\n first.stack += (addsEmptyLineAtEnd ? \"\" : \"\\n\") + separator + \"\\n\" + toAppend;\n }\n}\n\n\nexport class StackAssertionError extends Error {\n constructor(message: string, public readonly extraData?: Record<string, any> & ErrorOptions) {\n const disclaimer = `\\n\\nThis is likely an error in Stack. Please make sure you are running the newest version and report it.`;\n super(`${message}${message.endsWith(disclaimer) ? \"\" : disclaimer}`, pick(extraData ?? {}, [\"cause\"]));\n\n Object.defineProperty(this, \"customCaptureExtraArgs\", {\n get() {\n return [this.extraData];\n },\n enumerable: false,\n });\n\n if (process.env.NEXT_PUBLIC_STACK_DEBUGGER_ON_ASSERTION_ERROR === \"true\") {\n debugger;\n }\n }\n}\nStackAssertionError.prototype.name = \"StackAssertionError\";\n\n\nexport function errorToNiceString(error: unknown): string {\n if (!(error instanceof Error)) return `${typeof error}<${nicify(error)}>`;\n return nicify(error, { maxDepth: 8 });\n}\n\n\nconst errorSinks = new Set<(location: string, error: unknown, ...extraArgs: unknown[]) => void>();\nexport function registerErrorSink(sink: (location: string, error: unknown) => void): void {\n if (errorSinks.has(sink)) {\n return;\n }\n errorSinks.add(sink);\n}\nregisterErrorSink((location, error, ...extraArgs) => {\n console.error(\n `\\x1b[41mCaptured error in ${location}:`,\n // HACK: Log a nicified version of the error to get around buggy Next.js pretty-printing\n // https://www.reddit.com/r/nextjs/comments/1gkxdqe/comment/m19kxgn/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button\n errorToNiceString(error),\n ...extraArgs,\n \"\\x1b[0m\",\n );\n});\nregisterErrorSink((location, error, ...extraArgs) => {\n globalVar.stackCapturedErrors = globalVar.stackCapturedErrors ?? [];\n globalVar.stackCapturedErrors.push({ location, error, extraArgs });\n});\n\n/**\n * Captures an error and sends it to the error sinks (most notably, Sentry). Errors caught with captureError are\n * supposed to be seen by an engineer, so they should be actionable and important.\n *\n * The location string is a machine-readable ID, and should hence not contain spaces or anything like that. Good\n * examples are: \"api-route-handler\", \"renderPart()\", etc.\n *\n * Errors that bubble up to the top of runAsynchronously or a route handler are already captured with captureError.\n */\nexport function captureError(location: string, error: unknown): void {\n for (const sink of errorSinks) {\n sink(\n location,\n error,\n ...error && (typeof error === 'object' || typeof error === 'function') && \"customCaptureExtraArgs\" in error && Array.isArray(error.customCaptureExtraArgs) ? (error.customCaptureExtraArgs as any[]) : [],\n );\n }\n}\n\n\ntype Status = {\n statusCode: number,\n message: string,\n};\n\ntype StatusErrorConstructorParameters =\n| [\n status: Status,\n message?: string\n]\n| [\n statusCode: number | Status,\n message: string,\n];\n\nexport class StatusError extends Error {\n private readonly __stackStatusErrorBrand = \"stack-status-error-brand-sentinel\" as const;\n public name = \"StatusError\";\n public readonly statusCode: number;\n\n public static BadRequest = { statusCode: 400, message: \"Bad Request\" };\n public static Unauthorized = { statusCode: 401, message: \"Unauthorized\" };\n public static PaymentRequired = { statusCode: 402, message: \"Payment Required\" };\n public static Forbidden = { statusCode: 403, message: \"Forbidden\" };\n public static NotFound = { statusCode: 404, message: \"Not Found\" };\n public static MethodNotAllowed = { statusCode: 405, message: \"Method Not Allowed\" };\n public static NotAcceptable = { statusCode: 406, message: \"Not Acceptable\" };\n public static ProxyAuthenticationRequired = { statusCode: 407, message: \"Proxy Authentication Required\" };\n public static RequestTimeout = { statusCode: 408, message: \"Request Timeout\" };\n public static Conflict = { statusCode: 409, message: \"Conflict\" };\n public static Gone = { statusCode: 410, message: \"Gone\" };\n public static LengthRequired = { statusCode: 411, message: \"Length Required\" };\n public static PreconditionFailed = { statusCode: 412, message: \"Precondition Failed\" };\n public static PayloadTooLarge = { statusCode: 413, message: \"Payload Too Large\" };\n public static URITooLong = { statusCode: 414, message: \"URI Too Long\" };\n public static UnsupportedMediaType = { statusCode: 415, message: \"Unsupported Media Type\" };\n public static RangeNotSatisfiable = { statusCode: 416, message: \"Range Not Satisfiable\" };\n public static ExpectationFailed = { statusCode: 417, message: \"Expectation Failed\" };\n public static ImATeapot = { statusCode: 418, message: \"I'm a teapot\" };\n public static MisdirectedRequest = { statusCode: 421, message: \"Misdirected Request\" };\n public static UnprocessableEntity = { statusCode: 422, message: \"Unprocessable Entity\" };\n public static Locked = { statusCode: 423, message: \"Locked\" };\n public static FailedDependency = { statusCode: 424, message: \"Failed Dependency\" };\n public static TooEarly = { statusCode: 425, message: \"Too Early\" };\n public static UpgradeRequired = { statusCode: 426, message: \"Upgrade Required\" };\n public static PreconditionRequired = { statusCode: 428, message: \"Precondition Required\" };\n public static TooManyRequests = { statusCode: 429, message: \"Too Many Requests\" };\n public static RequestHeaderFieldsTooLarge = { statusCode: 431, message: \"Request Header Fields Too Large\" };\n public static UnavailableForLegalReasons = { statusCode: 451, message: \"Unavailable For Legal Reasons\" };\n\n public static InternalServerError = { statusCode: 500, message: \"Internal Server Error\" };\n public static NotImplemented = { statusCode: 501, message: \"Not Implemented\" };\n public static BadGateway = { statusCode: 502, message: \"Bad Gateway\" };\n public static ServiceUnavailable = { statusCode: 503, message: \"Service Unavailable\" };\n public static GatewayTimeout = { statusCode: 504, message: \"Gateway Timeout\" };\n public static HTTPVersionNotSupported = { statusCode: 505, message: \"HTTP Version Not Supported\" };\n public static VariantAlsoNegotiates = { statusCode: 506, message: \"Variant Also Negotiates\" };\n public static InsufficientStorage = { statusCode: 507, message: \"Insufficient Storage\" };\n public static LoopDetected = { statusCode: 508, message: \"Loop Detected\" };\n public static NotExtended = { statusCode: 510, message: \"Not Extended\" };\n public static NetworkAuthenticationRequired = { statusCode: 511, message: \"Network Authentication Required\" };\n\n\n constructor(...args: StatusErrorConstructorParameters);\n constructor(\n status: number | Status,\n message?: string,\n ) {\n if (typeof status === \"object\") {\n message ??= status.message;\n status = status.statusCode;\n }\n super(message);\n this.statusCode = status;\n if (!message) {\n throw new StackAssertionError(\"StatusError always requires a message unless a Status object is passed\", { cause: this });\n }\n }\n\n public static isStatusError(error: unknown): error is StatusError {\n // like instanceof, but also works for errors thrown in other realms or by different versions of the same package\n return typeof error === \"object\" && error !== null && \"__stackStatusErrorBrand\" in error && error.__stackStatusErrorBrand === \"stack-status-error-brand-sentinel\";\n }\n\n public isClientError() {\n return this.statusCode >= 400 && this.statusCode < 500;\n }\n\n public isServerError() {\n return !this.isClientError();\n }\n\n public getStatusCode(): number {\n return this.statusCode;\n }\n\n public getBody(): Uint8Array {\n return new TextEncoder().encode(this.message);\n }\n\n public getHeaders(): Record<string, string[]> {\n return {\n \"Content-Type\": [\"text/plain; charset=utf-8\"],\n };\n }\n\n public toDescriptiveJson(): Json {\n return {\n status_code: this.getStatusCode(),\n message: this.message,\n headers: this.getHeaders(),\n };\n }\n\n /**\n * @deprecated this is not a good way to make status errors human-readable, use toDescriptiveJson instead\n */\n public toHttpJson(): Json {\n return {\n status_code: this.statusCode,\n body: this.message,\n headers: this.getHeaders(),\n };\n }\n}\nStatusError.prototype.name = \"StatusError\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA0B;AAE1B,qBAAqB;AACrB,qBAAuB;AAMhB,SAAS,YAAY,MAAoB;AAC9C,MAAI,OAAO,KAAK,CAAC,MAAM,UAAU;AAC/B,UAAM,IAAI,oBAAoB,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC;AAAA,EAChD,WAAW,KAAK,CAAC,aAAa,OAAO;AACnC,UAAM,KAAK,CAAC;AAAA,EACd,OAAO;AAEL,UAAM,IAAI,YAAY,GAAG,IAAI;AAAA,EAC/B;AACF;AAEA,SAAS,yBAAyB,OAAuB;AAEvD,QAAM,eAAe,IAAI,MAAM,EAAE,OAAO,WAAW,SAAS;AAC5D,SAAO,MAAM,MAAM,IAAI,EAAE,MAAM,eAAe,IAAI,CAAC,EAAE,KAAK,IAAI;AAChE;AAwBO,SAAS,kBAAkB,UAAiB,QAAuB;AAExE,QAAM,qBAAqB,MAAM,OAAO,SAAS,IAAI;AAMrD,QAAM,YAAY,yBAAyB,IAAI,MAAM,EAAE,SAAS,EAAE,EAAE,MAAM,IAAI,EAAE,CAAC;AAGjF,aAAW,SAAS,QAAQ;AAC1B,UAAM,WAAW,yBAAyB,MAAM,SAAS,EAAE;AAC3D,UAAM,UAAU,qBAAqB,KAAK,QAAQ,YAAY,OAAO;AAAA,EACvE;AACF;AAGO,IAAM,sBAAN,cAAkC,MAAM;AAAA,EAC7C,YAAY,SAAiC,WAAgD;AAC3F,UAAM,aAAa;AAAA;AAAA;AACnB,UAAM,GAAG,OAAO,GAAG,QAAQ,SAAS,UAAU,IAAI,KAAK,UAAU,QAAI,qBAAK,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAF1D;AAI3C,WAAO,eAAe,MAAM,0BAA0B;AAAA,MACpD,MAAM;AACJ,eAAO,CAAC,KAAK,SAAS;AAAA,MACxB;AAAA,MACA,YAAY;AAAA,IACd,CAAC;AAED,QAAI,QAAQ,IAAI,kDAAkD,QAAQ;AACxE;AAAA,IACF;AAAA,EACF;AACF;AACA,oBAAoB,UAAU,OAAO;AAG9B,SAAS,kBAAkB,OAAwB;AACxD,MAAI,EAAE,iBAAiB,OAAQ,QAAO,GAAG,OAAO,KAAK,QAAI,uBAAO,KAAK,CAAC;AACtE,aAAO,uBAAO,OAAO,EAAE,UAAU,EAAE,CAAC;AACtC;AAGA,IAAM,aAAa,oBAAI,IAAyE;AACzF,SAAS,kBAAkB,MAAwD;AACxF,MAAI,WAAW,IAAI,IAAI,GAAG;AACxB;AAAA,EACF;AACA,aAAW,IAAI,IAAI;AACrB;AACA,kBAAkB,CAAC,UAAU,UAAU,cAAc;AACnD,UAAQ;AAAA,IACN,6BAA6B,QAAQ;AAAA;AAAA;AAAA,IAGrC,kBAAkB,KAAK;AAAA,IACvB,GAAG;AAAA,IACH;AAAA,EACF;AACF,CAAC;AACD,kBAAkB,CAAC,UAAU,UAAU,cAAc;AACnD,2BAAU,sBAAsB,yBAAU,uBAAuB,CAAC;AAClE,2BAAU,oBAAoB,KAAK,EAAE,UAAU,OAAO,UAAU,CAAC;AACnE,CAAC;AAWM,SAAS,aAAa,UAAkB,OAAsB;AACnE,aAAW,QAAQ,YAAY;AAC7B;AAAA,MACE;AAAA,MACA;AAAA,MACA,GAAG,UAAU,OAAO,UAAU,YAAY,OAAO,UAAU,eAAe,4BAA4B,SAAS,MAAM,QAAQ,MAAM,sBAAsB,IAAK,MAAM,yBAAmC,CAAC;AAAA,IAC1M;AAAA,EACF;AACF;AAkBO,IAAM,cAAN,cAA0B,MAAM;AAAA,EAiDrC,YACE,QACA,SACA;AACA,QAAI,OAAO,WAAW,UAAU;AAC9B,kBAAY,OAAO;AACnB,eAAS,OAAO;AAAA,IAClB;AACA,UAAM,OAAO;AAxDf,SAAiB,0BAA0B;AAC3C,SAAO,OAAO;AAwDZ,SAAK,aAAa;AAClB,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,oBAAoB,0EAA0E,EAAE,OAAO,KAAK,CAAC;AAAA,IACzH;AAAA,EACF;AAAA,EAEA,OAAc,cAAc,OAAsC;AAEhE,WAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,6BAA6B,SAAS,MAAM,4BAA4B;AAAA,EAChI;AAAA,EAEO,gBAAgB;AACrB,WAAO,KAAK,cAAc,OAAO,KAAK,aAAa;AAAA,EACrD;AAAA,EAEO,gBAAgB;AACrB,WAAO,CAAC,KAAK,cAAc;AAAA,EAC7B;AAAA,EAEO,gBAAwB;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,UAAsB;AAC3B,WAAO,IAAI,YAAY,EAAE,OAAO,KAAK,OAAO;AAAA,EAC9C;AAAA,EAEO,aAAuC;AAC5C,WAAO;AAAA,MACL,gBAAgB,CAAC,2BAA2B;AAAA,IAC9C;AAAA,EACF;AAAA,EAEO,oBAA0B;AAC/B,WAAO;AAAA,MACL,aAAa,KAAK,cAAc;AAAA,MAChC,SAAS,KAAK;AAAA,MACd,SAAS,KAAK,WAAW;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,aAAmB;AACxB,WAAO;AAAA,MACL,aAAa,KAAK;AAAA,MAClB,MAAM,KAAK;AAAA,MACX,SAAS,KAAK,WAAW;AAAA,IAC3B;AAAA,EACF;AACF;AA7Ga,YAKG,aAAa,EAAE,YAAY,KAAK,SAAS,cAAc;AAL1D,YAMG,eAAe,EAAE,YAAY,KAAK,SAAS,eAAe;AAN7D,YAOG,kBAAkB,EAAE,YAAY,KAAK,SAAS,mBAAmB;AAPpE,YAQG,YAAY,EAAE,YAAY,KAAK,SAAS,YAAY;AARvD,YASG,WAAW,EAAE,YAAY,KAAK,SAAS,YAAY;AATtD,YAUG,mBAAmB,EAAE,YAAY,KAAK,SAAS,qBAAqB;AAVvE,YAWG,gBAAgB,EAAE,YAAY,KAAK,SAAS,iBAAiB;AAXhE,YAYG,8BAA8B,EAAE,YAAY,KAAK,SAAS,gCAAgC;AAZ7F,YAaG,iBAAiB,EAAE,YAAY,KAAK,SAAS,kBAAkB;AAblE,YAcG,WAAW,EAAE,YAAY,KAAK,SAAS,WAAW;AAdrD,YAeG,OAAO,EAAE,YAAY,KAAK,SAAS,OAAO;AAf7C,YAgBG,iBAAiB,EAAE,YAAY,KAAK,SAAS,kBAAkB;AAhBlE,YAiBG,qBAAqB,EAAE,YAAY,KAAK,SAAS,sBAAsB;AAjB1E,YAkBG,kBAAkB,EAAE,YAAY,KAAK,SAAS,oBAAoB;AAlBrE,YAmBG,aAAa,EAAE,YAAY,KAAK,SAAS,eAAe;AAnB3D,YAoBG,uBAAuB,EAAE,YAAY,KAAK,SAAS,yBAAyB;AApB/E,YAqBG,sBAAsB,EAAE,YAAY,KAAK,SAAS,wBAAwB;AArB7E,YAsBG,oBAAoB,EAAE,YAAY,KAAK,SAAS,qBAAqB;AAtBxE,YAuBG,YAAY,EAAE,YAAY,KAAK,SAAS,eAAe;AAvB1D,YAwBG,qBAAqB,EAAE,YAAY,KAAK,SAAS,sBAAsB;AAxB1E,YAyBG,sBAAsB,EAAE,YAAY,KAAK,SAAS,uBAAuB;AAzB5E,YA0BG,SAAS,EAAE,YAAY,KAAK,SAAS,SAAS;AA1BjD,YA2BG,mBAAmB,EAAE,YAAY,KAAK,SAAS,oBAAoB;AA3BtE,YA4BG,WAAW,EAAE,YAAY,KAAK,SAAS,YAAY;AA5BtD,YA6BG,kBAAkB,EAAE,YAAY,KAAK,SAAS,mBAAmB;AA7BpE,YA8BG,uBAAuB,EAAE,YAAY,KAAK,SAAS,wBAAwB;AA9B9E,YA+BG,kBAAkB,EAAE,YAAY,KAAK,SAAS,oBAAoB;AA/BrE,YAgCG,8BAA8B,EAAE,YAAY,KAAK,SAAS,kCAAkC;AAhC/F,YAiCG,6BAA6B,EAAE,YAAY,KAAK,SAAS,gCAAgC;AAjC5F,YAmCG,sBAAsB,EAAE,YAAY,KAAK,SAAS,wBAAwB;AAnC7E,YAoCG,iBAAiB,EAAE,YAAY,KAAK,SAAS,kBAAkB;AApClE,YAqCG,aAAa,EAAE,YAAY,KAAK,SAAS,cAAc;AArC1D,YAsCG,qBAAqB,EAAE,YAAY,KAAK,SAAS,sBAAsB;AAtC1E,YAuCG,iBAAiB,EAAE,YAAY,KAAK,SAAS,kBAAkB;AAvClE,YAwCG,0BAA0B,EAAE,YAAY,KAAK,SAAS,6BAA6B;AAxCtF,YAyCG,wBAAwB,EAAE,YAAY,KAAK,SAAS,0BAA0B;AAzCjF,YA0CG,sBAAsB,EAAE,YAAY,KAAK,SAAS,uBAAuB;AA1C5E,YA2CG,eAAe,EAAE,YAAY,KAAK,SAAS,gBAAgB;AA3C9D,YA4CG,cAAc,EAAE,YAAY,KAAK,SAAS,eAAe;AA5C5D,YA6CG,gCAAgC,EAAE,YAAY,KAAK,SAAS,kCAAkC;AAiE9G,YAAY,UAAU,OAAO;","names":[]}
|
package/dist/utils/objects.d.mts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
declare function isNotNull<T>(value: T): value is NonNullable<T>;
|
|
2
|
-
type DeepPartial<T> = T extends object ? (T extends
|
|
2
|
+
type DeepPartial<T> = T extends object ? (T extends any[] ? {
|
|
3
|
+
[P in keyof T]: DeepPartial<T[P]>;
|
|
4
|
+
} : {
|
|
3
5
|
[P in keyof T]?: DeepPartial<T[P]>;
|
|
4
6
|
}) : T;
|
|
5
|
-
type DeepRequired<T> = T extends object ?
|
|
7
|
+
type DeepRequired<T> = T extends object ? {
|
|
6
8
|
[P in keyof T]-?: DeepRequired<T[P]>;
|
|
7
|
-
}
|
|
9
|
+
} : T;
|
|
10
|
+
type DeepRequiredOrUndefined<T> = T extends object ? {
|
|
11
|
+
[P in keyof {
|
|
12
|
+
[K in keyof T]-?: K;
|
|
13
|
+
}]: DeepRequiredOrUndefined<T[P]>;
|
|
14
|
+
} : T;
|
|
8
15
|
/**
|
|
9
16
|
* Assumes both objects are primitives, arrays, or non-function plain objects, and compares them deeply.
|
|
10
17
|
*
|
|
@@ -19,12 +26,17 @@ declare function deepPlainClone<T>(obj: T): T;
|
|
|
19
26
|
type DeepMerge<T, U> = U extends any ? DeepMergeNonDistributive<T, U> : never;
|
|
20
27
|
type DeepMergeNonDistributive<T, U> = Omit<T, keyof U> & Omit<U, keyof T> & DeepMergeInner<Pick<T, keyof U & keyof T>, Pick<U, keyof U & keyof T>>;
|
|
21
28
|
type DeepMergeInner<T, U> = {
|
|
22
|
-
[K in
|
|
29
|
+
[K in {
|
|
30
|
+
[Ki in keyof U]-?: Ki;
|
|
31
|
+
}[keyof U]]: undefined extends U[K] ? K extends keyof T ? T[K] extends object ? Exclude<U[K], undefined> extends object ? DeepMerge<T[K], Exclude<U[K], undefined>> : T[K] | Exclude<U[K], undefined> : T[K] | Exclude<U[K], undefined> : Exclude<U[K], undefined> : K extends keyof T ? T[K] extends object ? U[K] extends object ? DeepMerge<T[K], U[K]> : U[K] : U[K] : U[K];
|
|
23
32
|
};
|
|
24
33
|
declare function deepMerge<T extends {}, U extends {}>(baseObj: T, mergeObj: U): DeepMerge<T, U>;
|
|
25
|
-
|
|
34
|
+
type DeepOmit<T, U> = T extends object ? {
|
|
35
|
+
[K in keyof T]: K extends keyof U ? (T[K] extends U[K] ? undefined : T[K]) : T[K];
|
|
36
|
+
} : (T extends U ? undefined : T);
|
|
37
|
+
declare function typedEntries<T extends {}>(obj: T): [Exclude<keyof T, number>, T[keyof T]][];
|
|
26
38
|
declare function typedFromEntries<K extends PropertyKey, V>(entries: (readonly [K, V])[]): Record<K, V>;
|
|
27
|
-
declare function typedKeys<T extends {}>(obj: T): (keyof T)[];
|
|
39
|
+
declare function typedKeys<T extends {}>(obj: T): (Exclude<keyof T, number>)[];
|
|
28
40
|
declare function typedValues<T extends {}>(obj: T): T[keyof T][];
|
|
29
41
|
declare function typedAssign<T extends {}, U extends {}>(target: T, source: U): T & U;
|
|
30
42
|
type FilterUndefined<T> = {
|
|
@@ -65,6 +77,9 @@ declare function hasAndNotUndefined<T extends object, K extends keyof T>(obj: T,
|
|
|
65
77
|
[k in K]: Exclude<T[K], undefined>;
|
|
66
78
|
};
|
|
67
79
|
declare function deleteKey<T extends object, K extends keyof T>(obj: T, key: K): void;
|
|
68
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Returns true iff the value is an object or a function, but not null.
|
|
82
|
+
*/
|
|
83
|
+
declare function isObjectLike(value: unknown): value is object | Function;
|
|
69
84
|
|
|
70
|
-
export { type DeepFilterUndefined, type DeepMerge, type DeepPartial, type DeepRequired, type FilterUndefined, type FilterUndefinedOrNull, deepFilterUndefined, deepMerge, deepPlainClone, deepPlainEquals, deepSortKeys, deleteKey, filterUndefined, filterUndefinedOrNull, get, getOrUndefined, has, hasAndNotUndefined, isCloneable, isNotNull, isObjectLike, mapValues, omit, pick, set, shallowClone, sortKeys, split, typedAssign, typedEntries, typedFromEntries, typedKeys, typedValues };
|
|
85
|
+
export { type DeepFilterUndefined, type DeepMerge, type DeepOmit, type DeepPartial, type DeepRequired, type DeepRequiredOrUndefined, type FilterUndefined, type FilterUndefinedOrNull, deepFilterUndefined, deepMerge, deepPlainClone, deepPlainEquals, deepSortKeys, deleteKey, filterUndefined, filterUndefinedOrNull, get, getOrUndefined, has, hasAndNotUndefined, isCloneable, isNotNull, isObjectLike, mapValues, omit, pick, set, shallowClone, sortKeys, split, typedAssign, typedEntries, typedFromEntries, typedKeys, typedValues };
|
package/dist/utils/objects.d.ts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
declare function isNotNull<T>(value: T): value is NonNullable<T>;
|
|
2
|
-
type DeepPartial<T> = T extends object ? (T extends
|
|
2
|
+
type DeepPartial<T> = T extends object ? (T extends any[] ? {
|
|
3
|
+
[P in keyof T]: DeepPartial<T[P]>;
|
|
4
|
+
} : {
|
|
3
5
|
[P in keyof T]?: DeepPartial<T[P]>;
|
|
4
6
|
}) : T;
|
|
5
|
-
type DeepRequired<T> = T extends object ?
|
|
7
|
+
type DeepRequired<T> = T extends object ? {
|
|
6
8
|
[P in keyof T]-?: DeepRequired<T[P]>;
|
|
7
|
-
}
|
|
9
|
+
} : T;
|
|
10
|
+
type DeepRequiredOrUndefined<T> = T extends object ? {
|
|
11
|
+
[P in keyof {
|
|
12
|
+
[K in keyof T]-?: K;
|
|
13
|
+
}]: DeepRequiredOrUndefined<T[P]>;
|
|
14
|
+
} : T;
|
|
8
15
|
/**
|
|
9
16
|
* Assumes both objects are primitives, arrays, or non-function plain objects, and compares them deeply.
|
|
10
17
|
*
|
|
@@ -19,12 +26,17 @@ declare function deepPlainClone<T>(obj: T): T;
|
|
|
19
26
|
type DeepMerge<T, U> = U extends any ? DeepMergeNonDistributive<T, U> : never;
|
|
20
27
|
type DeepMergeNonDistributive<T, U> = Omit<T, keyof U> & Omit<U, keyof T> & DeepMergeInner<Pick<T, keyof U & keyof T>, Pick<U, keyof U & keyof T>>;
|
|
21
28
|
type DeepMergeInner<T, U> = {
|
|
22
|
-
[K in
|
|
29
|
+
[K in {
|
|
30
|
+
[Ki in keyof U]-?: Ki;
|
|
31
|
+
}[keyof U]]: undefined extends U[K] ? K extends keyof T ? T[K] extends object ? Exclude<U[K], undefined> extends object ? DeepMerge<T[K], Exclude<U[K], undefined>> : T[K] | Exclude<U[K], undefined> : T[K] | Exclude<U[K], undefined> : Exclude<U[K], undefined> : K extends keyof T ? T[K] extends object ? U[K] extends object ? DeepMerge<T[K], U[K]> : U[K] : U[K] : U[K];
|
|
23
32
|
};
|
|
24
33
|
declare function deepMerge<T extends {}, U extends {}>(baseObj: T, mergeObj: U): DeepMerge<T, U>;
|
|
25
|
-
|
|
34
|
+
type DeepOmit<T, U> = T extends object ? {
|
|
35
|
+
[K in keyof T]: K extends keyof U ? (T[K] extends U[K] ? undefined : T[K]) : T[K];
|
|
36
|
+
} : (T extends U ? undefined : T);
|
|
37
|
+
declare function typedEntries<T extends {}>(obj: T): [Exclude<keyof T, number>, T[keyof T]][];
|
|
26
38
|
declare function typedFromEntries<K extends PropertyKey, V>(entries: (readonly [K, V])[]): Record<K, V>;
|
|
27
|
-
declare function typedKeys<T extends {}>(obj: T): (keyof T)[];
|
|
39
|
+
declare function typedKeys<T extends {}>(obj: T): (Exclude<keyof T, number>)[];
|
|
28
40
|
declare function typedValues<T extends {}>(obj: T): T[keyof T][];
|
|
29
41
|
declare function typedAssign<T extends {}, U extends {}>(target: T, source: U): T & U;
|
|
30
42
|
type FilterUndefined<T> = {
|
|
@@ -65,6 +77,9 @@ declare function hasAndNotUndefined<T extends object, K extends keyof T>(obj: T,
|
|
|
65
77
|
[k in K]: Exclude<T[K], undefined>;
|
|
66
78
|
};
|
|
67
79
|
declare function deleteKey<T extends object, K extends keyof T>(obj: T, key: K): void;
|
|
68
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Returns true iff the value is an object or a function, but not null.
|
|
82
|
+
*/
|
|
83
|
+
declare function isObjectLike(value: unknown): value is object | Function;
|
|
69
84
|
|
|
70
|
-
export { type DeepFilterUndefined, type DeepMerge, type DeepPartial, type DeepRequired, type FilterUndefined, type FilterUndefinedOrNull, deepFilterUndefined, deepMerge, deepPlainClone, deepPlainEquals, deepSortKeys, deleteKey, filterUndefined, filterUndefinedOrNull, get, getOrUndefined, has, hasAndNotUndefined, isCloneable, isNotNull, isObjectLike, mapValues, omit, pick, set, shallowClone, sortKeys, split, typedAssign, typedEntries, typedFromEntries, typedKeys, typedValues };
|
|
85
|
+
export { type DeepFilterUndefined, type DeepMerge, type DeepOmit, type DeepPartial, type DeepRequired, type DeepRequiredOrUndefined, type FilterUndefined, type FilterUndefinedOrNull, deepFilterUndefined, deepMerge, deepPlainClone, deepPlainEquals, deepSortKeys, deleteKey, filterUndefined, filterUndefinedOrNull, get, getOrUndefined, has, hasAndNotUndefined, isCloneable, isNotNull, isObjectLike, mapValues, omit, pick, set, shallowClone, sortKeys, split, typedAssign, typedEntries, typedFromEntries, typedKeys, typedValues };
|
package/dist/utils/objects.js
CHANGED
|
@@ -52,6 +52,7 @@ module.exports = __toCommonJS(objects_exports);
|
|
|
52
52
|
var import_errors = require("./errors.js");
|
|
53
53
|
var import_functions = require("./functions.js");
|
|
54
54
|
var import_strings = require("./strings.js");
|
|
55
|
+
var import_types = require("./types.js");
|
|
55
56
|
function isNotNull(value) {
|
|
56
57
|
return value !== null && value !== void 0;
|
|
57
58
|
}
|
|
@@ -140,6 +141,7 @@ function filterUndefined(obj) {
|
|
|
140
141
|
function filterUndefinedOrNull(obj) {
|
|
141
142
|
return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== void 0 && v !== null));
|
|
142
143
|
}
|
|
144
|
+
(0, import_types.typeAssertIs)()();
|
|
143
145
|
function deepFilterUndefined(obj) {
|
|
144
146
|
return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== void 0).map(([k, v]) => [k, isObjectLike(v) ? deepFilterUndefined(v) : v]));
|
|
145
147
|
}
|