@cimplify/cli 0.7.11 → 0.7.14
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/dist/{add-3CEDUXNO.mjs → add-Z5I2F43P.mjs} +1 -1
- package/dist/{chunk-ZFCWAYK2.mjs → chunk-27BN2J4V.mjs} +1 -1
- package/dist/{chunk-XB4MMPXC.mjs → chunk-D2AUHLWS.mjs} +2 -2
- package/dist/{chunk-DAE3YSKU.mjs → chunk-V2MNBQ35.mjs} +329 -17
- package/dist/dispatcher.mjs +9 -9
- package/dist/{doctor-A3YU5YOX.mjs → doctor-J2Z4OLAV.mjs} +2 -2
- package/dist/{explain-WZQTCB3C.mjs → explain-J2Z2L5M5.mjs} +2 -2
- package/dist/{introspect-2GJIQ6CP.mjs → introspect-NJOPZP7H.mjs} +2 -2
- package/dist/{list-F3LBI7HF.mjs → list-URTQL6PV.mjs} +1 -1
- package/dist/{update-PINBW3NG.mjs → update-IZFFRPX7.mjs} +1 -1
- package/package.json +2 -2
- package/templates/storefront-auto/middleware.ts +39 -0
- package/templates/storefront-auto/package.json +1 -1
- package/templates/storefront-bakery/AGENTS.md +3 -3
- package/templates/storefront-bakery/middleware.ts +39 -0
- package/templates/storefront-bakery/package.json +1 -1
- package/templates/storefront-fashion/AGENTS.md +1 -1
- package/templates/storefront-fashion/middleware.ts +39 -0
- package/templates/storefront-fashion/package.json +1 -1
- package/templates/storefront-grocery/AGENTS.md +1 -1
- package/templates/storefront-grocery/middleware.ts +39 -0
- package/templates/storefront-grocery/package.json +1 -1
- package/templates/storefront-pharmacy/AGENTS.md +1 -1
- package/templates/storefront-pharmacy/middleware.ts +39 -0
- package/templates/storefront-pharmacy/package.json +1 -1
- package/templates/storefront-restaurant/AGENTS.md +1 -1
- package/templates/storefront-restaurant/middleware.ts +39 -0
- package/templates/storefront-restaurant/package.json +1 -1
- package/templates/storefront-retail/AGENTS.md +1 -1
- package/templates/storefront-retail/middleware.ts +39 -0
- package/templates/storefront-retail/package.json +1 -1
- package/templates/storefront-services/AGENTS.md +1 -1
- package/templates/storefront-services/middleware.ts +39 -0
- package/templates/storefront-services/package.json +1 -1
package/dist/dispatcher.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { TEMPLATES } from './chunk-
|
|
3
|
-
import { package_default } from './chunk-
|
|
2
|
+
import { TEMPLATES } from './chunk-V2MNBQ35.mjs';
|
|
3
|
+
import { package_default } from './chunk-D2AUHLWS.mjs';
|
|
4
4
|
|
|
5
5
|
// src/dispatcher.ts
|
|
6
6
|
var VERSION = package_default.version ?? "unknown";
|
|
@@ -138,16 +138,16 @@ var COMMANDS = {
|
|
|
138
138
|
logs: () => import('./logs-YNN2PQ24.mjs'),
|
|
139
139
|
status: () => import('./status-JSYXM5RT.mjs'),
|
|
140
140
|
dev: () => import('./dev-ONW2S77K.mjs'),
|
|
141
|
-
introspect: () => import('./introspect-
|
|
141
|
+
introspect: () => import('./introspect-NJOPZP7H.mjs'),
|
|
142
142
|
inspect: () => import('./inspect-CGYX4DDF.mjs'),
|
|
143
|
-
doctor: () => import('./doctor-
|
|
144
|
-
explain: () => import('./explain-
|
|
143
|
+
doctor: () => import('./doctor-J2Z4OLAV.mjs'),
|
|
144
|
+
explain: () => import('./explain-J2Z2L5M5.mjs'),
|
|
145
145
|
assets: () => import('./assets-74SK63TR.mjs'),
|
|
146
146
|
repo: () => import('./repo-KNQMSPVV.mjs'),
|
|
147
|
-
list: () => import('./list-
|
|
148
|
-
add: () => import('./add-
|
|
149
|
-
update: () => import('./update-
|
|
150
|
-
upgrade: () => import('./update-
|
|
147
|
+
list: () => import('./list-URTQL6PV.mjs'),
|
|
148
|
+
add: () => import('./add-Z5I2F43P.mjs'),
|
|
149
|
+
update: () => import('./update-IZFFRPX7.mjs'),
|
|
150
|
+
upgrade: () => import('./update-IZFFRPX7.mjs'),
|
|
151
151
|
"auth-step-up": () => import('./auth-step-up-BIUYQJP6.mjs')
|
|
152
152
|
};
|
|
153
153
|
var COMMAND_PREFIXES = {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { gatherIntrospection } from './chunk-
|
|
2
|
+
import { gatherIntrospection } from './chunk-27BN2J4V.mjs';
|
|
3
3
|
import './chunk-K5464A3L.mjs';
|
|
4
4
|
import './chunk-DBZ3UOQ2.mjs';
|
|
5
|
-
import './chunk-
|
|
5
|
+
import './chunk-D2AUHLWS.mjs';
|
|
6
6
|
import { parseArgs, flagBool } from './chunk-C4M3DXKC.mjs';
|
|
7
7
|
import { ApiClient } from './chunk-MAOO6ZZ5.mjs';
|
|
8
8
|
import { readAuthOrNull } from './chunk-UBAI443T.mjs';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { package_default } from './chunk-
|
|
2
|
+
import { package_default } from './chunk-D2AUHLWS.mjs';
|
|
3
3
|
import { parseArgs } from './chunk-C4M3DXKC.mjs';
|
|
4
4
|
import { bold, dim, info, result, CliError, CLI_ERROR_CODE } from './chunk-E2T2SBP5.mjs';
|
|
5
5
|
|
|
@@ -10,7 +10,7 @@ var TOPICS = [
|
|
|
10
10
|
"title": "Brand schema",
|
|
11
11
|
"description": "Single source of truth for visible strings (lib/brand.ts)",
|
|
12
12
|
"source_url": "https://cimplify.dev/docs/templates/brand",
|
|
13
|
-
"body": '## Field reference\n\n \n \n\n| Field | Required | Purpose |\n| --- | --- | --- |\n| `name` | yes | Full brand name; used in metadata, header, schema.org Organization |\n| `shortName` | yes | Compact form for tight spots (header, OG, app icons) |\n| `microTag` | yes | Tiny industry label shown beside the wordmark |\n| `description` | yes | Default OG / SEO description (\u2265 20 chars) |\n| `schemaType` | yes | schema.org Organization subtype (`Store`, `Bakery`, \u2026) |\n| `currency` | yes | ISO 4217 (e.g. `GHS`); used by every `formatPrice` |\n| `locale` | yes | BCP-47-ish, e.g. `en_GH` |\n| `contact` | yes | Address, email, phone, hours, country code |\n| `socials[]` | yes | Footer / contact chips with built-in icon keys |\n| `header.nav` | yes | Top nav links (label + href) |\n| `hero` | yes | Home hero: badge, title, subtitle, CTAs |\n| `trustItems?` | no | Hero trust strip (free shipping, warranty, \u2026) |\n| `brandStrip?` | no | "Authorised dealer for\u2026" strip |\n| `promo?` | no | Time-limited banner |\n| `terms` / `privacy` | yes | Standalone policy pages (eyebrow, sections, last updated) |\n| `shipping` / `returns` / `accessibility` | yes | Same shape as terms/privacy |\n| `newsletter` | yes | Footer signup copy |\n| `about` | yes | Eyebrow, title, paragraphs, sections |\n| `faq` | yes | Sectioned Q/A list |\n| `account` | yes | Login
|
|
13
|
+
"body": '## Field reference\n\n \n \n\n| Field | Required | Purpose |\n| --- | --- | --- |\n| `name` | yes | Full brand name; used in metadata, header, schema.org Organization |\n| `shortName` | yes | Compact form for tight spots (header, OG, app icons) |\n| `microTag` | yes | Tiny industry label shown beside the wordmark |\n| `description` | yes | Default OG / SEO description (\u2265 20 chars) |\n| `schemaType` | yes | schema.org Organization subtype (`Store`, `Bakery`, \u2026) |\n| `currency` | yes | ISO 4217 (e.g. `GHS`); used by every `formatPrice` |\n| `locale` | yes | BCP-47-ish, e.g. `en_GH` |\n| `contact` | yes | Address, email, phone, hours, country code |\n| `socials[]` | yes | Footer / contact chips with built-in icon keys |\n| `header.nav` | yes | Top nav links (label + href) |\n| `hero` | yes | Home hero: badge, title, subtitle, CTAs |\n| `trustItems?` | no | Hero trust strip (free shipping, warranty, \u2026) |\n| `brandStrip?` | no | "Authorised dealer for\u2026" strip |\n| `promo?` | no | Time-limited banner |\n| `terms` / `privacy` | yes | Standalone policy pages (eyebrow, sections, last updated) |\n| `shipping` / `returns` / `accessibility` | yes | Same shape as terms/privacy |\n| `newsletter` | yes | Footer signup copy |\n| `about` | yes | Eyebrow, title, paragraphs, sections |\n| `faq` | yes | Sectioned Q/A list |\n| `account` | yes | Login, signup, and account page copy for SDK-rendered account routes |\n| `contactPage` | yes | Eyebrow, title, body for `/contact` |\n| `trackOrder` | yes | Copy for the guest order lookup page |\n| `footer` | yes | Sitemap sections, blurb, optional "Powered by" |\n| `llms.summary` | yes | \u2265 20-char blurb that opens the `/llms.txt` index |\n| `mock.seed` | yes | Mock seed name (must match `SeedNameSchema`) |\n| `mock.businessId` | yes | Must start with `bus_` |\n\n \n\n \n\n## A complete example\n\n \n \n\n```ts title="lib/brand.ts (excerpt: the retail template)"\n\nexport const brand: Brand = {\n name: "Currents Electronics",\n shortName: "Currents",\n microTag: "ELECTRONICS",\n description:\n "Authorised dealer for Apple, Samsung, Sony, Bose. Same-day Accra delivery, two-year warranty.",\n schemaType: "Store",\n currency: "GHS",\n locale: "en_GH",\n\n contact: {\n email: "hello@currentselectronics.test",\n phone: "+233 244 000 000",\n phoneTel: "+233244000000",\n streetAddress: "Atomic Junction, East Legon",\n city: "Accra",\n countryCode: "GH",\n hours: "Mon\u2013Sat \xB7 9am\u20138pm",\n },\n\n socials: [\n { label: "Instagram", href: "https://instagram.com/currentselectronics", icon: "instagram" },\n { label: "WhatsApp", href: "https://wa.me/233244000000", icon: "whatsapp" },\n ],\n\n header: { nav: [\n { label: "Shop", href: "/shop" },\n { label: "Deals", href: "/categories/deals" },\n { label: "Support",href: "/faq" },\n ]},\n\n hero: {\n badge: "LAPTOPS \xB7 PHONES \xB7 AUDIO",\n title: "The tech you want, in stock today.",\n subtitle: "Same-day delivery in Accra. Two-year warranty on every product.",\n primaryCtaLabel: "Shop now",\n secondaryCtaLabel: "See deals",\n secondaryCtaHref: "/categories/deals",\n },\n\n // \u2026terms, privacy, shipping, returns, accessibility, about, faq, \u2026\n\n newsletter: {\n title: "New drops, real prices, in your inbox.",\n body: "One email a week. No newsletter chaff.",\n eyebrow: "The shortlist",\n },\n account: {\n loginEyebrow: "Welcome back", loginTitle: "Sign in to Currents",\n signupEyebrow: "Welcome", signupTitle: "Create your Currents account",\n accountEyebrow: "Your account", accountTitle: "Welcome back",\n },\n contactPage: { title: "Talk to a real human.", body: "We reply within a business day.", eyebrow: "Contact" },\n trackOrder: { title: "Where\'s my order?", body: "Enter your order number and email.", eyebrow: "Track an order" },\n footer: { sitemap: [/* \u2026 */], poweredBy: { label: "Cimplify", href: "https://app.cimplify.io" } },\n llms: { summary: "Authorised dealer for Apple, Samsung, Sony, Bose. Two-year warranty." },\n\n mock: { seed: "retail", businessId: "bus_currents_electronics" },\n};\n```\n\n \n\n \n\n## Validation: `assertBrand`\n\n \n\nTemplates run `assertBrand(brand)` in their `brand.test.ts`. Failures list every offending field with its dot-path; drift between the template and the schema is impossible to ship by accident.\n\n \n \n\n```ts title="__tests__/brand.test.ts"\n\ncreateBrandSuite({ brand });\n```\n\n \n\n \n\n## Industry-specific extensions\n\n \n\nNeed fields the base schema doesn\'t have (fashion\'s `lookbook`, services\' `bookingPolicy`)? Extend, don\'t fork. The base shape stays canonical and your custom fields type-check alongside it.\n\n \n \n\n```ts title="Extending BrandSchema"\n\nexport const FashionBrandSchema = BrandSchema.extend({\n lookbook: z.object({\n eyebrow: z.string(),\n title: z.string().min(1),\n drops: z.array(z.object({\n slug: z.string(),\n title: z.string(),\n heroImage: z.string().url(),\n })),\n }),\n});\n\nexport type FashionBrand = z.infer<typeof FashionBrandSchema>;\n```\n\n \n\n \n\n## Next\n\n \n \n- [**Templates overview**](/docs/templates)\n Six industry templates and what they ship\n\n \n- [**Customizing**](/docs/templates/customizing)\n Beyond brand: ejection and schema extensions\n'
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"name": "eject",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export { run as default, extractMockSeed, gatherIntrospection, renderIntrospection } from './chunk-
|
|
2
|
+
export { run as default, extractMockSeed, gatherIntrospection, renderIntrospection } from './chunk-27BN2J4V.mjs';
|
|
3
3
|
import './chunk-K5464A3L.mjs';
|
|
4
4
|
import './chunk-DBZ3UOQ2.mjs';
|
|
5
|
-
import './chunk-
|
|
5
|
+
import './chunk-D2AUHLWS.mjs';
|
|
6
6
|
import './chunk-C4M3DXKC.mjs';
|
|
7
7
|
import './chunk-UBAI443T.mjs';
|
|
8
8
|
import './chunk-E2T2SBP5.mjs';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { REGISTRY_INDEX } from './chunk-
|
|
2
|
+
import { REGISTRY_INDEX } from './chunk-V2MNBQ35.mjs';
|
|
3
3
|
import { parseArgs, flagBool } from './chunk-C4M3DXKC.mjs';
|
|
4
4
|
import { CliError, CLI_ERROR_CODE, info, bold, dim, green, result } from './chunk-E2T2SBP5.mjs';
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { package_default } from './chunk-
|
|
2
|
+
import { package_default } from './chunk-D2AUHLWS.mjs';
|
|
3
3
|
import { promptYesNo } from './chunk-ITAFAORS.mjs';
|
|
4
4
|
import { parseArgs, flagBool, flagString } from './chunk-C4M3DXKC.mjs';
|
|
5
5
|
import { success, bold, info, dim, result, failure, CliError, CLI_ERROR_CODE, step, isJsonMode } from './chunk-E2T2SBP5.mjs';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cimplify/cli",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.14",
|
|
4
4
|
"description": "Cimplify CLI — deploy, manage env vars, link projects, and scaffold storefronts",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cimplify",
|
|
@@ -45,6 +45,6 @@
|
|
|
45
45
|
"vitest": "^4.1.5"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@cimplify/sdk": "^0.
|
|
48
|
+
"@cimplify/sdk": "^0.70.2"
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { NextResponse, type NextRequest } from "next/server";
|
|
2
|
+
import { handleTokenRefresh, type OidcConfig } from "@cimplify/sdk/server";
|
|
3
|
+
|
|
4
|
+
function oidcConfig(): OidcConfig | null {
|
|
5
|
+
const clientId =
|
|
6
|
+
process.env.CIMPLIFY_CLIENT_ID?.trim() ||
|
|
7
|
+
process.env.NEXT_PUBLIC_CIMPLIFY_CLIENT_ID?.trim() ||
|
|
8
|
+
"";
|
|
9
|
+
if (!clientId) return null;
|
|
10
|
+
return {
|
|
11
|
+
clientId,
|
|
12
|
+
issuer: process.env.CIMPLIFY_ISSUER?.trim() || undefined,
|
|
13
|
+
authUrl: process.env.CIMPLIFY_AUTH_URL?.trim() || undefined,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Keeps the access token fresh before account pages render. Server Components
|
|
18
|
+
// can't write cookies, so this is the one place the rotated token can be both
|
|
19
|
+
// persisted (browser) and forwarded onto the current request (this render).
|
|
20
|
+
export async function middleware(request: NextRequest) {
|
|
21
|
+
const cfg = oidcConfig();
|
|
22
|
+
if (!cfg) return NextResponse.next();
|
|
23
|
+
|
|
24
|
+
const { outcome, setCookies, cookies } = await handleTokenRefresh(request, cfg);
|
|
25
|
+
if (outcome === "noop") return NextResponse.next();
|
|
26
|
+
|
|
27
|
+
for (const { name, value } of cookies) {
|
|
28
|
+
request.cookies.set(name, value);
|
|
29
|
+
}
|
|
30
|
+
const response = NextResponse.next({ request });
|
|
31
|
+
for (const cookie of setCookies) {
|
|
32
|
+
response.headers.append("set-cookie", cookie);
|
|
33
|
+
}
|
|
34
|
+
return response;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const config = {
|
|
38
|
+
matcher: ["/account/:path*"],
|
|
39
|
+
};
|
|
@@ -41,8 +41,8 @@ app/
|
|
|
41
41
|
account/orders/page.tsx <AccountOrdersPage /> (native)
|
|
42
42
|
account/addresses/page.tsx Native list + Server Actions for CRUD
|
|
43
43
|
account/wallets/page.tsx Native list + Server Actions for CRUD
|
|
44
|
-
login/page.tsx redirect →
|
|
45
|
-
signup/page.tsx redirect →
|
|
44
|
+
login/page.tsx redirect → hosted OAuth, then /account
|
|
45
|
+
signup/page.tsx redirect → hosted OAuth, then /account
|
|
46
46
|
|
|
47
47
|
contact/page.tsx Contact form (Server Action wiring TODO; currently fakes submit)
|
|
48
48
|
track-order/page.tsx Guest order lookup → /orders/[id]
|
|
@@ -78,7 +78,7 @@ app/
|
|
|
78
78
|
| `app/accessibility/page.tsx` | `brand.accessibility` |
|
|
79
79
|
| `app/contact/page.tsx` | `brand.contactPage`, `brand.contact` |
|
|
80
80
|
| `app/track-order/page.tsx` | `brand.trackOrder` |
|
|
81
|
-
| `app/account/*/page.tsx` | `brand.account` (
|
|
81
|
+
| `app/account/*/page.tsx` | `brand.account` (SDK account pages render the UI) |
|
|
82
82
|
| `app/login/page.tsx`, `app/signup/page.tsx` | `brand.account` (metadata only — both redirect to `/account`) |
|
|
83
83
|
| `app/llms.txt/route.ts` | `brand.llms`, contact, currency |
|
|
84
84
|
| `app/opensearch.xml/route.ts` | `brand.shortName`, `brand.name` |
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { NextResponse, type NextRequest } from "next/server";
|
|
2
|
+
import { handleTokenRefresh, type OidcConfig } from "@cimplify/sdk/server";
|
|
3
|
+
|
|
4
|
+
function oidcConfig(): OidcConfig | null {
|
|
5
|
+
const clientId =
|
|
6
|
+
process.env.CIMPLIFY_CLIENT_ID?.trim() ||
|
|
7
|
+
process.env.NEXT_PUBLIC_CIMPLIFY_CLIENT_ID?.trim() ||
|
|
8
|
+
"";
|
|
9
|
+
if (!clientId) return null;
|
|
10
|
+
return {
|
|
11
|
+
clientId,
|
|
12
|
+
issuer: process.env.CIMPLIFY_ISSUER?.trim() || undefined,
|
|
13
|
+
authUrl: process.env.CIMPLIFY_AUTH_URL?.trim() || undefined,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Keeps the access token fresh before account pages render. Server Components
|
|
18
|
+
// can't write cookies, so this is the one place the rotated token can be both
|
|
19
|
+
// persisted (browser) and forwarded onto the current request (this render).
|
|
20
|
+
export async function middleware(request: NextRequest) {
|
|
21
|
+
const cfg = oidcConfig();
|
|
22
|
+
if (!cfg) return NextResponse.next();
|
|
23
|
+
|
|
24
|
+
const { outcome, setCookies, cookies } = await handleTokenRefresh(request, cfg);
|
|
25
|
+
if (outcome === "noop") return NextResponse.next();
|
|
26
|
+
|
|
27
|
+
for (const { name, value } of cookies) {
|
|
28
|
+
request.cookies.set(name, value);
|
|
29
|
+
}
|
|
30
|
+
const response = NextResponse.next({ request });
|
|
31
|
+
for (const cookie of setCookies) {
|
|
32
|
+
response.headers.append("set-cookie", cookie);
|
|
33
|
+
}
|
|
34
|
+
return response;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const config = {
|
|
38
|
+
matcher: ["/account/:path*"],
|
|
39
|
+
};
|
|
@@ -70,7 +70,7 @@ app/
|
|
|
70
70
|
| `app/terms/page.tsx`, `app/privacy/page.tsx` | `brand.terms`, `brand.privacy` |
|
|
71
71
|
| `app/contact/page.tsx` | `brand.contactPage`, `brand.contact` |
|
|
72
72
|
| `app/track-order/page.tsx` | `brand.trackOrder` |
|
|
73
|
-
| `app/account/*/page.tsx` | `brand.account` (
|
|
73
|
+
| `app/account/*/page.tsx` | `brand.account` (SDK account pages render the UI) |
|
|
74
74
|
| `app/products/[slug]/page.tsx` | `brand.name`, `brand.currency` (Product JSON-LD) |
|
|
75
75
|
| `app/size-guide/page.tsx` | currently has its size charts inlined — hoist to `brand.sizeGuide` if you want agents to edit them |
|
|
76
76
|
| `app/lookbook/page.tsx` | currently has the lookbook entries inlined (image URLs + drop names) — hoist to `brand.lookbook` for agent editing |
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { NextResponse, type NextRequest } from "next/server";
|
|
2
|
+
import { handleTokenRefresh, type OidcConfig } from "@cimplify/sdk/server";
|
|
3
|
+
|
|
4
|
+
function oidcConfig(): OidcConfig | null {
|
|
5
|
+
const clientId =
|
|
6
|
+
process.env.CIMPLIFY_CLIENT_ID?.trim() ||
|
|
7
|
+
process.env.NEXT_PUBLIC_CIMPLIFY_CLIENT_ID?.trim() ||
|
|
8
|
+
"";
|
|
9
|
+
if (!clientId) return null;
|
|
10
|
+
return {
|
|
11
|
+
clientId,
|
|
12
|
+
issuer: process.env.CIMPLIFY_ISSUER?.trim() || undefined,
|
|
13
|
+
authUrl: process.env.CIMPLIFY_AUTH_URL?.trim() || undefined,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Keeps the access token fresh before account pages render. Server Components
|
|
18
|
+
// can't write cookies, so this is the one place the rotated token can be both
|
|
19
|
+
// persisted (browser) and forwarded onto the current request (this render).
|
|
20
|
+
export async function middleware(request: NextRequest) {
|
|
21
|
+
const cfg = oidcConfig();
|
|
22
|
+
if (!cfg) return NextResponse.next();
|
|
23
|
+
|
|
24
|
+
const { outcome, setCookies, cookies } = await handleTokenRefresh(request, cfg);
|
|
25
|
+
if (outcome === "noop") return NextResponse.next();
|
|
26
|
+
|
|
27
|
+
for (const { name, value } of cookies) {
|
|
28
|
+
request.cookies.set(name, value);
|
|
29
|
+
}
|
|
30
|
+
const response = NextResponse.next({ request });
|
|
31
|
+
for (const cookie of setCookies) {
|
|
32
|
+
response.headers.append("set-cookie", cookie);
|
|
33
|
+
}
|
|
34
|
+
return response;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const config = {
|
|
38
|
+
matcher: ["/account/:path*"],
|
|
39
|
+
};
|
|
@@ -58,7 +58,7 @@ app/
|
|
|
58
58
|
| `app/terms/page.tsx`, `app/privacy/page.tsx` | `brand.terms`, `brand.privacy` |
|
|
59
59
|
| `app/contact/page.tsx` | `brand.contactPage`, `brand.contact` |
|
|
60
60
|
| `app/track-order/page.tsx` | `brand.trackOrder` |
|
|
61
|
-
| `app/account/*/page.tsx` | `brand.account` (
|
|
61
|
+
| `app/account/*/page.tsx` | `brand.account` (SDK account pages render the UI) |
|
|
62
62
|
| `app/llms.txt/route.ts` | `brand.llms`, contact, currency |
|
|
63
63
|
| `components/header.tsx`, `footer.tsx` | `brand.header`, `brand.footer`, `brand.contact`, `brand.socials` |
|
|
64
64
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { NextResponse, type NextRequest } from "next/server";
|
|
2
|
+
import { handleTokenRefresh, type OidcConfig } from "@cimplify/sdk/server";
|
|
3
|
+
|
|
4
|
+
function oidcConfig(): OidcConfig | null {
|
|
5
|
+
const clientId =
|
|
6
|
+
process.env.CIMPLIFY_CLIENT_ID?.trim() ||
|
|
7
|
+
process.env.NEXT_PUBLIC_CIMPLIFY_CLIENT_ID?.trim() ||
|
|
8
|
+
"";
|
|
9
|
+
if (!clientId) return null;
|
|
10
|
+
return {
|
|
11
|
+
clientId,
|
|
12
|
+
issuer: process.env.CIMPLIFY_ISSUER?.trim() || undefined,
|
|
13
|
+
authUrl: process.env.CIMPLIFY_AUTH_URL?.trim() || undefined,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Keeps the access token fresh before account pages render. Server Components
|
|
18
|
+
// can't write cookies, so this is the one place the rotated token can be both
|
|
19
|
+
// persisted (browser) and forwarded onto the current request (this render).
|
|
20
|
+
export async function middleware(request: NextRequest) {
|
|
21
|
+
const cfg = oidcConfig();
|
|
22
|
+
if (!cfg) return NextResponse.next();
|
|
23
|
+
|
|
24
|
+
const { outcome, setCookies, cookies } = await handleTokenRefresh(request, cfg);
|
|
25
|
+
if (outcome === "noop") return NextResponse.next();
|
|
26
|
+
|
|
27
|
+
for (const { name, value } of cookies) {
|
|
28
|
+
request.cookies.set(name, value);
|
|
29
|
+
}
|
|
30
|
+
const response = NextResponse.next({ request });
|
|
31
|
+
for (const cookie of setCookies) {
|
|
32
|
+
response.headers.append("set-cookie", cookie);
|
|
33
|
+
}
|
|
34
|
+
return response;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const config = {
|
|
38
|
+
matcher: ["/account/:path*"],
|
|
39
|
+
};
|
|
@@ -68,7 +68,7 @@ app/
|
|
|
68
68
|
| `app/accessibility/page.tsx` | `brand.accessibility` |
|
|
69
69
|
| `app/contact/page.tsx` | `brand.contactPage`, `brand.contact` |
|
|
70
70
|
| `app/track-order/page.tsx` | `brand.trackOrder` |
|
|
71
|
-
| `app/account/*/page.tsx` | `brand.account` (
|
|
71
|
+
| `app/account/*/page.tsx` | `brand.account` (SDK account pages render the UI) |
|
|
72
72
|
| `app/products/[slug]/page.tsx` | `brand.name`, `brand.currency` (Product JSON-LD: brand, offer, availability) |
|
|
73
73
|
| `app/llms.txt/route.ts` | `brand.llms`, contact, currency |
|
|
74
74
|
| `app/opensearch.xml/route.ts` | `brand.shortName`, `brand.name` |
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { NextResponse, type NextRequest } from "next/server";
|
|
2
|
+
import { handleTokenRefresh, type OidcConfig } from "@cimplify/sdk/server";
|
|
3
|
+
|
|
4
|
+
function oidcConfig(): OidcConfig | null {
|
|
5
|
+
const clientId =
|
|
6
|
+
process.env.CIMPLIFY_CLIENT_ID?.trim() ||
|
|
7
|
+
process.env.NEXT_PUBLIC_CIMPLIFY_CLIENT_ID?.trim() ||
|
|
8
|
+
"";
|
|
9
|
+
if (!clientId) return null;
|
|
10
|
+
return {
|
|
11
|
+
clientId,
|
|
12
|
+
issuer: process.env.CIMPLIFY_ISSUER?.trim() || undefined,
|
|
13
|
+
authUrl: process.env.CIMPLIFY_AUTH_URL?.trim() || undefined,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Keeps the access token fresh before account pages render. Server Components
|
|
18
|
+
// can't write cookies, so this is the one place the rotated token can be both
|
|
19
|
+
// persisted (browser) and forwarded onto the current request (this render).
|
|
20
|
+
export async function middleware(request: NextRequest) {
|
|
21
|
+
const cfg = oidcConfig();
|
|
22
|
+
if (!cfg) return NextResponse.next();
|
|
23
|
+
|
|
24
|
+
const { outcome, setCookies, cookies } = await handleTokenRefresh(request, cfg);
|
|
25
|
+
if (outcome === "noop") return NextResponse.next();
|
|
26
|
+
|
|
27
|
+
for (const { name, value } of cookies) {
|
|
28
|
+
request.cookies.set(name, value);
|
|
29
|
+
}
|
|
30
|
+
const response = NextResponse.next({ request });
|
|
31
|
+
for (const cookie of setCookies) {
|
|
32
|
+
response.headers.append("set-cookie", cookie);
|
|
33
|
+
}
|
|
34
|
+
return response;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const config = {
|
|
38
|
+
matcher: ["/account/:path*"],
|
|
39
|
+
};
|
|
@@ -61,7 +61,7 @@ app/
|
|
|
61
61
|
| `app/terms/page.tsx`, `app/privacy/page.tsx` | `brand.terms`, `brand.privacy` |
|
|
62
62
|
| `app/contact/page.tsx` | `brand.contactPage`, `brand.contact` |
|
|
63
63
|
| `app/track-order/page.tsx` | `brand.trackOrder` |
|
|
64
|
-
| `app/account/*/page.tsx` | `brand.account` (
|
|
64
|
+
| `app/account/*/page.tsx` | `brand.account` (SDK account pages render the UI) |
|
|
65
65
|
| `app/reservations/*` | derives seating from service-type products in the catalogue |
|
|
66
66
|
| `app/llms.txt/route.ts` | `brand.llms`, contact, currency |
|
|
67
67
|
| `components/header.tsx`, `footer.tsx` | `brand.header`, `brand.footer`, `brand.contact`, `brand.socials` |
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { NextResponse, type NextRequest } from "next/server";
|
|
2
|
+
import { handleTokenRefresh, type OidcConfig } from "@cimplify/sdk/server";
|
|
3
|
+
|
|
4
|
+
function oidcConfig(): OidcConfig | null {
|
|
5
|
+
const clientId =
|
|
6
|
+
process.env.CIMPLIFY_CLIENT_ID?.trim() ||
|
|
7
|
+
process.env.NEXT_PUBLIC_CIMPLIFY_CLIENT_ID?.trim() ||
|
|
8
|
+
"";
|
|
9
|
+
if (!clientId) return null;
|
|
10
|
+
return {
|
|
11
|
+
clientId,
|
|
12
|
+
issuer: process.env.CIMPLIFY_ISSUER?.trim() || undefined,
|
|
13
|
+
authUrl: process.env.CIMPLIFY_AUTH_URL?.trim() || undefined,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Keeps the access token fresh before account pages render. Server Components
|
|
18
|
+
// can't write cookies, so this is the one place the rotated token can be both
|
|
19
|
+
// persisted (browser) and forwarded onto the current request (this render).
|
|
20
|
+
export async function middleware(request: NextRequest) {
|
|
21
|
+
const cfg = oidcConfig();
|
|
22
|
+
if (!cfg) return NextResponse.next();
|
|
23
|
+
|
|
24
|
+
const { outcome, setCookies, cookies } = await handleTokenRefresh(request, cfg);
|
|
25
|
+
if (outcome === "noop") return NextResponse.next();
|
|
26
|
+
|
|
27
|
+
for (const { name, value } of cookies) {
|
|
28
|
+
request.cookies.set(name, value);
|
|
29
|
+
}
|
|
30
|
+
const response = NextResponse.next({ request });
|
|
31
|
+
for (const cookie of setCookies) {
|
|
32
|
+
response.headers.append("set-cookie", cookie);
|
|
33
|
+
}
|
|
34
|
+
return response;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const config = {
|
|
38
|
+
matcher: ["/account/:path*"],
|
|
39
|
+
};
|
|
@@ -67,7 +67,7 @@ app/
|
|
|
67
67
|
| `app/accessibility/page.tsx` | `brand.accessibility` |
|
|
68
68
|
| `app/contact/page.tsx` | `brand.contactPage`, `brand.contact` |
|
|
69
69
|
| `app/track-order/page.tsx` | `brand.trackOrder` |
|
|
70
|
-
| `app/account/*/page.tsx` | `brand.account` (
|
|
70
|
+
| `app/account/*/page.tsx` | `brand.account` (SDK account pages render the UI) |
|
|
71
71
|
| `app/products/[slug]/page.tsx` | `brand.name`, `brand.currency` (Product JSON-LD: brand, offer, availability) |
|
|
72
72
|
| `app/llms.txt/route.ts` | `brand.llms`, contact, currency |
|
|
73
73
|
| `app/opensearch.xml/route.ts` | `brand.shortName`, `brand.name` |
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { NextResponse, type NextRequest } from "next/server";
|
|
2
|
+
import { handleTokenRefresh, type OidcConfig } from "@cimplify/sdk/server";
|
|
3
|
+
|
|
4
|
+
function oidcConfig(): OidcConfig | null {
|
|
5
|
+
const clientId =
|
|
6
|
+
process.env.CIMPLIFY_CLIENT_ID?.trim() ||
|
|
7
|
+
process.env.NEXT_PUBLIC_CIMPLIFY_CLIENT_ID?.trim() ||
|
|
8
|
+
"";
|
|
9
|
+
if (!clientId) return null;
|
|
10
|
+
return {
|
|
11
|
+
clientId,
|
|
12
|
+
issuer: process.env.CIMPLIFY_ISSUER?.trim() || undefined,
|
|
13
|
+
authUrl: process.env.CIMPLIFY_AUTH_URL?.trim() || undefined,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Keeps the access token fresh before account pages render. Server Components
|
|
18
|
+
// can't write cookies, so this is the one place the rotated token can be both
|
|
19
|
+
// persisted (browser) and forwarded onto the current request (this render).
|
|
20
|
+
export async function middleware(request: NextRequest) {
|
|
21
|
+
const cfg = oidcConfig();
|
|
22
|
+
if (!cfg) return NextResponse.next();
|
|
23
|
+
|
|
24
|
+
const { outcome, setCookies, cookies } = await handleTokenRefresh(request, cfg);
|
|
25
|
+
if (outcome === "noop") return NextResponse.next();
|
|
26
|
+
|
|
27
|
+
for (const { name, value } of cookies) {
|
|
28
|
+
request.cookies.set(name, value);
|
|
29
|
+
}
|
|
30
|
+
const response = NextResponse.next({ request });
|
|
31
|
+
for (const cookie of setCookies) {
|
|
32
|
+
response.headers.append("set-cookie", cookie);
|
|
33
|
+
}
|
|
34
|
+
return response;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const config = {
|
|
38
|
+
matcher: ["/account/:path*"],
|
|
39
|
+
};
|
|
@@ -62,7 +62,7 @@ app/
|
|
|
62
62
|
| `app/terms/page.tsx`, `app/privacy/page.tsx` | `brand.terms`, `brand.privacy` |
|
|
63
63
|
| `app/contact/page.tsx` | `brand.contactPage`, `brand.contact` |
|
|
64
64
|
| `app/track-order/page.tsx` | `brand.trackOrder` ("find a booking") |
|
|
65
|
-
| `app/account/*/page.tsx` | `brand.account` (
|
|
65
|
+
| `app/account/*/page.tsx` | `brand.account` (SDK account pages render the UI) |
|
|
66
66
|
| `app/book/*` | derives bookable services from product list (`type: "service"`) |
|
|
67
67
|
| `app/llms.txt/route.ts` | `brand.llms`, contact, currency |
|
|
68
68
|
| `components/header.tsx`, `footer.tsx` | `brand.header`, `brand.footer`, `brand.contact`, `brand.socials` |
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { NextResponse, type NextRequest } from "next/server";
|
|
2
|
+
import { handleTokenRefresh, type OidcConfig } from "@cimplify/sdk/server";
|
|
3
|
+
|
|
4
|
+
function oidcConfig(): OidcConfig | null {
|
|
5
|
+
const clientId =
|
|
6
|
+
process.env.CIMPLIFY_CLIENT_ID?.trim() ||
|
|
7
|
+
process.env.NEXT_PUBLIC_CIMPLIFY_CLIENT_ID?.trim() ||
|
|
8
|
+
"";
|
|
9
|
+
if (!clientId) return null;
|
|
10
|
+
return {
|
|
11
|
+
clientId,
|
|
12
|
+
issuer: process.env.CIMPLIFY_ISSUER?.trim() || undefined,
|
|
13
|
+
authUrl: process.env.CIMPLIFY_AUTH_URL?.trim() || undefined,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Keeps the access token fresh before account pages render. Server Components
|
|
18
|
+
// can't write cookies, so this is the one place the rotated token can be both
|
|
19
|
+
// persisted (browser) and forwarded onto the current request (this render).
|
|
20
|
+
export async function middleware(request: NextRequest) {
|
|
21
|
+
const cfg = oidcConfig();
|
|
22
|
+
if (!cfg) return NextResponse.next();
|
|
23
|
+
|
|
24
|
+
const { outcome, setCookies, cookies } = await handleTokenRefresh(request, cfg);
|
|
25
|
+
if (outcome === "noop") return NextResponse.next();
|
|
26
|
+
|
|
27
|
+
for (const { name, value } of cookies) {
|
|
28
|
+
request.cookies.set(name, value);
|
|
29
|
+
}
|
|
30
|
+
const response = NextResponse.next({ request });
|
|
31
|
+
for (const cookie of setCookies) {
|
|
32
|
+
response.headers.append("set-cookie", cookie);
|
|
33
|
+
}
|
|
34
|
+
return response;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const config = {
|
|
38
|
+
matcher: ["/account/:path*"],
|
|
39
|
+
};
|