Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,9 @@ features, implementation plan, and devops.
```bash
npm install
cp .env.example .env # set VITE_ADMIN_HUB_BASE_URL etc.
npm run dev # http://localhost:3100 (uses published SDK packages)
npm run dev:link # same, but resolves @norbix/react-redux + @norbix.ai/ts
# to LOCAL SOURCE for instant lib development (HMR)
npm run build # tsc -b + vite build
npm run dev # http://localhost:3100 (uses the published SDK packages)
npm run build # next build
npm run typecheck # tsc
npm run lint # eslint
npm test # vitest
```
Expand All @@ -45,12 +44,11 @@ Requires Node ≥ 22.12 (Vite 7).

### Data access via the Norbix SDK

The portal uses **`@norbix/react-redux`** (RTK Query hooks over the typed
The portal uses **`@norbix.ai/react-redux`** (RTK Query hooks over the typed
**`@norbix.ai/ts`** SDK) for data access instead of hand-written services
(`createNorbixApi` + `NorbixProvider`, wired in `src/services/norbix.ts`).
To develop the lib and the portal together with no publish/install cycle, see
[`docs/sdk-local-development.md`](./docs/sdk-local-development.md) and use
`npm run dev:link`.
Both come from npm. To try an SDK change before it is published, see
[`docs/sdk-local-development.md`](./docs/sdk-local-development.md).

For local dev without a `pr_` subdomain, pin a project with
`VITE_ADMIN_PROJECT_ID` in `.env`, or add a static config at
Expand Down
7 changes: 4 additions & 3 deletions docs/agreements.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ All three produce the same shape. Full design:

## 4. SDK + dev loop

- Data access uses **`@norbix/react-redux`** (RTK Query over the typed
- Data access uses **`@norbix.ai/react-redux`** (RTK Query over the typed
`@norbix.ai/ts` SDK), not hand-written services.
- Local development links the SDK from source for instant HMR — no publish
cycle. See [`sdk-local-development.md`](./sdk-local-development.md).
- Both packages come from npm (since 2026-10-03). An SDK change is tried
locally before it is published — see
[`sdk-local-development.md`](./sdk-local-development.md).

## 5. Legal documents (Terms & Conditions, Privacy Policy)

Expand Down
2 changes: 1 addition & 1 deletion docs/implementation-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ techniques** from Cloud while keeping the result safe to **open source**.
| Build | Vite + React 18 + TS, `@` → `/src` alias, SWC plugin | Copy `vite.config.ts` (trimmed: no Storybook/vitest browser stuff for v1). |
| State | Redux Toolkit, `configureStore`, feature **slices**, typed `useAppSelector/useAppDispatch` hooks | Same pattern as Cloud's `src/app/store.ts` + `src/app/hooks`. |
| Data fetching | RTK Query services that call the gateway | Cloud has `services/hub` + `services/api`. Admin keeps **only `services/api`** (end-user data plane) + a tiny **public** service for login config & legal docs. |
| SDK | `@norbix/react-redux` (RTK Query over the typed Norbix TS SDK) | Use its API-side hooks where they exist instead of hand-writing services. |
| SDK | `@norbix.ai/react-redux` (RTK Query over the typed Norbix TS SDK) | Use its API-side hooks where they exist instead of hand-writing services. |
| Styling | Tailwind CSS + the project color tokens | Copy `tailwind.config.cjs` color palette + `postcss.config.cjs`. |
| Routing | `react-router-dom`, central `routes.ts` constants | Smaller route map (see `features.md`). |
| Layouts | The *structure* of `authLayout` / content layout, menu, shell | **Rewritten** clean-room (see §3). |
Expand Down
120 changes: 34 additions & 86 deletions docs/sdk-local-development.md
Original file line number Diff line number Diff line change
@@ -1,90 +1,52 @@
# Developing against @norbix/react-redux locally
# The Norbix SDK packages in the admin portal

The admin portal uses **`@norbix/react-redux`** (RTK Query hooks over the typed
**`@norbix.ai/ts`** SDK) instead of hand-written API services. This doc explains
how to develop the lib and the portal together with an instant feedback loop —
no publish, no version bump, no reinstall.
The admin portal uses **`@norbix.ai/react-redux`** (RTK Query hooks over the
typed **`@norbix.ai/ts`** SDK) instead of hand-written API services. Since
2026-10-03 both come **from npm** (`package.json` has version ranges), so a
fresh clone, a worktree and CI all build without the sibling `../sdks`
checkouts.

## The problem we avoid
## Using a new SDK version

Without local linking, every lib change is a painful cycle:
When an SDK release adds what the portal needs:

1. change the portal, realize the lib needs a change
2. change `@norbix/react-redux`
3. `npm publish` it
4. bump + `npm install` the new version in admin
5. finally use the new functionality

## The loop we have instead

```
edit norbix-react-redux/src/*.ts → admin hot-reloads instantly
```bash
npm install @norbix.ai/ts@^<version> @norbix.ai/react-redux@^<version>
npm run typecheck && npm test && npm run build
```

When you're happy, you publish the lib **once**, and other consumers install it
normally. The portal keeps working because in production it uses the published
package — the local link is dev-only.
Commit `package.json` and `package-lock.json` together.

## Expected folder layout
## Trying an SDK change before it is published

The link assumes the sibling monorepo checkout:
Folder layout this assumes:

```
norbix/
admin/ ← this app
sdks/
norbix-react-redux/ ← the RTK lib (@norbix/react-redux)
norbix-js/ ← the core SDK (published as @norbix.ai/ts)
norbix-react-redux/ ← @norbix.ai/react-redux
norbix-js/ ← @norbix.ai/ts
```

## How it's wired (neither package is on npm yet)

`@norbix/react-redux` and `@norbix.ai/ts` are **not published yet**, so the
portal consumes them from the local checkouts. Two pieces make that work:

1. **`package.json` uses `file:` deps**, so `npm install` resolves them from
disk (no npm 404):

```jsonc
"@norbix.ai/ts": "file:../sdks/norbix-js",
"@norbix/react-redux": "file:../sdks/norbix-react-redux"
```

2. **`vite.config.ts` always aliases the lib to its TypeScript source**
(the lib ships no built `dist/`), and `tsconfig.app.json` has matching
`paths`. So both Vite and `tsc` resolve:

| import | resolves to |
| --- | --- |
| `@norbix/react-redux` | `../sdks/norbix-react-redux/src/index.ts` (always) |
| `norbix` (lib's internal import) | `../sdks/norbix-js/src/index.ts` |
| `@norbix.ai/ts` | `../sdks/norbix-js/src/index.ts` |

Both the lib and the core SDK resolve to **source** for type-checking, so a
new SDK endpoint type-checks in the portal **without** first rebuilding the
SDK's `dist/`. (Vite's runtime alias still follows `NORBIX_LINK` for the core
SDK — see `dev:link` below — but `tsc` always sees source.)

Because the lib resolves to **source**, editing `norbix-react-redux/src/*.ts`
hot-reloads the portal instantly — no `tsup` build, no publish, no reinstall.
Pack the changed SDK(s) and install the tarballs **without saving** them:

```bash
npm install # installs the file: deps from the sibling checkouts
npm run dev # http://localhost:3100 — lib already resolves from source
npm run dev:link # ALSO resolve the core SDK (@norbix.ai/ts) from source,
# for when you're editing norbix-js too (sets NORBIX_LINK=1)
(cd ../sdks/norbix-js && npm run build && npm pack --pack-destination /tmp)
(cd ../sdks/norbix-react-redux && npm run build && npm pack --pack-destination /tmp)
npm install --no-save /tmp/norbix.ai-ts-*.tgz /tmp/norbix.ai-react-redux-*.tgz
npm run dev
```

> The core SDK (`@norbix.ai/ts`) has a built `dist/`, so the **runtime** `file:`
> install works without `dev:link`. But a `dist/` that predates an SDK change is
> stale — so after editing `norbix-js` (or syncing its DTOs), rebuild it once:
>
> ```bash
> cd ../sdks/norbix-js && npm run build # refreshes dist/ for the non-link path
> ```
>
> `dev:link` (and the `tsc` source paths above) let you skip this while
> developing; the rebuild matters for the default `npm run dev` / `npm run build`.
Repeat the pack + install after each SDK edit. `npm ci` puts the published
versions back. Never commit a `file:` or tarball dependency — CI has no
`../sdks`, and that is what kept `main` red until 2026-10-03.

The order of a change that touches both: merge the SDK pull request, wait for
its release on npm, then raise the version range here.

(The legacy Vite dev server, `npm run _vite:dev:link`, still resolves both
packages to their `../sdks` TypeScript source when `NORBIX_LINK=1`.)

## Refreshing the SDK DTOs after an API change

Expand All @@ -106,29 +68,15 @@ gateway adds or changes an endpoint:
2. If the endpoint needs a typed hook in the portal, add a small SDK module
(e.g. `norbix-js/src/api/<group>.ts`, wired in `src/api/index.ts`) and a
matching RTK hook factory in `norbix-react-redux/src/hooks/...`, then spread
it in `hooks/index.ts`. The portal picks it up from source immediately.
3. `cd ../sdks/norbix-js && npm run build` to refresh `dist/` for the
non-link runtime path.
it in `hooks/index.ts`. Try it in the portal with the pack + install above.
3. Release the SDK(s), then raise the version range here (see above).

> The **Admin-Portal public endpoints** (`GET /public/projects/{id}/config` and
> `.../legal/{kind}`) already ship as `norbix.api.public.config(...)` /
> `.legal(...)`, surfaced as the `useGetPublicProjectConfigQuery` /
> `useGetPublicProjectLegalQuery` hooks. They use the `unauthenticated` transport
> scope (no bearer token) since they run before sign-in.

## When the packages are published to npm

Once `@norbix/react-redux` (and `@norbix.ai/ts`) are on npm:

1. In `../sdks/norbix-react-redux`: `npm run build && npm test`, then publish
(the repo's semantic-release pipeline handles versioning). Publishing also
produces the `dist/` the package's `main`/`types` point at.
2. In this repo, swap the `file:` deps for version ranges, e.g.
`"@norbix/react-redux": "^0.1.0"`, and remove the always-on lib alias /
tsconfig path (keep `dev:link` if you still want source linking on demand).
3. `npm install` — the portal now uses the published artifacts. Nothing in the
portal's own code changes; it only ever imported `@norbix/react-redux`.

## What the portal still owns (not in the SDK yet)

The SDK covers **login, logout, profile (getUser/updateUser), preferences
Expand All @@ -139,5 +87,5 @@ It does **not** yet expose password change/reset, 2FA (TOTP), or
compliance (data export / account deletion). Those screens use a small
app-owned service (`src/services/authService.ts`, `complianceService.ts`)
**temporarily**. The plan is to add these to `@norbix.ai/ts` first; once they
exist, delete those services and switch the screens to SDK hooks — with the
local link, you'll see it working in the portal immediately.
exist, delete those services and switch the screens to SDK hooks — try it
locally with the pack + install above before the SDK release.
77 changes: 77 additions & 0 deletions docs/tasks/published-sdks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Admin uses the published SDK packages (tracker step 29b)
This file: /Users/djovaisas/Projects/norbix/worktrees/admin/ci/published-sdks/docs/tasks/published-sdks.md (branch ci/published-sdks)

## Goal

Admin builds from the published `@norbix.ai/ts` and `@norbix.ai/react-redux`
packages instead of the sibling `../sdks` checkouts, so `main` CI (which has no
`../sdks`) is green: lint, format, typecheck, test, build, audit.

Not in scope: new features, the format debt in other repos, the Docker image
workflows (they build from this folder only and get the same fix for free).

## Plan

1. done — react-redux: lock and dev dependency on `@norbix.ai/ts` 4.4.0, drop
the three campaign-message hooks the SDK removed, so its Release job can
publish the AI hooks — merged (rebase) as
https://github.com/norbix-code/react-redux/pull/34, released as
`@norbix.ai/react-redux` 1.4.0; react-redux `main` CI, CodeQL and Release green.
2. done — `package.json`: `file:../sdks/…` → `"@norbix.ai/ts": "^4.4.0"`,
`"@norbix.ai/react-redux": "^1.4.0"`; the old name `@norbix/react-redux`
is gone (it was never on npm; the package is published as
`@norbix.ai/react-redux`).
3. done — imports and comments: `@norbix/react-redux` → `@norbix.ai/react-redux`.
4. done — `tsconfig.json`, `tsconfig.app.json`: remove the `../sdks` source
paths. `next.config.mjs`: remove `transpilePackages` and the `.js` →
`.ts` extension alias (both only existed for SDK source).
5. done — `vite.config.ts` (legacy `_vite:*` scripts): source linking only on
demand (`NORBIX_LINK=1`), for both packages.
6. done — docs: `README.md`, `docs/sdk-local-development.md` (published
packages by default; how to try an unpublished SDK change locally),
`docs/agreements.md`, `docs/implementation-plan.md`.
7. done — lock from the npm registry (`@norbix.ai/react-redux` 1.4.0,
`@norbix.ai/ts` 4.4.0); the stale extraneous `../sdks/norbix-react-redux`
lock entry removed. Every CI step green locally: `npm ci`, lint, format
check, typecheck, test (80 passed), build, production audit. Shipped with
`nbx-ship` (squash).

## Changes

| file | what changed | plan step |
|---|---|---|
| `package.json`, `package-lock.json` | published SDK versions; stale `../sdks` lock entry removed | 2, 7 |
| `src/App.tsx`, `src/services/norbix.ts`, `src/app/store.ts` | package name | 3 |
| `tsconfig.json`, `tsconfig.app.json`, `next.config.mjs` | no `../sdks` wiring | 4 |
| `vite.config.ts` | source linking on demand only | 5 |
| `README.md`, `docs/sdk-local-development.md`, `docs/agreements.md`, `docs/implementation-plan.md` | published packages | 6 |

## Findings

- `tsconfig.tsbuildinfo` is tracked in git (a build cache). Left open.
- react-redux: `npm run format:check` fails on ~20 files on `main`; its CI does
not run it. Left open.
- react-redux: Dependabot bumped the `@norbix.ai/ts` dev dependency to
`^4.2.0`, below the `>=4.3.0` peer range, and broke `main`. A Dependabot
`ignore` or a grouped rule for `@norbix.ai/*` would stop this. Left open.
- react-redux: no hook yet for `hub.email.getEmailPreferencesByLink`
(added in `@norbix.ai/ts` 4.3.0). Left open.
- SDK repos (react-redux, sdk-ts, likely all npm SDKs): the CI Security scan
(OSV) was red on every branch, `main` included, on 12 advisories no update
can fix — packages bundled inside the npm CLI that semantic-release runs,
and braces 3.0.3. Fixed in react-redux only, by an `osv-scanner.toml` with
exact ids, reasons and `ignoreUntil = 2026-11-03` (react-redux pull request
34, second commit). sdk-ts and the other npm SDKs still need the same file.
Left open.

## Rejected / moved out

- (none)

## Needs you

- (none)

## Open questions

- (none)
11 changes: 0 additions & 11 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,6 @@ const nextConfig = {
.filter(Boolean),
}
: {}),
// The SDK is consumed from source in the monorepo dev loop; transpile it so
// Next compiles its TS rather than expecting a prebuilt dist.
transpilePackages: ['@norbix.ai/ts', '@norbix/react-redux'],
// SDK source uses ESM-style `.js` specifiers (e.g. `./client/Norbix.js`) that
// map to `.ts` files — webpack needs this alias to resolve them.
webpack: (config) => {
config.resolve.extensionAlias = {
'.js': ['.ts', '.tsx', '.js'],
};
return config;
},
eslint: {
// Lint is run separately in CI; don't fail the production build on it.
ignoreDuringBuilds: true,
Expand Down
Loading
Loading