@biglogic/rgs 3.9.7 → 3.9.9

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/SKILL.md ADDED
@@ -0,0 +1,148 @@
1
+ ---
2
+ name: biglogic-rgs
3
+ description: Reactive global state management library for React - simple, secure, scalable
4
+ ---
5
+
6
+ # @biglogic/rgs - Reactive Global State
7
+
8
+ ## Overview
9
+
10
+ RGS (Argis) is a reactive global state management library for React. Simple, secure, and scalable. It provides typed state management with built-in persistence, security, and sync capabilities.
11
+
12
+ ## Instructions
13
+
14
+ ### Constraints
15
+
16
+ 1. **TypeScript Strict**: Always use strict typing - avoid `any` unless absolutely necessary
17
+ 2. **No console.log**: Use `console.debug` for debugging, or `console.warn`/`console.error` for warnings/errors
18
+ 3. **Build before commit**: Always run `npm run build` successfully before any commit
19
+ 4. **Test TypeScript**: Run `npx tsc --noEmit` to verify no type errors
20
+ 5. **No console.log debugging**: Never leave console.log statements in production code
21
+ 6. **Use arrow functions**: Prefer arrow functions over function declarations
22
+
23
+ ### Workflow
24
+
25
+ 1. **For new features**:
26
+ - Create in `core/` folder
27
+ - Export from `index.ts` if public API
28
+ - Add types to `core/types.ts`
29
+ - Run build and type-check
30
+
31
+ 2. **For bug fixes**:
32
+ - Run `npx tsc --noEmit` to identify issues
33
+ - Fix type errors first
34
+ - Verify build succeeds
35
+
36
+ 3. **For testing**:
37
+ - Run `npm run build` or `npm run test`
38
+ - Config is in `tests/` folder
39
+
40
+ ### Output Format
41
+
42
+ When adding new hooks or functions:
43
+
44
+ ```typescript
45
+ /**
46
+ * Description of what the hook does.
47
+ * @param param - Description of parameter
48
+ * @returns Description of return value
49
+ */
50
+ export const myHook = (param: string): boolean => {
51
+ // Implementation
52
+ }
53
+ ```
54
+
55
+ ## Usage Examples
56
+
57
+ ### Basic Store Creation
58
+
59
+ ```typescript
60
+ import { gstate } from '@biglogic/rgs'
61
+
62
+ // Create store with typed hook
63
+ const store = gstate({ count: 0, name: 'John' })
64
+
65
+ // Use typed hook for specific keys
66
+ const [count, setCount] = store('count')
67
+ const [name, setName] = store('name')
68
+
69
+ // Or use store directly
70
+ store.set('count', 5)
71
+ store.get('count')
72
+ ```
73
+
74
+ ### SSR Support
75
+
76
+ ```typescript
77
+ import { isServerSide, hydrateOnClient } from '@biglogic/rgs'
78
+
79
+ if (isServerSide()) {
80
+ // Server-side logic
81
+ }
82
+
83
+ hydrateOnClient(myStore)
84
+ ```
85
+
86
+ ### Security
87
+
88
+ ```typescript
89
+ import { generateEncryptionKey, validateKey } from '@biglogic/rgs'
90
+
91
+ // Generate encryption key for secure persistence
92
+ const key = generateEncryptionKey()
93
+
94
+ // Validate keys to prevent XSS
95
+ if (validateKey(userInput)) {
96
+ store.set(userInput, value)
97
+ }
98
+ ```
99
+
100
+ ## API Quick Reference
101
+
102
+ ### Core
103
+
104
+ | Function | Description |
105
+ |----------|-------------|
106
+ | `gstate(initialState, config?)` | Creates store + returns typed hook |
107
+ | `useStore(key, store?)` | React hook for state subscription |
108
+ | `createStore(config?)` | Creates store instance |
109
+ | `initState(config?)` | Initializes global store |
110
+ | `getStore()` | Gets current default store |
111
+
112
+ ### SSR
113
+
114
+ | Function | Description |
115
+ |----------|-------------|
116
+ | `isServerSide()` | Check if running on server |
117
+ | `isClientSide()` | Check if running on client |
118
+ | `hydrateOnClient(store)` | Hydrate store on client |
119
+
120
+ ### Security
121
+
122
+ | Function | Description |
123
+ |----------|-------------|
124
+ | `generateEncryptionKey()` | Generate AES-256 key |
125
+ | `validateKey(key)` | Validate key format (XSS prevention) |
126
+ | `sanitizeValue(value)` | Sanitize value |
127
+
128
+ ## Project Structure
129
+
130
+ ```
131
+ core/
132
+ ├── hooks.ts # React hooks (useStore, useSyncedState)
133
+ ├── store.ts # Core store implementation
134
+ ├── types.ts # TypeScript types
135
+ ├── security.ts # Security utilities
136
+ ├── persistence.ts # Storage persistence
137
+ ├── sync.ts # Sync engine
138
+ └── ssr.ts # SSR support
139
+ ```
140
+
141
+ ## Dependencies
142
+
143
+ - **peerDependencies**: `react`, `react-dom` (>=16.8.0)
144
+ - **devDependencies**: `typescript`, `tsup`, `terser`
145
+
146
+ ## License
147
+
148
+ MIT - Copyright Dario Passariello
package/core/hooks.d.ts CHANGED
@@ -15,3 +15,4 @@ export declare function useSyncedState<T = unknown>(key: string, store?: IStore<
15
15
  ];
16
16
  export declare const useSyncStatus: () => SyncState;
17
17
  export declare const triggerSync: (namespace?: string) => Promise<void>;
18
+ export declare function useStoreSubscribe<S extends Record<string, unknown> = Record<string, unknown>>(store?: IStore<S>): readonly [boolean, () => void];
package/core/ssr.d.ts ADDED
@@ -0,0 +1,73 @@
1
+ import type { IStore, StoreConfig } from "./types";
2
+ export declare const isServerSide: () => boolean;
3
+ export declare const isClientSide: () => boolean;
4
+ export interface SSRStoreConfig<S extends Record<string, unknown>> extends StoreConfig<S> {
5
+ deferHydration?: boolean;
6
+ initialState?: S;
7
+ ssrSafe?: boolean;
8
+ }
9
+ export declare const createSSRStore: <S extends Record<string, unknown>>(config?: SSRStoreConfig<S>) => IStore<S> & {
10
+ hydrate: () => Promise<void>;
11
+ getSerializedState: () => string | null;
12
+ isHydrated: () => boolean;
13
+ };
14
+ export declare const hydrateOnClient: (store: IStore<Record<string, unknown>>) => Promise<void>;
15
+ export declare const dehydrateStore: (store: IStore<Record<string, unknown>>) => string;
16
+ export declare const rehydrateStore: (store: IStore<Record<string, unknown>>, serializedState: string) => void;
17
+ export declare const useHydrated: () => boolean;
18
+ export declare const useHydrationStatus: () => {
19
+ isHydrated: boolean;
20
+ isHydrating: boolean;
21
+ };
22
+ export declare const useDeferredStore: <S extends Record<string, unknown>>(store: IStore<S> & {
23
+ isHydrated?: () => boolean;
24
+ }) => IStore<S>;
25
+ export declare const createNextStore: <S extends Record<string, unknown>>(config?: SSRStoreConfig<S>) => IStore<S> & {
26
+ hydrate: () => Promise<void>;
27
+ getSerializedState: () => string | null;
28
+ isHydrated: () => boolean;
29
+ } & {
30
+ useHydrated: () => boolean;
31
+ useHydrationStatus: () => {
32
+ isHydrated: boolean;
33
+ isHydrating: boolean;
34
+ };
35
+ useDeferredStore: <K extends keyof S>(key: K) => unknown;
36
+ };
37
+ export declare const getSSRInitialState: (store: IStore<Record<string, unknown>>) => Record<string, unknown>;
38
+ export declare const initializeFromSSR: (store: IStore<Record<string, unknown>>, initialState: Record<string, unknown>) => void;
39
+ declare const _default: {
40
+ isServerSide: () => boolean;
41
+ isClientSide: () => boolean;
42
+ createSSRStore: <S extends Record<string, unknown>>(config?: SSRStoreConfig<S>) => IStore<S> & {
43
+ hydrate: () => Promise<void>;
44
+ getSerializedState: () => string | null;
45
+ isHydrated: () => boolean;
46
+ };
47
+ hydrateOnClient: (store: IStore<Record<string, unknown>>) => Promise<void>;
48
+ dehydrateStore: (store: IStore<Record<string, unknown>>) => string;
49
+ rehydrateStore: (store: IStore<Record<string, unknown>>, serializedState: string) => void;
50
+ useHydrated: () => boolean;
51
+ useHydrationStatus: () => {
52
+ isHydrated: boolean;
53
+ isHydrating: boolean;
54
+ };
55
+ useDeferredStore: <S extends Record<string, unknown>>(store: IStore<S> & {
56
+ isHydrated?: () => boolean;
57
+ }) => IStore<S>;
58
+ createNextStore: <S extends Record<string, unknown>>(config?: SSRStoreConfig<S>) => IStore<S> & {
59
+ hydrate: () => Promise<void>;
60
+ getSerializedState: () => string | null;
61
+ isHydrated: () => boolean;
62
+ } & {
63
+ useHydrated: () => boolean;
64
+ useHydrationStatus: () => {
65
+ isHydrated: boolean;
66
+ isHydrating: boolean;
67
+ };
68
+ useDeferredStore: <K extends keyof S>(key: K) => unknown;
69
+ };
70
+ getSSRInitialState: (store: IStore<Record<string, unknown>>) => Record<string, unknown>;
71
+ initializeFromSSR: (store: IStore<Record<string, unknown>>, initialState: Record<string, unknown>) => void;
72
+ };
73
+ export default _default;
@@ -0,0 +1,75 @@
1
+ import type { IStore } from "./types";
2
+ export type ThunkAction<R = void, S extends Record<string, unknown> = Record<string, unknown>> = (dispatch: ThunkDispatch<S>, getState: () => S, extraArgument?: unknown) => Promise<R> | R;
3
+ export type ThunkDispatch<S extends Record<string, unknown> = Record<string, unknown>> = <R>(action: ThunkAction<R, S> | ThunkActionPayload<S>) => Promise<R>;
4
+ export interface ThunkActionPayload<_S extends Record<string, unknown> = Record<string, unknown>> {
5
+ type: string;
6
+ payload?: unknown;
7
+ meta?: Record<string, unknown>;
8
+ }
9
+ export interface ThunkMiddlewareConfig {
10
+ extraArgument?: unknown;
11
+ dispatchKey?: string;
12
+ }
13
+ export declare const createThunkStore: <S extends Record<string, unknown>>(store: IStore<S>, config?: ThunkMiddlewareConfig) => IStore<S> & {
14
+ dispatch: ThunkDispatch<S>;
15
+ };
16
+ export declare const createActions: <S extends Record<string, unknown>, T extends Record<string, unknown>>(store: IStore<S>, creators: T) => T & {
17
+ dispatch: ThunkDispatch<S>;
18
+ };
19
+ export declare const createAsyncAction: <T>(key: string, fetcher: () => Promise<T>) => ThunkAction<T, Record<string, {
20
+ data: T | null;
21
+ loading: boolean;
22
+ error: Error | null;
23
+ }>>;
24
+ export declare const createAsyncActions: <S extends Record<string, unknown>>(store: IStore<S>, actions: Record<string, () => Promise<unknown>>) => Record<string, ThunkAction<unknown, S>>;
25
+ export type Effect = {
26
+ type: 'call';
27
+ fn: () => Promise<unknown>;
28
+ args?: unknown[];
29
+ } | {
30
+ type: 'put';
31
+ action: ThunkActionPayload<Record<string, unknown>>;
32
+ } | {
33
+ type: 'select';
34
+ selector: (state: Record<string, unknown>) => unknown;
35
+ } | {
36
+ type: 'take';
37
+ pattern: string | ((action: ThunkActionPayload) => boolean);
38
+ } | {
39
+ type: 'all';
40
+ effects: Effect[];
41
+ } | {
42
+ type: 'race';
43
+ effects: Record<string, Effect>;
44
+ };
45
+ export declare const call: (fn: () => Promise<unknown>, ...args: unknown[]) => Effect;
46
+ export declare const put: (action: ThunkActionPayload<Record<string, unknown>>) => Effect;
47
+ export declare const select: (selector: (state: Record<string, unknown>) => unknown) => Effect;
48
+ export declare const take: (pattern: string | ((action: ThunkActionPayload) => boolean)) => Effect;
49
+ export declare const all: (effects: Effect[]) => Effect;
50
+ export declare const race: (effects: Record<string, Effect>) => Effect;
51
+ export declare const createSaga: <S extends Record<string, unknown>>(generator: Generator<Effect, void, unknown>) => ((dispatch: ThunkDispatch<S>, getState: () => S, extraArgument?: unknown) => Promise<void>);
52
+ export declare const runSaga: <S extends Record<string, unknown>>(store: IStore<S>, saga: ThunkAction<void, S>) => (() => void);
53
+ declare const _default: {
54
+ createThunkStore: <S extends Record<string, unknown>>(store: IStore<S>, config?: ThunkMiddlewareConfig) => IStore<S> & {
55
+ dispatch: ThunkDispatch<S>;
56
+ };
57
+ createActions: <S extends Record<string, unknown>, T extends Record<string, unknown>>(store: IStore<S>, creators: T) => T & {
58
+ dispatch: ThunkDispatch<S>;
59
+ };
60
+ createAsyncAction: <T>(key: string, fetcher: () => Promise<T>) => ThunkAction<T, Record<string, {
61
+ data: T | null;
62
+ loading: boolean;
63
+ error: Error | null;
64
+ }>>;
65
+ createAsyncActions: <S extends Record<string, unknown>>(store: IStore<S>, actions: Record<string, () => Promise<unknown>>) => Record<string, ThunkAction<unknown, S>>;
66
+ call: (fn: () => Promise<unknown>, ...args: unknown[]) => Effect;
67
+ put: (action: ThunkActionPayload<Record<string, unknown>>) => Effect;
68
+ select: (selector: (state: Record<string, unknown>) => unknown) => Effect;
69
+ take: (pattern: string | ((action: ThunkActionPayload) => boolean)) => Effect;
70
+ all: (effects: Effect[]) => Effect;
71
+ race: (effects: Record<string, Effect>) => Effect;
72
+ createSaga: <S extends Record<string, unknown>>(generator: Generator<Effect, void, unknown>) => ((dispatch: ThunkDispatch<S>, getState: () => S, extraArgument?: unknown) => Promise<void>);
73
+ runSaga: <S extends Record<string, unknown>>(store: IStore<S>, saga: ThunkAction<void, S>) => (() => void);
74
+ };
75
+ export default _default;
package/docs/SKILL.md ADDED
@@ -0,0 +1,148 @@
1
+ ---
2
+ name: biglogic-rgs
3
+ description: Reactive global state management library for React - simple, secure, scalable
4
+ ---
5
+
6
+ # @biglogic/rgs - Reactive Global State
7
+
8
+ ## Overview
9
+
10
+ RGS (Argis) is a reactive global state management library for React. Simple, secure, and scalable. It provides typed state management with built-in persistence, security, and sync capabilities.
11
+
12
+ ## Instructions
13
+
14
+ ### Constraints
15
+
16
+ 1. **TypeScript Strict**: Always use strict typing - avoid `any` unless absolutely necessary
17
+ 2. **No console.log**: Use `console.debug` for debugging, or `console.warn`/`console.error` for warnings/errors
18
+ 3. **Build before commit**: Always run `npm run build` successfully before any commit
19
+ 4. **Test TypeScript**: Run `npx tsc --noEmit` to verify no type errors
20
+ 5. **No console.log debugging**: Never leave console.log statements in production code
21
+ 6. **Use arrow functions**: Prefer arrow functions over function declarations
22
+
23
+ ### Workflow
24
+
25
+ 1. **For new features**:
26
+ - Create in `core/` folder
27
+ - Export from `index.ts` if public API
28
+ - Add types to `core/types.ts`
29
+ - Run build and type-check
30
+
31
+ 2. **For bug fixes**:
32
+ - Run `npx tsc --noEmit` to identify issues
33
+ - Fix type errors first
34
+ - Verify build succeeds
35
+
36
+ 3. **For testing**:
37
+ - Run `npm run build` or `npm run test`
38
+ - Config is in `tests/` folder
39
+
40
+ ### Output Format
41
+
42
+ When adding new hooks or functions:
43
+
44
+ ```typescript
45
+ /**
46
+ * Description of what the hook does.
47
+ * @param param - Description of parameter
48
+ * @returns Description of return value
49
+ */
50
+ export const myHook = (param: string): boolean => {
51
+ // Implementation
52
+ }
53
+ ```
54
+
55
+ ## Usage Examples
56
+
57
+ ### Basic Store Creation
58
+
59
+ ```typescript
60
+ import { gstate } from '@biglogic/rgs'
61
+
62
+ // Create store with typed hook
63
+ const store = gstate({ count: 0, name: 'John' })
64
+
65
+ // Use typed hook for specific keys
66
+ const [count, setCount] = store('count')
67
+ const [name, setName] = store('name')
68
+
69
+ // Or use store directly
70
+ store.set('count', 5)
71
+ store.get('count')
72
+ ```
73
+
74
+ ### SSR Support
75
+
76
+ ```typescript
77
+ import { isServerSide, hydrateOnClient } from '@biglogic/rgs'
78
+
79
+ if (isServerSide()) {
80
+ // Server-side logic
81
+ }
82
+
83
+ hydrateOnClient(myStore)
84
+ ```
85
+
86
+ ### Security
87
+
88
+ ```typescript
89
+ import { generateEncryptionKey, validateKey } from '@biglogic/rgs'
90
+
91
+ // Generate encryption key for secure persistence
92
+ const key = generateEncryptionKey()
93
+
94
+ // Validate keys to prevent XSS
95
+ if (validateKey(userInput)) {
96
+ store.set(userInput, value)
97
+ }
98
+ ```
99
+
100
+ ## API Quick Reference
101
+
102
+ ### Core
103
+
104
+ | Function | Description |
105
+ |----------|-------------|
106
+ | `gstate(initialState, config?)` | Creates store + returns typed hook |
107
+ | `useStore(key, store?)` | React hook for state subscription |
108
+ | `createStore(config?)` | Creates store instance |
109
+ | `initState(config?)` | Initializes global store |
110
+ | `getStore()` | Gets current default store |
111
+
112
+ ### SSR
113
+
114
+ | Function | Description |
115
+ |----------|-------------|
116
+ | `isServerSide()` | Check if running on server |
117
+ | `isClientSide()` | Check if running on client |
118
+ | `hydrateOnClient(store)` | Hydrate store on client |
119
+
120
+ ### Security
121
+
122
+ | Function | Description |
123
+ |----------|-------------|
124
+ | `generateEncryptionKey()` | Generate AES-256 key |
125
+ | `validateKey(key)` | Validate key format (XSS prevention) |
126
+ | `sanitizeValue(value)` | Sanitize value |
127
+
128
+ ## Project Structure
129
+
130
+ ```
131
+ core/
132
+ ├── hooks.ts # React hooks (useStore, useSyncedState)
133
+ ├── store.ts # Core store implementation
134
+ ├── types.ts # TypeScript types
135
+ ├── security.ts # Security utilities
136
+ ├── persistence.ts # Storage persistence
137
+ ├── sync.ts # Sync engine
138
+ └── ssr.ts # SSR support
139
+ ```
140
+
141
+ ## Dependencies
142
+
143
+ - **peerDependencies**: `react`, `react-dom` (>=16.8.0)
144
+ - **devDependencies**: `typescript`, `tsup`, `terser`
145
+
146
+ ## License
147
+
148
+ MIT - Copyright Dario Passariello
@@ -6,6 +6,38 @@ Complete API reference for RGS (Argis) - Reactive Global State.
6
6
 
7
7
  ## Core Functions
8
8
 
9
+ ### `gstate`
10
+
11
+ Creates a reactive store with a built-in typed hook in one line.
12
+
13
+ ```typescript
14
+ function gstate<S extends Record<string, unknown>>(
15
+ initialState: S,
16
+ configOrNamespace?: string | StoreConfig<S>
17
+ ): (<K extends keyof S>(key: K) => readonly [S[K] | undefined, (val: S[K] | StateUpdater<S[K]>, options?: PersistOptions) => boolean]) & IStore<S>
18
+ ```
19
+
20
+ **Parameters:**
21
+ - `initialState` - Initial state object
22
+ - `configOrNamespace` - Optional namespace string or full StoreConfig
23
+
24
+ **Returns:** A callable function that returns typed hooks when called with a key, plus the full store interface.
25
+
26
+ **Example:**
27
+ ```typescript
28
+ const useCounter = gstate({ count: 0, name: 'John' })
29
+
30
+ // Get typed hook for specific key
31
+ const [count, setCount] = useCounter('count')
32
+ const [name, setName] = useCounter('name')
33
+
34
+ // Or use store methods directly
35
+ useCounter.set('count', 5)
36
+ useCounter.get('count')
37
+ ```
38
+
39
+ ---
40
+
9
41
  ### `initState`
10
42
 
11
43
  Initializes a global store instance.
@@ -7,62 +7,56 @@ Stop wasting time on boilerplate. Here is how you deploy the RGS Panzer in your
7
7
  The engine is lightweight but armored.
8
8
 
9
9
  ```bash
10
- npm install rgs
10
+ npm install @biglogic/rgs
11
11
  ```
12
12
 
13
- ## 2. Initialization: The "Big Bang"
13
+ ## 2. Quick Start: The Zen Way (Recommended)
14
14
 
15
- In your main entry file (e.g., `main.tsx` or `App.tsx`), wake up the engine once.
15
+ The simplest way to use RGS - one line creates both store and typed hook.
16
16
 
17
17
  ```typescript
18
- import { initState, useStore } from '@biglogic/rgs';
18
+ import { gstate } from '@biglogic/rgs';
19
19
 
20
- // Initialize with optional settings
21
- initState({
22
- namespace: 'my-awesome-app',
23
- persistence: true // Optional: Saves everything to localStorage automatically
24
- });
25
- ```
26
-
27
- ## 3. Usage: Instant Reactions
28
-
29
- Use the `useStore` hook. No providers, no wrappers. Just raw, atomic power.
30
-
31
- ```tsx
32
- import { useStore } from '@biglogic/rgs';
20
+ // ONE line creates a typed store + hook
21
+ const useCounter = gstate({ count: 0, name: 'John' })
33
22
 
34
23
  function Counter() {
35
- // If 'count' doesn't exist yet, it defaults to undefined. Easy.
36
- const [count, setCount] = useStore<number>('count');
24
+ // Get typed hook for specific keys
25
+ const [count, setCount] = useCounter('count')
26
+ const [name, setName] = useCounter('name')
37
27
 
38
28
  return (
39
- <div className="card">
40
- <h1>Power Level: {count ?? 0}</h1>
41
- <button onClick={() => setCount((prev) => (prev || 0) + 1)}>
42
- Boost Power 💥
29
+ <div>
30
+ <p>Hello, {name}!</p>
31
+ <p>Count: {count}</p>
32
+ <button onClick={() =u003e setCount(count + 1)}>
33
+ +1
43
34
  </button>
44
35
  </div>
45
- );
36
+ )
46
37
  }
47
38
  ```
48
39
 
49
- ## 🧐 What just happened?
50
-
51
- - **Reactive Subscription**: `useStore('count')` tells React to watch the 'count' key. Surgical updates only.
52
- - **Global Scope**: `setCount` updates the value everywhere in the app, instantly.
53
- - **Resilient Nature**: If you access a key that hasn't been set yet, RGS returns `undefined` gracefully instead of throwing a tantrum.
40
+ Or use store methods directly:
41
+ ```typescript
42
+ useCounter.set('count', 5)
43
+ useCounter.get('count')
44
+ ```
54
45
 
55
- ## 🚨 Pro Tip: Direct Store Access
46
+ ## 3. Classic Way (Global Store)
56
47
 
57
- Need to access state outside of React components? Simple.
48
+ If you prefer a global store approach:
58
49
 
59
50
  ```typescript
60
- import { getStore } from '@biglogic/rgs';
61
-
62
- const value = getStore()?.get('count');
63
- getStore()?.set('count', 9001);
64
- ```
51
+ import { initState, useStore } from '@biglogic/rgs';
65
52
 
66
- ---
53
+ // Initialize once at app root
54
+ initState({
55
+ namespace: 'my-awesome-app',
56
+ persistence: true
57
+ });
67
58
 
68
- **Next step:** [The Magnetar Way: One-Liner Power](the-magnetar-way.md)
59
+ // Use anywhere in your app
60
+ const [count, setCount] = useStore('count')
61
+ const [user, setUser] = useStore('user')
62
+ ```