@codeleap/debug 6.3.0 → 6.8.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.
@@ -0,0 +1,55 @@
1
+ import { Keyof, StringRecord } from '@codeleap/types';
2
+ import { EnvironmentStore, EnvironmentManagerConfig, Editor } from './types';
3
+ /**
4
+ * Runtime switchboard for backend environments in debug builds.
5
+ *
6
+ * The override is opt-in: until `setEnabled` is called the manager always
7
+ * returns `defaultEnvironment`, making it safe to instantiate unconditionally.
8
+ * State is persisted via `@codeleap/store` `globalState` so it survives page
9
+ * reloads, but the `enabledBy` flag gates whether that persisted state is
10
+ * actually honoured.
11
+ *
12
+ * When the active environment is `customEnvironment`, `serverUrl` validates the
13
+ * stored URL against a strict regex and falls back to `defaultEnvironment` if
14
+ * it fails — callers can rely on `serverUrl` always returning a usable value.
15
+ */
16
+ export declare class EnvironmentManager<T extends StringRecord> {
17
+ private config;
18
+ private store;
19
+ private initialStoreValue;
20
+ readonly editors: {
21
+ readonly SYSTEM: "system";
22
+ readonly USER: "user";
23
+ };
24
+ get environments(): T;
25
+ get defaultConfig(): EnvironmentStore<T>;
26
+ constructor(config: EnvironmentManagerConfig<T>);
27
+ testUrl(url: string | undefined): boolean;
28
+ get env(): EnvironmentStore<T>;
29
+ setEnabled(by?: Editor | false): by is import("@codeleap/types").ValueOf<{
30
+ readonly SYSTEM: "system";
31
+ readonly USER: "user";
32
+ }>;
33
+ get isEnabled(): boolean;
34
+ get isEnabledBy(): Editor;
35
+ get isEnabledBySystem(): boolean;
36
+ get isEnabledByUser(): boolean;
37
+ get is(): Record<Capitalize<Keyof<T> extends string ? Keyof<T> : string>, boolean>;
38
+ get serverUrl(): string;
39
+ setEnvironment(environment: Keyof<T>): void;
40
+ isEnvironment(env: Keyof<T>): boolean;
41
+ setCustomUrl(url: string): void;
42
+ use(): {
43
+ enabled: boolean;
44
+ enabledByUser: boolean;
45
+ enabledBySystem: boolean;
46
+ config: {
47
+ environment: keyof T;
48
+ customUrl: string;
49
+ };
50
+ changed: boolean;
51
+ customUrl: string;
52
+ setCustomUrl: import("react").Dispatch<import("react").SetStateAction<string>>;
53
+ };
54
+ }
55
+ //# sourceMappingURL=class.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"class.d.ts","sourceRoot":"","sources":["../../src/EnvironmentManager/class.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,YAAY,EAAc,MAAM,iBAAiB,CAAA;AAGjE,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAG5E;;;;;;;;;;;;GAYG;AACH,qBAAa,kBAAkB,CAAC,CAAC,SAAS,YAAY;IAmBxC,OAAO,CAAC,MAAM;IAlB1B,OAAO,CAAC,KAAK,CAAqD;IAElE,OAAO,CAAC,iBAAiB,CAAqB;IAE9C,QAAQ,CAAC,OAAO;;;MAAU;IAE1B,IAAI,YAAY,MAEf;IAED,IAAI,aAAa,IAKV,gBAAgB,CAAC,CAAC,CAAC,CACzB;gBAEmB,MAAM,EAAE,wBAAwB,CAAC,CAAC,CAAC;IASvD,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAM/B,IAAI,GAAG,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAY7B;IAED,UAAU,CAAC,EAAE,GAAE,MAAM,GAAG,KAAa;;;;IAMrC,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,iBAAiB,IAAI,OAAO,CAE/B;IAED,IAAI,eAAe,IAAI,OAAO,CAE7B;IAED,IAAI,EAAE,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,OAAO,CAAC,CAOjF;IAED,IAAI,SAAS,WAYZ;IAED,cAAc,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;IAKpC,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO;IAKrC,YAAY,CAAC,GAAG,EAAE,MAAM;IAUxB,GAAG;;;;;;;;;;;;CAmBJ"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Identifies who enabled the environment override — the application itself
3
+ * (`SYSTEM`) or an end user via a debug UI (`USER`). Used to gate which
4
+ * controls are exposed and whether the override survives a session reset.
5
+ */
6
+ export declare const EDITORS: {
7
+ readonly SYSTEM: "system";
8
+ readonly USER: "user";
9
+ };
10
+ //# sourceMappingURL=const.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"const.d.ts","sourceRoot":"","sources":["../../src/EnvironmentManager/const.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,OAAO;;;CAGV,CAAA"}
@@ -0,0 +1,10 @@
1
+ import { StringRecord } from '@codeleap/types';
2
+ import { EnvironmentManager } from './class';
3
+ import { EnvironmentManagerConfig } from './types';
4
+ /**
5
+ * Preferred entry point for instantiating an `EnvironmentManager`.
6
+ * Keeps call-sites free of the generic `new` syntax and makes the config
7
+ * shape the only public API surface that needs to be imported.
8
+ */
9
+ export declare function createEnvironmentManager<T extends StringRecord>(config: EnvironmentManagerConfig<T>): EnvironmentManager<T>;
10
+ //# sourceMappingURL=factor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factor.d.ts","sourceRoot":"","sources":["../../src/EnvironmentManager/factor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAC5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAA;AAElD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,SAAS,YAAY,EAAE,MAAM,EAAE,wBAAwB,CAAC,CAAC,CAAC,yBAEnG"}
@@ -0,0 +1,4 @@
1
+ export * from './factor';
2
+ export * from './class';
3
+ export * from './types';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/EnvironmentManager/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA"}
@@ -0,0 +1,27 @@
1
+ import { Keyof, StringRecord, ValueOf } from '@codeleap/types';
2
+ import { EDITORS } from './const';
3
+ /** `null` means the override is disabled; a non-null value identifies who enabled it. */
4
+ export type Editor = ValueOf<typeof EDITORS> | null;
5
+ /**
6
+ * `customEnvironment` names the key whose URL is taken from `EnvironmentStore.customUrl`
7
+ * rather than the `environments` map, so it must exist as a key in `T` even though its
8
+ * map value is ignored at runtime. `persistKey` controls the localStorage slot;
9
+ * omitting it falls back to `'environment-manager'`.
10
+ */
11
+ export type EnvironmentManagerConfig<T extends StringRecord> = {
12
+ environments: T;
13
+ defaultEnvironment: Keyof<T>;
14
+ customEnvironment: Keyof<T>;
15
+ persistKey?: string;
16
+ };
17
+ /**
18
+ * Persisted slice of debug state. When `enabledBy` is `null` the manager
19
+ * ignores `environment` and `customUrl` entirely, returning the default config
20
+ * instead — so the store being populated does not mean the override is active.
21
+ */
22
+ export type EnvironmentStore<T extends StringRecord> = {
23
+ environment: Keyof<T>;
24
+ customUrl: string;
25
+ enabledBy: Editor;
26
+ };
27
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/EnvironmentManager/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEjC,yFAAyF;AACzF,MAAM,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,OAAO,CAAC,GAAG,IAAI,CAAA;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,wBAAwB,CAAC,CAAC,SAAS,YAAY,IAAI;IAC7D,YAAY,EAAE,CAAC,CAAA;IACf,kBAAkB,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;IAC5B,iBAAiB,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,YAAY,IAAI;IACrD,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA"}
@@ -0,0 +1,118 @@
1
+ import { FakeItem, FakeRestApiOptions, PaginationResponse } from './types';
2
+ /**
3
+ * A fake REST API implementation for testing and prototyping.
4
+ * Provides CRUD operations with pagination support and optional request delays.
5
+ * @template T - The type of items to manage, must extend FakeItem
6
+ * @template F - The type of filters to apply when listing items
7
+ */
8
+ export declare class FakeRestApi<T extends FakeItem, F = Record<string, unknown>> {
9
+ private data;
10
+ private options;
11
+ /**
12
+ * Gets the ID of the last item in the data array.
13
+ * @private
14
+ * @returns The highest ID or 0 if no items exist
15
+ */
16
+ private get lastId();
17
+ /**
18
+ * Gets the name of the API.
19
+ * @returns The API name
20
+ */
21
+ get name(): string;
22
+ /**
23
+ * Gets the current count of items.
24
+ * @returns The number of items in the data array
25
+ */
26
+ get count(): number;
27
+ /**
28
+ * Creates a new FakeRestApi instance.
29
+ * @param options - Configuration options for the API
30
+ */
31
+ constructor(options: FakeRestApiOptions<T, F>);
32
+ /**
33
+ * Initializes the data array with items up to maxCount.
34
+ * @private
35
+ */
36
+ private initialize;
37
+ /**
38
+ * Updates the API options partially.
39
+ * @param newOptions - Partial options to update
40
+ */
41
+ setOptions(newOptions: Partial<FakeRestApiOptions<T, F>>): void;
42
+ /**
43
+ * Generates a new item using the generator function.
44
+ * @param id - The ID for the new item (defaults to lastId + 1)
45
+ * @returns A newly generated item
46
+ */
47
+ generateItem(id?: T['id']): T;
48
+ /**
49
+ * Introduces an artificial delay if enabled in options.
50
+ * @private
51
+ * @returns A promise that resolves after the delay period
52
+ */
53
+ private delay;
54
+ /**
55
+ * Builds a URL with pagination parameters.
56
+ * @private
57
+ * @param limit - Number of items per page
58
+ * @param offset - Starting position
59
+ * @returns A formatted URL string
60
+ */
61
+ private buildUrl;
62
+ /**
63
+ * Retrieves a paginated list of items with optional filtering.
64
+ * @param limit - Number of items to return (default: 10)
65
+ * @param offset - Starting position (default: 0)
66
+ * @param filters - Optional filters to apply
67
+ * @returns A promise that resolves to a paginated response
68
+ */
69
+ listItems(limit?: number, offset?: number, filters?: F): Promise<PaginationResponse<T>>;
70
+ /**
71
+ * Retrieves a single item by ID.
72
+ * @param id - The ID of the item to retrieve
73
+ * @returns A promise that resolves to the requested item
74
+ * @throws {Error} If the item is not found
75
+ */
76
+ retrieveItem(id: T['id']): Promise<T>;
77
+ /**
78
+ * Creates a new item and adds it to the data array.
79
+ * @param item - Optional partial item data (ID will be auto-generated)
80
+ * @returns A promise that resolves to the created item
81
+ */
82
+ createItem(item?: Partial<T>): Promise<T>;
83
+ /**
84
+ * Updates an existing item by ID.
85
+ * @param id - The ID of the item to update
86
+ * @param updates - Partial item data to update
87
+ * @returns A promise that resolves to the updated item
88
+ * @throws {Error} If the item is not found
89
+ */
90
+ updateItem(id: T['id'], updates: Partial<T>): Promise<T>;
91
+ /**
92
+ * Deletes an item by ID.
93
+ * @param id - The ID of the item to delete
94
+ * @returns A promise that resolves to the deleted item
95
+ * @throws {Error} If the item is not found
96
+ */
97
+ deleteItem(id: T['id']): Promise<T>;
98
+ /**
99
+ * Resets the data array to its initial state by regenerating all items.
100
+ */
101
+ reset(): void;
102
+ /**
103
+ * Clears all items from the data array.
104
+ */
105
+ clear(): void;
106
+ /**
107
+ * Gets a readonly copy of all items in the data array.
108
+ * @returns A frozen array of all items
109
+ */
110
+ getData(): readonly T[];
111
+ /**
112
+ * Gets a single item by ID without delay.
113
+ * @param id - The ID of the item to retrieve
114
+ * @returns The item if found, undefined otherwise
115
+ */
116
+ getItem(id: T['id']): T | undefined;
117
+ }
118
+ //# sourceMappingURL=class.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"class.d.ts","sourceRoot":"","sources":["../../src/FakeRestApi/class.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAE1E;;;;;GAKG;AACH,qBAAa,WAAW,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACtE,OAAO,CAAC,IAAI,CAAU;IACtB,OAAO,CAAC,OAAO,CAAoC;IAEnD;;;;OAIG;IACH,OAAO,KAAK,MAAM,GAEjB;IAED;;;OAGG;IACH,IAAW,IAAI,IAAI,MAAM,CAExB;IAED;;;OAGG;IACH,IAAW,KAAK,IAAI,MAAM,CAEzB;IAED;;;OAGG;gBACS,OAAO,EAAE,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC;IAY7C;;;OAGG;IACH,OAAO,CAAC,UAAU;IAMlB;;;OAGG;IACI,UAAU,CAAC,UAAU,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI;IAItE;;;;OAIG;IACI,YAAY,CAAC,EAAE,GAAE,CAAC,CAAC,IAAI,CAAmB,GAAG,CAAC;IAIrD;;;;OAIG;YACW,KAAK;IAQnB;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ;IAIhB;;;;;;OAMG;IACG,SAAS,CACb,KAAK,SAAK,EACV,MAAM,SAAI,EACV,OAAO,CAAC,EAAE,CAAC,GACV,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAsBjC;;;;;OAKG;IACG,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAY3C;;;;OAIG;IACG,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAW/C;;;;;;OAMG;IACG,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAc9D;;;;;OAKG;IACG,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAczC;;OAEG;IACI,KAAK,IAAI,IAAI;IAIpB;;OAEG;IACI,KAAK,IAAI,IAAI;IAIpB;;;OAGG;IACI,OAAO,IAAI,SAAS,CAAC,EAAE;IAI9B;;;;OAIG;IACI,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,SAAS;CAG3C"}
@@ -0,0 +1,25 @@
1
+ import { FakeRestApi } from './class';
2
+ import { FakeItem, FakeRestApiOptions } from './types';
3
+ /**
4
+ * Factory function to create a new FakeRestApi instance.
5
+ * @template T - The type of items to manage, must extend FakeItem
6
+ * @template F - The type of filters to apply when listing items
7
+ * @param options - Configuration options for the API
8
+ * @returns A new FakeRestApi instance
9
+ * @example
10
+ * ```typescript
11
+ * type User = { id: number; name: string; email: string }
12
+ *
13
+ * const api = createFakeRestApi<User>({
14
+ * name: 'users',
15
+ * maxCount: 50,
16
+ * generatorFn: (id) => ({
17
+ * id,
18
+ * name: `User ${id}`,
19
+ * email: `user${id}@example.com`
20
+ * })
21
+ * })
22
+ * ```
23
+ */
24
+ export declare function createFakeRestApi<T extends FakeItem, F = Record<string, unknown>>(options: FakeRestApiOptions<T, F>): FakeRestApi<T, F>;
25
+ //# sourceMappingURL=factor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factor.d.ts","sourceRoot":"","sources":["../../src/FakeRestApi/factor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAEtD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/E,OAAO,EAAE,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,GAChC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAEnB"}
@@ -0,0 +1,4 @@
1
+ export * from './factor';
2
+ export * from './class';
3
+ export type { FakeRestApiOptions } from './types';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/FakeRestApi/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,YAAY,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Represents a basic item with an ID.
3
+ */
4
+ export type FakeItem = {
5
+ id: number;
6
+ };
7
+ /**
8
+ * Represents a paginated response structure.
9
+ * @template T - The type of items in the results array, must extend FakeItem
10
+ */
11
+ export type PaginationResponse<T extends FakeItem> = {
12
+ /** Total count of items */
13
+ count: number;
14
+ /** URL for the next page, or null if there are no more pages */
15
+ next: string | null;
16
+ /** URL for the previous page, or null if this is the first page */
17
+ previous: string | null;
18
+ /** Array of items for the current page */
19
+ results: T[];
20
+ };
21
+ /**
22
+ * Configuration options for creating a FakeRestApi instance.
23
+ * @template T - The type of items to manage, must extend FakeItem
24
+ * @template F - The type of filters to apply when listing items
25
+ */
26
+ export type FakeRestApiOptions<T extends FakeItem, F = Record<string, unknown>> = {
27
+ /** Name of the API (used in URLs and error messages) */
28
+ name: string;
29
+ /** Whether to enable artificial delay for requests */
30
+ enableDelay?: boolean;
31
+ /** Maximum number of items to generate on initialization */
32
+ maxCount?: number;
33
+ /** Delay duration in milliseconds */
34
+ delayMs?: number;
35
+ /** Function to generate a new item given an ID */
36
+ generatorFn: (id: T['id']) => T;
37
+ /** Optional function to filter items based on criteria */
38
+ filterFn?: (item: T, filters: F) => boolean;
39
+ };
40
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/FakeRestApi/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,QAAQ,IAAI;IACnD,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,gEAAgE;IAChE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,mEAAmE;IACnE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,0CAA0C;IAC1C,OAAO,EAAE,CAAC,EAAE,CAAA;CACb,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAChF,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAA;IACZ,sDAAsD;IACtD,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,kDAAkD;IAClD,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC/B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,OAAO,CAAA;CAC5C,CAAA"}
@@ -0,0 +1,17 @@
1
+ declare function number(min?: number, max?: number): number;
2
+ /**
3
+ * Lightweight fixture-data helper for tests and Storybook stories.
4
+ * All string generators draw from fixed lists, so output is deterministic
5
+ * in terms of domain (real-looking names/animals) but random in selection —
6
+ * not suitable as a seed-based reproducible faker. Use `number(min, max)`
7
+ * for bounded integers.
8
+ */
9
+ export declare const faker: {
10
+ lastName: () => string;
11
+ firstName: () => string;
12
+ animal: () => string;
13
+ number: typeof number;
14
+ name: () => string;
15
+ };
16
+ export {};
17
+ //# sourceMappingURL=faker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"faker.d.ts","sourceRoot":"","sources":["../src/faker.ts"],"names":[],"mappings":"AAuBA,iBAAS,MAAM,CAAC,GAAG,GAAE,MAAU,EAAE,GAAG,GAAE,MAAY,UAEjD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,KAAK;;;;;;CAMjB,CAAA"}
@@ -0,0 +1,4 @@
1
+ export * from './FakeRestApi';
2
+ export * from './EnvironmentManager';
3
+ export * from './faker';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,SAAS,CAAA"}
package/package.json CHANGED
@@ -1,7 +1,20 @@
1
1
  {
2
2
  "name": "@codeleap/debug",
3
- "version": "6.3.0",
3
+ "version": "6.8.0",
4
4
  "main": "src/index.ts",
5
+ "types": "dist/index.d.ts",
6
+ "exports": {
7
+ ".": {
8
+ "source": "./src/index.ts",
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "src"
17
+ ],
5
18
  "license": "UNLICENSED",
6
19
  "repository": {
7
20
  "url": "https://github.com/codeleap-uk/internal-libs-monorepo.git",
@@ -9,13 +22,21 @@
9
22
  "directory": "packages/debug"
10
23
  },
11
24
  "devDependencies": {
12
- "@codeleap/config": "6.3.0",
25
+ "@codeleap/config": "6.8.0",
26
+ "@codeleap/store": "6.8.0",
27
+ "@codeleap/types": "6.8.0",
28
+ "@codeleap/utils": "6.8.0",
13
29
  "ts-node-dev": "1.1.8"
14
30
  },
15
31
  "scripts": {
16
- "build": "echo 'No build needed'"
32
+ "build": "tsc --build tsconfig.build.json",
33
+ "typecheck": "bun tsc --noEmit -p ./tsconfig.json"
17
34
  },
18
35
  "peerDependencies": {
19
- "typescript": "5.5.2"
36
+ "typescript": "5.5.2",
37
+ "@codeleap/config": "6.8.0",
38
+ "@codeleap/store": "6.8.0",
39
+ "@codeleap/types": "6.8.0",
40
+ "@codeleap/utils": "6.8.0"
20
41
  }
21
- }
42
+ }
@@ -5,6 +5,19 @@ import { useState, useMemo } from 'react'
5
5
  import { EnvironmentStore, EnvironmentManagerConfig, Editor } from './types'
6
6
  import { EDITORS } from './const'
7
7
 
8
+ /**
9
+ * Runtime switchboard for backend environments in debug builds.
10
+ *
11
+ * The override is opt-in: until `setEnabled` is called the manager always
12
+ * returns `defaultEnvironment`, making it safe to instantiate unconditionally.
13
+ * State is persisted via `@codeleap/store` `globalState` so it survives page
14
+ * reloads, but the `enabledBy` flag gates whether that persisted state is
15
+ * actually honoured.
16
+ *
17
+ * When the active environment is `customEnvironment`, `serverUrl` validates the
18
+ * stored URL against a strict regex and falls back to `defaultEnvironment` if
19
+ * it fails — callers can rely on `serverUrl` always returning a usable value.
20
+ */
8
21
  export class EnvironmentManager<T extends StringRecord> {
9
22
  private store: ReturnType<typeof globalState<EnvironmentStore<T>>>
10
23
 
@@ -33,7 +46,8 @@ export class EnvironmentManager<T extends StringRecord> {
33
46
  this.initialStoreValue = this.store.get()
34
47
  }
35
48
 
36
- testUrl(url: string) {
49
+ testUrl(url: string | undefined) {
50
+ if (!url) return false
37
51
  const urlValidator: RegExp = /^https?:\/\/([a-zA-Z0-9.-]+|localhost|(\d{1,3}\.){3}\d{1,3})(?::\d+)?\/$/
38
52
  return urlValidator.test(url)
39
53
  }
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Identifies who enabled the environment override — the application itself
3
+ * (`SYSTEM`) or an end user via a debug UI (`USER`). Used to gate which
4
+ * controls are exposed and whether the override survives a session reset.
5
+ */
1
6
  export const EDITORS = {
2
7
  SYSTEM: 'system',
3
8
  USER: 'user',
@@ -2,6 +2,11 @@ import { StringRecord } from '@codeleap/types'
2
2
  import { EnvironmentManager } from './class'
3
3
  import { EnvironmentManagerConfig } from './types'
4
4
 
5
+ /**
6
+ * Preferred entry point for instantiating an `EnvironmentManager`.
7
+ * Keeps call-sites free of the generic `new` syntax and makes the config
8
+ * shape the only public API surface that needs to be imported.
9
+ */
5
10
  export function createEnvironmentManager<T extends StringRecord>(config: EnvironmentManagerConfig<T>) {
6
11
  return new EnvironmentManager<T>(config)
7
12
  }
@@ -1,8 +1,15 @@
1
1
  import { Keyof, StringRecord, ValueOf } from '@codeleap/types'
2
2
  import { EDITORS } from './const'
3
3
 
4
+ /** `null` means the override is disabled; a non-null value identifies who enabled it. */
4
5
  export type Editor = ValueOf<typeof EDITORS> | null
5
6
 
7
+ /**
8
+ * `customEnvironment` names the key whose URL is taken from `EnvironmentStore.customUrl`
9
+ * rather than the `environments` map, so it must exist as a key in `T` even though its
10
+ * map value is ignored at runtime. `persistKey` controls the localStorage slot;
11
+ * omitting it falls back to `'environment-manager'`.
12
+ */
6
13
  export type EnvironmentManagerConfig<T extends StringRecord> = {
7
14
  environments: T
8
15
  defaultEnvironment: Keyof<T>
@@ -10,8 +17,13 @@ export type EnvironmentManagerConfig<T extends StringRecord> = {
10
17
  persistKey?: string
11
18
  }
12
19
 
20
+ /**
21
+ * Persisted slice of debug state. When `enabledBy` is `null` the manager
22
+ * ignores `environment` and `customUrl` entirely, returning the default config
23
+ * instead — so the store being populated does not mean the override is active.
24
+ */
13
25
  export type EnvironmentStore<T extends StringRecord> = {
14
26
  environment: Keyof<T>
15
- customUrl?: string
27
+ customUrl: string
16
28
  enabledBy: Editor
17
29
  }
package/src/faker.ts CHANGED
@@ -25,6 +25,13 @@ function number(min: number = 0, max: number = 100) {
25
25
  return Math.floor(Math.random() * (max - min + 1)) + min
26
26
  }
27
27
 
28
+ /**
29
+ * Lightweight fixture-data helper for tests and Storybook stories.
30
+ * All string generators draw from fixed lists, so output is deterministic
31
+ * in terms of domain (real-looking names/animals) but random in selection —
32
+ * not suitable as a seed-based reproducible faker. Use `number(min, max)`
33
+ * for bounded integers.
34
+ */
28
35
  export const faker = {
29
36
  lastName: () => getRandom(surnames),
30
37
  firstName: () => getRandom(names),
package/package.json.bak DELETED
@@ -1,21 +0,0 @@
1
- {
2
- "name": "@codeleap/debug",
3
- "version": "6.3.0",
4
- "main": "src/index.ts",
5
- "license": "UNLICENSED",
6
- "repository": {
7
- "url": "https://github.com/codeleap-uk/internal-libs-monorepo.git",
8
- "type": "git",
9
- "directory": "packages/debug"
10
- },
11
- "devDependencies": {
12
- "@codeleap/config": "workspace:*",
13
- "ts-node-dev": "1.1.8"
14
- },
15
- "scripts": {
16
- "build": "echo 'No build needed'"
17
- },
18
- "peerDependencies": {
19
- "typescript": "5.5.2"
20
- }
21
- }