@cboxdk/id-nuxt 0.1.0 → 0.2.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.
- package/README.md +33 -4
- package/dist/module.d.mts +23 -3
- package/dist/module.json +1 -1
- package/dist/module.mjs +25 -4
- package/dist/runtime/plugin.d.ts +6 -1
- package/dist/runtime/plugin.js +22 -9
- package/dist/runtime/server/routes/account.get.d.ts +7 -0
- package/dist/runtime/server/routes/account.get.js +8 -0
- package/package.json +14 -5
package/README.md
CHANGED
|
@@ -5,8 +5,11 @@ Nuxt module for [Cbox ID](https://github.com/cboxdk/laravel-id). It wires the
|
|
|
5
5
|
drop-in **sign-in / callback / sign-out** routes, a sealed session, and a
|
|
6
6
|
`useCboxUser()` composable — add authentication with one module entry.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
`<CboxUserButton>` and
|
|
8
|
+
It also bundles the [`@cboxdk/id-vue`](https://github.com/cboxdk/id-vue) widgets
|
|
9
|
+
(`<CboxUserButton>` and friends) as **auto-imported, globally-provided** components:
|
|
10
|
+
no import, no `<CboxIdProvider>` wrapper. The module provides their context app-wide
|
|
11
|
+
from the session and injects the stylesheet through `useHead`, so they render
|
|
12
|
+
correctly during SSR.
|
|
10
13
|
|
|
11
14
|
## Install
|
|
12
15
|
|
|
@@ -45,9 +48,32 @@ The module registers these routes for you:
|
|
|
45
48
|
| `GET /auth/sign-in` | starts login (accepts `?redirect=/where/next`) |
|
|
46
49
|
| `GET /auth/callback` | verifies the login and stores the session |
|
|
47
50
|
| `GET /auth/sign-out` | clears the session and logs out |
|
|
51
|
+
| `GET /auth/account` | redirects to the hosted profile page (accepts `?return_to=`) |
|
|
48
52
|
| `GET /api/_cbox/user` | the current user as JSON (used internally) |
|
|
49
53
|
|
|
50
|
-
|
|
54
|
+
### Widgets
|
|
55
|
+
|
|
56
|
+
Drop the widgets in anywhere — they're auto-imported and already wired to the
|
|
57
|
+
session, so this is the whole integration:
|
|
58
|
+
|
|
59
|
+
```vue
|
|
60
|
+
<template>
|
|
61
|
+
<header>
|
|
62
|
+
<!-- avatar + account menu when signed in, a sign-in button when not -->
|
|
63
|
+
<CboxUserButton />
|
|
64
|
+
</header>
|
|
65
|
+
</template>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Also available: `<CboxSignInButton>`, `<CboxSignOutButton>`, `<CboxUserProfileCard>`,
|
|
69
|
+
`<CboxOrganizationBadge>`, and `<CboxIdProvider>` (for a scoped override). Their
|
|
70
|
+
"Manage account" links point at `GET /auth/account`; "Sign out" at `logoutPath`.
|
|
71
|
+
Theme them with the `appearance` option (below). Set `components: false` to opt out
|
|
72
|
+
and wire `@cboxdk/id-vue` yourself.
|
|
73
|
+
|
|
74
|
+
### Composable
|
|
75
|
+
|
|
76
|
+
Or read the user reactively and build your own UI:
|
|
51
77
|
|
|
52
78
|
```vue
|
|
53
79
|
<script setup lang="ts">
|
|
@@ -80,8 +106,11 @@ export default defineNuxtRouteMiddleware(() => {
|
|
|
80
106
|
|---|---|---|
|
|
81
107
|
| `issuer` / `clientId` / `clientSecret` / `redirectUri` | from env | the Cbox ID connection |
|
|
82
108
|
| `scopes` | `openid profile email` | requested at login |
|
|
83
|
-
| `accountPath` | `/settings` | hosted profile page path |
|
|
109
|
+
| `accountPath` | `/settings` | hosted profile page path on the instance |
|
|
84
110
|
| `loginPath` / `callbackPath` / `logoutPath` | `/auth/*` | override the route paths |
|
|
111
|
+
| `profilePath` | `/auth/account` | app route that redirects to the hosted profile |
|
|
112
|
+
| `appearance` | `{}` | widget theming (`accent`, `accentForeground`, `radius`, `fontFamily`) |
|
|
113
|
+
| `components` | `true` | auto-register the `@cboxdk/id-vue` widgets globally |
|
|
85
114
|
|
|
86
115
|
## Scope
|
|
87
116
|
|
package/dist/module.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
import { CboxWidgetAppearance } from '@cboxdk/id-vue';
|
|
2
3
|
|
|
3
4
|
interface ModuleOptions {
|
|
4
5
|
/** Base URL of the Cbox ID instance (or set CBOX_ID_ISSUER). */
|
|
@@ -19,11 +20,30 @@ interface ModuleOptions {
|
|
|
19
20
|
callbackPath?: string;
|
|
20
21
|
/** Route that signs out. Defaults to /auth/sign-out. */
|
|
21
22
|
logoutPath?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Route that redirects to the instance's hosted account/profile page (what the
|
|
25
|
+
* widgets' "Manage account" links point at). Defaults to /auth/account.
|
|
26
|
+
*/
|
|
27
|
+
profilePath?: string;
|
|
28
|
+
/** Theming applied to the auto-provided widgets. */
|
|
29
|
+
appearance?: CboxWidgetAppearance;
|
|
30
|
+
/**
|
|
31
|
+
* Auto-register the `@cboxdk/id-vue` widget components (`<CboxUserButton>` etc.)
|
|
32
|
+
* as global components and wire their context app-wide. Defaults to `true`.
|
|
33
|
+
*/
|
|
34
|
+
components?: boolean;
|
|
22
35
|
}
|
|
23
36
|
/**
|
|
24
|
-
* Nuxt module for Cbox ID.
|
|
25
|
-
*
|
|
26
|
-
*
|
|
37
|
+
* Nuxt module for Cbox ID. Wires the whole embeddable-identity story into a Nuxt app:
|
|
38
|
+
*
|
|
39
|
+
* - server routes for sign-in / callback / sign-out / hosted-profile redirect, backed
|
|
40
|
+
* by `@cboxdk/id-js` and a sealed h3 session;
|
|
41
|
+
* - a `useCboxUser()` composable, SSR-hydrated from that session;
|
|
42
|
+
* - the `@cboxdk/id-vue` widgets (`<CboxUserButton>` and friends) as global,
|
|
43
|
+
* auto-imported components, provided their context app-wide so they work with no
|
|
44
|
+
* `<CboxIdProvider>` boilerplate — SSR-safe, stylesheet injected via `useHead`.
|
|
45
|
+
*
|
|
46
|
+
* Configure it under the `cboxId` key or via environment variables.
|
|
27
47
|
*/
|
|
28
48
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
29
49
|
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
import { defineNuxtModule, createResolver, addServerHandler, addImportsDir, addPlugin } from '@nuxt/kit';
|
|
1
|
+
import { defineNuxtModule, createResolver, addServerHandler, addImportsDir, addPlugin, addComponent } from '@nuxt/kit';
|
|
2
2
|
import { defu } from 'defu';
|
|
3
3
|
|
|
4
|
+
const WIDGET_COMPONENTS = [
|
|
5
|
+
"CboxIdProvider",
|
|
6
|
+
"CboxSignInButton",
|
|
7
|
+
"CboxSignOutButton",
|
|
8
|
+
"CboxUserButton",
|
|
9
|
+
"CboxUserProfileCard",
|
|
10
|
+
"CboxOrganizationBadge"
|
|
11
|
+
];
|
|
4
12
|
const module$1 = defineNuxtModule({
|
|
5
13
|
meta: {
|
|
6
14
|
name: "@cboxdk/id-nuxt",
|
|
@@ -11,7 +19,9 @@ const module$1 = defineNuxtModule({
|
|
|
11
19
|
accountPath: "/settings",
|
|
12
20
|
loginPath: "/auth/sign-in",
|
|
13
21
|
callbackPath: "/auth/callback",
|
|
14
|
-
logoutPath: "/auth/sign-out"
|
|
22
|
+
logoutPath: "/auth/sign-out",
|
|
23
|
+
profilePath: "/auth/account",
|
|
24
|
+
components: true
|
|
15
25
|
},
|
|
16
26
|
setup(options, nuxt) {
|
|
17
27
|
const resolver = createResolver(import.meta.url);
|
|
@@ -32,10 +42,11 @@ const module$1 = defineNuxtModule({
|
|
|
32
42
|
{
|
|
33
43
|
loginPath: options.loginPath,
|
|
34
44
|
logoutPath: options.logoutPath,
|
|
35
|
-
|
|
45
|
+
profilePath: options.profilePath,
|
|
46
|
+
appearance: options.appearance ?? {}
|
|
36
47
|
}
|
|
37
48
|
);
|
|
38
|
-
nuxt.options.build.transpile.push(resolver.resolve("./runtime"));
|
|
49
|
+
nuxt.options.build.transpile.push(resolver.resolve("./runtime"), "@cboxdk/id-vue");
|
|
39
50
|
addServerHandler({
|
|
40
51
|
route: options.loginPath,
|
|
41
52
|
method: "get",
|
|
@@ -51,6 +62,11 @@ const module$1 = defineNuxtModule({
|
|
|
51
62
|
method: "get",
|
|
52
63
|
handler: resolver.resolve("./runtime/server/routes/sign-out.get")
|
|
53
64
|
});
|
|
65
|
+
addServerHandler({
|
|
66
|
+
route: options.profilePath,
|
|
67
|
+
method: "get",
|
|
68
|
+
handler: resolver.resolve("./runtime/server/routes/account.get")
|
|
69
|
+
});
|
|
54
70
|
addServerHandler({
|
|
55
71
|
route: "/api/_cbox/user",
|
|
56
72
|
method: "get",
|
|
@@ -58,6 +74,11 @@ const module$1 = defineNuxtModule({
|
|
|
58
74
|
});
|
|
59
75
|
addImportsDir(resolver.resolve("./runtime/composables"));
|
|
60
76
|
addPlugin(resolver.resolve("./runtime/plugin"));
|
|
77
|
+
if (options.components) {
|
|
78
|
+
for (const name of WIDGET_COMPONENTS) {
|
|
79
|
+
addComponent({ name, export: name, filePath: "@cboxdk/id-vue", mode: "all" });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
61
82
|
}
|
|
62
83
|
});
|
|
63
84
|
|
package/dist/runtime/plugin.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Hydrate the current user from the server session, then provide the widget context
|
|
3
|
+
* app-wide so `@cboxdk/id-vue` components work anywhere without a `<CboxIdProvider>`.
|
|
4
|
+
* Runs on both server and client (so SSR renders the signed-in state), and injects
|
|
5
|
+
* the widget stylesheet via `useHead` — SSR-safe, no `document` access at import time.
|
|
6
|
+
*/
|
|
2
7
|
declare const _default: any;
|
|
3
8
|
export default _default;
|
package/dist/runtime/plugin.js
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
|
-
import { defineNuxtPlugin, useRequestFetch } from "#imports";
|
|
1
|
+
import { defineNuxtPlugin, useHead, useRequestFetch, useRuntimeConfig } from "#imports";
|
|
2
|
+
import { computed } from "vue";
|
|
3
|
+
import { CSS, CboxIdKey, STYLE_ID } from "@cboxdk/id-vue";
|
|
2
4
|
import { useCboxUser } from "./composables/useCboxUser.js";
|
|
3
|
-
export default defineNuxtPlugin(async () => {
|
|
5
|
+
export default defineNuxtPlugin(async (nuxtApp) => {
|
|
4
6
|
const user = useCboxUser();
|
|
5
|
-
if (user.value
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
user.value = null;
|
|
7
|
+
if (user.value === null) {
|
|
8
|
+
try {
|
|
9
|
+
user.value = await useRequestFetch()("/api/_cbox/user");
|
|
10
|
+
} catch {
|
|
11
|
+
user.value = null;
|
|
12
|
+
}
|
|
12
13
|
}
|
|
14
|
+
const config = useRuntimeConfig().public.cboxId;
|
|
15
|
+
const appearance = config.appearance ?? {};
|
|
16
|
+
const urls = {
|
|
17
|
+
signIn: config.loginPath,
|
|
18
|
+
signOut: config.logoutPath,
|
|
19
|
+
profile: config.profilePath
|
|
20
|
+
};
|
|
21
|
+
nuxtApp.vueApp.provide(
|
|
22
|
+
CboxIdKey,
|
|
23
|
+
computed(() => ({ user: user.value, urls, appearance }))
|
|
24
|
+
);
|
|
25
|
+
useHead({ style: [{ id: STYLE_ID, key: STYLE_ID, innerHTML: CSS }] });
|
|
13
26
|
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redirect to the instance's hosted account/profile page (self-service password,
|
|
3
|
+
* MFA, passkeys, sessions). `return_to` is honoured so the page can link back; it
|
|
4
|
+
* defaults to the app's origin.
|
|
5
|
+
*/
|
|
6
|
+
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { defineEventHandler, getQuery, getRequestURL, sendRedirect } from "h3";
|
|
2
|
+
import { getCboxClient } from "../utils/client.js";
|
|
3
|
+
export default defineEventHandler((event) => {
|
|
4
|
+
const client = getCboxClient(event);
|
|
5
|
+
const returnTo = getQuery(event).return_to;
|
|
6
|
+
const origin = getRequestURL(event).origin;
|
|
7
|
+
return sendRedirect(event, client.profileUrl(typeof returnTo === "string" ? returnTo : origin));
|
|
8
|
+
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cboxdk/id-nuxt",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Nuxt module for Cbox ID
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Nuxt module for Cbox ID \u2014 drop-in sign-in / callback / sign-out routes and session handling built on @cboxdk/id-js. Add authentication to a Nuxt app with one module entry.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Sylvester Damgaard <sn@cbox.dk>",
|
|
@@ -42,17 +42,26 @@
|
|
|
42
42
|
"scripts": {
|
|
43
43
|
"prepare-types": "nuxt-module-build prepare",
|
|
44
44
|
"build": "nuxt-module-build build",
|
|
45
|
-
"
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"test:watch": "vitest",
|
|
47
|
+
"check": "npm run prepare-types && npm run build && npm run test"
|
|
46
48
|
},
|
|
47
49
|
"dependencies": {
|
|
48
|
-
"@cboxdk/id-js": "^0.
|
|
50
|
+
"@cboxdk/id-js": "^0.2.0",
|
|
51
|
+
"@cboxdk/id-vue": "^0.2.0",
|
|
49
52
|
"@nuxt/kit": "^3.0.0 || ^4.0.0",
|
|
50
53
|
"defu": "^6.1.0",
|
|
51
54
|
"h3": "^1.13.0"
|
|
52
55
|
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"vue": "^3.4.0"
|
|
58
|
+
},
|
|
53
59
|
"devDependencies": {
|
|
54
60
|
"@nuxt/module-builder": "^1.0.0",
|
|
55
61
|
"@nuxt/schema": "^3.0.0 || ^4.0.0",
|
|
56
|
-
"
|
|
62
|
+
"nuxt": "^3.0.0",
|
|
63
|
+
"typescript": "^5.9.2",
|
|
64
|
+
"vitest": "^4.1.0",
|
|
65
|
+
"vue": "^3.5.0"
|
|
57
66
|
}
|
|
58
67
|
}
|