@marvalt/digivalt-core 0.2.11 → 0.2.13

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/CHANGELOG.md CHANGED
@@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.13] - 2026-04-20
9
+
10
+ ### Added
11
+ - Build-time Google Reviews export via `generateAllData()` now writes `public/google-reviews-data.json` from the `vibune-google-reviews` endpoint, with optional override env vars `GOOGLE_REVIEWS_API_URL` / `VITE_GOOGLE_REVIEWS_API_URL`.
12
+
13
+ ### Changed
14
+ - Full static generation now fails when Google Reviews fetch fails (same hard-fail behavior as other required generation tasks).
15
+ - Gravity Forms static field normalization now accepts both snake_case and camelCase field keys (`is_required`/`isRequired`, `default_value`/`defaultValue`, etc.) so form schema remains consistent across endpoint variants.
16
+ - Static Gravity Form renderer now supports Gravity Forms `html` fields by rendering field `content` blocks.
17
+
18
+ ## [0.2.12] - 2026-04-13
19
+
20
+ ### Added
21
+ - `GLOBAL-SHORTCODES.md`: consolidated shortcode reference covering DigiValt core form/popup shortcodes (`gf_embed`, `popupbtn_gf`, `popupbtn_mautic`, aliases) plus `@marvalt/shcoder` member/testimonial/event shortcodes and legacy event aliases.
22
+ - `docs/LOVABLE-MASTER-PROMPT.md`: promoted to a tool-agnostic AI master prompt (Cursor / Claude Code / Antigravity / Lovable) for full local WordPress-control scaffolds with explicit AI-vs-human responsibilities and first-run `build` + `dev` expectations.
23
+ - `docs/AI-LOCAL-WORDPRESS-BOOTSTRAP.md`: new local-first runbook with minimum env matrix, first-run commands, artifact checks, and common recovery steps.
24
+ - Template starter fixtures for Lovable-first app bootstraps:
25
+ - `template/public/wordpress-data.json`
26
+ - `template/public/gravity-forms-data.json`
27
+ - `template/src/data/mautic-data.json`
28
+ These placeholder files are safe defaults that prevent first-run runtime failures before real generated exports are available.
29
+ - Cross-links added from package README and `digivalt-landing/DIGIVALT_SETUP.md` to the new unified AI docs.
30
+
8
31
  ## [0.2.11] - 2026-04-03
9
32
 
10
33
  ### Added
package/README.md CHANGED
@@ -57,6 +57,12 @@ When to rerun it:
57
57
 
58
58
  **Sitemap:** Each build regenerates **`public/sitemap-paths.json`** from **`public/sitemap-static-paths.json`** (paths you add for SPA-only routes) plus WordPress menu and CPT links in **`wordpress-data.json`**. See **[docs/SEO-PERFORMANCE.md](./docs/SEO-PERFORMANCE.md)**.
59
59
 
60
+ **Google Reviews static data:** `generateAllData()` also fetches `vibune-google-reviews` and writes **`public/google-reviews-data.json`**. By default it derives the endpoint from `WORDPRESS_API_URL` / `VITE_WORDPRESS_API_URL` and calls `/wp-json/vibune-google-reviews/v1/reviews`. Override with `GOOGLE_REVIEWS_API_URL` / `VITE_GOOGLE_REVIEWS_API_URL` when needed.
61
+
62
+ **AI builders (Cursor / Claude Code / Antigravity / Lovable):**
63
+ - Tool-agnostic master prompt: **[docs/LOVABLE-MASTER-PROMPT.md](./docs/LOVABLE-MASTER-PROMPT.md)**
64
+ - Local-first human runbook: **[docs/AI-LOCAL-WORDPRESS-BOOTSTRAP.md](./docs/AI-LOCAL-WORDPRESS-BOOTSTRAP.md)**
65
+
60
66
  ## Developing this package
61
67
 
62
68
  This repo uses **`.npmrc`** with `legacy-peer-deps=true` so `react-helmet-async` installs cleanly alongside **React 19**-compatible transitive deps during local builds. Consumers of the published package only need to satisfy peers (`react`, `react-dom`, `react-helmet-async`).
@@ -9,6 +9,9 @@ VITE_WORDPRESS_API_URL=https://cms.example.com/wp-json
9
9
  VITE_AUTH_MODE=direct
10
10
  VITE_CLOUDFLARE_WORKER_URL=
11
11
  VITE_LOCAL_DEVELOPMENT=false
12
+ # Optional explicit endpoint for vibune-google-reviews static generation.
13
+ # Defaults to <WORDPRESS_API_URL>/vibune-google-reviews/v1/reviews.
14
+ # VITE_GOOGLE_REVIEWS_API_URL=https://cms.example.com/wp-json/vibune-google-reviews/v1/reviews
12
15
 
13
16
  # Multi-frontend (digivalt-multi-frontends)
14
17
  VITE_FRONTEND_ID=my-app
@@ -4,8 +4,10 @@ export interface GravityFormField {
4
4
  label: string;
5
5
  description?: string;
6
6
  isRequired: boolean;
7
+ cssClass?: string;
7
8
  placeholder?: string;
8
9
  defaultValue?: string;
10
+ content?: string;
9
11
  choices?: Array<{
10
12
  text: string;
11
13
  value: string;
@@ -0,0 +1,5 @@
1
+ interface GenerateGoogleReviewsOptions {
2
+ outputPath?: string;
3
+ }
4
+ export declare function generateGoogleReviewsData(options?: GenerateGoogleReviewsOptions): Promise<boolean>;
5
+ export {};
@@ -2,5 +2,6 @@ export * from './wp';
2
2
  export * from './gf';
3
3
  export * from './mautic';
4
4
  export * from './suitecrm';
5
+ export * from './google-reviews';
5
6
  export * from './sitemap-paths';
6
7
  export declare function generateAllData(): Promise<void>;
@@ -4,6 +4,7 @@ var dotenv = require('dotenv');
4
4
  var path = require('path');
5
5
  var fs = require('fs');
6
6
  var sadapter = require('@marvalt/sadapter');
7
+ var promises = require('fs/promises');
7
8
 
8
9
  /**
9
10
  * @license GPL-3.0-or-later
@@ -2453,6 +2454,92 @@ async function generateSuiteCRMData(options) {
2453
2454
  }
2454
2455
  }
2455
2456
 
2457
+ function trimTrailingSlash(value) {
2458
+ return value.replace(/\/+$/, '');
2459
+ }
2460
+ function resolveEndpointUrl() {
2461
+ const explicit = process.env.GOOGLE_REVIEWS_API_URL ||
2462
+ process.env.VITE_GOOGLE_REVIEWS_API_URL ||
2463
+ '';
2464
+ if (explicit) {
2465
+ return explicit;
2466
+ }
2467
+ const wpApiBase = process.env.WORDPRESS_API_URL ||
2468
+ process.env.VITE_WORDPRESS_API_URL ||
2469
+ '';
2470
+ if (!wpApiBase) {
2471
+ return '';
2472
+ }
2473
+ const normalizedBase = trimTrailingSlash(wpApiBase);
2474
+ if (normalizedBase.endsWith('/wp-json')) {
2475
+ return `${normalizedBase}/vibune-google-reviews/v1/reviews`;
2476
+ }
2477
+ return `${normalizedBase}/wp-json/vibune-google-reviews/v1/reviews`;
2478
+ }
2479
+ function buildHeaders() {
2480
+ const headers = {
2481
+ Accept: 'application/json',
2482
+ };
2483
+ const username = process.env.WP_API_USERNAME || process.env.VITE_WP_API_USERNAME || '';
2484
+ const password = process.env.WP_APP_PASSWORD || process.env.VITE_WP_APP_PASSWORD || '';
2485
+ if (username && password) {
2486
+ headers.Authorization = `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}`;
2487
+ }
2488
+ const cfAccessClientId = process.env.CF_ACCESS_CLIENT_ID || process.env.VITE_CF_ACCESS_CLIENT_ID || '';
2489
+ const cfAccessClientSecret = process.env.CF_ACCESS_CLIENT_SECRET || process.env.VITE_CF_ACCESS_CLIENT_SECRET || '';
2490
+ if (cfAccessClientId && cfAccessClientSecret) {
2491
+ headers['CF-Access-Client-Id'] = cfAccessClientId;
2492
+ headers['CF-Access-Client-Secret'] = cfAccessClientSecret;
2493
+ }
2494
+ return headers;
2495
+ }
2496
+ function hasExpectedShape(payload) {
2497
+ if (!payload || typeof payload !== 'object') {
2498
+ return false;
2499
+ }
2500
+ const obj = payload;
2501
+ return Array.isArray(obj.reviews) && typeof obj.business === 'object' && obj.business !== null;
2502
+ }
2503
+ function truncateBody(body, max = 1200) {
2504
+ if (body.length <= max) {
2505
+ return body;
2506
+ }
2507
+ return `${body.slice(0, max)}...`;
2508
+ }
2509
+ async function generateGoogleReviewsData(options) {
2510
+ const outputPath = options?.outputPath || './public/google-reviews-data.json';
2511
+ const endpointUrl = resolveEndpointUrl();
2512
+ if (!endpointUrl) {
2513
+ console.error('❌ Missing Google Reviews endpoint. Set GOOGLE_REVIEWS_API_URL or VITE_GOOGLE_REVIEWS_API_URL, or configure WORDPRESS_API_URL/VITE_WORDPRESS_API_URL.');
2514
+ return false;
2515
+ }
2516
+ try {
2517
+ const response = await fetch(endpointUrl, {
2518
+ method: 'GET',
2519
+ headers: buildHeaders(),
2520
+ });
2521
+ if (!response.ok) {
2522
+ const body = truncateBody(await response.text());
2523
+ console.error(`❌ Google Reviews generation failed (HTTP ${response.status}): ${body}`);
2524
+ return false;
2525
+ }
2526
+ const payload = (await response.json());
2527
+ if (!hasExpectedShape(payload)) {
2528
+ console.error('❌ Google Reviews generation failed: endpoint returned unexpected payload shape.');
2529
+ return false;
2530
+ }
2531
+ const outputFilePath = path.join(process.cwd(), outputPath);
2532
+ await promises.mkdir(path.dirname(outputFilePath), { recursive: true });
2533
+ await promises.writeFile(outputFilePath, `${JSON.stringify(payload, null, 2)}\n`, 'utf-8');
2534
+ console.log(`📁 Google Reviews data written to: ${outputFilePath}`);
2535
+ return true;
2536
+ }
2537
+ catch (e) {
2538
+ console.error('❌ Google Reviews generation failed:', e.message);
2539
+ return false;
2540
+ }
2541
+ }
2542
+
2456
2543
  const SITEMAP_SKIP_TOP_LEVEL_KEYS = new Set([
2457
2544
  'config',
2458
2545
  'site_settings',
@@ -2676,7 +2763,8 @@ async function generateAllData() {
2676
2763
  const gfSuccess = await generateGravityFormsData();
2677
2764
  const mauticSuccess = await generateMauticData();
2678
2765
  const suitecrmSuccess = await generateSuiteCRMData();
2679
- if (!wpSuccess || !gfSuccess || !mauticSuccess || !suitecrmSuccess) {
2766
+ const googleReviewsSuccess = await generateGoogleReviewsData();
2767
+ if (!wpSuccess || !gfSuccess || !mauticSuccess || !suitecrmSuccess || !googleReviewsSuccess) {
2680
2768
  console.error('❌ Some generation tasks failed. See above for details.');
2681
2769
  process.exit(1);
2682
2770
  }
@@ -2685,6 +2773,7 @@ async function generateAllData() {
2685
2773
  }
2686
2774
 
2687
2775
  exports.generateAllData = generateAllData;
2776
+ exports.generateGoogleReviewsData = generateGoogleReviewsData;
2688
2777
  exports.generateGravityFormsData = generateGravityFormsData;
2689
2778
  exports.generateMauticData = generateMauticData;
2690
2779
  exports.generateSitemapPaths = generateSitemapPaths;