immutable-builtins 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Francesco Salvi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # Immutable Built-ins
2
+
3
+ Dependency-free collection of immutable replacements for JavaScript builtins
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ yarn add immutable-builtins
9
+ ```
10
+
11
+ ## Example Usage
12
+
13
+ ```typescript
14
+ import { ImmutableDate } from 'immutable-builtins';
15
+
16
+ const d1 = new ImmutableDate();
17
+ const d2 = new ImmutableDate(d1.toMutable().setFullYear(0));
18
+
19
+ // TypeScript error: "Property 'setFullYear' does not exist on type 'ImmutableDate'";
20
+ // Runtime/JavaScript error: "Cannot use a mutating method on an ImmutableDate instance"
21
+ d1.setFullYear(0);
22
+ ```
23
+
24
+ ## Contributing
25
+
26
+ Issues and PRs welcome!
27
+
28
+ ## License
29
+
30
+ MIT
@@ -0,0 +1,41 @@
1
+ /**
2
+ * This is the *instance* type
3
+ */
4
+ export type ImmutableDate = Omit<Date, 'setTime' | 'setMilliseconds' | 'setUTCMilliseconds' | 'setSeconds' | 'setUTCSeconds' | 'setMinutes' | 'setUTCMinutes' | 'setHours' | 'setUTCHours' | 'setDate' | 'setUTCDate' | 'setMonth' | 'setUTCMonth' | 'setFullYear' | 'setUTCFullYear' | 'setYear'> & {
5
+ readonly __ImmutableDate__brand: undefined;
6
+ /**
7
+ * Creates a new regular (mutable) date by cloning the current instance
8
+ */
9
+ toMutable(): Date;
10
+ };
11
+ /**
12
+ * Notes for users:
13
+ *
14
+ * A derived `Date` definition where all the mutating methods have been disabled
15
+ * both at compile-time (TS) and runtime (JS).
16
+ * To obtain (cast to) a regular `Date` from it, use the `toMutable` extension method.
17
+ * Constructor signatures support is identical to that of `Date`, with the added
18
+ * benefit that it automatically throws in case an `Invalid Date` is yielded internally.
19
+ *
20
+ * ---
21
+ * Notes for maintainers:
22
+ *
23
+ * This is the class/constructor definition
24
+ * - we implement a class that extends Date
25
+ * - we forbid invocation of methods that mutate the internal date value (runtime guards)
26
+ * - we assign the new class (constructor) to a constant that we type as
27
+ * a modified DateConstructor that instead of returning Date returns our
28
+ * "trimmed" version without setters (plus the additional `toMutable` utility).
29
+ */
30
+ export declare const ImmutableDate: {
31
+ readonly prototype: ImmutableDate;
32
+ new (): ImmutableDate;
33
+ new (value: number | string | Date | ImmutableDate): ImmutableDate;
34
+ new (year: number, monthIndex: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): ImmutableDate;
35
+ /** @see Date.parse */
36
+ parse(s: string): number;
37
+ /** @see Date.UTC */
38
+ UTC(...args: Parameters<DateConstructor['UTC']>): number;
39
+ /** @see Date.now */
40
+ now(): number;
41
+ };
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImmutableDate = void 0;
4
+ /**
5
+ * Notes for users:
6
+ *
7
+ * A derived `Date` definition where all the mutating methods have been disabled
8
+ * both at compile-time (TS) and runtime (JS).
9
+ * To obtain (cast to) a regular `Date` from it, use the `toMutable` extension method.
10
+ * Constructor signatures support is identical to that of `Date`, with the added
11
+ * benefit that it automatically throws in case an `Invalid Date` is yielded internally.
12
+ *
13
+ * ---
14
+ * Notes for maintainers:
15
+ *
16
+ * This is the class/constructor definition
17
+ * - we implement a class that extends Date
18
+ * - we forbid invocation of methods that mutate the internal date value (runtime guards)
19
+ * - we assign the new class (constructor) to a constant that we type as
20
+ * a modified DateConstructor that instead of returning Date returns our
21
+ * "trimmed" version without setters (plus the additional `toMutable` utility).
22
+ */
23
+ const ImmutableDate = class extends Date {
24
+ __ImmutableDate__brand;
25
+ setTime = throwCannotUseMutatingMethodError;
26
+ setMilliseconds = throwCannotUseMutatingMethodError;
27
+ setUTCMilliseconds = throwCannotUseMutatingMethodError;
28
+ setSeconds = throwCannotUseMutatingMethodError;
29
+ setUTCSeconds = throwCannotUseMutatingMethodError;
30
+ setMinutes = throwCannotUseMutatingMethodError;
31
+ setUTCMinutes = throwCannotUseMutatingMethodError;
32
+ setHours = throwCannotUseMutatingMethodError;
33
+ setUTCHours = throwCannotUseMutatingMethodError;
34
+ setDate = throwCannotUseMutatingMethodError;
35
+ setUTCDate = throwCannotUseMutatingMethodError;
36
+ setMonth = throwCannotUseMutatingMethodError;
37
+ setUTCMonth = throwCannotUseMutatingMethodError;
38
+ setFullYear = throwCannotUseMutatingMethodError;
39
+ setUTCFullYear = throwCannotUseMutatingMethodError;
40
+ /* override */ setYear = throwCannotUseMutatingMethodError; // not included in default lib
41
+ // as an added QoL improvement, let's also enforce the construction of valid dates
42
+ constructor(...args) {
43
+ // @ts-expect-error[TS2556]: A spread argument must either have a tuple type or be passed to a rest parameter.
44
+ super(...args);
45
+ if (isNaN(this.valueOf())) {
46
+ throw new Error('Could not construct a valid date');
47
+ }
48
+ }
49
+ toMutable() {
50
+ return new Date(this.valueOf());
51
+ }
52
+ };
53
+ exports.ImmutableDate = ImmutableDate;
54
+ function throwCannotUseMutatingMethodError() {
55
+ throw new Error('Cannot use a mutating method on an ImmutableDate instance');
56
+ }
57
+ ;
58
+ //# sourceMappingURL=ImmutableDate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImmutableDate.js","sourceRoot":"","sources":["../../src/ImmutableDate.ts"],"names":[],"mappings":";;;AA6BA;;;;;;;;;;;;;;;;;;GAkBG;AACI,MAAM,aAAa,GAgBtB,KAAM,SAAQ,IAAI;IACX,sBAAsB,CAAY;IAElC,OAAO,GAAiB,iCAAiC,CAAC;IAC1D,eAAe,GAAiB,iCAAiC,CAAC;IAClE,kBAAkB,GAAiB,iCAAiC,CAAC;IACrE,UAAU,GAAiB,iCAAiC,CAAC;IAC7D,aAAa,GAAiB,iCAAiC,CAAC;IAChE,UAAU,GAAiB,iCAAiC,CAAC;IAC7D,aAAa,GAAiB,iCAAiC,CAAC;IAChE,QAAQ,GAAiB,iCAAiC,CAAC;IAC3D,WAAW,GAAiB,iCAAiC,CAAC;IAC9D,OAAO,GAAiB,iCAAiC,CAAC;IAC1D,UAAU,GAAiB,iCAAiC,CAAC;IAC7D,QAAQ,GAAiB,iCAAiC,CAAC;IAC3D,WAAW,GAAiB,iCAAiC,CAAC;IAC9D,WAAW,GAAiB,iCAAiC,CAAC;IAC9D,cAAc,GAAiB,iCAAiC,CAAC;IAC1E,cAAc,CAAC,OAAO,GAAiB,iCAAiC,CAAC,CAAC,8BAA8B;IAExG,kFAAkF;IAClF,YAAY,GAAG,IAAe;QAC5B,8GAA8G;QAC9G,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;QAEf,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,SAAS;QACP,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAClC,CAAC;CACF,CAAC;AAjDW,QAAA,aAAa,iBAiDxB;AAEF,SAAS,iCAAiC;IACxC,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;AAC/E,CAAC;AAAA,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { ImmutableURLSearchParamsUnbranded } from './ImmutableURLSearchParams';
2
+ /**
3
+ * This is the *instance* type
4
+ */
5
+ export type ImmutableURL = {
6
+ readonly [K in keyof URL]: K extends 'searchParams' ? ImmutableURLSearchParamsUnbranded : URL[K];
7
+ } & {
8
+ readonly __ImmutableURL__brand: undefined;
9
+ };
10
+ /**
11
+ * This is the class/constructor definition
12
+ */
13
+ export declare const ImmutableURL: {
14
+ readonly prototype: ImmutableURL;
15
+ new (url: string | URL | ImmutableURL, base?: string | URL | ImmutableURL): ImmutableURL;
16
+ /** @see {URL.canParse} */
17
+ canParse(url: string | URL, base?: string): boolean;
18
+ /** @see {URL.createObjectURL} */
19
+ createObjectURL(obj: Blob): string;
20
+ /** @see {URL.revokeObjectURL} */
21
+ revokeObjectURL(url: string): void;
22
+ };
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImmutableURL = void 0;
4
+ const ImmutableURLSearchParams_1 = require("./ImmutableURLSearchParams");
5
+ /**
6
+ * This is the class/constructor definition
7
+ */
8
+ const ImmutableURL = class extends URL {
9
+ __ImmutableURL__brand;
10
+ constructor(...args) {
11
+ // @ts-expect-error[TS2556]: A spread argument must either have a tuple type or be passed to a rest parameter.
12
+ super(...args);
13
+ const makePropImmutable = (propName) => {
14
+ const propValue = this[propName];
15
+ Object.defineProperties(this, {
16
+ [propName]: {
17
+ configurable: false,
18
+ get: () => propValue,
19
+ set: () => {
20
+ throw new Error('Cannot use property setter on an ImmutableURL instance');
21
+ }
22
+ }
23
+ });
24
+ };
25
+ makePropImmutable('hash');
26
+ makePropImmutable('host');
27
+ makePropImmutable('hostname');
28
+ makePropImmutable('href');
29
+ makePropImmutable('origin');
30
+ makePropImmutable('password');
31
+ makePropImmutable('pathname');
32
+ makePropImmutable('port');
33
+ makePropImmutable('protocol');
34
+ makePropImmutable('search');
35
+ makePropImmutable('username');
36
+ const searchParams = this.searchParams;
37
+ Object.defineProperties(this, {
38
+ searchParams: {
39
+ configurable: false,
40
+ get: () => new ImmutableURLSearchParams_1.ImmutableURLSearchParams(searchParams),
41
+ set: () => {
42
+ throw new Error('Cannot use property setter on an ImmutableURL instance');
43
+ }
44
+ },
45
+ });
46
+ }
47
+ };
48
+ exports.ImmutableURL = ImmutableURL;
49
+ //# sourceMappingURL=ImmutableURL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImmutableURL.js","sourceRoot":"","sources":["../../src/ImmutableURL.ts"],"names":[],"mappings":";;;AAAA,yEAAyG;AAazG;;GAEG;AACI,MAAM,YAAY,GAWrB,KAAM,SAAQ,GAAG;IACV,qBAAqB,CAAY;IAE1C,YAAY,GAAG,IAAe;QAC5B,8GAA8G;QAC9G,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;QAEf,MAAM,iBAAiB,GAAG,CAAC,QAAmB,EAAQ,EAAE;YACtD,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;YAEjC,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE;gBAC5B,CAAC,QAAQ,CAAC,EAAE;oBACV,YAAY,EAAE,KAAK;oBACnB,GAAG,EAAE,GAAqB,EAAE,CAAC,SAAS;oBACtC,GAAG,EAAE,GAAW,EAAE;wBAChB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;oBAC5E,CAAC;iBACF;aACF,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC1B,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC1B,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAC9B,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC1B,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC5B,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAC9B,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAC9B,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC1B,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAC9B,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC5B,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAE9B,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QAEvC,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE;YAC5B,YAAY,EAAE;gBACZ,YAAY,EAAE,KAAK;gBACnB,GAAG,EAAE,GAA6B,EAAE,CAAC,IAAI,mDAAwB,CAAC,YAAY,CAAC;gBAC/E,GAAG,EAAE,GAAW,EAAE;oBAChB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;gBAC5E,CAAC;aACD;SACH,CAAC,CAAC;IACL,CAAC;CACF,CAAC;AAxDW,QAAA,YAAY,gBAwDvB"}
@@ -0,0 +1,14 @@
1
+ export type ImmutableURLSearchParamsUnbranded = Readonly<Omit<URLSearchParams, 'append' | 'delete' | 'set' | 'sort'>>;
2
+ /**
3
+ * This is the *instance* type
4
+ */
5
+ export type ImmutableURLSearchParams = ImmutableURLSearchParamsUnbranded & {
6
+ readonly __ImmutableURLSearchParams__brand: undefined;
7
+ };
8
+ /**
9
+ * This is the class/constructor definition
10
+ */
11
+ export declare const ImmutableURLSearchParams: {
12
+ readonly prototype: ImmutableURLSearchParams;
13
+ new (init?: string[][] | Record<string, string> | string | URLSearchParams | ImmutableURLSearchParams): ImmutableURLSearchParams;
14
+ };
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImmutableURLSearchParams = void 0;
4
+ /**
5
+ * This is the class/constructor definition
6
+ */
7
+ const ImmutableURLSearchParams = class extends URLSearchParams {
8
+ __ImmutableURLSearchParams__brand;
9
+ append = throwCannotUseMutatingMethodError;
10
+ delete = throwCannotUseMutatingMethodError;
11
+ set = throwCannotUseMutatingMethodError;
12
+ sort = throwCannotUseMutatingMethodError;
13
+ // eslint-disable-next-line @typescript-eslint/no-useless-constructor
14
+ constructor(...args) {
15
+ // @ts-expect-error[TS2345]: Argument of type unknown is not assignable to parameter of type...
16
+ super(...args);
17
+ }
18
+ };
19
+ exports.ImmutableURLSearchParams = ImmutableURLSearchParams;
20
+ function throwCannotUseMutatingMethodError() {
21
+ throw new Error('Cannot use a mutating method on an ImmutableURLSearchParams instance');
22
+ }
23
+ ;
24
+ //# sourceMappingURL=ImmutableURLSearchParams.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImmutableURLSearchParams.js","sourceRoot":"","sources":["../../src/ImmutableURLSearchParams.ts"],"names":[],"mappings":";;;AAcA;;GAEG;AACI,MAAM,wBAAwB,GAIjC,KAAM,SAAQ,eAAe;IACtB,iCAAiC,CAAY;IAE7C,MAAM,GAAe,iCAAiC,CAAC;IACvD,MAAM,GAAe,iCAAiC,CAAC;IACvD,GAAG,GAAe,iCAAiC,CAAC;IACpD,IAAI,GAAe,iCAAiC,CAAC;IAE9D,qEAAqE;IACrE,YAAY,GAAG,IAAe;QAC5B,+FAA+F;QAC/F,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACjB,CAAC;CACF,CAAC;AAjBW,QAAA,wBAAwB,4BAiBnC;AAEF,SAAS,iCAAiC;IACxC,MAAM,IAAI,KAAK,CACb,sEAAsE,CACvE,CAAC;AACJ,CAAC;AAAA,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { ImmutableDate } from './ImmutableDate';
2
+ export { ImmutableURL } from './ImmutableURL';
3
+ export { ImmutableURLSearchParams } from './ImmutableURLSearchParams';
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImmutableURLSearchParams = exports.ImmutableURL = exports.ImmutableDate = void 0;
4
+ var ImmutableDate_1 = require("./ImmutableDate");
5
+ Object.defineProperty(exports, "ImmutableDate", { enumerable: true, get: function () { return ImmutableDate_1.ImmutableDate; } });
6
+ var ImmutableURL_1 = require("./ImmutableURL");
7
+ Object.defineProperty(exports, "ImmutableURL", { enumerable: true, get: function () { return ImmutableURL_1.ImmutableURL; } });
8
+ var ImmutableURLSearchParams_1 = require("./ImmutableURLSearchParams");
9
+ Object.defineProperty(exports, "ImmutableURLSearchParams", { enumerable: true, get: function () { return ImmutableURLSearchParams_1.ImmutableURLSearchParams; } });
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AACrB,uEAAsE;AAA7D,oIAAA,wBAAwB,OAAA"}
@@ -0,0 +1 @@
1
+ {"type": "commonjs"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * This is the *instance* type
3
+ */
4
+ export type ImmutableDate = Omit<Date, 'setTime' | 'setMilliseconds' | 'setUTCMilliseconds' | 'setSeconds' | 'setUTCSeconds' | 'setMinutes' | 'setUTCMinutes' | 'setHours' | 'setUTCHours' | 'setDate' | 'setUTCDate' | 'setMonth' | 'setUTCMonth' | 'setFullYear' | 'setUTCFullYear' | 'setYear'> & {
5
+ readonly __ImmutableDate__brand: undefined;
6
+ /**
7
+ * Creates a new regular (mutable) date by cloning the current instance
8
+ */
9
+ toMutable(): Date;
10
+ };
11
+ /**
12
+ * Notes for users:
13
+ *
14
+ * A derived `Date` definition where all the mutating methods have been disabled
15
+ * both at compile-time (TS) and runtime (JS).
16
+ * To obtain (cast to) a regular `Date` from it, use the `toMutable` extension method.
17
+ * Constructor signatures support is identical to that of `Date`, with the added
18
+ * benefit that it automatically throws in case an `Invalid Date` is yielded internally.
19
+ *
20
+ * ---
21
+ * Notes for maintainers:
22
+ *
23
+ * This is the class/constructor definition
24
+ * - we implement a class that extends Date
25
+ * - we forbid invocation of methods that mutate the internal date value (runtime guards)
26
+ * - we assign the new class (constructor) to a constant that we type as
27
+ * a modified DateConstructor that instead of returning Date returns our
28
+ * "trimmed" version without setters (plus the additional `toMutable` utility).
29
+ */
30
+ export declare const ImmutableDate: {
31
+ readonly prototype: ImmutableDate;
32
+ new (): ImmutableDate;
33
+ new (value: number | string | Date | ImmutableDate): ImmutableDate;
34
+ new (year: number, monthIndex: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): ImmutableDate;
35
+ /** @see Date.parse */
36
+ parse(s: string): number;
37
+ /** @see Date.UTC */
38
+ UTC(...args: Parameters<DateConstructor['UTC']>): number;
39
+ /** @see Date.now */
40
+ now(): number;
41
+ };
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Notes for users:
3
+ *
4
+ * A derived `Date` definition where all the mutating methods have been disabled
5
+ * both at compile-time (TS) and runtime (JS).
6
+ * To obtain (cast to) a regular `Date` from it, use the `toMutable` extension method.
7
+ * Constructor signatures support is identical to that of `Date`, with the added
8
+ * benefit that it automatically throws in case an `Invalid Date` is yielded internally.
9
+ *
10
+ * ---
11
+ * Notes for maintainers:
12
+ *
13
+ * This is the class/constructor definition
14
+ * - we implement a class that extends Date
15
+ * - we forbid invocation of methods that mutate the internal date value (runtime guards)
16
+ * - we assign the new class (constructor) to a constant that we type as
17
+ * a modified DateConstructor that instead of returning Date returns our
18
+ * "trimmed" version without setters (plus the additional `toMutable` utility).
19
+ */
20
+ export const ImmutableDate = class extends Date {
21
+ __ImmutableDate__brand;
22
+ setTime = throwCannotUseMutatingMethodError;
23
+ setMilliseconds = throwCannotUseMutatingMethodError;
24
+ setUTCMilliseconds = throwCannotUseMutatingMethodError;
25
+ setSeconds = throwCannotUseMutatingMethodError;
26
+ setUTCSeconds = throwCannotUseMutatingMethodError;
27
+ setMinutes = throwCannotUseMutatingMethodError;
28
+ setUTCMinutes = throwCannotUseMutatingMethodError;
29
+ setHours = throwCannotUseMutatingMethodError;
30
+ setUTCHours = throwCannotUseMutatingMethodError;
31
+ setDate = throwCannotUseMutatingMethodError;
32
+ setUTCDate = throwCannotUseMutatingMethodError;
33
+ setMonth = throwCannotUseMutatingMethodError;
34
+ setUTCMonth = throwCannotUseMutatingMethodError;
35
+ setFullYear = throwCannotUseMutatingMethodError;
36
+ setUTCFullYear = throwCannotUseMutatingMethodError;
37
+ /* override */ setYear = throwCannotUseMutatingMethodError; // not included in default lib
38
+ // as an added QoL improvement, let's also enforce the construction of valid dates
39
+ constructor(...args) {
40
+ // @ts-expect-error[TS2556]: A spread argument must either have a tuple type or be passed to a rest parameter.
41
+ super(...args);
42
+ if (isNaN(this.valueOf())) {
43
+ throw new Error('Could not construct a valid date');
44
+ }
45
+ }
46
+ toMutable() {
47
+ return new Date(this.valueOf());
48
+ }
49
+ };
50
+ function throwCannotUseMutatingMethodError() {
51
+ throw new Error('Cannot use a mutating method on an ImmutableDate instance');
52
+ }
53
+ ;
54
+ //# sourceMappingURL=ImmutableDate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImmutableDate.js","sourceRoot":"","sources":["../../src/ImmutableDate.ts"],"names":[],"mappings":"AA6BA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,aAAa,GAgBtB,KAAM,SAAQ,IAAI;IACX,sBAAsB,CAAY;IAElC,OAAO,GAAiB,iCAAiC,CAAC;IAC1D,eAAe,GAAiB,iCAAiC,CAAC;IAClE,kBAAkB,GAAiB,iCAAiC,CAAC;IACrE,UAAU,GAAiB,iCAAiC,CAAC;IAC7D,aAAa,GAAiB,iCAAiC,CAAC;IAChE,UAAU,GAAiB,iCAAiC,CAAC;IAC7D,aAAa,GAAiB,iCAAiC,CAAC;IAChE,QAAQ,GAAiB,iCAAiC,CAAC;IAC3D,WAAW,GAAiB,iCAAiC,CAAC;IAC9D,OAAO,GAAiB,iCAAiC,CAAC;IAC1D,UAAU,GAAiB,iCAAiC,CAAC;IAC7D,QAAQ,GAAiB,iCAAiC,CAAC;IAC3D,WAAW,GAAiB,iCAAiC,CAAC;IAC9D,WAAW,GAAiB,iCAAiC,CAAC;IAC9D,cAAc,GAAiB,iCAAiC,CAAC;IAC1E,cAAc,CAAC,OAAO,GAAiB,iCAAiC,CAAC,CAAC,8BAA8B;IAExG,kFAAkF;IAClF,YAAY,GAAG,IAAe;QAC5B,8GAA8G;QAC9G,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;QAEf,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,SAAS;QACP,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAClC,CAAC;CACF,CAAC;AAEF,SAAS,iCAAiC;IACxC,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;AAC/E,CAAC;AAAA,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { ImmutableURLSearchParamsUnbranded } from './ImmutableURLSearchParams.js';
2
+ /**
3
+ * This is the *instance* type
4
+ */
5
+ export type ImmutableURL = {
6
+ readonly [K in keyof URL]: K extends 'searchParams' ? ImmutableURLSearchParamsUnbranded : URL[K];
7
+ } & {
8
+ readonly __ImmutableURL__brand: undefined;
9
+ };
10
+ /**
11
+ * This is the class/constructor definition
12
+ */
13
+ export declare const ImmutableURL: {
14
+ readonly prototype: ImmutableURL;
15
+ new (url: string | URL | ImmutableURL, base?: string | URL | ImmutableURL): ImmutableURL;
16
+ /** @see {URL.canParse} */
17
+ canParse(url: string | URL, base?: string): boolean;
18
+ /** @see {URL.createObjectURL} */
19
+ createObjectURL(obj: Blob): string;
20
+ /** @see {URL.revokeObjectURL} */
21
+ revokeObjectURL(url: string): void;
22
+ };
@@ -0,0 +1,45 @@
1
+ import { ImmutableURLSearchParams } from './ImmutableURLSearchParams.js';
2
+ /**
3
+ * This is the class/constructor definition
4
+ */
5
+ export const ImmutableURL = class extends URL {
6
+ __ImmutableURL__brand;
7
+ constructor(...args) {
8
+ // @ts-expect-error[TS2556]: A spread argument must either have a tuple type or be passed to a rest parameter.
9
+ super(...args);
10
+ const makePropImmutable = (propName) => {
11
+ const propValue = this[propName];
12
+ Object.defineProperties(this, {
13
+ [propName]: {
14
+ configurable: false,
15
+ get: () => propValue,
16
+ set: () => {
17
+ throw new Error('Cannot use property setter on an ImmutableURL instance');
18
+ }
19
+ }
20
+ });
21
+ };
22
+ makePropImmutable('hash');
23
+ makePropImmutable('host');
24
+ makePropImmutable('hostname');
25
+ makePropImmutable('href');
26
+ makePropImmutable('origin');
27
+ makePropImmutable('password');
28
+ makePropImmutable('pathname');
29
+ makePropImmutable('port');
30
+ makePropImmutable('protocol');
31
+ makePropImmutable('search');
32
+ makePropImmutable('username');
33
+ const searchParams = this.searchParams;
34
+ Object.defineProperties(this, {
35
+ searchParams: {
36
+ configurable: false,
37
+ get: () => new ImmutableURLSearchParams(searchParams),
38
+ set: () => {
39
+ throw new Error('Cannot use property setter on an ImmutableURL instance');
40
+ }
41
+ },
42
+ });
43
+ }
44
+ };
45
+ //# sourceMappingURL=ImmutableURL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImmutableURL.js","sourceRoot":"","sources":["../../src/ImmutableURL.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAqC,MAAM,4BAA4B,CAAC;AAazG;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAWrB,KAAM,SAAQ,GAAG;IACV,qBAAqB,CAAY;IAE1C,YAAY,GAAG,IAAe;QAC5B,8GAA8G;QAC9G,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;QAEf,MAAM,iBAAiB,GAAG,CAAC,QAAmB,EAAQ,EAAE;YACtD,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;YAEjC,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE;gBAC5B,CAAC,QAAQ,CAAC,EAAE;oBACV,YAAY,EAAE,KAAK;oBACnB,GAAG,EAAE,GAAqB,EAAE,CAAC,SAAS;oBACtC,GAAG,EAAE,GAAW,EAAE;wBAChB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;oBAC5E,CAAC;iBACF;aACF,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC1B,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC1B,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAC9B,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC1B,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC5B,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAC9B,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAC9B,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC1B,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAC9B,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC5B,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAE9B,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QAEvC,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE;YAC5B,YAAY,EAAE;gBACZ,YAAY,EAAE,KAAK;gBACnB,GAAG,EAAE,GAA6B,EAAE,CAAC,IAAI,wBAAwB,CAAC,YAAY,CAAC;gBAC/E,GAAG,EAAE,GAAW,EAAE;oBAChB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;gBAC5E,CAAC;aACD;SACH,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -0,0 +1,14 @@
1
+ export type ImmutableURLSearchParamsUnbranded = Readonly<Omit<URLSearchParams, 'append' | 'delete' | 'set' | 'sort'>>;
2
+ /**
3
+ * This is the *instance* type
4
+ */
5
+ export type ImmutableURLSearchParams = ImmutableURLSearchParamsUnbranded & {
6
+ readonly __ImmutableURLSearchParams__brand: undefined;
7
+ };
8
+ /**
9
+ * This is the class/constructor definition
10
+ */
11
+ export declare const ImmutableURLSearchParams: {
12
+ readonly prototype: ImmutableURLSearchParams;
13
+ new (init?: string[][] | Record<string, string> | string | URLSearchParams | ImmutableURLSearchParams): ImmutableURLSearchParams;
14
+ };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * This is the class/constructor definition
3
+ */
4
+ export const ImmutableURLSearchParams = class extends URLSearchParams {
5
+ __ImmutableURLSearchParams__brand;
6
+ append = throwCannotUseMutatingMethodError;
7
+ delete = throwCannotUseMutatingMethodError;
8
+ set = throwCannotUseMutatingMethodError;
9
+ sort = throwCannotUseMutatingMethodError;
10
+ // eslint-disable-next-line @typescript-eslint/no-useless-constructor
11
+ constructor(...args) {
12
+ // @ts-expect-error[TS2345]: Argument of type unknown is not assignable to parameter of type...
13
+ super(...args);
14
+ }
15
+ };
16
+ function throwCannotUseMutatingMethodError() {
17
+ throw new Error('Cannot use a mutating method on an ImmutableURLSearchParams instance');
18
+ }
19
+ ;
20
+ //# sourceMappingURL=ImmutableURLSearchParams.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImmutableURLSearchParams.js","sourceRoot":"","sources":["../../src/ImmutableURLSearchParams.ts"],"names":[],"mappings":"AAcA;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAIjC,KAAM,SAAQ,eAAe;IACtB,iCAAiC,CAAY;IAE7C,MAAM,GAAe,iCAAiC,CAAC;IACvD,MAAM,GAAe,iCAAiC,CAAC;IACvD,GAAG,GAAe,iCAAiC,CAAC;IACpD,IAAI,GAAe,iCAAiC,CAAC;IAE9D,qEAAqE;IACrE,YAAY,GAAG,IAAe;QAC5B,+FAA+F;QAC/F,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACjB,CAAC;CACF,CAAC;AAEF,SAAS,iCAAiC;IACxC,MAAM,IAAI,KAAK,CACb,sEAAsE,CACvE,CAAC;AACJ,CAAC;AAAA,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { ImmutableDate } from './ImmutableDate.js';
2
+ export { ImmutableURL } from './ImmutableURL.js';
3
+ export { ImmutableURLSearchParams } from './ImmutableURLSearchParams.js';
@@ -0,0 +1,4 @@
1
+ export { ImmutableDate } from './ImmutableDate.js';
2
+ export { ImmutableURL } from './ImmutableURL.js';
3
+ export { ImmutableURLSearchParams } from './ImmutableURLSearchParams.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "immutable-builtins",
3
+ "version": "1.0.0",
4
+ "description": "Dependency-free collection of immutable replacements for JavaScript builtins",
5
+ "keywords": [
6
+ "immutable",
7
+ "immutability",
8
+ "builtins",
9
+ "readonly",
10
+ "value-object",
11
+ "date",
12
+ "url",
13
+ "urlsearchparams",
14
+ "javascript",
15
+ "typescript"
16
+ ],
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/francescosalvi/immutable-builtins.git"
20
+ },
21
+ "author": "Francesco Salvi <salvsuperb@gmail.com>",
22
+ "license": "MIT",
23
+ "private": false,
24
+ "type": "module",
25
+ "files": ["dist"],
26
+ "types": "./dist/esm/index.d.ts",
27
+ "module": "./dist/esm/index.js",
28
+ "main": "./dist/cjs/index.js",
29
+ "exports": {
30
+ ".": {
31
+ "import": {
32
+ "types": "./dist/esm/index.d.ts",
33
+ "default": "./dist/esm/index.js"
34
+ },
35
+ "require": {
36
+ "types": "./dist/cjs/index.d.ts",
37
+ "default": "./dist/cjs/index.js"
38
+ }
39
+ }
40
+ },
41
+ "sideEffects": false,
42
+ "scripts": {
43
+ "clean": "rimraf dist",
44
+ "prebuild": "yarn clean",
45
+ "build": "yarn build:esm && yarn build:cjs",
46
+ "build:esm": "tsc",
47
+ "build:cjs": "tsc --module commonjs --outDir dist/cjs",
48
+ "postbuild:esm": "yarn exec tsc-esm-fix --target='target/es6'",
49
+ "postbuild:cjs": "echo '{\"type\": \"commonjs\"}' > dist/cjs/package.json",
50
+ "test": "jest",
51
+ "lint": "eslint ."
52
+ },
53
+ "devDependencies": {
54
+ "@eslint/js": "^9.39.2",
55
+ "@types/eslint": "^9.6.1",
56
+ "@types/jest": "^30.0.0",
57
+ "@types/node": "24",
58
+ "date-fns": "^4.1.0",
59
+ "eslint": "^9.39.2",
60
+ "jest": "^30.2.0",
61
+ "rimraf": "^6.1.2",
62
+ "ts-jest": "^29.4.6",
63
+ "tsc-esm-fix": "^3.1.2",
64
+ "typescript": "^5.9.3",
65
+ "typescript-eslint": "^8.49.0"
66
+ }
67
+ }