@aranova/tracking-next 0.20.2 → 0.22.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 +12 -0
- package/dist/blog-server.js.map +1 -1
- package/dist/blog-server.mjs +12 -0
- package/dist/blog-server.mjs.map +1 -1
- package/dist/blog.js +7 -0
- package/dist/blog.js.map +1 -1
- package/dist/blog.mjs +7 -0
- 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 +524 -0
- package/dist/calendar.js.map +1 -0
- package/dist/calendar.mjs +464 -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 +62 -5
- package/dist/index.d.ts +62 -5
- package/dist/index.js +566 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +529 -21
- package/dist/index.mjs.map +1 -1
- package/dist/{phone-utils-B2vHJkNz.d.mts → phone-utils-BhWfNuPS.d.mts} +8 -0
- package/dist/{phone-utils-B2vHJkNz.d.ts → phone-utils-BhWfNuPS.d.ts} +8 -0
- package/dist/phone.d.mts +1 -1
- package/dist/phone.d.ts +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-C7tPnqbq.d.ts} +9 -48
- package/dist/{sales-DrH6dY5F.d.ts → sales-H_6bHrL-.d.mts} +9 -48
- package/dist/sales.d.mts +3 -1
- package/dist/sales.d.ts +3 -1
- package/dist/sales.js +29 -17
- package/dist/sales.js.map +1 -1
- package/dist/sales.mjs +29 -17
- package/dist/sales.mjs.map +1 -1
- package/dist/server.d.mts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/transport-C-_rFSR4.d.ts +721 -0
- package/dist/transport-yUF5Wize.d.mts +721 -0
- package/package.json +21 -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
|
@@ -84,6 +84,13 @@ __export(blog_server_exports, {
|
|
|
84
84
|
module.exports = __toCommonJS(blog_server_exports);
|
|
85
85
|
var import_server_only = require("server-only");
|
|
86
86
|
|
|
87
|
+
// ../tracking-core/src/capabilities.ts
|
|
88
|
+
var CAPABILITY_DOM_ATTRIBUTE = "data-aranova-capability";
|
|
89
|
+
var registered = /* @__PURE__ */ new Set();
|
|
90
|
+
function registerCapability(capability) {
|
|
91
|
+
registered.add(capability);
|
|
92
|
+
}
|
|
93
|
+
|
|
87
94
|
// ../tracking-core/src/resources/blog/schema.ts
|
|
88
95
|
var import_zod2 = require("zod");
|
|
89
96
|
|
|
@@ -422,6 +429,7 @@ function parseBlogPostContent(raw) {
|
|
|
422
429
|
|
|
423
430
|
// ../tracking-core/src/resources/blog/client.ts
|
|
424
431
|
function createBlogClient(config) {
|
|
432
|
+
registerCapability("blog_rendering");
|
|
425
433
|
const base = config.cdnBaseUrl.replace(/\/+$/, "");
|
|
426
434
|
const doFetch = (...args) => (config.fetchImpl ?? fetch)(...args);
|
|
427
435
|
async function fetchJson(url, init) {
|
|
@@ -1984,6 +1992,7 @@ var BLOG_BASE_CSS = `/* Aranova blog post base stylesheet \u2014 authored source
|
|
|
1984
1992
|
|
|
1985
1993
|
// ../tracking-core/src/resources/blog/view/blog-post-view.tsx
|
|
1986
1994
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1995
|
+
var CAPABILITY_MARKER = { [CAPABILITY_DOM_ATTRIBUTE]: "blog_rendering" };
|
|
1987
1996
|
async function BlogPostView({
|
|
1988
1997
|
mdx,
|
|
1989
1998
|
theme = BASE_BLOG_THEME,
|
|
@@ -2006,6 +2015,7 @@ async function BlogPostView({
|
|
|
2006
2015
|
className: joinClassNames("aranova-blog-post", classNames?.article),
|
|
2007
2016
|
"data-error": "mdx-validation-failed",
|
|
2008
2017
|
style,
|
|
2018
|
+
...CAPABILITY_MARKER,
|
|
2009
2019
|
children: [
|
|
2010
2020
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: BLOG_BASE_CSS }),
|
|
2011
2021
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { children: [
|
|
@@ -2032,6 +2042,7 @@ async function BlogPostView({
|
|
|
2032
2042
|
className: joinClassNames("aranova-blog-post", classNames?.article),
|
|
2033
2043
|
"data-error": "mdx-render-failed",
|
|
2034
2044
|
style,
|
|
2045
|
+
...CAPABILITY_MARKER,
|
|
2035
2046
|
children: [
|
|
2036
2047
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: BLOG_BASE_CSS }),
|
|
2037
2048
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: "This post could not be displayed." })
|
|
@@ -2045,6 +2056,7 @@ async function BlogPostView({
|
|
|
2045
2056
|
className: joinClassNames("aranova-blog-post", classNames?.article),
|
|
2046
2057
|
"data-motion": motion,
|
|
2047
2058
|
style,
|
|
2059
|
+
...CAPABILITY_MARKER,
|
|
2048
2060
|
children: [
|
|
2049
2061
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: BLOG_BASE_CSS }),
|
|
2050
2062
|
header,
|