{"_id":"@afreakk/integrations","name":"@afreakk/integrations","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"@afreakk/integrations","version":"0.0.1","description":"Integrations for Ory Cloud","author":{"name":"Ory GmbH"},"prettier":"ory-prettier-styles","license":"Apache-2.0","repository":{"type":"git","url":"git+https://github.com/ory/integrations.git"},"config":{"prettierTarget":"**/*.{tsx,ts,json,md,js,css}"},"scripts":{"format":"prettier --write ${npm_package_config_prettierTarget}","format:check":"prettier --check ${npm_package_config_prettierTarget}","build":"rm -rf dist ui nextjs && rollup -c","prepublishOnly":"npm run build","test":"jest --forceExit"},"devDependencies":{"ory-prettier-styles":"1.3.0","prettier":"3.2.5","@babel/core":"7.23.9","@babel/preset-env":"7.23.9","@babel/preset-typescript":"7.23.3","@ory/client":"1.6.2","@types/cookie":"0.6.0","@types/express":"4.17.21","@types/jest":"29.5.12","@types/node":"18.17.14","@types/set-cookie-parser":"2.4.7","@types/supertest":"6.0.2","babel-jest":"29.7.0","esbuild":"0.20.1","express":"4.18.2","jest":"29.7.0","rollup":"4.12.0","rollup-plugin-dts":"6.1.0","rollup-plugin-esbuild":"6.1.1","supertest":"6.3.4","typescript":"5.3.3","tough-cookie":"4.1.3"},"peerDependencies":{"@ory/client":">1.1.38","next":">=12.0.10"},"dependencies":{"@types/tldjs":"2.3.4","cookie":"0.6.0","istextorbinary":"9.5.0","next":">=12.0.10","set-cookie-parser":"2.6.0","tldjs":"2.3.1"},"_id":"@afreakk/integrations@0.0.1","gitHead":"a948503eeb3f5ca1f9352831e4af3d6ddd72830c","bugs":{"url":"https://github.com/ory/integrations/issues"},"homepage":"https://github.com/ory/integrations#readme","_nodeVersion":"20.17.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-CQlNk896PaRR3vi9g6f5jbu4/x5/dzOySDZgcBsl8w95wAX3iEz3x5RDxYfOt3XlWlFw0Mrnz0ThdenCqKDciA==","shasum":"c2f7697d2176a313f19a850eab0c816aa38d22e3","tarball":"https://registry.npmjs.org/@afreakk/integrations/-/integrations-0.0.1.tgz","fileCount":50,"unpackedSize":185786,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFJBM1VDQz6v/dYTPQIM4zwd/DtwdZChW8aRA2jJVJnOAiARSTXcPt4pYJFEhHgHSQUbiF9aVMwJhYxIaIdPwxAdqw=="}]},"_npmUser":{"name":"afreakk","email":"laderud@hotmail.com"},"directories":{},"maintainers":[{"name":"afreakk","email":"laderud@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/integrations_0.0.1_1728390452082_0.5781712849540981"},"_hasShrinkwrap":false}},"time":{"created":"2024-10-08T12:27:31.983Z","0.0.1":"2024-10-08T12:27:32.269Z","modified":"2024-10-08T12:27:32.503Z"},"maintainers":[{"name":"afreakk","email":"laderud@hotmail.com"}],"description":"Integrations for Ory Cloud","homepage":"https://github.com/ory/integrations#readme","repository":{"type":"git","url":"git+https://github.com/ory/integrations.git"},"author":{"name":"Ory GmbH"},"bugs":{"url":"https://github.com/ory/integrations/issues"},"license":"Apache-2.0","readme":"# Integrations with Ory\n\nThis repository contains integrations for connecting with Ory Cloud.\n\n## Table of Contents\n\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n\n- [NextJS](#nextjs)\n- [Vercel](#vercel)\n- [SDK Helpers](#sdk-helpers)\n  - [Type Guards](#type-guards)\n  - [UI Node Helpers](#ui-node-helpers)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## NextJS\n\nTo connect a NextJS app with Ory, do the following in your NextJS App:\n\n```\n$ npm i --save @ory/integrations\n```\n\nThen create a file at `<your-nextjs-app>/api/.ory/[...paths].ts` with the\nfollowing contents:\n\n```typescript\nimport { config, createApiHandler } from \"@ory/integrations/next-edge\"\n\nexport { config }\n\nexport default createApiHandler({\n  /* ... */\n})\n```\n\nYou need to set the environment variable `ORY_SDK_URL` to your\n[Ory Cloud Project SDK URL](https://www.ory.sh/docs/concepts/services-api). For\na list of available options head over to\n[`src/nextjs/index.ts`](src/next-edge/index.ts).\n\n## Vercel\n\nTo connect a non NextJS vercel app, do the following in your vercel app:\n\n```\n$ npm i --save @ory/integrations\n```\n\nThen create a file at `<your-vercel-app>/api/oryproxy.js` with the following\ncontents:\n\n```javascript\nimport { config, createApiHandler } from \"@ory/integrations/next-edge\"\n\nexport { config }\n\nconst ah = createApiHandler({\n  /* ... */\n})\nconst apiHandlerWrapper = (req, res) => {\n  req.query.paths = req.url.replace(/^\\/api\\/.ory\\//, \"\").split(\"?\")[0]\n  ah(req, res)\n}\nexport default apiHandlerWrapper\n```\n\nThen add the following contents to `<your-vercel-app>/vercel.json`:\n\n```\n{\n    \"rewrites\": [\n        { \"source\": \"/api/.ory/:match*\", \"destination\": \"/api/oryproxy\" }\n    ]\n}\n```\n\n## SDK Helpers\n\nThis package contains several helpers for using the Ory SDKs with TypeScript,\nJavaScript, and NodeJS.\n\n### Type Guards\n\nThis package includes type guards for identifying UI nodes.\n\n```ts\nimport {\n  isUiNodeImageAttributes,\n  isUiNodeInputAttributes,\n  isUiNodeScriptAttributes,\n  isUiNodeTextAttributes,\n  // ...\n} from \"@ory/integrations/ui\"\n\n// ...\n\nif (isUiNodeImageAttributes(node.attributes)) {\n  console.log(\"it is an image: \", node.attributes.src)\n}\n```\n\n### UI Node Helpers\n\nThis package contains convenience functions for UI nodes:\n\n- `import { getNodeLabel } from '@ory/integrations/ui'`: Returns the node's\n  label.\n- `import { getNodeId } from '@ory/integrations/ui'`: Returns a node's ID.\n- `import { filterNodesByGroups } from '@ory/integrations/ui'`: Filters nodes by\n  their groups.\n\nAn example of using the `filterNodesByGroups` function could be to map the\nUiNode[] to a certain JSX components.\n\nThe example below is from the [ory/themes](https://github.com/ory/themes)\nrepository and is used to map out the UI Nodes to JSX Components.\n\nUnderstanding `filterNodesByGroups` is quite easy if you think about it as a\nhierarchy:\n\n```ts\nconst nodes = [\n  {\n    group: \"webauthn\",\n    attributes: {\n      node_type: \"input\",\n      type: \"input\",\n    },\n  },\n  {\n    group: \"oidc\",\n    attributes: {\n      node_types: \"button\",\n      type: \"submit\",\n    },\n  },\n  {\n    group: \"oidc\", //<-- take note here, we have 2 oidc groups\n    attributes: {\n      node_types: \"input\",\n      type: \"checkbox\"\n    }\n  }\n  {\n    group: \"foo\",\n    attributes: {\n      node_types: \"bar\",\n      type: \"bar\",\n    },\n  },\n]\n\nfilterNodesByGroups({\n  nodes: nodes,\n  groups: \"oidc,webauthn\", //<-- filter these first\n  attributes: \"submit\", // <-- then these will only take nodes containing the `submit` attributes\n  withoutDefaultAttributes: true, //<-- dont add 'hidden' and 'script' fields when we specify attributes\n  excludeAttributes: \"checkbox\", // <-- defining this wont do much here since we defined attributes. exclude the attributes to see what happens.\n})\n```\n\nHow will our output look like?\n\n```diff\n[\n-  {\n-    group: \"webauthn\",\n-    attributes: {\n-      node_type: \"input\",\n-      type: \"input\",\n-    },\n-  },\n+  {\n+    group: \"oidc\",\n+    attributes: {\n+      node_types: \"button\",\n+      type: \"submit\",\n+    },\n+  },\n-  {\n-    group: \"oidc\", //<-- take note here, we have 2 oidc groups\n-    attributes: {\n-      node_types: \"input\",\n-      type: \"checkbox\"\n-    }\n-  }\n-  {\n-    group: \"foo\",\n-    attributes: {\n-      node_types: \"bar\",\n-      type: \"bar\",\n-    },\n-  },\n]\n```\n\nAn example is we have a UINode containing the group \"totp\" and attributes node\ntype \"input\".\n\n```json5\n{\n  group: \"totp\",\n  attributes: {\n    name: \"f\",\n    type: \"input\",\n    node_type: \"input\",\n  },\n}\n```\n\nOur end goal is to map it to HTML, something like this.\n\n```html\n<input type=\"input\" name=\"f\" />\n```\n\nTo achieve that, we could wrap it in a nifty JSX component which returns the\ncorrect component based on our UI node type.\n\nWe accept a `filter` object which is basically the `FilterNodesByGroups` type\nand return a `<Node />` component, which is a component that helps us return our\nspecific HTML.\n\n```tsx\nexport const FilterFlowNodes = ({\n  filter,\n  includeCSRF,\n}: {\n  filter: FilterNodesByGroups\n  includeCSRF?: boolean\n}): JSX.Element | null => {\n  const getInputName = (node: UiNode): string =>\n    isUiNodeInputAttributes(node.attributes) ? node.attributes.name : \"\"\n\n  // Here we are using our filterNodesByGroups to get the nodes we really want. We can even do some more filtering and mapping\n  const nodes = filterNodesByGroups(filter)\n    // we don't want to map the csrf token every time, only on the form level\n    .filter((node) =>\n      getInputName(node) === \"csrf_token\" && !includeCSRF ? false : true,\n    )\n    .map((node, k) =>\n      [\"hidden\"].includes(getNodeInputType(node.attributes))\n        ? {\n            node: <Node node={node} key={k} />,\n            hidden: true,\n          }\n        : {\n            node: <Node node={node} key={k} />,\n            hidden: false,\n          },\n    )\n\n  return nodes.length > 0 ? (\n    <>\n      // we don't want hidden fields to create new gaps\n      {nodes.filter((node) => node.hidden).map((node) => node.node)}\n      <div className={gridStyle({ gap: 16 })}>\n        {nodes.filter((node) => !node.hidden).map((node) => node.node)}\n      </div>\n    </>\n  ) : null\n}\n```\n\nNow we can use our wrapper to return the HTML we want based on the `nodes`.\n\nHere we only want nodes that do not have the `hidden` attribute.\n\n```tsx\n<FilterFlowNodes\n  filter={{\n    nodes: nodes,\n    excludeAttributes: \"hidden\",\n  }}\n/>\n```\n\nAnother more complex example is to filter out the UI nodes to only retrieve the\n`oidc` and `password` groups. We also exclude the `default` group here with\n`withoutDefaultGroup: true`. Furthermore we do some exclusions on the\n`submit and `hidden`attributes, so any group which has an attribute containing a node type`submit`or`hidden`\nwill be filtered out.\n\n```tsx\n<FilterFlowNodes\n  filter={{\n    nodes: nodes,\n    groups: [\"oidc\", \"password\"],\n    withoutDefaultGroup: true,\n    excludeAttributes: [\"submit\", \"hidden\"],\n  }}\n/>\n```\n\nAnother example of us wanting the `oidc` and `webauthn` group (note: we can use\ncomma seperated strings instead of an array). We also exclude default attributes\nwith `withoutDefaultAttributes: true` which are `hidden` and `script` elements.\nThis will also only return us the nodes which have a `submit` attribute.\n\n```tsx\n<FilterFlowNodes\n  filter={{\n    nodes: flow.ui.nodes,\n    groups: \"oidc,webauthn\",\n    withoutDefaultAttributes: true,\n    attributes: \"submit\",\n  }}\n/>\n```\n","readmeFilename":"README.md"}