create-nscope-app 1.0.0 → 1.0.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-nscope-app",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Scaffold a Nscope client app (Vite or Next.js)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -19,4 +19,4 @@
19
19
  ],
20
20
  "license": "ISC",
21
21
  "author": "Traton Digital"
22
- }
22
+ }
@@ -1,3 +1,5 @@
1
1
  NEXT_PUBLIC_NSCOPE_API_KEY={{API_KEY}}
2
- NEXT_PUBLIC_NSCOPE_BASE_URL={{BASE_URL}}
3
2
  NEXT_PUBLIC_NSCOPE_REDIRECT_URI={{REDIRECT_URI}}
3
+
4
+ # Referência local — a URL da API é definida no build do pacote @nscope/sdk
5
+ # NEXT_PUBLIC_NSCOPE_BASE_URL={{BASE_URL}}
@@ -15,6 +15,12 @@ pnpm dev
15
15
 
16
16
  Open [http://localhost:3000](http://localhost:3000).
17
17
 
18
+ ## How it works
19
+
20
+ - `lib/nscope.ts` exports `nscopeConfig` for `NscopeProvider`.
21
+ - `Providers` wraps the app with `loadingFallback` while the session initializes.
22
+ - `HomePage` uses `useNscope()` — `authenticated`, `customer`, `login`, `logout`, and `<Can>`.
23
+
18
24
  ## Next steps
19
25
 
20
26
  - Wrap protected pages with `<GuardedRoute>`
@@ -19,6 +19,18 @@ body {
19
19
  padding: 0 1rem;
20
20
  }
21
21
 
22
+ .muted {
23
+ color: #71717a;
24
+ font-size: 0.95rem;
25
+ }
26
+
27
+ code {
28
+ font-size: 0.9em;
29
+ background: #f4f4f5;
30
+ padding: 0.1em 0.35em;
31
+ border-radius: 4px;
32
+ }
33
+
22
34
  button {
23
35
  border: none;
24
36
  border-radius: 8px;
@@ -3,37 +3,48 @@
3
3
  import { Can, useNscope } from "@nscope/react";
4
4
 
5
5
  export function HomePage() {
6
- const { user, isAuthenticated, isLoading, login, logout } = useNscope();
7
-
8
- if (isLoading) {
9
- return <main className="page">Loading…</main>;
10
- }
6
+ const { authenticated, customer, login, logout } = useNscope();
11
7
 
12
8
  return (
13
9
  <main className="page">
14
10
  <h1>{{PROJECT_NAME}}</h1>
15
11
 
16
- {isAuthenticated && user ? (
12
+ {authenticated && customer ? (
17
13
  <>
18
- <p>Signed in as {user.name ?? user.email}</p>
19
- <Can subject="users" action="LIST">
20
- <p>You can list users.</p>
14
+ <p>
15
+ Signed in as <strong>{customer.name || customer.email}</strong>
16
+ </p>
17
+ <p className="muted">Role: {customer.role.name}</p>
18
+
19
+ <Can
20
+ subject="profile"
21
+ action="list"
22
+ fallback={<p className="muted">Sem permissão de perfil.</p>}
23
+ >
24
+ <p>Permissão <code>profile:list</code> concedida.</p>
21
25
  </Can>
26
+
22
27
  <button type="button" onClick={() => logout()}>
23
28
  Sign out
24
29
  </button>
25
30
  </>
26
31
  ) : (
27
- <button
28
- type="button"
29
- onClick={() =>
30
- login({
31
- redirectUri: process.env.NEXT_PUBLIC_NSCOPE_REDIRECT_URI,
32
- })
33
- }
34
- >
35
- Sign in with Nscope
36
- </button>
32
+ <>
33
+ <p className="muted">
34
+ Login hospedado via OAuth. A SDK troca <code>?code=</code> e
35
+ restaura o token automaticamente.
36
+ </p>
37
+ <button
38
+ type="button"
39
+ onClick={() =>
40
+ login({
41
+ redirectUri: process.env.NEXT_PUBLIC_NSCOPE_REDIRECT_URI,
42
+ })
43
+ }
44
+ >
45
+ Sign in with Nscope
46
+ </button>
47
+ </>
37
48
  )}
38
49
  </main>
39
50
  );
@@ -1,8 +1,19 @@
1
1
  "use client";
2
2
 
3
3
  import { NscopeProvider } from "@nscope/react";
4
- import { nscope } from "@/lib/nscope";
4
+ import { nscopeConfig } from "@/lib/nscope";
5
5
 
6
6
  export function Providers({ children }: { children: React.ReactNode }) {
7
- return <NscopeProvider config={nscope}>{children}</NscopeProvider>;
7
+ return (
8
+ <NscopeProvider
9
+ config={nscopeConfig}
10
+ loadingFallback={
11
+ <main className="page">
12
+ <p className="muted">Carregando sessão…</p>
13
+ </main>
14
+ }
15
+ >
16
+ {children}
17
+ </NscopeProvider>
18
+ );
8
19
  }
@@ -1,10 +1,9 @@
1
- import { SDK } from "@nscope/sdk";
1
+ import type { SDKConfig } from "@nscope/sdk";
2
2
 
3
- export const nscope = SDK.init({
4
- baseUrl: process.env.NEXT_PUBLIC_NSCOPE_BASE_URL!,
5
- apiKey: process.env.NEXT_PUBLIC_NSCOPE_API_KEY!,
3
+ export const nscopeConfig: SDKConfig = {
4
+ apiKey: process.env.NEXT_PUBLIC_NSCOPE_API_KEY,
6
5
  auth: {
7
6
  autoHandleCallback: true,
8
7
  storage: "localStorage",
9
8
  },
10
- });
9
+ };
@@ -8,8 +8,8 @@
8
8
  "start": "next start"
9
9
  },
10
10
  "dependencies": {
11
- "@nscope/react": "^1.0.0",
12
- "@nscope/sdk": "^1.3.0",
11
+ "@nscope/react": "latest",
12
+ "@nscope/sdk": "latest",
13
13
  "next": "^15.3.0",
14
14
  "react": "^19.0.0",
15
15
  "react-dom": "^19.0.0"
@@ -1,3 +1,8 @@
1
+ # Chave pública do projeto (Configurações → API keys)
1
2
  VITE_NSCOPE_API_KEY={{API_KEY}}
2
- VITE_NSCOPE_BASE_URL={{BASE_URL}}
3
+
4
+ # URL de retorno após login OAuth (cadastre em Domínios permitidos)
3
5
  VITE_NSCOPE_REDIRECT_URI={{REDIRECT_URI}}
6
+
7
+ # Referência local — a URL da API é definida no build do pacote @nscope/sdk
8
+ # VITE_NSCOPE_BASE_URL={{BASE_URL}}
@@ -13,8 +13,14 @@ pnpm install
13
13
  pnpm dev
14
14
  ```
15
15
 
16
+ ## How it works
17
+
18
+ - `src/nscope.ts` exports `nscopeConfig` (`SDKConfig`) — not a pre-initialized SDK instance.
19
+ - `NscopeProvider` receives `config` and shows `loadingFallback` while `sdk.ready` resolves (OAuth callback + token restore).
20
+ - `useNscope()` exposes `ready`, `authenticated`, `customer`, `permissions`, `login`, `logout`, `can()` and `refresh()`.
21
+
16
22
  ## Next steps
17
23
 
18
- - Customize login redirect in `src/App.tsx`
19
- - Protect routes with `<GuardedRoute>` from `@nscope/react`
24
+ - Customize login in `src/App.tsx` — `login()` accepts optional `redirectUri`
25
+ - Protect UI with `<Can>` or `<GuardedRoute>` from `@nscope/react`
20
26
  - Read the SDK docs in your Nscope panel at `/docs/sdk`
@@ -9,8 +9,8 @@
9
9
  "preview": "vite preview"
10
10
  },
11
11
  "dependencies": {
12
- "@nscope/react": "^1.0.0",
13
- "@nscope/sdk": "^1.3.0",
12
+ "@nscope/react": "latest",
13
+ "@nscope/sdk": "latest",
14
14
  "react": "^19.0.0",
15
15
  "react-dom": "^19.0.0"
16
16
  },
@@ -1,30 +1,48 @@
1
1
  import { Can, useNscope } from "@nscope/react";
2
2
 
3
3
  export default function App() {
4
- const { user, isAuthenticated, isLoading, login, logout } = useNscope();
5
-
6
- if (isLoading) {
7
- return <main className="page">Loading…</main>;
8
- }
4
+ const { authenticated, customer, login, logout } = useNscope();
9
5
 
10
6
  return (
11
7
  <main className="page">
12
8
  <h1>{{PROJECT_NAME}}</h1>
13
9
 
14
- {isAuthenticated && user ? (
10
+ {authenticated && customer ? (
15
11
  <>
16
- <p>Signed in as {user.name ?? user.email}</p>
17
- <Can subject="users" action="LIST">
18
- <p>You can list users.</p>
12
+ <p>
13
+ Signed in as <strong>{customer.name || customer.email}</strong>
14
+ </p>
15
+ <p className="muted">Role: {customer.role.name}</p>
16
+
17
+ <Can
18
+ subject="profile"
19
+ action="list"
20
+ fallback={<p className="muted">Sem permissão de perfil.</p>}
21
+ >
22
+ <p>Permissão <code>profile:list</code> concedida.</p>
19
23
  </Can>
24
+
20
25
  <button type="button" onClick={() => logout()}>
21
26
  Sign out
22
27
  </button>
23
28
  </>
24
29
  ) : (
25
- <button type="button" onClick={() => login({ redirectUri: import.meta.env.VITE_NSCOPE_REDIRECT_URI })}>
26
- Sign in with Nscope
27
- </button>
30
+ <>
31
+ <p className="muted">
32
+ Login hospedado via OAuth. A SDK troca <code>?code=</code> e
33
+ restaura o token automaticamente.
34
+ </p>
35
+ <button
36
+ type="button"
37
+ onClick={() =>
38
+ login({
39
+ redirectUri: import.meta.env.VITE_NSCOPE_REDIRECT_URI,
40
+ })
41
+ }
42
+ >
43
+ Sign in with Nscope
44
+ </button>
45
+ </>
28
46
  )}
29
47
  </main>
30
48
  );
@@ -19,6 +19,18 @@ body {
19
19
  padding: 0 1rem;
20
20
  }
21
21
 
22
+ .muted {
23
+ color: #71717a;
24
+ font-size: 0.95rem;
25
+ }
26
+
27
+ code {
28
+ font-size: 0.9em;
29
+ background: #f4f4f5;
30
+ padding: 0.1em 0.35em;
31
+ border-radius: 4px;
32
+ }
33
+
22
34
  button {
23
35
  border: none;
24
36
  border-radius: 8px;
@@ -2,12 +2,19 @@ import { StrictMode } from "react";
2
2
  import { createRoot } from "react-dom/client";
3
3
  import { NscopeProvider } from "@nscope/react";
4
4
  import App from "./App";
5
- import { nscope } from "./nscope";
5
+ import { nscopeConfig } from "./nscope";
6
6
  import "./index.css";
7
7
 
8
8
  createRoot(document.getElementById("root")!).render(
9
9
  <StrictMode>
10
- <NscopeProvider config={nscope}>
10
+ <NscopeProvider
11
+ config={nscopeConfig}
12
+ loadingFallback={
13
+ <main className="page">
14
+ <p className="muted">Carregando sessão…</p>
15
+ </main>
16
+ }
17
+ >
11
18
  <App />
12
19
  </NscopeProvider>
13
20
  </StrictMode>,
@@ -1,10 +1,9 @@
1
- import { SDK } from "@nscope/sdk";
1
+ import type { SDKConfig } from "@nscope/sdk";
2
2
 
3
- export const nscope = SDK.init({
4
- baseUrl: import.meta.env.VITE_NSCOPE_BASE_URL,
3
+ export const nscopeConfig: SDKConfig = {
5
4
  apiKey: import.meta.env.VITE_NSCOPE_API_KEY,
6
5
  auth: {
7
6
  autoHandleCallback: true,
8
7
  storage: "localStorage",
9
8
  },
10
- });
9
+ };
@@ -0,0 +1,10 @@
1
+ /// <reference types="vite/client" />
2
+
3
+ interface ImportMetaEnv {
4
+ readonly VITE_NSCOPE_API_KEY: string;
5
+ readonly VITE_NSCOPE_REDIRECT_URI: string;
6
+ }
7
+
8
+ interface ImportMeta {
9
+ readonly env: ImportMetaEnv;
10
+ }