@aranova/tracking-next 0.20.1 → 0.21.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 +80 -1
- package/dist/blog-server.js +6 -3
- package/dist/blog-server.js.map +1 -1
- package/dist/blog-server.mjs +6 -3
- package/dist/blog-server.mjs.map +1 -1
- package/dist/blog.js +4 -2
- package/dist/blog.js.map +1 -1
- package/dist/blog.mjs +4 -2
- package/dist/blog.mjs.map +1 -1
- package/dist/calendar-server.d.mts +53 -0
- package/dist/calendar-server.d.ts +53 -0
- package/dist/calendar-server.js +206 -0
- package/dist/calendar-server.js.map +1 -0
- package/dist/calendar-server.mjs +180 -0
- package/dist/calendar-server.mjs.map +1 -0
- package/dist/calendar.d.mts +112 -0
- package/dist/calendar.d.ts +112 -0
- package/dist/calendar.js +517 -0
- package/dist/calendar.js.map +1 -0
- package/dist/calendar.mjs +457 -0
- package/dist/calendar.mjs.map +1 -0
- package/dist/date-BHetnL7s.d.mts +26 -0
- package/dist/date-BHetnL7s.d.ts +26 -0
- package/dist/index.d.mts +60 -3
- package/dist/index.d.ts +60 -3
- package/dist/index.js +511 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +474 -18
- package/dist/index.mjs.map +1 -1
- package/dist/request-Doq36Rt0.d.mts +19 -0
- package/dist/request-Doq36Rt0.d.ts +19 -0
- package/dist/{sales-DrH6dY5F.d.mts → sales-B3BnYncU.d.mts} +5 -44
- package/dist/{sales-DrH6dY5F.d.ts → sales-CDjXRdmd.d.ts} +5 -44
- package/dist/sales.d.mts +3 -1
- package/dist/sales.d.ts +3 -1
- package/dist/sales.js +22 -17
- package/dist/sales.js.map +1 -1
- package/dist/sales.mjs +22 -17
- package/dist/sales.mjs.map +1 -1
- package/dist/transport-Bku8zftU.d.mts +721 -0
- package/dist/transport-DsOY6kcW.d.ts +721 -0
- package/package.json +22 -1
package/README.md
CHANGED
|
@@ -341,6 +341,81 @@ npx @aranova/tracking-cli gen # reads ARANOVA_TRACKING_SECRET_KEY from
|
|
|
341
341
|
See the full guide: [sales-tracking.md](https://github.com/AranovaIO/aranova_internal/blob/master/docs/tracking-package/sales-tracking.md)
|
|
342
342
|
and the CLI reference: [cli.md](https://github.com/AranovaIO/aranova_internal/blob/master/docs/tracking-package/cli.md).
|
|
343
343
|
|
|
344
|
+
## Calendar Bookings
|
|
345
|
+
|
|
346
|
+
Take bookings on a client site against a connected Google Calendar. Unlike sales,
|
|
347
|
+
reads and writes are **separate entries**, and the split is structural rather than a
|
|
348
|
+
convention — the read entry exposes no write verb at all.
|
|
349
|
+
|
|
350
|
+
Read availability with your **public** key, straight from the browser:
|
|
351
|
+
|
|
352
|
+
```ts
|
|
353
|
+
import { createCalendarReadClient, computeSlots } from "@aranova/tracking-next/calendar";
|
|
354
|
+
import type { AranovaCalendarKey } from "./aranova-services"; // generated, see below
|
|
355
|
+
|
|
356
|
+
const calendar = createCalendarReadClient<AranovaCalendarKey>({
|
|
357
|
+
apiKey: process.env.NEXT_PUBLIC_ARANOVA_TRACKING_API_KEY!,
|
|
358
|
+
endpoint,
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
// Busy intervals only — never the contents of anyone's events.
|
|
362
|
+
// `since`/`until` are ISO instants WITH an offset; a date-only value is a 400.
|
|
363
|
+
const { busy, time_zone } = await calendar.busy("consultations", { since, until });
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
**Opening hours live in your app, not in the dashboard.** The API answers only "when is
|
|
367
|
+
this person busy"; `computeSlots()` is a pure, dependency-free helper that turns that plus
|
|
368
|
+
your own hours into offerable slots:
|
|
369
|
+
|
|
370
|
+
```ts
|
|
371
|
+
const { slots, nextAvailableAt } = computeSlots({
|
|
372
|
+
busy,
|
|
373
|
+
timeZone: time_zone,
|
|
374
|
+
openingHours: { weekly: { 1: [{ start: "09:00", end: "17:00" }] } },
|
|
375
|
+
durationMinutes: 30,
|
|
376
|
+
minNoticeMinutes: 240,
|
|
377
|
+
bufferAfterMinutes: 15,
|
|
378
|
+
});
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
Writes need your **secret** key, so they run only on your own server. Drop in one route
|
|
382
|
+
file — `./calendar-server` carries `import "server-only"`, so a client component importing
|
|
383
|
+
it fails the build instead of shipping the key to a browser:
|
|
384
|
+
|
|
385
|
+
```ts
|
|
386
|
+
// app/api/aranova/calendar/[...route]/route.ts
|
|
387
|
+
import { createCalendarRoutes } from "@aranova/tracking-next/calendar-server";
|
|
388
|
+
|
|
389
|
+
export const runtime = "nodejs";
|
|
390
|
+
export const dynamic = "force-dynamic";
|
|
391
|
+
|
|
392
|
+
export const { POST, PATCH, DELETE } = createCalendarRoutes({
|
|
393
|
+
secretKey: process.env.ARANOVA_TRACKING_SECRET_KEY!, // never NEXT_PUBLIC_
|
|
394
|
+
endpoint: process.env.ARANOVA_TRACKING_ENDPOINT!,
|
|
395
|
+
});
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
Why the split, when sales is one isomorphic client: a public key ships in a JS bundle and
|
|
399
|
+
its Origin allowlist is a browser-enforced header a script forges trivially. A junk sale is
|
|
400
|
+
a database row you can delete; a junk **booking** puts an event on a real person's calendar
|
|
401
|
+
and emails their contacts.
|
|
402
|
+
|
|
403
|
+
`bookings.create()` returns a one-time `manage_token`. Put it in your confirmation email and
|
|
404
|
+
send it as `X-Aranova-Manage-Token` to reschedule or cancel — it authorises exactly that one
|
|
405
|
+
booking, which is why a public key alone still manages nothing.
|
|
406
|
+
|
|
407
|
+
Headless hooks on the root entry (no booking UI ships, for the same reason no consent UI does):
|
|
408
|
+
|
|
409
|
+
```tsx
|
|
410
|
+
"use client";
|
|
411
|
+
import { useCalendarBusy, useSlots, useBookingForm } from "@aranova/tracking-next";
|
|
412
|
+
// wrap in <CalendarClientProvider value={calendar}> — the hooks need a read client
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
Generate the typed `AranovaCalendarKey` union with the CLI (`npx @aranova/tracking-cli gen`).
|
|
416
|
+
|
|
417
|
+
Full guide: [calendar.md](https://github.com/AranovaIO/aranova_internal/blob/master/docs/tracking-package/calendar.md)
|
|
418
|
+
|
|
344
419
|
## On-site conversion firing
|
|
345
420
|
|
|
346
421
|
Run `tracking-cli gen` once to emit `ARANOVA_TRACKING_CONFIG`, then use that
|
|
@@ -495,8 +570,12 @@ Reads are best-effort: network/parse failures degrade to `null`/empty — a blog
|
|
|
495
570
|
attribution hooks, event types; `createSalesClient()` (isomorphic — public key writes;
|
|
496
571
|
secret key reads/CRUD, `summary`, `customers.*`, `business.config`) +
|
|
497
572
|
`toMinor`/`fromMinor`/`formatMoney`/`formatDateInTz`; phone
|
|
498
|
-
(`parsePhone`/`toE164`/`formatPhone`/`phoneField`, `usePhoneField`, `PhoneField`)
|
|
573
|
+
(`parsePhone`/`toE164`/`formatPhone`/`phoneField`, `usePhoneField`, `PhoneField`); calendar
|
|
574
|
+
read surface + headless hooks (`CalendarClientProvider`, `useCalendarBusy`, `useSlots`,
|
|
575
|
+
`useBookingForm`) — booking **writes** are not here, see `/calendar-server`
|
|
499
576
|
- `@aranova/tracking-next/sales`: **React-free** server-safe SDK — `createSalesClient`, money/date helpers, and all sale/customer/config types. Use this in Server Components, route handlers, and Node servers; the root entry re-exports the same symbols for back-compat.
|
|
577
|
+
- `@aranova/tracking-next/calendar`: **React-free, read-only** — `createCalendarReadClient`, `computeSlots`, timezone helpers, and the booking types. Public key, browser-safe. Deliberately exposes no write verb.
|
|
578
|
+
- `@aranova/tracking-next/calendar-server`: **`server-only`** — `createCalendarWriteClient` and `createCalendarRoutes()` (drop-in booking route handler). Secret key; importing this from a client component fails the build.
|
|
500
579
|
- `@aranova/tracking-next/middleware`: `createTrackingMiddleware()`
|
|
501
580
|
- `@aranova/tracking-next/server`: `getTrackingParamsServer()`
|
|
502
581
|
- `@aranova/tracking-next/phone`: isomorphic phone utils (no React)
|
package/dist/blog-server.js
CHANGED
|
@@ -679,6 +679,7 @@ function buildBlogSitemapEntries(posts, opts) {
|
|
|
679
679
|
|
|
680
680
|
// ../tracking-core/src/resources/blog/toc.ts
|
|
681
681
|
var import_github_slugger = __toESM(require("github-slugger"));
|
|
682
|
+
var import_remark_gfm = __toESM(require("remark-gfm"));
|
|
682
683
|
var import_remark_mdx = __toESM(require("remark-mdx"));
|
|
683
684
|
var import_remark_parse = __toESM(require("remark-parse"));
|
|
684
685
|
var import_unified = require("unified");
|
|
@@ -707,7 +708,7 @@ function headingText(node) {
|
|
|
707
708
|
function extractBlogHeadings(mdx) {
|
|
708
709
|
let tree;
|
|
709
710
|
try {
|
|
710
|
-
tree = (0, import_unified.unified)().use(import_remark_parse.default).use(import_remark_mdx.default).parse(mdx);
|
|
711
|
+
tree = (0, import_unified.unified)().use(import_remark_parse.default).use(import_remark_gfm.default).use(import_remark_mdx.default).parse(mdx);
|
|
711
712
|
} catch {
|
|
712
713
|
return [];
|
|
713
714
|
}
|
|
@@ -740,6 +741,7 @@ function estimateReadingTime(mdx) {
|
|
|
740
741
|
}
|
|
741
742
|
|
|
742
743
|
// ../tracking-core/src/resources/blog/validate-mdx.ts
|
|
744
|
+
var import_remark_gfm2 = __toESM(require("remark-gfm"));
|
|
743
745
|
var import_remark_mdx2 = __toESM(require("remark-mdx"));
|
|
744
746
|
var import_remark_parse2 = __toESM(require("remark-parse"));
|
|
745
747
|
var import_unified2 = require("unified");
|
|
@@ -932,7 +934,7 @@ function validateBlogMdx(mdx, options) {
|
|
|
932
934
|
}
|
|
933
935
|
let tree;
|
|
934
936
|
try {
|
|
935
|
-
tree = (0, import_unified2.unified)().use(import_remark_parse2.default).use(import_remark_mdx2.default).parse(mdx);
|
|
937
|
+
tree = (0, import_unified2.unified)().use(import_remark_parse2.default).use(import_remark_gfm2.default).use(import_remark_mdx2.default).parse(mdx);
|
|
936
938
|
} catch (error) {
|
|
937
939
|
const line = error.line;
|
|
938
940
|
return {
|
|
@@ -1008,6 +1010,7 @@ function validateBlogMdx(mdx, options) {
|
|
|
1008
1010
|
// ../tracking-core/src/resources/blog/view/blog-post-view.tsx
|
|
1009
1011
|
var import_rsc = require("next-mdx-remote/rsc");
|
|
1010
1012
|
var import_rehype_slug = __toESM(require("rehype-slug"));
|
|
1013
|
+
var import_remark_gfm3 = __toESM(require("remark-gfm"));
|
|
1011
1014
|
|
|
1012
1015
|
// ../tracking-core/src/resources/blog/view/components.tsx
|
|
1013
1016
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -2019,7 +2022,7 @@ async function BlogPostView({
|
|
|
2019
2022
|
const compiled = await (0, import_rsc.compileMDX)({
|
|
2020
2023
|
source: mdx,
|
|
2021
2024
|
components: merged,
|
|
2022
|
-
options: { mdxOptions: { rehypePlugins: [import_rehype_slug.default] } }
|
|
2025
|
+
options: { mdxOptions: { remarkPlugins: [import_remark_gfm3.default], rehypePlugins: [import_rehype_slug.default] } }
|
|
2023
2026
|
});
|
|
2024
2027
|
content = compiled.content;
|
|
2025
2028
|
} catch {
|