@prisma-next/utils 0.3.0-dev.4 → 0.3.0-dev.5

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.
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Checks if two arrays are equal using Object.is() for element comparison.
3
+ * Arrays are considered equal if they have the same length and each element
4
+ * at corresponding indices is equal according to Object.is().
5
+ *
6
+ * @param a - First array to compare
7
+ * @param b - Second array to compare
8
+ * @returns true if arrays are equal, false otherwise
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * isArrayEqual(['a', 'b'], ['a', 'b']); // true
13
+ * isArrayEqual(['a'], ['a', 'b']); // false
14
+ * isArrayEqual([0], [-0]); // false (Object.is distinguishes +0 and -0)
15
+ * ```
16
+ */
17
+ export declare function isArrayEqual<T>(a: readonly T[], b: readonly T[]): boolean;
18
+ //# sourceMappingURL=array-equal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array-equal.d.ts","sourceRoot":"","sources":["../src/array-equal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,EAAE,GAAG,OAAO,CAUzE"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Returns an object with the key/value if value is defined, otherwise an empty object.
3
+ *
4
+ * Use with spread to conditionally include optional properties while satisfying
5
+ * exactOptionalPropertyTypes. This is explicit about which properties are optional
6
+ * and won't inadvertently strip other undefined values.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * // Instead of:
11
+ * const obj = {
12
+ * required: 'value',
13
+ * ...(optional ? { optional } : {}),
14
+ * };
15
+ *
16
+ * // Use:
17
+ * const obj = {
18
+ * required: 'value',
19
+ * ...ifDefined('optional', optional),
20
+ * };
21
+ * ```
22
+ */
23
+ export declare function ifDefined<K extends string, V>(key: K, value: V | undefined): Record<never, never> | {
24
+ [P in K]: V;
25
+ };
26
+ //# sourceMappingURL=defined.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defined.d.ts","sourceRoot":"","sources":["../src/defined.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAC3C,GAAG,EAAE,CAAC,EACN,KAAK,EAAE,CAAC,GAAG,SAAS,GACnB,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG;KAAG,CAAC,IAAI,CAAC,GAAG,CAAC;CAAE,CAExC"}
@@ -1,19 +1,2 @@
1
- /**
2
- * Checks if two arrays are equal using Object.is() for element comparison.
3
- * Arrays are considered equal if they have the same length and each element
4
- * at corresponding indices is equal according to Object.is().
5
- *
6
- * @param a - First array to compare
7
- * @param b - Second array to compare
8
- * @returns true if arrays are equal, false otherwise
9
- *
10
- * @example
11
- * ```typescript
12
- * isArrayEqual(['a', 'b'], ['a', 'b']); // true
13
- * isArrayEqual(['a'], ['a', 'b']); // false
14
- * isArrayEqual([0], [-0]); // false (Object.is distinguishes +0 and -0)
15
- * ```
16
- */
17
- declare function isArrayEqual<T>(a: readonly T[], b: readonly T[]): boolean;
18
-
19
- export { isArrayEqual };
1
+ export { isArrayEqual } from '../array-equal';
2
+ //# sourceMappingURL=array-equal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array-equal.d.ts","sourceRoot":"","sources":["../../src/exports/array-equal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
@@ -1,27 +1,2 @@
1
- /**
2
- * Returns an object with the key/value if value is defined, otherwise an empty object.
3
- *
4
- * Use with spread to conditionally include optional properties while satisfying
5
- * exactOptionalPropertyTypes. This is explicit about which properties are optional
6
- * and won't inadvertently strip other undefined values.
7
- *
8
- * @example
9
- * ```typescript
10
- * // Instead of:
11
- * const obj = {
12
- * required: 'value',
13
- * ...(optional ? { optional } : {}),
14
- * };
15
- *
16
- * // Use:
17
- * const obj = {
18
- * required: 'value',
19
- * ...ifDefined('optional', optional),
20
- * };
21
- * ```
22
- */
23
- declare function ifDefined<K extends string, V>(key: K, value: V | undefined): Record<never, never> | {
24
- [P in K]: V;
25
- };
26
-
27
- export { ifDefined };
1
+ export { ifDefined } from '../defined';
2
+ //# sourceMappingURL=defined.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defined.d.ts","sourceRoot":"","sources":["../../src/exports/defined.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC"}
@@ -1,19 +1,3 @@
1
- /**
2
- * Minimal metadata extracted from a database URL for logging or error output.
3
- * Sensitive fields (password, full URL) are never returned.
4
- */
5
- interface RedactedDatabaseUrl {
6
- readonly host?: string;
7
- readonly port?: string;
8
- readonly database?: string;
9
- readonly username?: string;
10
- }
11
- /**
12
- * Redacts a database connection URL to a minimal metadata object.
13
- *
14
- * Parsing errors are ignored and result in an empty object so callers never
15
- * leak raw URLs when the input is malformed.
16
- */
17
- declare function redactDatabaseUrl(url: string): RedactedDatabaseUrl;
18
-
19
- export { type RedactedDatabaseUrl, redactDatabaseUrl };
1
+ export type { RedactedDatabaseUrl } from '../redact-db-url';
2
+ export { redactDatabaseUrl } from '../redact-db-url';
3
+ //# sourceMappingURL=redact-db-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact-db-url.d.ts","sourceRoot":"","sources":["../../src/exports/redact-db-url.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -1,51 +1,3 @@
1
- /**
2
- * Generic Result type for representing success or failure outcomes.
3
- *
4
- * This is the standard way to return "expected failures" as values rather than
5
- * throwing exceptions. See docs/Error Handling.md for the full taxonomy.
6
- *
7
- * Naming rationale:
8
- * - `Ok<T>` / `NotOk<F>` mirror the `ok: true/false` discriminator
9
- * - `NotOk` avoids collision with domain types like "Failure" or "Error"
10
- * - `failure` property distinguishes from JS Error semantics
11
- */
12
- /**
13
- * Represents a successful result containing a value.
14
- */
15
- interface Ok<T> {
16
- readonly ok: true;
17
- readonly value: T;
18
- assertOk(): T;
19
- assertNotOk(): never;
20
- }
21
- /**
22
- * Represents an unsuccessful result containing failure details.
23
- */
24
- interface NotOk<F> {
25
- readonly ok: false;
26
- readonly failure: F;
27
- assertOk(): never;
28
- assertNotOk(): F;
29
- }
30
- /**
31
- * A discriminated union representing either success (Ok) or failure (NotOk).
32
- *
33
- * @typeParam T - The success value type
34
- * @typeParam F - The failure details type
35
- */
36
- type Result<T, F> = Ok<T> | NotOk<F>;
37
- /**
38
- * Creates a successful result.
39
- */
40
- declare function ok<T>(value: T): Ok<T>;
41
- /**
42
- * Creates an unsuccessful result.
43
- */
44
- declare function notOk<F>(failure: F): NotOk<F>;
45
- /**
46
- * Returns a successful void result.
47
- * Use this for validation checks that don't produce a value.
48
- */
49
- declare function okVoid(): Ok<void>;
50
-
51
- export { type NotOk, type Ok, type Result, notOk, ok, okVoid };
1
+ export type { NotOk, Ok, Result } from '../result';
2
+ export { notOk, ok, okVoid } from '../result';
3
+ //# sourceMappingURL=result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/exports/result.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Minimal metadata extracted from a database URL for logging or error output.
3
+ * Sensitive fields (password, full URL) are never returned.
4
+ */
5
+ export interface RedactedDatabaseUrl {
6
+ readonly host?: string;
7
+ readonly port?: string;
8
+ readonly database?: string;
9
+ readonly username?: string;
10
+ }
11
+ /**
12
+ * Redacts a database connection URL to a minimal metadata object.
13
+ *
14
+ * Parsing errors are ignored and result in an empty object so callers never
15
+ * leak raw URLs when the input is malformed.
16
+ */
17
+ export declare function redactDatabaseUrl(url: string): RedactedDatabaseUrl;
18
+ //# sourceMappingURL=redact-db-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact-db-url.d.ts","sourceRoot":"","sources":["../src/redact-db-url.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,CAclE"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Generic Result type for representing success or failure outcomes.
3
+ *
4
+ * This is the standard way to return "expected failures" as values rather than
5
+ * throwing exceptions. See docs/Error Handling.md for the full taxonomy.
6
+ *
7
+ * Naming rationale:
8
+ * - `Ok<T>` / `NotOk<F>` mirror the `ok: true/false` discriminator
9
+ * - `NotOk` avoids collision with domain types like "Failure" or "Error"
10
+ * - `failure` property distinguishes from JS Error semantics
11
+ */
12
+ /**
13
+ * Represents a successful result containing a value.
14
+ */
15
+ export interface Ok<T> {
16
+ readonly ok: true;
17
+ readonly value: T;
18
+ assertOk(): T;
19
+ assertNotOk(): never;
20
+ }
21
+ /**
22
+ * Represents an unsuccessful result containing failure details.
23
+ */
24
+ export interface NotOk<F> {
25
+ readonly ok: false;
26
+ readonly failure: F;
27
+ assertOk(): never;
28
+ assertNotOk(): F;
29
+ }
30
+ /**
31
+ * A discriminated union representing either success (Ok) or failure (NotOk).
32
+ *
33
+ * @typeParam T - The success value type
34
+ * @typeParam F - The failure details type
35
+ */
36
+ export type Result<T, F> = Ok<T> | NotOk<F>;
37
+ /**
38
+ * Creates a successful result.
39
+ */
40
+ export declare function ok<T>(value: T): Ok<T>;
41
+ /**
42
+ * Creates an unsuccessful result.
43
+ */
44
+ export declare function notOk<F>(failure: F): NotOk<F>;
45
+ /**
46
+ * Returns a successful void result.
47
+ * Use this for validation checks that don't produce a value.
48
+ */
49
+ export declare function okVoid(): Ok<void>;
50
+ //# sourceMappingURL=result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;GAEG;AACH,MAAM,WAAW,EAAE,CAAC,CAAC;IACnB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,QAAQ,IAAI,CAAC,CAAC;IACd,WAAW,IAAI,KAAK,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,KAAK,CAAC,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,QAAQ,IAAI,KAAK,CAAC;IAClB,WAAW,IAAI,CAAC,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;AA6E5C;;GAEG;AACH,wBAAgB,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAErC;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAE7C;AAQD;;;GAGG;AACH,wBAAgB,MAAM,IAAI,EAAE,CAAC,IAAI,CAAC,CAEjC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma-next/utils",
3
- "version": "0.3.0-dev.4",
3
+ "version": "0.3.0-dev.5",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "Shared utility functions for Prisma Next",
@@ -11,7 +11,8 @@
11
11
  "vitest": "4.0.16"
12
12
  },
13
13
  "files": [
14
- "dist"
14
+ "dist",
15
+ "src"
15
16
  ],
16
17
  "exports": {
17
18
  "./array-equal": {
@@ -32,7 +33,7 @@
32
33
  }
33
34
  },
34
35
  "scripts": {
35
- "build": "tsup --config tsup.config.ts",
36
+ "build": "tsup --config tsup.config.ts && tsc --project tsconfig.build.json",
36
37
  "test": "vitest run",
37
38
  "test:coverage": "vitest run --coverage",
38
39
  "typecheck": "tsc --project tsconfig.json --noEmit",
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Checks if two arrays are equal using Object.is() for element comparison.
3
+ * Arrays are considered equal if they have the same length and each element
4
+ * at corresponding indices is equal according to Object.is().
5
+ *
6
+ * @param a - First array to compare
7
+ * @param b - Second array to compare
8
+ * @returns true if arrays are equal, false otherwise
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * isArrayEqual(['a', 'b'], ['a', 'b']); // true
13
+ * isArrayEqual(['a'], ['a', 'b']); // false
14
+ * isArrayEqual([0], [-0]); // false (Object.is distinguishes +0 and -0)
15
+ * ```
16
+ */
17
+ export function isArrayEqual<T>(a: readonly T[], b: readonly T[]): boolean {
18
+ if (a.length !== b.length) {
19
+ return false;
20
+ }
21
+ for (let i = 0; i < a.length; i++) {
22
+ if (!Object.is(a[i], b[i])) {
23
+ return false;
24
+ }
25
+ }
26
+ return true;
27
+ }
package/src/defined.ts ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Returns an object with the key/value if value is defined, otherwise an empty object.
3
+ *
4
+ * Use with spread to conditionally include optional properties while satisfying
5
+ * exactOptionalPropertyTypes. This is explicit about which properties are optional
6
+ * and won't inadvertently strip other undefined values.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * // Instead of:
11
+ * const obj = {
12
+ * required: 'value',
13
+ * ...(optional ? { optional } : {}),
14
+ * };
15
+ *
16
+ * // Use:
17
+ * const obj = {
18
+ * required: 'value',
19
+ * ...ifDefined('optional', optional),
20
+ * };
21
+ * ```
22
+ */
23
+ export function ifDefined<K extends string, V>(
24
+ key: K,
25
+ value: V | undefined,
26
+ ): Record<never, never> | { [P in K]: V } {
27
+ return value !== undefined ? ({ [key]: value } as { [P in K]: V }) : {};
28
+ }
@@ -0,0 +1 @@
1
+ export { isArrayEqual } from '../array-equal';
@@ -0,0 +1 @@
1
+ export { ifDefined } from '../defined';
@@ -0,0 +1,2 @@
1
+ export type { RedactedDatabaseUrl } from '../redact-db-url';
2
+ export { redactDatabaseUrl } from '../redact-db-url';
@@ -0,0 +1,2 @@
1
+ export type { NotOk, Ok, Result } from '../result';
2
+ export { notOk, ok, okVoid } from '../result';
@@ -0,0 +1,34 @@
1
+ import { ifDefined } from './defined';
2
+
3
+ /**
4
+ * Minimal metadata extracted from a database URL for logging or error output.
5
+ * Sensitive fields (password, full URL) are never returned.
6
+ */
7
+ export interface RedactedDatabaseUrl {
8
+ readonly host?: string;
9
+ readonly port?: string;
10
+ readonly database?: string;
11
+ readonly username?: string;
12
+ }
13
+
14
+ /**
15
+ * Redacts a database connection URL to a minimal metadata object.
16
+ *
17
+ * Parsing errors are ignored and result in an empty object so callers never
18
+ * leak raw URLs when the input is malformed.
19
+ */
20
+ export function redactDatabaseUrl(url: string): RedactedDatabaseUrl {
21
+ try {
22
+ const parsed = new URL(url);
23
+ const database = parsed.pathname?.replace(/^\//, '') || undefined;
24
+ return {
25
+ ...ifDefined('host', parsed.hostname || undefined),
26
+ ...ifDefined('port', parsed.port || undefined),
27
+ ...ifDefined('database', database),
28
+ ...ifDefined('username', parsed.username || undefined),
29
+ };
30
+ } catch {
31
+ // Ignore parsing errors; return empty metadata
32
+ return {};
33
+ }
34
+ }
package/src/result.ts ADDED
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Generic Result type for representing success or failure outcomes.
3
+ *
4
+ * This is the standard way to return "expected failures" as values rather than
5
+ * throwing exceptions. See docs/Error Handling.md for the full taxonomy.
6
+ *
7
+ * Naming rationale:
8
+ * - `Ok<T>` / `NotOk<F>` mirror the `ok: true/false` discriminator
9
+ * - `NotOk` avoids collision with domain types like "Failure" or "Error"
10
+ * - `failure` property distinguishes from JS Error semantics
11
+ */
12
+
13
+ /**
14
+ * Represents a successful result containing a value.
15
+ */
16
+ export interface Ok<T> {
17
+ readonly ok: true;
18
+ readonly value: T;
19
+ assertOk(): T;
20
+ assertNotOk(): never;
21
+ }
22
+
23
+ /**
24
+ * Represents an unsuccessful result containing failure details.
25
+ */
26
+ export interface NotOk<F> {
27
+ readonly ok: false;
28
+ readonly failure: F;
29
+ assertOk(): never;
30
+ assertNotOk(): F;
31
+ }
32
+
33
+ /**
34
+ * A discriminated union representing either success (Ok) or failure (NotOk).
35
+ *
36
+ * @typeParam T - The success value type
37
+ * @typeParam F - The failure details type
38
+ */
39
+ export type Result<T, F> = Ok<T> | NotOk<F>;
40
+
41
+ /**
42
+ * Result class that implements both Ok and NotOk variants.
43
+ */
44
+ class ResultImpl<T, F> {
45
+ readonly ok: boolean;
46
+ private readonly _value?: T;
47
+ private readonly _failure?: F;
48
+
49
+ private constructor(ok: boolean, valueOrFailure: T | F) {
50
+ this.ok = ok;
51
+ if (ok) {
52
+ this._value = valueOrFailure as T;
53
+ } else {
54
+ this._failure = valueOrFailure as F;
55
+ }
56
+ Object.freeze(this);
57
+ }
58
+
59
+ get value(): T {
60
+ if (!this.ok) {
61
+ throw new Error('Cannot access value on NotOk result');
62
+ }
63
+ // biome-ignore lint/style/noNonNullAssertion: must be present if ok is true
64
+ return this._value!;
65
+ }
66
+
67
+ get failure(): F {
68
+ if (this.ok) {
69
+ throw new Error('Cannot access failure on Ok result');
70
+ }
71
+ // biome-ignore lint/style/noNonNullAssertion: must be present if ok is false
72
+ return this._failure!;
73
+ }
74
+
75
+ /**
76
+ * Creates a successful result.
77
+ */
78
+ static ok<T, F = never>(value: T): Ok<T> {
79
+ // TypeScript cannot express discriminated return types for a single implementation.
80
+ // Cast is safe: ok=true guarantees this is an Ok<T> at runtime.
81
+ return new ResultImpl<T, F>(true, value) as unknown as Ok<T>;
82
+ }
83
+
84
+ /**
85
+ * Creates an unsuccessful result.
86
+ */
87
+ static notOk<T = never, F = unknown>(failure: F): NotOk<F> {
88
+ // TypeScript cannot express discriminated return types for a single implementation.
89
+ // Cast is safe: ok=false guarantees this is a NotOk<F> at runtime.
90
+ return new ResultImpl<T, F>(false, failure) as unknown as NotOk<F>;
91
+ }
92
+
93
+ /**
94
+ * Asserts that this result is Ok and returns the value.
95
+ * Throws if the result is NotOk.
96
+ */
97
+ assertOk(this: Result<T, F>): T {
98
+ if (!this.ok) {
99
+ throw new Error('Expected Ok result but got NotOk');
100
+ }
101
+ return this.value;
102
+ }
103
+
104
+ /**
105
+ * Asserts that this result is NotOk and returns the failure.
106
+ * Throws if the result is Ok.
107
+ */
108
+ assertNotOk(this: Result<T, F>): F {
109
+ if (this.ok) {
110
+ throw new Error('Expected NotOk result but got Ok');
111
+ }
112
+ return this.failure;
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Creates a successful result.
118
+ */
119
+ export function ok<T>(value: T): Ok<T> {
120
+ return ResultImpl.ok(value);
121
+ }
122
+
123
+ /**
124
+ * Creates an unsuccessful result.
125
+ */
126
+ export function notOk<F>(failure: F): NotOk<F> {
127
+ return ResultImpl.notOk(failure);
128
+ }
129
+
130
+ /**
131
+ * Singleton for void success results.
132
+ * Use this for validation checks that don't produce a value.
133
+ */
134
+ const OK_VOID: Ok<void> = ResultImpl.ok<void>(undefined);
135
+
136
+ /**
137
+ * Returns a successful void result.
138
+ * Use this for validation checks that don't produce a value.
139
+ */
140
+ export function okVoid(): Ok<void> {
141
+ return OK_VOID;
142
+ }