@stackframe/stack-shared 2.8.35 → 2.8.36

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.
Files changed (74) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/config/schema.d.mts +167 -107
  3. package/dist/config/schema.d.ts +167 -107
  4. package/dist/config/schema.js +39 -25
  5. package/dist/config/schema.js.map +1 -1
  6. package/dist/esm/config/schema.js +39 -25
  7. package/dist/esm/config/schema.js.map +1 -1
  8. package/dist/esm/helpers/vault/client-side.js +46 -0
  9. package/dist/esm/helpers/vault/client-side.js.map +1 -0
  10. package/dist/esm/helpers/vault/server-side.js +92 -0
  11. package/dist/esm/helpers/vault/server-side.js.map +1 -0
  12. package/dist/esm/hooks/use-hover.js +71 -0
  13. package/dist/esm/hooks/use-hover.js.map +1 -0
  14. package/dist/esm/interface/admin-interface.js +21 -3
  15. package/dist/esm/interface/admin-interface.js.map +1 -1
  16. package/dist/esm/interface/server-interface.js +38 -0
  17. package/dist/esm/interface/server-interface.js.map +1 -1
  18. package/dist/esm/known-errors.js +38 -1
  19. package/dist/esm/known-errors.js.map +1 -1
  20. package/dist/esm/utils/bytes.js +1 -2
  21. package/dist/esm/utils/bytes.js.map +1 -1
  22. package/dist/esm/utils/crypto.js +83 -2
  23. package/dist/esm/utils/crypto.js.map +1 -1
  24. package/dist/esm/utils/numbers.js.map +1 -1
  25. package/dist/esm/utils/react.js +7 -3
  26. package/dist/esm/utils/react.js.map +1 -1
  27. package/dist/helpers/password.d.mts +4 -4
  28. package/dist/helpers/password.d.ts +4 -4
  29. package/dist/helpers/vault/client-side.d.mts +14 -0
  30. package/dist/helpers/vault/client-side.d.ts +14 -0
  31. package/dist/helpers/vault/client-side.js +73 -0
  32. package/dist/helpers/vault/client-side.js.map +1 -0
  33. package/dist/helpers/vault/server-side.d.mts +7 -0
  34. package/dist/helpers/vault/server-side.d.ts +7 -0
  35. package/dist/helpers/vault/server-side.js +111 -0
  36. package/dist/helpers/vault/server-side.js.map +1 -0
  37. package/dist/hooks/use-hover.d.mts +6 -0
  38. package/dist/hooks/use-hover.d.ts +6 -0
  39. package/dist/hooks/use-hover.js +96 -0
  40. package/dist/hooks/use-hover.js.map +1 -0
  41. package/dist/index.d.mts +3 -3
  42. package/dist/index.d.ts +3 -3
  43. package/dist/interface/admin-interface.d.mts +11 -5
  44. package/dist/interface/admin-interface.d.ts +11 -5
  45. package/dist/interface/admin-interface.js +21 -3
  46. package/dist/interface/admin-interface.js.map +1 -1
  47. package/dist/interface/crud/current-user.d.mts +1 -1
  48. package/dist/interface/crud/current-user.d.ts +1 -1
  49. package/dist/interface/crud/project-api-keys.d.mts +4 -4
  50. package/dist/interface/crud/project-api-keys.d.ts +4 -4
  51. package/dist/interface/crud/team-member-profiles.d.mts +2 -2
  52. package/dist/interface/crud/team-member-profiles.d.ts +2 -2
  53. package/dist/interface/crud/users.d.mts +2 -2
  54. package/dist/interface/crud/users.d.ts +2 -2
  55. package/dist/interface/server-interface.d.mts +2 -0
  56. package/dist/interface/server-interface.d.ts +2 -0
  57. package/dist/interface/server-interface.js +38 -0
  58. package/dist/interface/server-interface.js.map +1 -1
  59. package/dist/known-errors.d.mts +9 -0
  60. package/dist/known-errors.d.ts +9 -0
  61. package/dist/known-errors.js +38 -1
  62. package/dist/known-errors.js.map +1 -1
  63. package/dist/schema-fields.d.mts +1 -1
  64. package/dist/schema-fields.d.ts +1 -1
  65. package/dist/utils/bytes.js +1 -2
  66. package/dist/utils/bytes.js.map +1 -1
  67. package/dist/utils/crypto.d.mts +31 -1
  68. package/dist/utils/crypto.d.ts +31 -1
  69. package/dist/utils/crypto.js +87 -2
  70. package/dist/utils/crypto.js.map +1 -1
  71. package/dist/utils/numbers.js.map +1 -1
  72. package/dist/utils/react.js +7 -3
  73. package/dist/utils/react.js.map +1 -1
  74. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/react.tsx"],"sourcesContent":["import React, { SetStateAction } from \"react\";\nimport { isBrowserLike } from \"./env\";\nimport { neverResolve } from \"./promises\";\nimport { deindent } from \"./strings\";\n\nexport function componentWrapper<\n C extends React.ComponentType<any> | keyof React.JSX.IntrinsicElements,\n ExtraProps extends {} = {}\n>(displayName: string, render: React.ForwardRefRenderFunction<RefFromComponent<C>, React.ComponentPropsWithRef<C> & ExtraProps>) {\n const Component = forwardRefIfNeeded(render);\n Component.displayName = displayName;\n return Component;\n}\ntype RefFromComponent<C extends React.ComponentType<any> | keyof React.JSX.IntrinsicElements> = NonNullable<RefFromComponentDistCond<React.ComponentPropsWithRef<C>[\"ref\"]>>;\ntype RefFromComponentDistCond<A> = A extends React.RefObject<infer T> ? T : never; // distributive conditional type; see https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types\n\nexport function forwardRefIfNeeded<T, P = {}>(render: React.ForwardRefRenderFunction<T, P>): React.FC<P & { ref?: React.Ref<T> }> {\n // TODO: when we drop support for react 18, remove this\n\n const version = React.version;\n const major = parseInt(version.split(\".\")[0]);\n if (major < 19) {\n return React.forwardRef<T, P>(render as any) as any;\n } else {\n return ((props: P) => render(props, (props as any).ref)) as any;\n }\n}\n\nexport function getNodeText(node: React.ReactNode): string {\n if ([\"number\", \"string\"].includes(typeof node)) {\n return `${node}`;\n }\n if (!node) {\n return \"\";\n }\n if (Array.isArray(node)) {\n return node.map(getNodeText).join(\"\");\n }\n if (typeof node === \"object\" && \"props\" in node) {\n return getNodeText(node.props.children);\n }\n throw new Error(`Unknown node type: ${typeof node}`);\n}\nundefined?.test(\"getNodeText\", ({ expect }) => {\n // Test with string\n expect(getNodeText(\"hello\")).toBe(\"hello\");\n\n // Test with number\n expect(getNodeText(42)).toBe(\"42\");\n\n // Test with null/undefined\n expect(getNodeText(null)).toBe(\"\");\n expect(getNodeText(undefined)).toBe(\"\");\n\n // Test with array\n expect(getNodeText([\"hello\", \" \", \"world\"])).toBe(\"hello world\");\n expect(getNodeText([1, 2, 3])).toBe(\"123\");\n\n // Test with mixed array\n expect(getNodeText([\"hello\", 42, null])).toBe(\"hello42\");\n\n // Test with React element (mocked)\n const mockElement = {\n props: {\n children: \"child text\"\n }\n } as React.ReactElement;\n expect(getNodeText(mockElement)).toBe(\"child text\");\n\n // Test with nested React elements\n const nestedElement = {\n props: {\n children: {\n props: {\n children: \"nested text\"\n }\n } as React.ReactElement\n }\n } as React.ReactElement;\n expect(getNodeText(nestedElement)).toBe(\"nested text\");\n\n // Test with array of React elements\n const arrayOfElements = [\n { props: { children: \"first\" } } as React.ReactElement,\n { props: { children: \"second\" } } as React.ReactElement\n ];\n expect(getNodeText(arrayOfElements)).toBe(\"firstsecond\");\n});\n\n/**\n * Suspends the currently rendered component indefinitely. Will not unsuspend unless the component rerenders.\n *\n * You can use this to translate older query- or AsyncResult-based code to new the Suspense system, for example: `if (query.isLoading) suspend();`\n */\nexport function suspend(): never {\n React.use(neverResolve());\n throw new Error(\"Somehow a Promise that never resolves was resolved?\");\n}\n\nexport function mapRef<T, R>(ref: ReadonlyRef<T>, mapper: (value: T) => R): ReadonlyRef<R> {\n let last: [T, R] | null = null;\n return {\n get current() {\n const input = ref.current;\n if (last === null || input !== last[0]) {\n last = [input, mapper(input)];\n }\n return last[1];\n },\n };\n}\n\nexport type ReadonlyRef<T> = {\n readonly current: T,\n};\n\nexport type RefState<T> = ReadonlyRef<T> & {\n set: (updater: SetStateAction<T>) => void,\n};\n\n/**\n * Like useState, but its value is immediately available on refState.current after being set.\n *\n * Like useRef, but setting the value will cause a rerender.\n *\n * Note that useRefState returns a new object every time a rerender happens due to a value change, which is intentional\n * as it allows you to specify it in a dependency array like this:\n *\n * ```tsx\n * useEffect(() => {\n * // do something with refState.current\n * }, [refState]); // instead of refState.current\n * ```\n *\n * If you don't want this, you can wrap the result in a useMemo call.\n */\nexport function useRefState<T>(initialValue: T): RefState<T> {\n const [, setState] = React.useState(initialValue);\n const ref = React.useRef(initialValue);\n const setValue = React.useCallback((updater: SetStateAction<T>) => {\n const value: T = typeof updater === \"function\" ? (updater as any)(ref.current) : updater;\n setState(value);\n ref.current = value;\n }, []);\n const res = React.useMemo(() => ({\n current: ref.current,\n set: setValue,\n }), [ref.current, setValue]);\n return res;\n}\n\nexport function mapRefState<T, R>(refState: RefState<T>, mapper: (value: T) => R, reverseMapper: (oldT: T, newR: R) => T): RefState<R> {\n let last: [T, R] | null = null;\n return {\n get current() {\n const input = refState.current;\n if (last === null || input !== last[0]) {\n last = [input, mapper(input)];\n }\n return last[1];\n },\n set(updater: SetStateAction<R>) {\n const value: R = typeof updater === \"function\" ? (updater as any)(this.current) : updater;\n refState.set(reverseMapper(refState.current, value));\n },\n };\n}\n\nexport class NoSuspenseBoundaryError extends Error {\n digest: string;\n reason: string;\n\n constructor(options: { caller?: string }) {\n super(deindent`\n ${options.caller ?? \"This code path\"} attempted to display a loading indicator, but didn't find a Suspense boundary above it. Please read the error message below carefully.\n \n The fix depends on which of the 3 scenarios caused it:\n \n 1. You are missing a loading.tsx file in your app directory. Fix it by adding a loading.tsx file in your app directory.\n\n 2. The component is rendered in the root (outermost) layout.tsx or template.tsx file. Next.js does not wrap those files in a Suspense boundary, even if there is a loading.tsx file in the same folder. To fix it, wrap your layout inside a route group like this:\n\n - app\n - - layout.tsx // contains <html> and <body>, alongside providers and other components that don't need ${options.caller ?? \"this code path\"}\n - - loading.tsx // required for suspense\n - - (main)\n - - - layout.tsx // contains the main layout of your app, like a sidebar or a header, and can use ${options.caller ?? \"this code path\"}\n - - - route.tsx // your actual main page\n - - - the rest of your app\n\n For more information on this approach, see Next's documentation on route groups: https://nextjs.org/docs/app/building-your-application/routing/route-groups\n \n 3. You caught this error with try-catch or a custom error boundary. Fix this by rethrowing the error or not catching it in the first place.\n\n See: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout\n\n More information on SSR and Suspense boundaries: https://react.dev/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content\n `);\n\n this.name = \"NoSuspenseBoundaryError\";\n this.reason = options.caller ?? \"suspendIfSsr()\";\n\n // set the digest so nextjs doesn't log the error\n // https://github.com/vercel/next.js/blob/d01d6d9c35a8c2725b3d74c1402ab76d4779a6cf/packages/next/src/shared/lib/lazy-dynamic/bailout-to-csr.ts#L14\n this.digest = \"BAILOUT_TO_CLIENT_SIDE_RENDERING\";\n }\n}\nundefined?.test(\"NoSuspenseBoundaryError\", ({ expect }) => {\n // Test with default options\n const defaultError = new NoSuspenseBoundaryError({});\n expect(defaultError.name).toBe(\"NoSuspenseBoundaryError\");\n expect(defaultError.reason).toBe(\"suspendIfSsr()\");\n expect(defaultError.digest).toBe(\"BAILOUT_TO_CLIENT_SIDE_RENDERING\");\n expect(defaultError.message).toContain(\"This code path attempted to display a loading indicator\");\n\n // Test with custom caller\n const customError = new NoSuspenseBoundaryError({ caller: \"CustomComponent\" });\n expect(customError.name).toBe(\"NoSuspenseBoundaryError\");\n expect(customError.reason).toBe(\"CustomComponent\");\n expect(customError.digest).toBe(\"BAILOUT_TO_CLIENT_SIDE_RENDERING\");\n expect(customError.message).toContain(\"CustomComponent attempted to display a loading indicator\");\n\n // Verify error message contains all the necessary information\n expect(customError.message).toContain(\"loading.tsx\");\n expect(customError.message).toContain(\"route groups\");\n expect(customError.message).toContain(\"https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout\");\n});\n\n\n/**\n * Use this in a component or a hook to disable SSR. Should be wrapped in a Suspense boundary, or it will throw an error.\n */\nexport function suspendIfSsr(caller?: string) {\n if (!isBrowserLike()) {\n throw new NoSuspenseBoundaryError({ caller });\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/utils/react.tsx"],"sourcesContent":["import React, { SetStateAction } from \"react\";\nimport { isBrowserLike } from \"./env\";\nimport { neverResolve } from \"./promises\";\nimport { deindent } from \"./strings\";\n\nexport function componentWrapper<\n C extends React.ComponentType<any> | keyof React.JSX.IntrinsicElements,\n ExtraProps extends {} = {}\n>(displayName: string, render: React.ForwardRefRenderFunction<RefFromComponent<C>, React.ComponentPropsWithRef<C> & ExtraProps>) {\n const Component = forwardRefIfNeeded(render);\n Component.displayName = displayName;\n return Component;\n}\ntype RefFromComponent<C extends React.ComponentType<any> | keyof React.JSX.IntrinsicElements> = NonNullable<RefFromComponentDistCond<React.ComponentPropsWithRef<C>[\"ref\"]>>;\ntype RefFromComponentDistCond<A> = A extends React.RefObject<infer T> ? T : never; // distributive conditional type; see https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types\n\nexport function forwardRefIfNeeded<T, P = {}>(render: React.ForwardRefRenderFunction<T, P>): React.FC<P & { ref?: React.Ref<T> }> {\n // TODO: when we drop support for react 18, remove this\n\n const version = React.version;\n const major = parseInt(version.split(\".\")[0]);\n if (major < 19) {\n return React.forwardRef<T, P>(render as any) as any;\n } else {\n return ((props: P) => render(props, (props as any).ref)) as any;\n }\n}\n\nexport function getNodeText(node: React.ReactNode): string {\n if ([\"number\", \"string\"].includes(typeof node)) {\n return `${node}`;\n }\n if (!node) {\n return \"\";\n }\n if (Array.isArray(node)) {\n return node.map(getNodeText).join(\"\");\n }\n if (typeof node === \"object\" && \"props\" in node) {\n return getNodeText(node.props.children);\n }\n throw new Error(`Unknown node type: ${typeof node}`);\n}\nundefined?.test(\"getNodeText\", ({ expect }) => {\n // Test with string\n expect(getNodeText(\"hello\")).toBe(\"hello\");\n\n // Test with number\n expect(getNodeText(42)).toBe(\"42\");\n\n // Test with null/undefined\n expect(getNodeText(null)).toBe(\"\");\n expect(getNodeText(undefined)).toBe(\"\");\n\n // Test with array\n expect(getNodeText([\"hello\", \" \", \"world\"])).toBe(\"hello world\");\n expect(getNodeText([1, 2, 3])).toBe(\"123\");\n\n // Test with mixed array\n expect(getNodeText([\"hello\", 42, null])).toBe(\"hello42\");\n\n // Test with React element (mocked)\n const mockElement = {\n props: {\n children: \"child text\"\n }\n } as React.ReactElement;\n expect(getNodeText(mockElement)).toBe(\"child text\");\n\n // Test with nested React elements\n const nestedElement = {\n props: {\n children: {\n props: {\n children: \"nested text\"\n }\n } as React.ReactElement\n }\n } as React.ReactElement;\n expect(getNodeText(nestedElement)).toBe(\"nested text\");\n\n // Test with array of React elements\n const arrayOfElements = [\n { props: { children: \"first\" } } as React.ReactElement,\n { props: { children: \"second\" } } as React.ReactElement\n ];\n expect(getNodeText(arrayOfElements)).toBe(\"firstsecond\");\n});\n\n/**\n * Suspends the currently rendered component indefinitely. Will not unsuspend unless the component rerenders.\n *\n * You can use this to translate older query- or AsyncResult-based code to new the Suspense system, for example: `if (query.isLoading) suspend();`\n */\nexport function suspend(): never {\n React.use(neverResolve());\n throw new Error(\"Somehow a Promise that never resolves was resolved?\");\n}\n\nexport function mapRef<T, R>(ref: ReadonlyRef<T>, mapper: (value: T) => R): ReadonlyRef<R> {\n let last: [T, R] | null = null;\n return {\n get current() {\n const input = ref.current;\n if (last === null || input !== last[0]) {\n last = [input, mapper(input)];\n }\n return last[1];\n },\n };\n}\n\nexport type ReadonlyRef<T> = {\n readonly current: T,\n};\n\nexport type RefState<T> = ReadonlyRef<T> & {\n set: (updater: SetStateAction<T>) => void,\n};\n\n/**\n * Like useState, but its value is immediately available on refState.current after being set.\n *\n * Like useRef, but setting the value will cause a rerender.\n *\n * Note that useRefState returns a new object every time a rerender happens due to a value change, which is intentional\n * as it allows you to specify it in a dependency array like this:\n *\n * ```tsx\n * useEffect(() => {\n * // do something with refState.current\n * }, [refState]); // instead of refState.current\n * ```\n *\n * If you don't want this, you can wrap the result in a useMemo call.\n */\nexport function useRefState<T>(initialValue: T): RefState<T> {\n const [, setState] = React.useState(initialValue);\n const ref = React.useRef(initialValue);\n const setValue = React.useCallback((updater: SetStateAction<T>) => {\n const value: T = typeof updater === \"function\" ? (updater as any)(ref.current) : updater;\n console.log(\"setValue\", ref.current);\n ref.current = value;\n console.log(\"setValue\", ref.current);\n setState(value);\n }, []);\n const res = React.useMemo(() => ({\n get current() {\n return ref.current;\n },\n set: setValue,\n }), [setValue]);\n return res;\n}\n\nexport function mapRefState<T, R>(refState: RefState<T>, mapper: (value: T) => R, reverseMapper: (oldT: T, newR: R) => T): RefState<R> {\n let last: [T, R] | null = null;\n return {\n get current() {\n const input = refState.current;\n if (last === null || input !== last[0]) {\n last = [input, mapper(input)];\n }\n return last[1];\n },\n set(updater: SetStateAction<R>) {\n const value: R = typeof updater === \"function\" ? (updater as any)(this.current) : updater;\n refState.set(reverseMapper(refState.current, value));\n },\n };\n}\n\nexport class NoSuspenseBoundaryError extends Error {\n digest: string;\n reason: string;\n\n constructor(options: { caller?: string }) {\n super(deindent`\n ${options.caller ?? \"This code path\"} attempted to display a loading indicator, but didn't find a Suspense boundary above it. Please read the error message below carefully.\n \n The fix depends on which of the 3 scenarios caused it:\n \n 1. You are missing a loading.tsx file in your app directory. Fix it by adding a loading.tsx file in your app directory.\n\n 2. The component is rendered in the root (outermost) layout.tsx or template.tsx file. Next.js does not wrap those files in a Suspense boundary, even if there is a loading.tsx file in the same folder. To fix it, wrap your layout inside a route group like this:\n\n - app\n - - layout.tsx // contains <html> and <body>, alongside providers and other components that don't need ${options.caller ?? \"this code path\"}\n - - loading.tsx // required for suspense\n - - (main)\n - - - layout.tsx // contains the main layout of your app, like a sidebar or a header, and can use ${options.caller ?? \"this code path\"}\n - - - route.tsx // your actual main page\n - - - the rest of your app\n\n For more information on this approach, see Next's documentation on route groups: https://nextjs.org/docs/app/building-your-application/routing/route-groups\n \n 3. You caught this error with try-catch or a custom error boundary. Fix this by rethrowing the error or not catching it in the first place.\n\n See: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout\n\n More information on SSR and Suspense boundaries: https://react.dev/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content\n `);\n\n this.name = \"NoSuspenseBoundaryError\";\n this.reason = options.caller ?? \"suspendIfSsr()\";\n\n // set the digest so nextjs doesn't log the error\n // https://github.com/vercel/next.js/blob/d01d6d9c35a8c2725b3d74c1402ab76d4779a6cf/packages/next/src/shared/lib/lazy-dynamic/bailout-to-csr.ts#L14\n this.digest = \"BAILOUT_TO_CLIENT_SIDE_RENDERING\";\n }\n}\nundefined?.test(\"NoSuspenseBoundaryError\", ({ expect }) => {\n // Test with default options\n const defaultError = new NoSuspenseBoundaryError({});\n expect(defaultError.name).toBe(\"NoSuspenseBoundaryError\");\n expect(defaultError.reason).toBe(\"suspendIfSsr()\");\n expect(defaultError.digest).toBe(\"BAILOUT_TO_CLIENT_SIDE_RENDERING\");\n expect(defaultError.message).toContain(\"This code path attempted to display a loading indicator\");\n\n // Test with custom caller\n const customError = new NoSuspenseBoundaryError({ caller: \"CustomComponent\" });\n expect(customError.name).toBe(\"NoSuspenseBoundaryError\");\n expect(customError.reason).toBe(\"CustomComponent\");\n expect(customError.digest).toBe(\"BAILOUT_TO_CLIENT_SIDE_RENDERING\");\n expect(customError.message).toContain(\"CustomComponent attempted to display a loading indicator\");\n\n // Verify error message contains all the necessary information\n expect(customError.message).toContain(\"loading.tsx\");\n expect(customError.message).toContain(\"route groups\");\n expect(customError.message).toContain(\"https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout\");\n});\n\n\n/**\n * Use this in a component or a hook to disable SSR. Should be wrapped in a Suspense boundary, or it will throw an error.\n */\nexport function suspendIfSsr(caller?: string) {\n if (!isBrowserLike()) {\n throw new NoSuspenseBoundaryError({ caller });\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,12 +1,12 @@
1
- import '../crud.mjs';
2
1
  import { KnownErrors } from '../known-errors.mjs';
2
+ import '../crud.mjs';
3
3
  import '../schema-fields.mjs';
4
- import 'yup';
5
- import '../utils/types.mjs';
6
- import '../utils/strings.mjs';
7
4
  import '../utils/errors.mjs';
8
5
  import '../utils/json.mjs';
9
6
  import '../utils/results.mjs';
7
+ import 'yup';
8
+ import '../utils/types.mjs';
9
+ import '../utils/strings.mjs';
10
10
  import '../utils/currency-constants.mjs';
11
11
  import '../utils/dates.mjs';
12
12
 
@@ -1,12 +1,12 @@
1
- import '../crud.js';
2
1
  import { KnownErrors } from '../known-errors.js';
2
+ import '../crud.js';
3
3
  import '../schema-fields.js';
4
- import 'yup';
5
- import '../utils/types.js';
6
- import '../utils/strings.js';
7
4
  import '../utils/errors.js';
8
5
  import '../utils/json.js';
9
6
  import '../utils/results.js';
7
+ import 'yup';
8
+ import '../utils/types.js';
9
+ import '../utils/strings.js';
10
10
  import '../utils/currency-constants.js';
11
11
  import '../utils/dates.js';
12
12
 
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Use to hash the key so the server cannot infer it.
3
+ */
4
+ declare function hashKey(secret: string, key: string): Promise<string>;
5
+ /**
6
+ * Use to encrypt the value so that the server cannot read the value without knowing the key.
7
+ */
8
+ declare function encryptValue(secret: string, key: string, value: string): Promise<string>;
9
+ /**
10
+ * Use to decrypt the value. See encryptValue.
11
+ */
12
+ declare function decryptValue(secret: string, key: string, encryptedValue: string): Promise<string>;
13
+
14
+ export { decryptValue, encryptValue, hashKey };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Use to hash the key so the server cannot infer it.
3
+ */
4
+ declare function hashKey(secret: string, key: string): Promise<string>;
5
+ /**
6
+ * Use to encrypt the value so that the server cannot read the value without knowing the key.
7
+ */
8
+ declare function encryptValue(secret: string, key: string, value: string): Promise<string>;
9
+ /**
10
+ * Use to decrypt the value. See encryptValue.
11
+ */
12
+ declare function decryptValue(secret: string, key: string, encryptedValue: string): Promise<string>;
13
+
14
+ export { decryptValue, encryptValue, hashKey };
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/helpers/vault/client-side.ts
21
+ var client_side_exports = {};
22
+ __export(client_side_exports, {
23
+ decryptValue: () => decryptValue,
24
+ encryptValue: () => encryptValue,
25
+ hashKey: () => hashKey
26
+ });
27
+ module.exports = __toCommonJS(client_side_exports);
28
+ var import_bytes = require("../../utils/bytes.js");
29
+ var import_crypto = require("../../utils/crypto.js");
30
+ var hashPurpose = "stack-data-vault-client-side-encryption-key-hash";
31
+ var encryptionSecretPurpose = "stack-data-vault-client-side-encryption-value-encryption-key-hash";
32
+ var encryptionValuePurpose = "stack-data-vault-client-side-encryption-value-encryption-value-encryption";
33
+ async function getDerivedKey(secret, key) {
34
+ return await (0, import_crypto.iteratedHash)({
35
+ purpose: encryptionSecretPurpose,
36
+ extra: secret,
37
+ value: key,
38
+ iterations: 1e5
39
+ });
40
+ }
41
+ async function hashKey(secret, key) {
42
+ return (0, import_bytes.encodeBase64)(await (0, import_crypto.hash)({
43
+ purpose: hashPurpose,
44
+ extra: secret,
45
+ value: await getDerivedKey(secret, key)
46
+ }));
47
+ }
48
+ async function encryptValue(secret, key, value) {
49
+ const valueEncryptionDerivedKey = await getDerivedKey(secret, key);
50
+ const bytes = await (0, import_crypto.encrypt)({
51
+ purpose: encryptionValuePurpose,
52
+ secret: valueEncryptionDerivedKey,
53
+ value: new TextEncoder().encode(value)
54
+ });
55
+ return (0, import_bytes.encodeBase64)(bytes);
56
+ }
57
+ async function decryptValue(secret, key, encryptedValue) {
58
+ const valueEncryptionDerivedKey = await getDerivedKey(secret, key);
59
+ const bytesResult = await (0, import_crypto.decrypt)({
60
+ purpose: encryptionValuePurpose,
61
+ secret: valueEncryptionDerivedKey,
62
+ cipher: (0, import_bytes.decodeBase64)(encryptedValue)
63
+ });
64
+ if (bytesResult.status === "error") throw new Error("Data vault client-side decryption failed. Are you sure you're using the correct secret?", { cause: bytesResult.error });
65
+ return new TextDecoder().decode(bytesResult.data);
66
+ }
67
+ // Annotate the CommonJS export names for ESM import in node:
68
+ 0 && (module.exports = {
69
+ decryptValue,
70
+ encryptValue,
71
+ hashKey
72
+ });
73
+ //# sourceMappingURL=client-side.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/helpers/vault/client-side.ts"],"sourcesContent":["import { decodeBase64, encodeBase64 } from \"../../utils/bytes\";\nimport { decrypt, encrypt, hash, iteratedHash } from \"../../utils/crypto\";\n\nconst hashPurpose = \"stack-data-vault-client-side-encryption-key-hash\";\nconst encryptionSecretPurpose = \"stack-data-vault-client-side-encryption-value-encryption-key-hash\";\nconst encryptionValuePurpose = \"stack-data-vault-client-side-encryption-value-encryption-value-encryption\";\n\n\nasync function getDerivedKey(secret: string, key: string) {\n return await iteratedHash({\n purpose: encryptionSecretPurpose,\n extra: secret,\n value: key,\n iterations: 100_000,\n });\n}\n\n/**\n * Use to hash the key so the server cannot infer it.\n */\nexport async function hashKey(secret: string, key: string) {\n return encodeBase64(await hash({\n purpose: hashPurpose,\n extra: secret,\n value: await getDerivedKey(secret, key),\n }));\n}\n\n/**\n * Use to encrypt the value so that the server cannot read the value without knowing the key.\n */\nexport async function encryptValue(secret: string, key: string, value: string) {\n const valueEncryptionDerivedKey = await getDerivedKey(secret, key);\n\n const bytes = await encrypt({\n purpose: encryptionValuePurpose,\n secret: valueEncryptionDerivedKey,\n value: new TextEncoder().encode(value)\n });\n return encodeBase64(bytes);\n}\n\n/**\n * Use to decrypt the value. See encryptValue.\n */\nexport async function decryptValue(secret: string, key: string, encryptedValue: string) {\n const valueEncryptionDerivedKey = await getDerivedKey(secret, key);\n\n const bytesResult = await decrypt({\n purpose: encryptionValuePurpose,\n secret: valueEncryptionDerivedKey,\n cipher: decodeBase64(encryptedValue),\n });\n if (bytesResult.status === \"error\") throw new Error(\"Data vault client-side decryption failed. Are you sure you're using the correct secret?\", { cause: bytesResult.error });\n return new TextDecoder().decode(bytesResult.data);\n}\n\n\nundefined?.describe(\"encryptValue & decryptValue\", () => {\n undefined?.it(\"should encrypt and decrypt a value\", async ({ expect }) => {\n const secret = \"test-secret\";\n const value = \"test-value\";\n const encrypted = await encryptValue(secret, \"key\", value);\n const decrypted = await decryptValue(secret, \"key\", encrypted);\n expect(decrypted).toEqual(value);\n });\n\n undefined?.it(\"should not decrypt a value with a different secret\", async ({ expect }) => {\n const secret = \"test-secret\";\n const value = \"test-value\";\n const encrypted = await encryptValue(secret, \"key\", value);\n await expect(decryptValue(\"different-secret\", \"key\", encrypted)).rejects.toThrow();\n });\n\n undefined?.it(\"should not decrypt a value with a different key\", async ({ expect }) => {\n const secret = \"test-secret\";\n const value = \"test-value\";\n const encrypted = await encryptValue(secret, \"key\", value);\n await expect(decryptValue(secret, \"different-key\", encrypted)).rejects.toThrow();\n });\n\n undefined?.it(\"should not decrypt a value if the cipher was tampered with\", async ({ expect }) => {\n const secret = \"test-secret\";\n const value = \"test-value\";\n const encrypted = await encryptValue(secret, \"key\", value);\n const tampered = encrypted + \"7\";\n await expect(decryptValue(secret, \"key\", tampered)).rejects.toThrow();\n });\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA2C;AAC3C,oBAAqD;AAErD,IAAM,cAAc;AACpB,IAAM,0BAA0B;AAChC,IAAM,yBAAyB;AAG/B,eAAe,cAAc,QAAgB,KAAa;AACxD,SAAO,UAAM,4BAAa;AAAA,IACxB,SAAS;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,IACP,YAAY;AAAA,EACd,CAAC;AACH;AAKA,eAAsB,QAAQ,QAAgB,KAAa;AACzD,aAAO,2BAAa,UAAM,oBAAK;AAAA,IAC7B,SAAS;AAAA,IACT,OAAO;AAAA,IACP,OAAO,MAAM,cAAc,QAAQ,GAAG;AAAA,EACxC,CAAC,CAAC;AACJ;AAKA,eAAsB,aAAa,QAAgB,KAAa,OAAe;AAC7E,QAAM,4BAA4B,MAAM,cAAc,QAAQ,GAAG;AAEjE,QAAM,QAAQ,UAAM,uBAAQ;AAAA,IAC1B,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,OAAO,IAAI,YAAY,EAAE,OAAO,KAAK;AAAA,EACvC,CAAC;AACD,aAAO,2BAAa,KAAK;AAC3B;AAKA,eAAsB,aAAa,QAAgB,KAAa,gBAAwB;AACtF,QAAM,4BAA4B,MAAM,cAAc,QAAQ,GAAG;AAEjE,QAAM,cAAc,UAAM,uBAAQ;AAAA,IAChC,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,YAAQ,2BAAa,cAAc;AAAA,EACrC,CAAC;AACD,MAAI,YAAY,WAAW,QAAS,OAAM,IAAI,MAAM,2FAA2F,EAAE,OAAO,YAAY,MAAM,CAAC;AAC3K,SAAO,IAAI,YAAY,EAAE,OAAO,YAAY,IAAI;AAClD;","names":[]}
@@ -0,0 +1,7 @@
1
+ declare function encryptWithKms(value: string): Promise<{
2
+ edkBase64: string;
3
+ ciphertextBase64: string;
4
+ }>;
5
+ declare function decryptWithKms(encrypted: Awaited<ReturnType<typeof encryptWithKms>>): Promise<string>;
6
+
7
+ export { decryptWithKms, encryptWithKms };
@@ -0,0 +1,7 @@
1
+ declare function encryptWithKms(value: string): Promise<{
2
+ edkBase64: string;
3
+ ciphertextBase64: string;
4
+ }>;
5
+ declare function decryptWithKms(encrypted: Awaited<ReturnType<typeof encryptWithKms>>): Promise<string>;
6
+
7
+ export { decryptWithKms, encryptWithKms };
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/helpers/vault/server-side.ts
21
+ var server_side_exports = {};
22
+ __export(server_side_exports, {
23
+ decryptWithKms: () => decryptWithKms,
24
+ encryptWithKms: () => encryptWithKms
25
+ });
26
+ module.exports = __toCommonJS(server_side_exports);
27
+ var import_client_kms = require("@aws-sdk/client-kms");
28
+ var import_bytes = require("../../utils/bytes.js");
29
+ var import_crypto = require("../../utils/crypto.js");
30
+ var import_env = require("../../utils/env.js");
31
+ var import_results = require("../../utils/results.js");
32
+ function getKmsClient() {
33
+ return new import_client_kms.KMSClient({
34
+ region: (0, import_env.getEnvVariable)("STACK_AWS_REGION"),
35
+ endpoint: (0, import_env.getEnvVariable)("STACK_AWS_KMS_ENDPOINT"),
36
+ credentials: {
37
+ accessKeyId: (0, import_env.getEnvVariable)("STACK_AWS_ACCESS_KEY_ID"),
38
+ secretAccessKey: (0, import_env.getEnvVariable)("STACK_AWS_SECRET_ACCESS_KEY")
39
+ }
40
+ });
41
+ }
42
+ async function getOrCreateKekId() {
43
+ const id = "alias/stack-data-vault-server-side-kek";
44
+ const kms = getKmsClient();
45
+ try {
46
+ const describeResult = await kms.send(new import_client_kms.DescribeKeyCommand({ KeyId: id }));
47
+ if (describeResult.KeyMetadata?.KeyId) return describeResult.KeyMetadata.KeyId;
48
+ } catch (e) {
49
+ if (e instanceof Error && e.name !== "NotFoundException") {
50
+ throw e;
51
+ }
52
+ }
53
+ const { KeyMetadata } = await kms.send(new import_client_kms.CreateKeyCommand({
54
+ KeyUsage: "ENCRYPT_DECRYPT",
55
+ Description: "DataVault KEK"
56
+ }));
57
+ await kms.send(new import_client_kms.CreateAliasCommand({ AliasName: id, TargetKeyId: KeyMetadata.KeyId }));
58
+ return id;
59
+ }
60
+ async function genDEK() {
61
+ const kekId = await getOrCreateKekId();
62
+ const kms = getKmsClient();
63
+ const out = await kms.send(new import_client_kms.GenerateDataKeyCommand({ KeyId: kekId, KeySpec: "AES_256" }));
64
+ if (!out.Plaintext || !out.CiphertextBlob) throw new Error("GenerateDataKey failed");
65
+ return {
66
+ dekBytes: out.Plaintext,
67
+ edkBytes: out.CiphertextBlob
68
+ };
69
+ }
70
+ async function unwrapDEK(edk_b64) {
71
+ const edkBytes = (0, import_bytes.decodeBase64)(edk_b64);
72
+ const kms = getKmsClient();
73
+ const out = await kms.send(new import_client_kms.DecryptCommand({ CiphertextBlob: edkBytes }));
74
+ if (!out.Plaintext) throw new Error("KMS Decrypt failed");
75
+ return {
76
+ dekBytes: out.Plaintext,
77
+ edkBytes
78
+ };
79
+ }
80
+ async function encryptWithKms(value) {
81
+ const { dekBytes, edkBytes } = await genDEK();
82
+ try {
83
+ const ciphertext = await (0, import_crypto.encrypt)({
84
+ purpose: "stack-data-vault-server-side-encryption",
85
+ secret: dekBytes,
86
+ value: new TextEncoder().encode(value)
87
+ });
88
+ return { edkBase64: (0, import_bytes.encodeBase64)(edkBytes), ciphertextBase64: (0, import_bytes.encodeBase64)(ciphertext) };
89
+ } finally {
90
+ dekBytes.fill(0);
91
+ }
92
+ }
93
+ async function decryptWithKms(encrypted) {
94
+ const { dekBytes } = await unwrapDEK(encrypted.edkBase64);
95
+ try {
96
+ const value = import_results.Result.orThrow(await (0, import_crypto.decrypt)({
97
+ purpose: "stack-data-vault-server-side-encryption",
98
+ secret: dekBytes,
99
+ cipher: (0, import_bytes.decodeBase64)(encrypted.ciphertextBase64)
100
+ }));
101
+ return new TextDecoder().decode(value);
102
+ } finally {
103
+ dekBytes.fill(0);
104
+ }
105
+ }
106
+ // Annotate the CommonJS export names for ESM import in node:
107
+ 0 && (module.exports = {
108
+ decryptWithKms,
109
+ encryptWithKms
110
+ });
111
+ //# sourceMappingURL=server-side.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/helpers/vault/server-side.ts"],"sourcesContent":["import {\n CreateAliasCommand,\n CreateKeyCommand,\n DecryptCommand,\n DescribeKeyCommand,\n GenerateDataKeyCommand,\n KMSClient\n} from \"@aws-sdk/client-kms\";\nimport { decodeBase64, encodeBase64 } from \"../../utils/bytes\";\nimport { decrypt, encrypt } from \"../../utils/crypto\";\nimport { getEnvVariable } from \"../../utils/env\";\nimport { Result } from \"../../utils/results\";\n\nfunction getKmsClient() {\n return new KMSClient({\n region: getEnvVariable(\"STACK_AWS_REGION\"),\n endpoint: getEnvVariable(\"STACK_AWS_KMS_ENDPOINT\"),\n credentials: {\n accessKeyId: getEnvVariable(\"STACK_AWS_ACCESS_KEY_ID\"),\n secretAccessKey: getEnvVariable(\"STACK_AWS_SECRET_ACCESS_KEY\")\n }\n });\n}\n\nasync function getOrCreateKekId(): Promise<string> {\n const id = \"alias/stack-data-vault-server-side-kek\";\n const kms = getKmsClient();\n try {\n const describeResult = await kms.send(new DescribeKeyCommand({ KeyId: id }));\n if (describeResult.KeyMetadata?.KeyId) return describeResult.KeyMetadata.KeyId;\n } catch (e) {\n if (e instanceof Error && e.name !== \"NotFoundException\") {\n throw e;\n }\n }\n const { KeyMetadata } = await kms.send(new CreateKeyCommand({\n KeyUsage: \"ENCRYPT_DECRYPT\",\n Description: \"DataVault KEK\"\n }));\n await kms.send(new CreateAliasCommand({ AliasName: id, TargetKeyId: KeyMetadata!.KeyId! }));\n return id;\n}\n\nasync function genDEK() {\n const kekId = await getOrCreateKekId();\n const kms = getKmsClient();\n const out = await kms.send(new GenerateDataKeyCommand({ KeyId: kekId, KeySpec: \"AES_256\" }));\n if (!out.Plaintext || !out.CiphertextBlob) throw new Error(\"GenerateDataKey failed\");\n return {\n dekBytes: out.Plaintext,\n edkBytes: out.CiphertextBlob,\n };\n}\n\nasync function unwrapDEK(edk_b64: string) {\n const edkBytes = decodeBase64(edk_b64);\n const kms = getKmsClient();\n const out = await kms.send(new DecryptCommand({ CiphertextBlob: edkBytes }));\n if (!out.Plaintext) throw new Error(\"KMS Decrypt failed\");\n return {\n dekBytes: out.Plaintext,\n edkBytes,\n };\n}\n\nexport async function encryptWithKms(value: string) {\n const { dekBytes, edkBytes } = await genDEK();\n try {\n const ciphertext = await encrypt({\n purpose: \"stack-data-vault-server-side-encryption\",\n secret: dekBytes,\n value: new TextEncoder().encode(value),\n });\n return { edkBase64: encodeBase64(edkBytes), ciphertextBase64: encodeBase64(ciphertext) };\n } finally {\n dekBytes.fill(0);\n }\n}\n\nexport async function decryptWithKms(encrypted: Awaited<ReturnType<typeof encryptWithKms>>) {\n const { dekBytes } = await unwrapDEK(encrypted.edkBase64);\n try {\n const value = Result.orThrow(await decrypt({\n purpose: \"stack-data-vault-server-side-encryption\",\n secret: dekBytes,\n cipher: decodeBase64(encrypted.ciphertextBase64),\n }));\n return new TextDecoder().decode(value);\n } finally {\n dekBytes.fill(0);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAOO;AACP,mBAA2C;AAC3C,oBAAiC;AACjC,iBAA+B;AAC/B,qBAAuB;AAEvB,SAAS,eAAe;AACtB,SAAO,IAAI,4BAAU;AAAA,IACnB,YAAQ,2BAAe,kBAAkB;AAAA,IACzC,cAAU,2BAAe,wBAAwB;AAAA,IACjD,aAAa;AAAA,MACX,iBAAa,2BAAe,yBAAyB;AAAA,MACrD,qBAAiB,2BAAe,6BAA6B;AAAA,IAC/D;AAAA,EACF,CAAC;AACH;AAEA,eAAe,mBAAoC;AACjD,QAAM,KAAK;AACX,QAAM,MAAM,aAAa;AACzB,MAAI;AACF,UAAM,iBAAiB,MAAM,IAAI,KAAK,IAAI,qCAAmB,EAAE,OAAO,GAAG,CAAC,CAAC;AAC3E,QAAI,eAAe,aAAa,MAAO,QAAO,eAAe,YAAY;AAAA,EAC3E,SAAS,GAAG;AACV,QAAI,aAAa,SAAS,EAAE,SAAS,qBAAqB;AACxD,YAAM;AAAA,IACR;AAAA,EACF;AACA,QAAM,EAAE,YAAY,IAAI,MAAM,IAAI,KAAK,IAAI,mCAAiB;AAAA,IAC1D,UAAU;AAAA,IACV,aAAa;AAAA,EACf,CAAC,CAAC;AACF,QAAM,IAAI,KAAK,IAAI,qCAAmB,EAAE,WAAW,IAAI,aAAa,YAAa,MAAO,CAAC,CAAC;AAC1F,SAAO;AACT;AAEA,eAAe,SAAS;AACtB,QAAM,QAAQ,MAAM,iBAAiB;AACrC,QAAM,MAAM,aAAa;AACzB,QAAM,MAAM,MAAM,IAAI,KAAK,IAAI,yCAAuB,EAAE,OAAO,OAAO,SAAS,UAAU,CAAC,CAAC;AAC3F,MAAI,CAAC,IAAI,aAAa,CAAC,IAAI,eAAgB,OAAM,IAAI,MAAM,wBAAwB;AACnF,SAAO;AAAA,IACL,UAAU,IAAI;AAAA,IACd,UAAU,IAAI;AAAA,EAChB;AACF;AAEA,eAAe,UAAU,SAAiB;AACxC,QAAM,eAAW,2BAAa,OAAO;AACrC,QAAM,MAAM,aAAa;AACzB,QAAM,MAAM,MAAM,IAAI,KAAK,IAAI,iCAAe,EAAE,gBAAgB,SAAS,CAAC,CAAC;AAC3E,MAAI,CAAC,IAAI,UAAW,OAAM,IAAI,MAAM,oBAAoB;AACxD,SAAO;AAAA,IACL,UAAU,IAAI;AAAA,IACd;AAAA,EACF;AACF;AAEA,eAAsB,eAAe,OAAe;AAClD,QAAM,EAAE,UAAU,SAAS,IAAI,MAAM,OAAO;AAC5C,MAAI;AACF,UAAM,aAAa,UAAM,uBAAQ;AAAA,MAC/B,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,OAAO,IAAI,YAAY,EAAE,OAAO,KAAK;AAAA,IACvC,CAAC;AACD,WAAO,EAAE,eAAW,2BAAa,QAAQ,GAAG,sBAAkB,2BAAa,UAAU,EAAE;AAAA,EACzF,UAAE;AACA,aAAS,KAAK,CAAC;AAAA,EACjB;AACF;AAEA,eAAsB,eAAe,WAAuD;AAC1F,QAAM,EAAE,SAAS,IAAI,MAAM,UAAU,UAAU,SAAS;AACxD,MAAI;AACF,UAAM,QAAQ,sBAAO,QAAQ,UAAM,uBAAQ;AAAA,MACzC,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,YAAQ,2BAAa,UAAU,gBAAgB;AAAA,IACjD,CAAC,CAAC;AACF,WAAO,IAAI,YAAY,EAAE,OAAO,KAAK;AAAA,EACvC,UAAE;AACA,aAAS,KAAK,CAAC;AAAA,EACjB;AACF;","names":[]}
@@ -0,0 +1,6 @@
1
+ declare function useHover<T extends HTMLElement>(ref: React.RefObject<T>, options?: {
2
+ onMouseEnter?: () => void;
3
+ onMouseLeave?: () => void;
4
+ }): boolean;
5
+
6
+ export { useHover };
@@ -0,0 +1,6 @@
1
+ declare function useHover<T extends HTMLElement>(ref: React.RefObject<T>, options?: {
2
+ onMouseEnter?: () => void;
3
+ onMouseLeave?: () => void;
4
+ }): boolean;
5
+
6
+ export { useHover };
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/hooks/use-hover.tsx
21
+ var use_hover_exports = {};
22
+ __export(use_hover_exports, {
23
+ useHover: () => useHover
24
+ });
25
+ module.exports = __toCommonJS(use_hover_exports);
26
+ var import_react = require("react");
27
+ var import_react2 = require("../utils/react.js");
28
+ function useHover(ref, options = {}) {
29
+ const counter = (0, import_react2.useRefState)(0);
30
+ (0, import_react.useLayoutEffect)(() => {
31
+ const el = ref.current;
32
+ if (!el) return;
33
+ let incr = 0;
34
+ let prevInside = false;
35
+ const contains = (r, x, y) => x >= r.left && x <= r.right && y >= r.top && y <= r.bottom;
36
+ const enter = () => {
37
+ incr++;
38
+ counter.set((c) => c + 1);
39
+ if (counter.current === 1) {
40
+ options.onMouseEnter?.();
41
+ }
42
+ };
43
+ const leave = () => {
44
+ incr--;
45
+ requestAnimationFrame(() => {
46
+ requestAnimationFrame(() => {
47
+ counter.set((c) => c - 1);
48
+ if (counter.current === 0) {
49
+ options.onMouseLeave?.();
50
+ }
51
+ });
52
+ });
53
+ };
54
+ const topMatchesTarget = (x, y) => {
55
+ const top = document.elementFromPoint(x, y);
56
+ return !!(top && (top === el || el.contains(top)));
57
+ };
58
+ const processPoint = (x, y) => {
59
+ const rect = el.getBoundingClientRect();
60
+ const inside = contains(rect, x, y) && topMatchesTarget(x, y);
61
+ if (inside && !prevInside) {
62
+ enter();
63
+ } else if (!inside && prevInside) {
64
+ leave();
65
+ }
66
+ prevInside = inside;
67
+ };
68
+ const onMove = (e) => {
69
+ if (e.pointerType !== "mouse") return;
70
+ const batch = e.getCoalescedEvents();
71
+ if (batch.length) {
72
+ for (let eventIndex = 0; eventIndex < batch.length - 1; eventIndex++) {
73
+ const e1 = batch[eventIndex];
74
+ const e2 = batch[eventIndex + 1];
75
+ const steps = 10;
76
+ for (let i = 0; i <= steps; i++) {
77
+ processPoint(e1.clientX + (e2.clientX - e1.clientX) * i / steps, e1.clientY + (e2.clientY - e1.clientY) * i / steps);
78
+ }
79
+ }
80
+ } else {
81
+ processPoint(e.clientX, e.clientY);
82
+ }
83
+ };
84
+ window.addEventListener("pointermove", onMove, { passive: true });
85
+ return () => {
86
+ window.removeEventListener("pointermove", onMove);
87
+ counter.set((c) => c - incr);
88
+ };
89
+ }, []);
90
+ return counter.current > 0;
91
+ }
92
+ // Annotate the CommonJS export names for ESM import in node:
93
+ 0 && (module.exports = {
94
+ useHover
95
+ });
96
+ //# sourceMappingURL=use-hover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/use-hover.tsx"],"sourcesContent":["import { useLayoutEffect } from \"react\";\nimport { useRefState } from \"../utils/react\";\n\nexport function useHover<T extends HTMLElement>(\n ref: React.RefObject<T>,\n options: {\n onMouseEnter?: () => void,\n onMouseLeave?: () => void,\n } = {},\n): boolean {\n // Internal counter: mouseenter++ / mouseleave-- (isHovering = counter > 0)\n const counter = useRefState(0);\n\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el) return;\n let incr = 0;\n let prevInside = false;\n\n const contains = (r: DOMRect, x: number, y: number) =>\n x >= r.left && x <= r.right && y >= r.top && y <= r.bottom;\n\n const enter = () => {\n incr++;\n counter.set(c => c + 1);\n if (counter.current === 1) {\n options.onMouseEnter?.();\n }\n };\n\n const leave = () => {\n incr--;\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n counter.set(c => c - 1);\n if (counter.current === 0) {\n options.onMouseLeave?.();\n }\n });\n });\n };\n\n const topMatchesTarget = (x: number, y: number) => {\n const top = document.elementFromPoint(x, y);\n return !!(top && (top === el || el.contains(top)));\n };\n\n const processPoint = (x: number, y: number) => {\n const rect = el.getBoundingClientRect();\n\n // True “hoverability”: inside rect AND not occluded by others\n const inside = contains(rect, x, y) && topMatchesTarget(x, y);\n if (inside && !prevInside) {\n enter();\n } else if (!inside && prevInside) {\n leave();\n }\n prevInside = inside;\n };\n\n const onMove = (e: PointerEvent) => {\n if (e.pointerType !== \"mouse\") return; // keep it hover-only\n // Use coalesced points when available\n const batch = e.getCoalescedEvents();\n if (batch.length) {\n for (let eventIndex = 0; eventIndex < batch.length - 1; eventIndex++) {\n const e1 = batch[eventIndex];\n const e2 = batch[eventIndex + 1];\n const steps = 10;\n for (let i = 0; i <= steps; i++) {\n processPoint(e1.clientX + (e2.clientX - e1.clientX) * i / steps, e1.clientY + (e2.clientY - e1.clientY) * i / steps);\n }\n }\n } else {\n processPoint(e.clientX, e.clientY);\n }\n };\n\n window.addEventListener(\"pointermove\", onMove, { passive: true });\n\n return () => {\n window.removeEventListener(\"pointermove\", onMove);\n counter.set(c => c - incr);\n };\n }, []);\n\n return counter.current > 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAgC;AAChC,IAAAA,gBAA4B;AAErB,SAAS,SACd,KACA,UAGI,CAAC,GACI;AAET,QAAM,cAAU,2BAAY,CAAC;AAE7B,oCAAgB,MAAM;AACpB,UAAM,KAAK,IAAI;AACf,QAAI,CAAC,GAAI;AACT,QAAI,OAAO;AACX,QAAI,aAAa;AAEjB,UAAM,WAAW,CAAC,GAAY,GAAW,MACvC,KAAK,EAAE,QAAQ,KAAK,EAAE,SAAS,KAAK,EAAE,OAAO,KAAK,EAAE;AAEtD,UAAM,QAAQ,MAAM;AAClB;AACA,cAAQ,IAAI,OAAK,IAAI,CAAC;AACtB,UAAI,QAAQ,YAAY,GAAG;AACzB,gBAAQ,eAAe;AAAA,MACzB;AAAA,IACF;AAEA,UAAM,QAAQ,MAAM;AAClB;AACA,4BAAsB,MAAM;AAC1B,8BAAsB,MAAM;AAC1B,kBAAQ,IAAI,OAAK,IAAI,CAAC;AACtB,cAAI,QAAQ,YAAY,GAAG;AACzB,oBAAQ,eAAe;AAAA,UACzB;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAEA,UAAM,mBAAmB,CAAC,GAAW,MAAc;AACjD,YAAM,MAAM,SAAS,iBAAiB,GAAG,CAAC;AAC1C,aAAO,CAAC,EAAE,QAAQ,QAAQ,MAAM,GAAG,SAAS,GAAG;AAAA,IACjD;AAEA,UAAM,eAAe,CAAC,GAAW,MAAc;AAC7C,YAAM,OAAO,GAAG,sBAAsB;AAGtC,YAAM,SAAS,SAAS,MAAM,GAAG,CAAC,KAAK,iBAAiB,GAAG,CAAC;AAC5D,UAAI,UAAU,CAAC,YAAY;AACzB,cAAM;AAAA,MACR,WAAW,CAAC,UAAU,YAAY;AAChC,cAAM;AAAA,MACR;AACA,mBAAa;AAAA,IACf;AAEA,UAAM,SAAS,CAAC,MAAoB;AAClC,UAAI,EAAE,gBAAgB,QAAS;AAE/B,YAAM,QAAQ,EAAE,mBAAmB;AACnC,UAAI,MAAM,QAAQ;AAChB,iBAAS,aAAa,GAAG,aAAa,MAAM,SAAS,GAAG,cAAc;AACpE,gBAAM,KAAK,MAAM,UAAU;AAC3B,gBAAM,KAAK,MAAM,aAAa,CAAC;AAC/B,gBAAM,QAAQ;AACd,mBAAS,IAAI,GAAG,KAAK,OAAO,KAAK;AAC/B,yBAAa,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,IAAI,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,IAAI,KAAK;AAAA,UACrH;AAAA,QACF;AAAA,MACF,OAAO;AACL,qBAAa,EAAE,SAAS,EAAE,OAAO;AAAA,MACnC;AAAA,IACF;AAEA,WAAO,iBAAiB,eAAe,QAAQ,EAAE,SAAS,KAAK,CAAC;AAEhE,WAAO,MAAM;AACX,aAAO,oBAAoB,eAAe,MAAM;AAChD,cAAQ,IAAI,OAAK,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO,QAAQ,UAAU;AAC3B;","names":["import_react"]}
package/dist/index.d.mts CHANGED
@@ -4,6 +4,7 @@ export { StackServerInterface } from './interface/server-interface.mjs';
4
4
  export { KnownError, KnownErrors } from './known-errors.mjs';
5
5
  import './sessions.mjs';
6
6
  import 'jose';
7
+ import './utils/results.mjs';
7
8
  import './interface/crud/config.mjs';
8
9
  import './crud.mjs';
9
10
  import 'yup';
@@ -15,7 +16,8 @@ import './interface/crud/project-permissions.mjs';
15
16
  import './interface/crud/projects.mjs';
16
17
  import './interface/crud/svix-token.mjs';
17
18
  import './interface/crud/team-permissions.mjs';
18
- import './utils/results.mjs';
19
+ import './utils/errors.mjs';
20
+ import './utils/json.mjs';
19
21
  import './interface/crud/connected-accounts.mjs';
20
22
  import './interface/crud/contact-channels.mjs';
21
23
  import './interface/crud/current-user.mjs';
@@ -27,8 +29,6 @@ import './interface/crud/team-member-profiles.mjs';
27
29
  import './interface/crud/team-memberships.mjs';
28
30
  import './interface/crud/teams.mjs';
29
31
  import './interface/crud/users.mjs';
30
- import './utils/errors.mjs';
31
- import './utils/json.mjs';
32
32
  import './schema-fields.mjs';
33
33
  import './utils/currency-constants.mjs';
34
34
  import './utils/dates.mjs';
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export { StackServerInterface } from './interface/server-interface.js';
4
4
  export { KnownError, KnownErrors } from './known-errors.js';
5
5
  import './sessions.js';
6
6
  import 'jose';
7
+ import './utils/results.js';
7
8
  import './interface/crud/config.js';
8
9
  import './crud.js';
9
10
  import 'yup';
@@ -15,7 +16,8 @@ import './interface/crud/project-permissions.js';
15
16
  import './interface/crud/projects.js';
16
17
  import './interface/crud/svix-token.js';
17
18
  import './interface/crud/team-permissions.js';
18
- import './utils/results.js';
19
+ import './utils/errors.js';
20
+ import './utils/json.js';
19
21
  import './interface/crud/connected-accounts.js';
20
22
  import './interface/crud/contact-channels.js';
21
23
  import './interface/crud/current-user.js';
@@ -27,8 +29,6 @@ import './interface/crud/team-member-profiles.js';
27
29
  import './interface/crud/team-memberships.js';
28
30
  import './interface/crud/teams.js';
29
31
  import './interface/crud/users.js';
30
- import './utils/errors.js';
31
- import './utils/json.js';
32
32
  import './schema-fields.js';
33
33
  import './utils/currency-constants.js';
34
34
  import './utils/dates.js';
@@ -1,4 +1,6 @@
1
+ import { KnownErrors } from '../known-errors.mjs';
1
2
  import { InternalSession, AccessToken, RefreshToken } from '../sessions.mjs';
3
+ import { Result } from '../utils/results.mjs';
2
4
  import { ConfigCrud, ConfigOverrideCrud } from './crud/config.mjs';
3
5
  import { InternalEmailsCrud } from './crud/emails.mjs';
4
6
  import { InternalApiKeysCrud } from './crud/internal-api-keys.mjs';
@@ -8,13 +10,13 @@ import { SvixTokenCrud } from './crud/svix-token.mjs';
8
10
  import { TeamPermissionDefinitionsCrud } from './crud/team-permissions.mjs';
9
11
  import { ServerAuthApplicationOptions, StackServerInterface } from './server-interface.mjs';
10
12
  import './client-interface.mjs';
11
- import '../known-errors.mjs';
13
+ import '../utils/errors.mjs';
14
+ import '../utils/json.mjs';
12
15
  import 'jose';
13
16
  import '../crud.mjs';
14
17
  import 'yup';
15
18
  import '../utils/types.mjs';
16
19
  import '../utils/strings.mjs';
17
- import '../utils/results.mjs';
18
20
  import './crud/connected-accounts.mjs';
19
21
  import './crud/contact-channels.mjs';
20
22
  import './crud/current-user.mjs';
@@ -26,8 +28,6 @@ import './crud/team-member-profiles.mjs';
26
28
  import './crud/team-memberships.mjs';
27
29
  import './crud/teams.mjs';
28
30
  import './crud/users.mjs';
29
- import '../utils/errors.mjs';
30
- import '../utils/json.mjs';
31
31
  import '../schema-fields.mjs';
32
32
  import '../utils/currency-constants.mjs';
33
33
  import '../utils/dates.mjs';
@@ -71,6 +71,12 @@ declare class StackAdminInterface extends StackServerInterface {
71
71
  refreshToken: RefreshToken | null;
72
72
  } | null;
73
73
  }>;
74
+ protected sendAdminRequestAndCatchKnownError<E extends typeof KnownErrors[keyof KnownErrors]>(path: string, requestOptions: RequestInit, tokenStoreOrNull: InternalSession | null, errorsToCatch: readonly E[]): Promise<Result<Response & {
75
+ usedTokens: {
76
+ accessToken: AccessToken;
77
+ refreshToken: RefreshToken | null;
78
+ } | null;
79
+ }, InstanceType<E>>>;
74
80
  getProject(): Promise<ProjectsCrud["Admin"]["Read"]>;
75
81
  updateProject(update: ProjectsCrud["Admin"]["Update"]): Promise<ProjectsCrud["Admin"]["Read"]>;
76
82
  createInternalApiKey(options: InternalApiKeyCreateCrudRequest): Promise<InternalApiKeyCreateCrudResponse>;
@@ -154,7 +160,7 @@ declare class StackAdminInterface extends StackServerInterface {
154
160
  setupPayments(): Promise<{
155
161
  url: string;
156
162
  }>;
157
- getStripeAccountInfo(): Promise<{
163
+ getStripeAccountInfo(): Promise<null | {
158
164
  account_id: string;
159
165
  charges_enabled: boolean;
160
166
  details_submitted: boolean;
@@ -1,4 +1,6 @@
1
+ import { KnownErrors } from '../known-errors.js';
1
2
  import { InternalSession, AccessToken, RefreshToken } from '../sessions.js';
3
+ import { Result } from '../utils/results.js';
2
4
  import { ConfigCrud, ConfigOverrideCrud } from './crud/config.js';
3
5
  import { InternalEmailsCrud } from './crud/emails.js';
4
6
  import { InternalApiKeysCrud } from './crud/internal-api-keys.js';
@@ -8,13 +10,13 @@ import { SvixTokenCrud } from './crud/svix-token.js';
8
10
  import { TeamPermissionDefinitionsCrud } from './crud/team-permissions.js';
9
11
  import { ServerAuthApplicationOptions, StackServerInterface } from './server-interface.js';
10
12
  import './client-interface.js';
11
- import '../known-errors.js';
13
+ import '../utils/errors.js';
14
+ import '../utils/json.js';
12
15
  import 'jose';
13
16
  import '../crud.js';
14
17
  import 'yup';
15
18
  import '../utils/types.js';
16
19
  import '../utils/strings.js';
17
- import '../utils/results.js';
18
20
  import './crud/connected-accounts.js';
19
21
  import './crud/contact-channels.js';
20
22
  import './crud/current-user.js';
@@ -26,8 +28,6 @@ import './crud/team-member-profiles.js';
26
28
  import './crud/team-memberships.js';
27
29
  import './crud/teams.js';
28
30
  import './crud/users.js';
29
- import '../utils/errors.js';
30
- import '../utils/json.js';
31
31
  import '../schema-fields.js';
32
32
  import '../utils/currency-constants.js';
33
33
  import '../utils/dates.js';
@@ -71,6 +71,12 @@ declare class StackAdminInterface extends StackServerInterface {
71
71
  refreshToken: RefreshToken | null;
72
72
  } | null;
73
73
  }>;
74
+ protected sendAdminRequestAndCatchKnownError<E extends typeof KnownErrors[keyof KnownErrors]>(path: string, requestOptions: RequestInit, tokenStoreOrNull: InternalSession | null, errorsToCatch: readonly E[]): Promise<Result<Response & {
75
+ usedTokens: {
76
+ accessToken: AccessToken;
77
+ refreshToken: RefreshToken | null;
78
+ } | null;
79
+ }, InstanceType<E>>>;
74
80
  getProject(): Promise<ProjectsCrud["Admin"]["Read"]>;
75
81
  updateProject(update: ProjectsCrud["Admin"]["Update"]): Promise<ProjectsCrud["Admin"]["Read"]>;
76
82
  createInternalApiKey(options: InternalApiKeyCreateCrudRequest): Promise<InternalApiKeyCreateCrudResponse>;
@@ -154,7 +160,7 @@ declare class StackAdminInterface extends StackServerInterface {
154
160
  setupPayments(): Promise<{
155
161
  url: string;
156
162
  }>;
157
- getStripeAccountInfo(): Promise<{
163
+ getStripeAccountInfo(): Promise<null | {
158
164
  account_id: string;
159
165
  charges_enabled: boolean;
160
166
  details_submitted: boolean;