@oneclick.dev/cms-core-modules 0.0.74 → 0.0.76
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/{Overview-B8OF-JJr.mjs → Overview-CuCQgqVp.mjs} +1 -1
- package/dist/{Overview-DSU1Nh7B.js → Overview-pCO_47Zt.js} +1 -1
- package/dist/{SeoHealth-DG004AsJ.mjs → SeoHealth-CC0rW1AG.mjs} +1 -1
- package/dist/{SeoHealth-BqlYiSCj.js → SeoHealth-EZzDmPDM.js} +1 -1
- package/dist/{TableView-fYC7kB6j.mjs → TableView-Ccp2Vkhr.mjs} +5171 -5170
- package/dist/{TableView-CU0a9ih2.js → TableView-DD3y_PZ3.js} +35 -35
- package/dist/{index-O_QNuTdG.js → index-DTzdHh6g.js} +2 -2
- package/dist/index-DYpruS-A-CA2jEOA3.js +88 -0
- package/dist/{index-N6w5-hDF-6k_ELHYC.mjs → index-DYpruS-A-D38FBcI3.mjs} +141 -141
- package/dist/{index-D2DYuz8R.mjs → index-N0NoDEsI.mjs} +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.mjs +4 -4
- package/dist/server-handlers.cjs.js +1 -0
- package/dist/server-handlers.mjs +898 -0
- package/package.json +8 -6
- package/dist/index-N6w5-hDF-DCuxwPBX.js +0 -88
- package/src/appointments/server.ts +0 -195
- package/src/googleAnalytics/server.ts +0 -1188
- package/src/products/server.ts +0 -146
- package/src/server-handlers.ts +0 -10
|
@@ -3,7 +3,7 @@ import { useModuleRoute as ye, useModule as be, useFirebaseIntegration as _e, us
|
|
|
3
3
|
import { Layers as ge, ChevronDown as Fe, ChevronLeft as We, ChevronRight as Ge, Users as ke, RefreshCw as He, Search as Ue, X as qe, Clock as Ye, Calendar as Xe } from "lucide-vue-next";
|
|
4
4
|
import { _ as Qe } from "./EditLayout.vue_vue_type_script_setup_true_lang-CcysXzmW.mjs";
|
|
5
5
|
import { h as fe, t as Je, s as Ke, M as re, a3 as he, a4 as Ze, J as Se, _ as De, y as le, P as Ce, a5 as et, a6 as tt, a7 as st, q as at, j as ot, R as nt, Q as rt, Z as lt } from "./index-CMk3uhUt.mjs";
|
|
6
|
-
import { g as we, h as $e } from "./index-
|
|
6
|
+
import { g as we, h as $e } from "./index-DYpruS-A-D38FBcI3.mjs";
|
|
7
7
|
import { a as it } from "./index-B-lVEpFX.mjs";
|
|
8
8
|
import { X as ct, O as Ie, a as dt, b as ut, r as mt, D as de, S as Me, C as ue, z as Ve, A as Re } from "./index-_2lRVt_k.mjs";
|
|
9
9
|
import { F as pt, _ as vt } from "./ReservationDetailDialog.vue_vue_type_script_setup_true_lang-B7ks5mbf.mjs";
|
package/dist/index.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@oneclick.dev/cms-kit"),t={name:"Table",description:"Manage tables and structured data.",icon:"mdi-table",version:"1.0.0"},o=e.defineModuleConfig({getItems:{label:"Fetch items",type:"flow"},viewable:{label:"Viewable",type:"checkbox",default:!1},editable:{label:"Editable",type:"checkbox",default:!1},deletable:{label:"Deletable",type:"checkbox",default:!1},addable:{label:"Addable",type:"checkbox",default:!1},searchable:{label:"Searchable",type:"checkbox",default:!1},downloadable:{label:"Downloadable",type:"checkbox",default:!1},allowBulkActions:{label:"Allow Bulk Actions",type:"checkbox",default:!1}}),r=[{path:"",component:()=>Promise.resolve().then(()=>require("./TableView-CU0a9ih2.js"))}],n=[],i={component:()=>Promise.resolve().then(()=>require("./index-DFQGVHTs.js")),metadata:t,config:o,routes:r,permissions:n},a={name:"Products",description:"Manage products",icon:"mdi-table",version:"1.0.0"},s=e.defineModuleConfig({project:{label:"Database",type:"resource",accept:["FIREBASE"]},productCollection:{label:"Product Collection",type:"input",default:"products"},collectionsCollection:{label:"Collections Collection",type:"input",default:"public/e-commerce:collections"},allowedMediaSources:{label:"Allowed Media Sources",type:"mediaSource",multiple:!0},defaultUploadMediaSource:{label:"Default Upload Media Source",type:"mediaSource",multiple:!1},previewUrl:{label:"Preview URL",type:"input",default:"https://preview.com/shop/{{slug}}"}}),c=[{path:"",component:()=>Promise.resolve().then(()=>require("./Overview-B-8TLLjh.js"))},{path:"/:productId",component:()=>Promise.resolve().then(()=>require("./Detail-BcboL7NF.js"))},{path:"/new",component:()=>Promise.resolve().then(()=>require("./Detail-BcboL7NF.js"))}],p=[{key:"create-product",name:"Create product",description:"Team member can create a new product"},{key:"edit-product",name:"Edit product",description:"Team member can edit a product"},{key:"delete-product",name:"Delete product",description:"Team member can delete a product"}],l=[{name:"getEmptyStock",description:"Get a list of products with empty stock.",executionMode:"api",parameters:{type:"object",properties:{category:{type:"string",description:"Category of the product"}},required:["category"]}},{name:"viewProductDetails",description:"Show a card in chat with details of a product based on product ID.",executionMode:"component",chatComponent:"ProductDetailsCard",parameters:{type:"object",properties:{productId:{type:"string",description:"ID of the product"}},required:["productId"]}}],d={component:()=>Promise.resolve().then(()=>require("./index-R2oUDsjx.js")),metadata:a,config:s,routes:c,permissions:p,tools:l,chatComponents:{ProductDetailsCard:()=>Promise.resolve().then(()=>require("./ProductDetailsCard-BwktdlIf.js"))}},m={name:"Custom",description:"Custom module",icon:"mdi-table",version:"1.0.0"},u=e.defineModuleConfig({formLayout:{label:"Design View",type:"form"}}),h=[{path:"",component:()=>Promise.resolve().then(()=>require("./View-DfzaVOzS.js"))}],f=[],g={component:()=>Promise.resolve().then(()=>require("./index-CSxYBeVA.js")),metadata:m,config:u,routes:h,permissions:f},y={name:"Promo Codes",description:"Create and manage promo codes",icon:"mdi-table",version:"1.0.0"},b=e.defineModuleConfig({project:{label:"Project",type:"resource",accept:["FIREBASE"]},promoCodeCollection:{label:"Promo Code Collection",type:"input",default:"promo-codes"}}),v=[{path:"",component:()=>Promise.resolve().then(()=>require("./Create-CRn2sMHp.js"))},{path:"/promo-codes",component:()=>Promise.resolve().then(()=>require("./Find-Ds6OvuH6.js"))},{path:"/promo-codes/:promoCodeId",component:()=>Promise.resolve().then(()=>require("./Detail-Bxi7lG9x.js"))}],C=[{key:"create-promo-codes",name:"Create promo codes",description:"Team member can create promo codes"},{key:"view-promo-codes",name:"View promo codes",description:"Team member can view promo codes"},{key:"delete-promo-codes",name:"Delete promo codes",description:"Team member can delete promo codes"}],w={component:()=>Promise.resolve().then(()=>require("./index-CkiNvRzs.js")),metadata:y,config:b,routes:v,permissions:C},P={name:"Product Collections",description:"Manage product collections",icon:"mdi-table",version:"1.0.0"},q=e.defineModuleConfig({project:{label:"Project",type:"resource",accept:["FIREBASE"]},collectionsCollection:{label:"Collections Collection",type:"input",default:"public/e-commerce:collections"},allowedMediaSources:{label:"Allowed Media Sources",type:"mediaSource",multiple:!0},defaultUploadMediaSource:{label:"Default Upload Media Source",type:"mediaSource",multiple:!1}}),D=[{path:"",component:()=>Promise.resolve().then(()=>require("./Overview-T-lsy3UZ.js"))},{path:"/:collectionId",component:()=>Promise.resolve().then(()=>require("./Detail-CnK-qbhE.js"))},{path:"/new",component:()=>Promise.resolve().then(()=>require("./Detail-CnK-qbhE.js"))}],S=[{key:"create-collection",name:"Create product collection",description:"Team member can create a new product collection"},{key:"edit-collection",name:"Edit product collection",description:"Team member can edit a product collection"},{key:"delete-collection",name:"Delete product collection",description:"Team member can delete a product collection"}],k={component:()=>Promise.resolve().then(()=>require("./index-CwqrAU-H.js")),metadata:P,config:q,routes:D,permissions:S},M={name:"Shipping Options",description:"Manage shipping options",icon:"mdi-table",version:"1.0.0"},A=e.defineModuleConfig({project:{label:"Project",type:"resource",accept:["FIREBASE"]},shippingOptionsCollection:{label:"Shipping Options Collection",type:"input",default:"public/e-commerce:shipping-options"}}),$=[{path:"",component:()=>Promise.resolve().then(()=>require("./Overview-BbvfH1u-.js"))},{path:"/:optionId",component:()=>Promise.resolve().then(()=>require("./Detail-BayNaAg9.js"))},{path:"/new",component:()=>Promise.resolve().then(()=>require("./Detail-BayNaAg9.js"))}],T=[{key:"create-option",name:"Create shipping option",description:"Team member can create a new shipping option"},{key:"edit-option",name:"Edit shipping option",description:"Team member can edit a shipping option"},{key:"delete-option",name:"Delete shipping option",description:"Team member can delete a shipping option"}],x={component:()=>Promise.resolve().then(()=>require("./index-Co4ON2Di.js")),metadata:M,config:A,routes:$,permissions:T},E={name:"Google Analytics",description:"Configure Google Analytics settings.",icon:"mdi-google-analytics",version:"1.0.0"},I=e.defineModuleConfig({serviceAccount:{label:"Google Service Account",type:"resource",accept:["GOOGLE_SERVICE_ACCOUNT"]},propertyId:{label:"GA4 Property ID",type:"input",default:""},siteUrl:{label:"Search Console Site URL",type:"input",default:"",placeholder:"https://example.com or sc-domain:example.com",description:"Optional. When set, the module will fetch real keyword data from Google Search Console. Use the same site URL format as shown in Search Console."}}),j=[{path:"",component:()=>Promise.resolve().then(()=>require("./Overview-DSU1Nh7B.js"))},{path:"/acquisition",component:()=>Promise.resolve().then(()=>require("./Acquisition-_-cq972V.js"))},{path:"/content",component:()=>Promise.resolve().then(()=>require("./Content-C-4Cdniz.js"))},{path:"/audience",component:()=>Promise.resolve().then(()=>require("./Audience-QnFQs93n.js"))},{path:"/seo",component:()=>Promise.resolve().then(()=>require("./SeoHealth-BqlYiSCj.js"))}],U=[],Y=[{name:"getTopPages",description:"Show a card in chat with the most popular/visited pages on the website for a given period.",executionMode:"component",chatComponent:"TopPagesCard",parameters:{type:"object",properties:{startDate:{type:"string",description:"Start date for the report. Use relative formats like 'yesterday', '7daysAgo', '30daysAgo', '90daysAgo', '365daysAgo' or exact dates 'YYYY-MM-DD'. Default: '30daysAgo'"},endDate:{type:"string",description:"End date for the report. Use 'today', 'yesterday', or exact dates 'YYYY-MM-DD'. Default: 'today'"},limit:{type:"number",description:"Number of pages to show. Default: 10, max: 50",default:10}},required:[]}},{name:"getVisitorStats",description:"Show a card in chat with visitor/traffic statistics (sessions, users, page views, bounce rate, etc.) for a given period. Use this when the user asks about traffic, visitors, how many people visited, etc.",executionMode:"component",chatComponent:"VisitorStatsCard",parameters:{type:"object",properties:{startDate:{type:"string",description:"Start date for the report. Use 'yesterday' for yesterday, '7daysAgo' for last week, '30daysAgo' for last month, '90daysAgo' for last quarter, '365daysAgo' for last year, or exact 'YYYY-MM-DD'. Default: '30daysAgo'"},endDate:{type:"string",description:"End date for the report. Use 'today', 'yesterday', or exact 'YYYY-MM-DD'. Default: 'today'"}},required:[]}},{name:"getSearchTerms",description:"Show a card in chat with search terms/keywords that bring visitors to the website. Use this when the user asks about keywords, SEO terms, what people search for, or search queries.",executionMode:"component",chatComponent:"SearchTermsCard",parameters:{type:"object",properties:{startDate:{type:"string",description:"Start date for the report. Default: '30daysAgo'"},endDate:{type:"string",description:"End date for the report. Default: 'today'"}},required:[]}},{name:"getTrafficSources",description:"Show a card in chat with where website visitors are coming from (traffic sources, channels, referrals). Use this when the user asks about traffic sources, where visitors come from, referrals, channels, etc.",executionMode:"component",chatComponent:"TrafficSourcesCard",parameters:{type:"object",properties:{startDate:{type:"string",description:"Start date for the report. Default: '30daysAgo'"},endDate:{type:"string",description:"End date for the report. Default: 'today'"}},required:[]}},{name:"getRealtimeVisitors",description:"Show a card in chat with the current real-time active visitors on the website right now.",executionMode:"component",chatComponent:"RealtimeCard",parameters:{type:"object",properties:{},required:[]}},{name:"getCountryBreakdown",description:"Show a card in chat with a geographic breakdown of where website visitors are located. Use this when the user asks about visitor countries, geographic distribution, or where their audience is from.",executionMode:"component",chatComponent:"CountryBreakdownCard",parameters:{type:"object",properties:{startDate:{type:"string",description:"Start date for the report. Default: '30daysAgo'"},endDate:{type:"string",description:"End date for the report. Default: 'today'"}},required:[]}},{name:"getDeviceBreakdown",description:"Show a card in chat with a device breakdown (desktop, mobile, tablet) of website visitors. Use this when the user asks about what devices people use, mobile vs desktop traffic, or if their site is mobile-friendly.",executionMode:"component",chatComponent:"DeviceBreakdownCard",parameters:{type:"object",properties:{startDate:{type:"string",description:"Start date for the report. Default: '30daysAgo'"},endDate:{type:"string",description:"End date for the report. Default: 'today'"}},required:[]}},{name:"getPeakHours",description:"Show a card in chat with peak traffic hours and a weekly heatmap showing when visitors are most active. Use this when the user asks about best times to post, peak hours, busiest times, or when their audience is online.",executionMode:"component",chatComponent:"PeakHoursCard",parameters:{type:"object",properties:{startDate:{type:"string",description:"Start date for the report. Default: '30daysAgo'"},endDate:{type:"string",description:"End date for the report. Default: 'today'"}},required:[]}}],R={component:()=>Promise.resolve().then(()=>require("./index-DwHYfZl_.js")),metadata:E,config:I,routes:j,permissions:U,tools:Y,chatComponents:{TopPagesCard:()=>Promise.resolve().then(()=>require("./TopPagesCard-pZ-nAsaI.js")),VisitorStatsCard:()=>Promise.resolve().then(()=>require("./VisitorStatsCard-tApB_7v8.js")),SearchTermsCard:()=>Promise.resolve().then(()=>require("./SearchTermsCard-DGRbo5ZP.js")),TrafficSourcesCard:()=>Promise.resolve().then(()=>require("./TrafficSourcesCard-CBOPV1J1.js")),RealtimeCard:()=>Promise.resolve().then(()=>require("./RealtimeCard-CxtqQHee.js")),CountryBreakdownCard:()=>Promise.resolve().then(()=>require("./CountryBreakdownCard-BUfJ-umQ.js")),DeviceBreakdownCard:()=>Promise.resolve().then(()=>require("./DeviceBreakdownCard-CsoK6JUO.js")),PeakHoursCard:()=>Promise.resolve().then(()=>require("./PeakHoursCard-BNl_U1r_.js"))}},B={name:"Content Manager",description:"Create and manage content",icon:"mdi-table",version:"1.0.0"},O=e.defineModuleConfig({project:{label:"Database",type:"resource",accept:["FIREBASE"]},domain:{label:"Domain",type:"input",default:"https://domain.com"},collectionsCollection:{label:"Collections Collection",type:"input",default:"content_collections"},contentCollection:{label:"Content Collection",type:"input",default:"content"},allowedMediaSources:{label:"Allowed Media Sources",type:"mediaSource",multiple:!0},defaultUploadMediaSource:{label:"Default Upload Media Source",type:"mediaSource",multiple:!1},supportedLanguages:{label:"Supported Languages",type:"select",predefinedOptions:"languages",multiple:!0},defaultLanguage:{label:"Default Language",type:"select",predefinedOptions:"languages"}}),L=[{path:"",component:()=>Promise.resolve().then(()=>require("./Overview-CwCAeBnX.js"))},{path:"/collections",component:()=>Promise.resolve().then(()=>require("./Overview-CwCAeBnX.js"))},{path:"/collections/:collectionId",component:()=>Promise.resolve().then(()=>require("./Entries-BPkZ7Jg5.js"))},{path:"/collections/:collectionId/:entryId",component:()=>Promise.resolve().then(()=>require("./ContentEditor-3JFlC9N1.js"))},{path:"/components",component:()=>Promise.resolve().then(()=>require("./Components-DXbx0RLV.js"))},{path:"/global-styling",component:()=>Promise.resolve().then(()=>require("./GlobalStyling-CnSlXkZc.js"))}],G=[{key:"create-content",name:"Create content",description:"Team member can create content"},{key:"edit-content",name:"Edit content",description:"Team member can edit content"},{key:"delete-content",name:"Delete content",description:"Team member can delete content"}],F={component:()=>Promise.resolve().then(()=>require("./index-UtjLbLw-.js")),metadata:B,config:O,routes:L,permissions:G},V={name:"Mail Templates",description:"Build templates for your transactional emails.",icon:"mdi-table",version:"1.0.0"},N=e.defineModuleConfig({project:{label:"Project",type:"resource",accept:["FIREBASE"]},templateCollection:{label:"Mail Templates Collection",type:"input",default:"mail-templates"}}),_=[{path:"",component:()=>Promise.resolve().then(()=>require("./Overview-BDlBCUI_.js"))},{path:"/:optionId",component:()=>Promise.resolve().then(()=>require("./Detail-mvSGbnFU.js"))},{path:"/new",component:()=>Promise.resolve().then(()=>require("./Detail-mvSGbnFU.js"))}],H=[{key:"create-template",name:"Create mail template",description:"Team member can create a new mail template"},{key:"edit-template",name:"Edit mail template",description:"Team member can edit a mail template"},{key:"delete-template",name:"Delete mail template",description:"Team member can delete a mail template"}],K={component:()=>Promise.resolve().then(()=>require("./index-Cz-baGax.js")),metadata:V,config:N,routes:_,permissions:H},W={name:"Appointments",description:"Create and manage agendas for booking appointments.",icon:"mdi-table",version:"1.0.0"},z=e.defineModuleConfig({project:{label:"Project",type:"resource",accept:["FIREBASE"]},mailAccount:{label:"Mail account",type:"resource",accept:["GMAIL"]},agendaCollection:{label:"Agenda Collection",type:"input",default:"agendas"},reservationsCollection:{label:"Reservations Collection",type:"input",default:"bookings_orders"},reservedSpotsCollection:{label:"Reserved Spots Collection",type:"input",default:"reserved_spots"}}),J=[{path:"",component:()=>Promise.resolve().then(()=>require("./Overview-t0pG5xjA.js"))},{path:"/create",component:()=>Promise.resolve().then(()=>require("./index-D2a6wEPh.js"))},{path:"/create/regular",component:()=>Promise.resolve().then(()=>require("./regular-1LXNPviB.js"))},{path:"/edit/:id",component:()=>Promise.resolve().then(()=>require("./index-O_QNuTdG.js"))},{path:"/edit/:id/agenda",component:()=>Promise.resolve().then(()=>require("./agenda-wNFDKn0G.js"))},{path:"/edit/:id/regular-slots",component:()=>Promise.resolve().then(()=>require("./regular-slots-Bs3WJB3U.js"))},{path:"/edit/:id/exceptions",component:()=>Promise.resolve().then(()=>require("./exceptions-wEQEVzIs.js"))},{path:"/edit/:id/availability",component:()=>Promise.resolve().then(()=>require("./availability-BiBbzEIM.js"))},{path:"/edit/:id/payment",component:()=>Promise.resolve().then(()=>require("./payment-BQaAqQ5q.js"))},{path:"/edit/:id/resources",component:()=>Promise.resolve().then(()=>require("./resources-eb0pivDL.js"))},{path:"/edit/:id/orders",component:()=>Promise.resolve().then(()=>require("./orders-D5GJOZXN.js"))}],Q=[{key:"create-agendas",name:"Create agendas",description:"Team member can create agendas"},{key:"edit-agendas",name:"Edit agendas",description:"Team member can edit agendas"},{key:"delete-agendas",name:"Delete agendas",description:"Team member can delete agendas"},{key:"manage-reservations",name:"Manage reservations",description:"Team member can create, edit, and delete reservations"}],X=[{name:"findAppointment",description:"Show a card in chat with details of an appointment/booking/reservation/...",executionMode:"component",chatComponent:"AppointmentDetailsCard",parameters:{type:"object",properties:{name:{type:"string",description:"Name of the booker"},email:{type:"string",description:"Email of the booker"},date:{type:"string",description:"Date of the appointment (YYYY-MM-DD)"}},required:["date"]}},{name:"getRecentAppointments",description:"Show a table in chat with recent appointments, default loading the latest 20 appointments.",executionMode:"component",chatComponent:"AppointmentListTable",parameters:{type:"object",properties:{quantity:{type:"number",description:"Number of appointments to load. default: 20 max: 100",default:20}},required:["quantity"]}},{name:"changeAppointmentDetails",description:"Show a card in chat where user can edit name, email and date of an existing appointment.",executionMode:"component",chatComponent:"AppointmentEditor",parameters:{type:"object",properties:{orderId:{type:"string",description:"ID of the order / appointment. This is NOT the reservation ID."}},required:["orderId"]}}],Z={component:()=>Promise.resolve().then(()=>require("./index-9HVlmvK3.js")),metadata:W,config:z,routes:J,permissions:Q,tools:X,chatComponents:{AppointmentDetailsCard:()=>Promise.resolve().then(()=>require("./AppointmentDetailsCard-CtK0Cj_O.js")),AppointmentListTable:()=>Promise.resolve().then(()=>require("./AppointmentListTable-CQ3uXfa8.js")),AppointmentEditor:()=>Promise.resolve().then(()=>require("./AppointmentEditor-CaTfbkIf.js"))}};exports.appointments=Z;exports.contentManager=F;exports.custom=g;exports.googleAnalytics=R;exports.mailTemplates=K;exports.productCollections=k;exports.products=d;exports.promoCodes=w;exports.shippingOptions=x;exports.table=i;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@oneclick.dev/cms-kit"),t={name:"Table",description:"Manage tables and structured data.",icon:"mdi-table",version:"1.0.0"},o=e.defineModuleConfig({getItems:{label:"Fetch items",type:"flow"},viewable:{label:"Viewable",type:"checkbox",default:!1},editable:{label:"Editable",type:"checkbox",default:!1},deletable:{label:"Deletable",type:"checkbox",default:!1},addable:{label:"Addable",type:"checkbox",default:!1},searchable:{label:"Searchable",type:"checkbox",default:!1},downloadable:{label:"Downloadable",type:"checkbox",default:!1},allowBulkActions:{label:"Allow Bulk Actions",type:"checkbox",default:!1}}),r=[{path:"",component:()=>Promise.resolve().then(()=>require("./TableView-DD3y_PZ3.js"))}],n=[],i={component:()=>Promise.resolve().then(()=>require("./index-DFQGVHTs.js")),metadata:t,config:o,routes:r,permissions:n},a={name:"Products",description:"Manage products",icon:"mdi-table",version:"1.0.0"},s=e.defineModuleConfig({project:{label:"Database",type:"resource",accept:["FIREBASE"]},productCollection:{label:"Product Collection",type:"input",default:"products"},collectionsCollection:{label:"Collections Collection",type:"input",default:"public/e-commerce:collections"},allowedMediaSources:{label:"Allowed Media Sources",type:"mediaSource",multiple:!0},defaultUploadMediaSource:{label:"Default Upload Media Source",type:"mediaSource",multiple:!1},previewUrl:{label:"Preview URL",type:"input",default:"https://preview.com/shop/{{slug}}"}}),c=[{path:"",component:()=>Promise.resolve().then(()=>require("./Overview-B-8TLLjh.js"))},{path:"/:productId",component:()=>Promise.resolve().then(()=>require("./Detail-BcboL7NF.js"))},{path:"/new",component:()=>Promise.resolve().then(()=>require("./Detail-BcboL7NF.js"))}],p=[{key:"create-product",name:"Create product",description:"Team member can create a new product"},{key:"edit-product",name:"Edit product",description:"Team member can edit a product"},{key:"delete-product",name:"Delete product",description:"Team member can delete a product"}],l=[{name:"getEmptyStock",description:"Get a list of products with empty stock.",executionMode:"api",parameters:{type:"object",properties:{category:{type:"string",description:"Category of the product"}},required:["category"]}},{name:"viewProductDetails",description:"Show a card in chat with details of a product based on product ID.",executionMode:"component",chatComponent:"ProductDetailsCard",parameters:{type:"object",properties:{productId:{type:"string",description:"ID of the product"}},required:["productId"]}}],d={component:()=>Promise.resolve().then(()=>require("./index-R2oUDsjx.js")),metadata:a,config:s,routes:c,permissions:p,tools:l,chatComponents:{ProductDetailsCard:()=>Promise.resolve().then(()=>require("./ProductDetailsCard-BwktdlIf.js"))}},m={name:"Custom",description:"Custom module",icon:"mdi-table",version:"1.0.0"},u=e.defineModuleConfig({formLayout:{label:"Design View",type:"form"}}),h=[{path:"",component:()=>Promise.resolve().then(()=>require("./View-DfzaVOzS.js"))}],f=[],g={component:()=>Promise.resolve().then(()=>require("./index-CSxYBeVA.js")),metadata:m,config:u,routes:h,permissions:f},y={name:"Promo Codes",description:"Create and manage promo codes",icon:"mdi-table",version:"1.0.0"},b=e.defineModuleConfig({project:{label:"Project",type:"resource",accept:["FIREBASE"]},promoCodeCollection:{label:"Promo Code Collection",type:"input",default:"promo-codes"}}),v=[{path:"",component:()=>Promise.resolve().then(()=>require("./Create-CRn2sMHp.js"))},{path:"/promo-codes",component:()=>Promise.resolve().then(()=>require("./Find-Ds6OvuH6.js"))},{path:"/promo-codes/:promoCodeId",component:()=>Promise.resolve().then(()=>require("./Detail-Bxi7lG9x.js"))}],C=[{key:"create-promo-codes",name:"Create promo codes",description:"Team member can create promo codes"},{key:"view-promo-codes",name:"View promo codes",description:"Team member can view promo codes"},{key:"delete-promo-codes",name:"Delete promo codes",description:"Team member can delete promo codes"}],w={component:()=>Promise.resolve().then(()=>require("./index-CkiNvRzs.js")),metadata:y,config:b,routes:v,permissions:C},P={name:"Product Collections",description:"Manage product collections",icon:"mdi-table",version:"1.0.0"},q=e.defineModuleConfig({project:{label:"Project",type:"resource",accept:["FIREBASE"]},collectionsCollection:{label:"Collections Collection",type:"input",default:"public/e-commerce:collections"},allowedMediaSources:{label:"Allowed Media Sources",type:"mediaSource",multiple:!0},defaultUploadMediaSource:{label:"Default Upload Media Source",type:"mediaSource",multiple:!1}}),D=[{path:"",component:()=>Promise.resolve().then(()=>require("./Overview-T-lsy3UZ.js"))},{path:"/:collectionId",component:()=>Promise.resolve().then(()=>require("./Detail-CnK-qbhE.js"))},{path:"/new",component:()=>Promise.resolve().then(()=>require("./Detail-CnK-qbhE.js"))}],S=[{key:"create-collection",name:"Create product collection",description:"Team member can create a new product collection"},{key:"edit-collection",name:"Edit product collection",description:"Team member can edit a product collection"},{key:"delete-collection",name:"Delete product collection",description:"Team member can delete a product collection"}],k={component:()=>Promise.resolve().then(()=>require("./index-CwqrAU-H.js")),metadata:P,config:q,routes:D,permissions:S},M={name:"Shipping Options",description:"Manage shipping options",icon:"mdi-table",version:"1.0.0"},A=e.defineModuleConfig({project:{label:"Project",type:"resource",accept:["FIREBASE"]},shippingOptionsCollection:{label:"Shipping Options Collection",type:"input",default:"public/e-commerce:shipping-options"}}),$=[{path:"",component:()=>Promise.resolve().then(()=>require("./Overview-BbvfH1u-.js"))},{path:"/:optionId",component:()=>Promise.resolve().then(()=>require("./Detail-BayNaAg9.js"))},{path:"/new",component:()=>Promise.resolve().then(()=>require("./Detail-BayNaAg9.js"))}],T=[{key:"create-option",name:"Create shipping option",description:"Team member can create a new shipping option"},{key:"edit-option",name:"Edit shipping option",description:"Team member can edit a shipping option"},{key:"delete-option",name:"Delete shipping option",description:"Team member can delete a shipping option"}],x={component:()=>Promise.resolve().then(()=>require("./index-Co4ON2Di.js")),metadata:M,config:A,routes:$,permissions:T},E={name:"Google Analytics",description:"Configure Google Analytics settings.",icon:"mdi-google-analytics",version:"1.0.0"},I=e.defineModuleConfig({serviceAccount:{label:"Google Service Account",type:"resource",accept:["GOOGLE_SERVICE_ACCOUNT"]},propertyId:{label:"GA4 Property ID",type:"input",default:""},siteUrl:{label:"Search Console Site URL",type:"input",default:"",placeholder:"https://example.com or sc-domain:example.com",description:"Optional. When set, the module will fetch real keyword data from Google Search Console. Use the same site URL format as shown in Search Console."}}),j=[{path:"",component:()=>Promise.resolve().then(()=>require("./Overview-pCO_47Zt.js"))},{path:"/acquisition",component:()=>Promise.resolve().then(()=>require("./Acquisition-_-cq972V.js"))},{path:"/content",component:()=>Promise.resolve().then(()=>require("./Content-C-4Cdniz.js"))},{path:"/audience",component:()=>Promise.resolve().then(()=>require("./Audience-QnFQs93n.js"))},{path:"/seo",component:()=>Promise.resolve().then(()=>require("./SeoHealth-EZzDmPDM.js"))}],U=[],Y=[{name:"getTopPages",description:"Show a card in chat with the most popular/visited pages on the website for a given period.",executionMode:"component",chatComponent:"TopPagesCard",parameters:{type:"object",properties:{startDate:{type:"string",description:"Start date for the report. Use relative formats like 'yesterday', '7daysAgo', '30daysAgo', '90daysAgo', '365daysAgo' or exact dates 'YYYY-MM-DD'. Default: '30daysAgo'"},endDate:{type:"string",description:"End date for the report. Use 'today', 'yesterday', or exact dates 'YYYY-MM-DD'. Default: 'today'"},limit:{type:"number",description:"Number of pages to show. Default: 10, max: 50",default:10}},required:[]}},{name:"getVisitorStats",description:"Show a card in chat with visitor/traffic statistics (sessions, users, page views, bounce rate, etc.) for a given period. Use this when the user asks about traffic, visitors, how many people visited, etc.",executionMode:"component",chatComponent:"VisitorStatsCard",parameters:{type:"object",properties:{startDate:{type:"string",description:"Start date for the report. Use 'yesterday' for yesterday, '7daysAgo' for last week, '30daysAgo' for last month, '90daysAgo' for last quarter, '365daysAgo' for last year, or exact 'YYYY-MM-DD'. Default: '30daysAgo'"},endDate:{type:"string",description:"End date for the report. Use 'today', 'yesterday', or exact 'YYYY-MM-DD'. Default: 'today'"}},required:[]}},{name:"getSearchTerms",description:"Show a card in chat with search terms/keywords that bring visitors to the website. Use this when the user asks about keywords, SEO terms, what people search for, or search queries.",executionMode:"component",chatComponent:"SearchTermsCard",parameters:{type:"object",properties:{startDate:{type:"string",description:"Start date for the report. Default: '30daysAgo'"},endDate:{type:"string",description:"End date for the report. Default: 'today'"}},required:[]}},{name:"getTrafficSources",description:"Show a card in chat with where website visitors are coming from (traffic sources, channels, referrals). Use this when the user asks about traffic sources, where visitors come from, referrals, channels, etc.",executionMode:"component",chatComponent:"TrafficSourcesCard",parameters:{type:"object",properties:{startDate:{type:"string",description:"Start date for the report. Default: '30daysAgo'"},endDate:{type:"string",description:"End date for the report. Default: 'today'"}},required:[]}},{name:"getRealtimeVisitors",description:"Show a card in chat with the current real-time active visitors on the website right now.",executionMode:"component",chatComponent:"RealtimeCard",parameters:{type:"object",properties:{},required:[]}},{name:"getCountryBreakdown",description:"Show a card in chat with a geographic breakdown of where website visitors are located. Use this when the user asks about visitor countries, geographic distribution, or where their audience is from.",executionMode:"component",chatComponent:"CountryBreakdownCard",parameters:{type:"object",properties:{startDate:{type:"string",description:"Start date for the report. Default: '30daysAgo'"},endDate:{type:"string",description:"End date for the report. Default: 'today'"}},required:[]}},{name:"getDeviceBreakdown",description:"Show a card in chat with a device breakdown (desktop, mobile, tablet) of website visitors. Use this when the user asks about what devices people use, mobile vs desktop traffic, or if their site is mobile-friendly.",executionMode:"component",chatComponent:"DeviceBreakdownCard",parameters:{type:"object",properties:{startDate:{type:"string",description:"Start date for the report. Default: '30daysAgo'"},endDate:{type:"string",description:"End date for the report. Default: 'today'"}},required:[]}},{name:"getPeakHours",description:"Show a card in chat with peak traffic hours and a weekly heatmap showing when visitors are most active. Use this when the user asks about best times to post, peak hours, busiest times, or when their audience is online.",executionMode:"component",chatComponent:"PeakHoursCard",parameters:{type:"object",properties:{startDate:{type:"string",description:"Start date for the report. Default: '30daysAgo'"},endDate:{type:"string",description:"End date for the report. Default: 'today'"}},required:[]}}],R={component:()=>Promise.resolve().then(()=>require("./index-DwHYfZl_.js")),metadata:E,config:I,routes:j,permissions:U,tools:Y,chatComponents:{TopPagesCard:()=>Promise.resolve().then(()=>require("./TopPagesCard-pZ-nAsaI.js")),VisitorStatsCard:()=>Promise.resolve().then(()=>require("./VisitorStatsCard-tApB_7v8.js")),SearchTermsCard:()=>Promise.resolve().then(()=>require("./SearchTermsCard-DGRbo5ZP.js")),TrafficSourcesCard:()=>Promise.resolve().then(()=>require("./TrafficSourcesCard-CBOPV1J1.js")),RealtimeCard:()=>Promise.resolve().then(()=>require("./RealtimeCard-CxtqQHee.js")),CountryBreakdownCard:()=>Promise.resolve().then(()=>require("./CountryBreakdownCard-BUfJ-umQ.js")),DeviceBreakdownCard:()=>Promise.resolve().then(()=>require("./DeviceBreakdownCard-CsoK6JUO.js")),PeakHoursCard:()=>Promise.resolve().then(()=>require("./PeakHoursCard-BNl_U1r_.js"))}},B={name:"Content Manager",description:"Create and manage content",icon:"mdi-table",version:"1.0.0"},O=e.defineModuleConfig({project:{label:"Database",type:"resource",accept:["FIREBASE"]},domain:{label:"Domain",type:"input",default:"https://domain.com"},collectionsCollection:{label:"Collections Collection",type:"input",default:"content_collections"},contentCollection:{label:"Content Collection",type:"input",default:"content"},allowedMediaSources:{label:"Allowed Media Sources",type:"mediaSource",multiple:!0},defaultUploadMediaSource:{label:"Default Upload Media Source",type:"mediaSource",multiple:!1},supportedLanguages:{label:"Supported Languages",type:"select",predefinedOptions:"languages",multiple:!0},defaultLanguage:{label:"Default Language",type:"select",predefinedOptions:"languages"}}),L=[{path:"",component:()=>Promise.resolve().then(()=>require("./Overview-CwCAeBnX.js"))},{path:"/collections",component:()=>Promise.resolve().then(()=>require("./Overview-CwCAeBnX.js"))},{path:"/collections/:collectionId",component:()=>Promise.resolve().then(()=>require("./Entries-BPkZ7Jg5.js"))},{path:"/collections/:collectionId/:entryId",component:()=>Promise.resolve().then(()=>require("./ContentEditor-3JFlC9N1.js"))},{path:"/components",component:()=>Promise.resolve().then(()=>require("./Components-DXbx0RLV.js"))},{path:"/global-styling",component:()=>Promise.resolve().then(()=>require("./GlobalStyling-CnSlXkZc.js"))}],G=[{key:"create-content",name:"Create content",description:"Team member can create content"},{key:"edit-content",name:"Edit content",description:"Team member can edit content"},{key:"delete-content",name:"Delete content",description:"Team member can delete content"}],F={component:()=>Promise.resolve().then(()=>require("./index-UtjLbLw-.js")),metadata:B,config:O,routes:L,permissions:G},V={name:"Mail Templates",description:"Build templates for your transactional emails.",icon:"mdi-table",version:"1.0.0"},N=e.defineModuleConfig({project:{label:"Project",type:"resource",accept:["FIREBASE"]},templateCollection:{label:"Mail Templates Collection",type:"input",default:"mail-templates"}}),_=[{path:"",component:()=>Promise.resolve().then(()=>require("./Overview-BDlBCUI_.js"))},{path:"/:optionId",component:()=>Promise.resolve().then(()=>require("./Detail-mvSGbnFU.js"))},{path:"/new",component:()=>Promise.resolve().then(()=>require("./Detail-mvSGbnFU.js"))}],H=[{key:"create-template",name:"Create mail template",description:"Team member can create a new mail template"},{key:"edit-template",name:"Edit mail template",description:"Team member can edit a mail template"},{key:"delete-template",name:"Delete mail template",description:"Team member can delete a mail template"}],K={component:()=>Promise.resolve().then(()=>require("./index-Cz-baGax.js")),metadata:V,config:N,routes:_,permissions:H},W={name:"Appointments",description:"Create and manage agendas for booking appointments.",icon:"mdi-table",version:"1.0.0"},z=e.defineModuleConfig({project:{label:"Project",type:"resource",accept:["FIREBASE"]},mailAccount:{label:"Mail account",type:"resource",accept:["GMAIL"]},agendaCollection:{label:"Agenda Collection",type:"input",default:"agendas"},reservationsCollection:{label:"Reservations Collection",type:"input",default:"bookings_orders"},reservedSpotsCollection:{label:"Reserved Spots Collection",type:"input",default:"reserved_spots"}}),J=[{path:"",component:()=>Promise.resolve().then(()=>require("./Overview-t0pG5xjA.js"))},{path:"/create",component:()=>Promise.resolve().then(()=>require("./index-D2a6wEPh.js"))},{path:"/create/regular",component:()=>Promise.resolve().then(()=>require("./regular-1LXNPviB.js"))},{path:"/edit/:id",component:()=>Promise.resolve().then(()=>require("./index-DTzdHh6g.js"))},{path:"/edit/:id/agenda",component:()=>Promise.resolve().then(()=>require("./agenda-wNFDKn0G.js"))},{path:"/edit/:id/regular-slots",component:()=>Promise.resolve().then(()=>require("./regular-slots-Bs3WJB3U.js"))},{path:"/edit/:id/exceptions",component:()=>Promise.resolve().then(()=>require("./exceptions-wEQEVzIs.js"))},{path:"/edit/:id/availability",component:()=>Promise.resolve().then(()=>require("./availability-BiBbzEIM.js"))},{path:"/edit/:id/payment",component:()=>Promise.resolve().then(()=>require("./payment-BQaAqQ5q.js"))},{path:"/edit/:id/resources",component:()=>Promise.resolve().then(()=>require("./resources-eb0pivDL.js"))},{path:"/edit/:id/orders",component:()=>Promise.resolve().then(()=>require("./orders-D5GJOZXN.js"))}],Q=[{key:"create-agendas",name:"Create agendas",description:"Team member can create agendas"},{key:"edit-agendas",name:"Edit agendas",description:"Team member can edit agendas"},{key:"delete-agendas",name:"Delete agendas",description:"Team member can delete agendas"},{key:"manage-reservations",name:"Manage reservations",description:"Team member can create, edit, and delete reservations"}],X=[{name:"findAppointment",description:"Show a card in chat with details of an appointment/booking/reservation/...",executionMode:"component",chatComponent:"AppointmentDetailsCard",parameters:{type:"object",properties:{name:{type:"string",description:"Name of the booker"},email:{type:"string",description:"Email of the booker"},date:{type:"string",description:"Date of the appointment (YYYY-MM-DD)"}},required:["date"]}},{name:"getRecentAppointments",description:"Show a table in chat with recent appointments, default loading the latest 20 appointments.",executionMode:"component",chatComponent:"AppointmentListTable",parameters:{type:"object",properties:{quantity:{type:"number",description:"Number of appointments to load. default: 20 max: 100",default:20}},required:["quantity"]}},{name:"changeAppointmentDetails",description:"Show a card in chat where user can edit name, email and date of an existing appointment.",executionMode:"component",chatComponent:"AppointmentEditor",parameters:{type:"object",properties:{orderId:{type:"string",description:"ID of the order / appointment. This is NOT the reservation ID."}},required:["orderId"]}}],Z={component:()=>Promise.resolve().then(()=>require("./index-9HVlmvK3.js")),metadata:W,config:z,routes:J,permissions:Q,tools:X,chatComponents:{AppointmentDetailsCard:()=>Promise.resolve().then(()=>require("./AppointmentDetailsCard-CtK0Cj_O.js")),AppointmentListTable:()=>Promise.resolve().then(()=>require("./AppointmentListTable-CQ3uXfa8.js")),AppointmentEditor:()=>Promise.resolve().then(()=>require("./AppointmentEditor-CaTfbkIf.js"))}};exports.appointments=Z;exports.contentManager=F;exports.custom=g;exports.googleAnalytics=R;exports.mailTemplates=K;exports.productCollections=k;exports.products=d;exports.promoCodes=w;exports.shippingOptions=x;exports.table=i;
|
package/dist/index.mjs
CHANGED
|
@@ -45,7 +45,7 @@ const t = {
|
|
|
45
45
|
default: !1
|
|
46
46
|
}
|
|
47
47
|
}), a = [
|
|
48
|
-
{ path: "", component: () => import("./TableView-
|
|
48
|
+
{ path: "", component: () => import("./TableView-Ccp2Vkhr.mjs") }
|
|
49
49
|
], n = [], _ = {
|
|
50
50
|
component: () => import("./index-Bkq58CeQ.mjs"),
|
|
51
51
|
metadata: t,
|
|
@@ -284,11 +284,11 @@ const t = {
|
|
|
284
284
|
description: "Optional. When set, the module will fetch real keyword data from Google Search Console. Use the same site URL format as shown in Search Console."
|
|
285
285
|
}
|
|
286
286
|
}), x = [
|
|
287
|
-
{ path: "", component: () => import("./Overview-
|
|
287
|
+
{ path: "", component: () => import("./Overview-CuCQgqVp.mjs") },
|
|
288
288
|
{ path: "/acquisition", component: () => import("./Acquisition-D_Qx7XRY.mjs") },
|
|
289
289
|
{ path: "/content", component: () => import("./Content-DW6xvbUo.mjs") },
|
|
290
290
|
{ path: "/audience", component: () => import("./Audience-BdlrWkY-.mjs") },
|
|
291
|
-
{ path: "/seo", component: () => import("./SeoHealth-
|
|
291
|
+
{ path: "/seo", component: () => import("./SeoHealth-CC0rW1AG.mjs") }
|
|
292
292
|
], T = [], E = [
|
|
293
293
|
{
|
|
294
294
|
name: "getTopPages",
|
|
@@ -594,7 +594,7 @@ const t = {
|
|
|
594
594
|
{ path: "/create/regular", component: () => import("./regular-_05oq5Tx.mjs") },
|
|
595
595
|
// { path: '/create/full-day', component: () => import('./pages/create/full-day.vue') },
|
|
596
596
|
// { path: '/create/multi-day', component: () => import('./pages/create/multi-day.vue') },
|
|
597
|
-
{ path: "/edit/:id", component: () => import("./index-
|
|
597
|
+
{ path: "/edit/:id", component: () => import("./index-N0NoDEsI.mjs") },
|
|
598
598
|
{ path: "/edit/:id/agenda", component: () => import("./agenda-XqvbrU72.mjs") },
|
|
599
599
|
{ path: "/edit/:id/regular-slots", component: () => import("./regular-slots-C2NYxLPn.mjs") },
|
|
600
600
|
{ path: "/edit/:id/exceptions", component: () => import("./exceptions-CLgeeUSy.mjs") },
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("h3");require("vue");function M(f){const{initFirebase:E,normalizeTimestamps:D}=f,g=r.createRouter();async function l(u){const{supabase:d,instanceId:y}=u.context.module,{data:e,error:n}=await d.from("project_modules").select("config").eq("id",y).single();if(n||!e?.config)throw r.createError({statusCode:500,statusMessage:"Failed to load module config."});const o=e.config,t=o.project,s=o.productCollection||"products";if(!t)throw r.createError({statusCode:400,statusMessage:"Products module has no Firebase integration configured."});return{firebase:await E(u,t),collection:s}}return g.get("/products",r.defineEventHandler(async u=>{try{const{firebase:d,collection:y}=await l(u);return(await d.firestore().collection(y).get()).docs.map(n=>D({id:n.id,...n.data()}))}catch(d){throw console.error("Products handler — list error:",d),r.createError({statusCode:d.statusCode||500,statusMessage:d.statusMessage||"Failed to list products"})}})),g.get("/products/:productId",r.defineEventHandler(async u=>{const d=r.getRouterParam(u,"productId");if(!d)throw r.createError({statusCode:400,statusMessage:"Product ID is required."});try{const{firebase:y,collection:e}=await l(u),n=await y.firestore().collection(e).doc(d).get();if(!n.exists)throw r.createError({statusCode:404,statusMessage:"Product not found."});return D({id:n.id,...n.data()})}catch(y){throw console.error("Products handler — get error:",y),r.createError({statusCode:y.statusCode||500,statusMessage:y.statusMessage||"Failed to get product"})}})),g.get("/empty-stock",r.defineEventHandler(async u=>{const y=r.getQuery(u).category;try{const{firebase:e,collection:n}=await l(u);let o=e.firestore().collection(n).where("stock","==",0);y&&(o=o.where("collections","array-contains",y));const s=(await o.get()).docs.map(a=>D({id:a.id,...a.data()}));return{count:s.length,products:s.map(a=>({id:a.id,title:a.title,slug:a.slug,stock:a.stock,price:a.price,currency:a.currency,status:a.status}))}}catch(e){throw console.error("Products handler — empty-stock error:",e),r.createError({statusCode:e.statusCode||500,statusMessage:e.statusMessage||"Failed to query empty stock"})}})),g.handler}function T(f){const{initFirebase:E,normalizeTimestamps:D}=f,g=r.createRouter();async function l(d){const{supabase:y,instanceId:e}=d.context.module,{data:n,error:o}=await y.from("project_modules").select("config").eq("id",e).single();if(o||!n?.config)throw r.createError({statusCode:500,statusMessage:"Failed to load module config."});const t=n.config,s=t.project,a=t.reservationsCollection||"bookings_orders",i=t.agendaCollection||"agendas";if(!s)throw r.createError({statusCode:400,statusMessage:"Appointments module has no Firebase integration configured."});return{firebase:await E(d,s),reservationsCollection:a,agendaCollection:i}}function u(d){return(d.reservations||[]).map(e=>({orderId:d.id,reservationId:e.id,customerInfo:d.customerInfo,date:e.date,startTime:e.timeslot?.startTime,endTime:e.timeslot?.endTime,spots:e.spots,status:d.status,reservationStatus:e.status,resourceId:e.resourceId,reservationPrice:e.totalPrice,reservationBasePrice:e.basePrice,reservationAddOnsPrice:e.addOnsPrice,pricingOption:e.pricingOption,amountDue:d.amountDue,amountPaid:d.amountPaid,createdAt:d.createdAt}))}return g.get("/appointments",r.defineEventHandler(async d=>{const y=r.getQuery(d),e=Math.min(Number(y.quantity)||20,100);try{const{firebase:n,reservationsCollection:o}=await l(d),s=(await n.firestore().collection(o).orderBy("createdAt","desc").limit(e).get()).docs.flatMap(a=>u(D({id:a.id,...a.data()})));return{count:s.length,appointments:s}}catch(n){throw console.error("Appointments handler — list error:",n),r.createError({statusCode:n.statusCode||500,statusMessage:n.statusMessage||"Failed to list appointments"})}})),g.get("/appointments/find",r.defineEventHandler(async d=>{const y=r.getQuery(d),e=(y.name||"").toLowerCase().trim(),n=(y.email||"").toLowerCase().trim(),o=y.date;try{const{firebase:t,reservationsCollection:s}=await l(d);let a=t.firestore().collection(s);n&&(a=a.where("customerInfo.email","==",n));let c=(await a.orderBy("createdAt","desc").limit(200).get()).docs.flatMap(m=>u(D({id:m.id,...m.data()})));return o&&(c=c.filter(m=>m.date===o)),e&&(c=c.filter(m=>{const p=(m.customerInfo?.firstName||"").toLowerCase(),w=(m.customerInfo?.lastName||"").toLowerCase();return p.includes(e)||w.includes(e)||`${p} ${w}`.includes(e)})),{count:c.length,appointments:c}}catch(t){throw console.error("Appointments handler — find error:",t),r.createError({statusCode:t.statusCode||500,statusMessage:t.statusMessage||"Failed to find appointments"})}})),g.get("/appointments/:appointmentId",r.defineEventHandler(async d=>{const y=r.getRouterParam(d,"appointmentId");if(!y)throw r.createError({statusCode:400,statusMessage:"Appointment ID is required."});try{const{firebase:e,reservationsCollection:n}=await l(d);console.log("Fetching appointment with ID:",y,n);const o=await e.firestore().collection(n).doc(y).get();if(!o.exists)throw r.createError({statusCode:404,statusMessage:"Appointment not found."});const t=D({id:o.id,...o.data()});return{...t,reservations:u(t)}}catch(e){throw console.error("Appointments handler — get error:",e),r.createError({statusCode:e.statusCode||500,statusMessage:e.statusMessage||"Failed to get appointment"})}})),g.handler}const S="https://analyticsdata.googleapis.com/v1beta",N=["https://www.googleapis.com/auth/analytics.readonly","https://www.googleapis.com/auth/webmasters.readonly"],I="https://searchconsole.googleapis.com/webmasters/v3";function U(f){const{decrypt:E,getGoogleAccessToken:D}=f,g=r.createRouter();async function l(e){const{supabase:n,instanceId:o}=e.context.module,{data:t,error:s}=await n.from("project_modules").select("config").eq("id",o).single();if(s||!t?.config)throw r.createError({statusCode:500,statusMessage:"Failed to load module config."});const a=t.config,i=a.propertyId,c=a.serviceAccount,m=a.siteUrl||"";if(!c)throw r.createError({statusCode:400,statusMessage:"No Google Service Account configured for this module."});if(!i)throw r.createError({statusCode:400,statusMessage:"No GA4 Property ID configured for this module."});const{data:p,error:w}=await n.from("integrations").select("config").eq("id",c).single();let h=p?.config;if(w||!h){const{data:P,error:q}=await n.from("agency_integrations").select("config").eq("id",c).single();if(q||!P?.config)throw r.createError({statusCode:500,statusMessage:"Failed to load Google Service Account credentials."});h=P.config}const A=E(h.clientEmail),v=E(h.privateKey),R=E(h.projectId);return{accessToken:await D({clientEmail:A,privateKey:v,projectId:R},N),propertyId:i,siteUrl:m}}async function u(e,n,o){const t=await fetch(`${S}/properties/${n}:runReport`,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(o)});if(!t.ok){const s=await t.json().catch(()=>({}));throw console.error("GA4 runReport failed:",s),r.createError({statusCode:t.status,statusMessage:s?.error?.message||"GA4 API request failed"})}return t.json()}g.get("/report",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=s.match(/^(\d+)daysAgo$/),c=i?parseInt(i[1],10):30,m=`${c*2}daysAgo`,p=`${c+1}daysAgo`,w=[{name:"sessions"},{name:"totalUsers"},{name:"screenPageViews"},{name:"bounceRate"},{name:"averageSessionDuration"},{name:"newUsers"},{name:"engagementRate"},{name:"sessionsPerUser"},{name:"screenPageViewsPerSession"}];let h,A=!0;try{h=await u(n,o,{dateRanges:[{startDate:s,endDate:a,name:"current"},{startDate:m,endDate:p,name:"previous"}],dimensions:[{name:"date"}],metrics:w,metricAggregations:["TOTAL"],orderBys:[{dimension:{dimensionName:"date"}}]})}catch{A=!1,h=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"date"}],metrics:w,metricAggregations:["TOTAL"],orderBys:[{dimension:{dimensionName:"date"}}]})}return b(h,A)})),g.get("/realtime",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=await fetch(`${S}/properties/${o}:runRealtimeReport`,{method:"POST",headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json"},body:JSON.stringify({dimensions:[{name:"unifiedScreenName"}],metrics:[{name:"activeUsers"}],orderBys:[{metric:{metricName:"activeUsers"},desc:!0}],limit:5})});if(!t.ok){const c=await t.json().catch(()=>({}));throw r.createError({statusCode:t.status,statusMessage:c?.error?.message||"Realtime API failed"})}const s=await t.json(),a=(s?.rows||[]).reduce((c,m)=>c+parseInt(m.metricValues?.[0]?.value||"0",10),0),i=(s?.rows||[]).map(c=>({page:c.dimensionValues?.[0]?.value||"(not set)",activeUsers:parseInt(c.metricValues?.[0]?.value||"0",10)}));return{activeUsers:a,activePages:i}})),g.get("/top-pages",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=parseInt(t.limit||"10",10),c=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"pagePath"}],metrics:[{name:"screenPageViews"},{name:"totalUsers"},{name:"averageSessionDuration"}],orderBys:[{metric:{metricName:"screenPageViews"},desc:!0}],limit:i*2}),m=C(c,"pagePath"),p=new Map;for(const h of m.rows){const A=h.pagePath.toLowerCase().replace(/\/+$/,""),v=p.get(A);if(v){v.screenPageViews+=h.screenPageViews||0,v.totalUsers+=h.totalUsers||0;const R=v.screenPageViews;R>0&&(v.averageSessionDuration=(v.averageSessionDuration*(R-(h.screenPageViews||0))+(h.averageSessionDuration||0)*(h.screenPageViews||0))/R)}else p.set(A,{...h})}return{rows:[...p.values()].sort((h,A)=>(A.screenPageViews||0)-(h.screenPageViews||0)).slice(0,i),rowCount:m.rowCount}})),g.get("/top-sources",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"sessionSource"}],metrics:[{name:"sessions"},{name:"totalUsers"}],orderBys:[{metric:{metricName:"sessions"},desc:!0}],limit:10});return C(i,"sessionSource")})),g.get("/devices",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"deviceCategory"}],metrics:[{name:"sessions"},{name:"totalUsers"}],orderBys:[{metric:{metricName:"sessions"},desc:!0}]});return C(i,"deviceCategory")})),g.get("/countries",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"country"}],metrics:[{name:"sessions"},{name:"totalUsers"}],orderBys:[{metric:{metricName:"sessions"},desc:!0}],limit:10});return C(i,"country")})),g.get("/acquisition/channels",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"sessionDefaultChannelGroup"}],metrics:[{name:"sessions"},{name:"totalUsers"},{name:"newUsers"},{name:"engagementRate"},{name:"averageSessionDuration"},{name:"screenPageViewsPerSession"},{name:"conversions"}],orderBys:[{metric:{metricName:"sessions"},desc:!0}],limit:15});return C(i,"sessionDefaultChannelGroup")})),g.get("/acquisition/source-medium",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"sessionSourceMedium"}],metrics:[{name:"sessions"},{name:"totalUsers"},{name:"newUsers"},{name:"bounceRate"},{name:"averageSessionDuration"},{name:"conversions"}],orderBys:[{metric:{metricName:"sessions"},desc:!0}],limit:20});return C(i,"sessionSourceMedium")})),g.get("/acquisition/referrals",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"sessionSource"}],dimensionFilter:{filter:{fieldName:"sessionMedium",stringFilter:{value:"referral"}}},metrics:[{name:"sessions"},{name:"totalUsers"},{name:"engagementRate"},{name:"averageSessionDuration"}],orderBys:[{metric:{metricName:"sessions"},desc:!0}],limit:20});return C(i,"sessionSource")})),g.get("/acquisition/campaigns",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"sessionCampaignName"}],dimensionFilter:{notExpression:{filter:{fieldName:"sessionCampaignName",stringFilter:{value:"(not set)"}}}},metrics:[{name:"sessions"},{name:"totalUsers"},{name:"conversions"},{name:"engagementRate"}],orderBys:[{metric:{metricName:"sessions"},desc:!0}],limit:20});return C(i,"sessionCampaignName")})),g.get("/content/all-pages",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=parseInt(t.limit||"50",10),c=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"pagePath"}],metrics:[{name:"screenPageViews"},{name:"totalUsers"},{name:"averageSessionDuration"},{name:"bounceRate"},{name:"engagementRate"},{name:"sessions"},{name:"userEngagementDuration"}],orderBys:[{metric:{metricName:"screenPageViews"},desc:!0}],limit:i});return C(c,"pagePath")})),g.get("/content/landing-pages",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"landingPagePlusQueryString"}],metrics:[{name:"sessions"},{name:"totalUsers"},{name:"bounceRate"},{name:"averageSessionDuration"},{name:"screenPageViews"},{name:"engagementRate"}],orderBys:[{metric:{metricName:"sessions"},desc:!0}],limit:30});return C(i,"landingPagePlusQueryString")})),g.get("/content/exit-pages",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"pagePath"}],metrics:[{name:"sessions"},{name:"screenPageViews"},{name:"totalUsers"},{name:"bounceRate"}],orderBys:[{metric:{metricName:"screenPageViews"},desc:!0}],limit:20}),c=C(i,"pagePath");return c.rows=c.rows.map(m=>({...m,exitRate:m.bounceRate||0})),c})),g.get("/content/search-terms",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o,siteUrl:t}=await l(e),s=r.getQuery(e),a=s.startDate||"30daysAgo",i=s.endDate||"today";if(t)try{const p=`${I}/sites/${encodeURIComponent(t)}/searchAnalytics/query`;console.log("[GA Module] Attempting Search Console query for site:",t);const w=await fetch(p,{method:"POST",headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json"},body:JSON.stringify({startDate:d(a),endDate:d(i),dimensions:["query"],rowLimit:30})});if(w.ok){const A=((await w.json()).rows||[]).map(v=>({query:v.keys[0],clicks:v.clicks,impressions:v.impressions,ctr:v.ctr,position:v.position}));if(A.length>0)return console.log(`[GA Module] Search Console returned ${A.length} keyword rows`),{rows:A,rowCount:A.length,source:"search_console"};console.log("[GA Module] Search Console returned 0 rows, falling through")}else{const h=await w.text().catch(()=>"");console.error(`[GA Module] Search Console API error (${w.status}):`,h)}}catch(p){console.error("[GA Module] Search Console request failed:",p?.message||p)}else console.log("[GA Module] No siteUrl configured, skipping Search Console");try{const p=await u(n,o,{dateRanges:[{startDate:a,endDate:i}],dimensions:[{name:"sessionGoogleAdsQuery"}],metrics:[{name:"sessions"},{name:"totalUsers"},{name:"engagementRate"}],dimensionFilter:{andGroup:{expressions:[{notExpression:{filter:{fieldName:"sessionGoogleAdsQuery",stringFilter:{value:"(not set)"}}}},{notExpression:{filter:{fieldName:"sessionGoogleAdsQuery",stringFilter:{value:"(not provided)"}}}}]}},orderBys:[{metric:{metricName:"sessions"},desc:!0}],limit:30}),w=C(p,"sessionGoogleAdsQuery");if(w.rows.length>0)return{...w,source:"google_ads"}}catch{}const c=await u(n,o,{dateRanges:[{startDate:a,endDate:i}],dimensions:[{name:"landingPagePlusQueryString"}],metrics:[{name:"sessions"},{name:"totalUsers"},{name:"engagementRate"}],dimensionFilter:{andGroup:{expressions:[{filter:{fieldName:"sessionMedium",stringFilter:{matchType:"EXACT",value:"organic"}}},{notExpression:{filter:{fieldName:"landingPagePlusQueryString",stringFilter:{value:"(not set)"}}}}]}},orderBys:[{metric:{metricName:"sessions"},desc:!0}],limit:30});return{...C(c,"landingPagePlusQueryString"),source:"organic_landing_pages"}})),g.get("/audience/overview",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"newVsReturning"}],metrics:[{name:"totalUsers"},{name:"sessions"},{name:"engagementRate"},{name:"averageSessionDuration"},{name:"screenPageViewsPerSession"}],metricAggregations:["TOTAL"]});return C(i,"newVsReturning")})),g.get("/audience/technology",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=t.dimension||"browser",m=["browser","operatingSystem","screenResolution"].includes(i)?i:"browser",p=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:m}],metrics:[{name:"totalUsers"},{name:"sessions"},{name:"engagementRate"}],orderBys:[{metric:{metricName:"totalUsers"},desc:!0}],limit:10});return C(p,m)})),g.get("/audience/languages",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"language"}],metrics:[{name:"totalUsers"},{name:"sessions"}],orderBys:[{metric:{metricName:"totalUsers"},desc:!0}],limit:15});return C(i,"language")})),g.get("/audience/hours",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"dayOfWeekName"},{name:"hour"}],metrics:[{name:"sessions"}],orderBys:[{dimension:{dimensionName:"dayOfWeekName"}},{dimension:{dimensionName:"hour"}}],limit:168});return k(i,["dayOfWeekName","hour"])})),g.get("/audience/cities",r.defineEventHandler(async e=>{const{accessToken:n,propertyId:o}=await l(e),t=r.getQuery(e),s=t.startDate||"30daysAgo",a=t.endDate||"today",i=await u(n,o,{dateRanges:[{startDate:s,endDate:a}],dimensions:[{name:"city"},{name:"country"}],metrics:[{name:"totalUsers"},{name:"sessions"}],dimensionFilter:{notExpression:{filter:{fieldName:"city",stringFilter:{value:"(not set)"}}}},orderBys:[{metric:{metricName:"totalUsers"},desc:!0}],limit:20});return k(i,["city","country"])}));function d(e){const n=e.match(/^(\d+)daysAgo$/);if(n){const o=new Date;return o.setDate(o.getDate()-parseInt(n[1],10)),o.toISOString().slice(0,10)}if(e==="today")return new Date().toISOString().slice(0,10);if(e==="yesterday"){const o=new Date;return o.setDate(o.getDate()-1),o.toISOString().slice(0,10)}return e}async function y(e,n,o){const t=`${I}/sites/${encodeURIComponent(n)}/searchAnalytics/query`,s=await fetch(t,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify(o)});if(!s.ok){const a=await s.json().catch(()=>({}));throw r.createError({statusCode:s.status,statusMessage:a?.error?.message||"Search Console API request failed"})}return s.json()}return g.get("/seo/keywords",r.defineEventHandler(async e=>{const{accessToken:n,siteUrl:o}=await l(e);if(!o)throw r.createError({statusCode:400,statusMessage:"Search Console Site URL is not configured. Add it in module settings."});const t=r.getQuery(e),s=d(t.startDate||"30daysAgo"),a=d(t.endDate||"today"),i=Math.min(parseInt(t.limit)||50,100),c=await y(n,o,{startDate:s,endDate:a,dimensions:["query"],rowLimit:i});return{rows:(c.rows||[]).map(m=>({query:m.keys[0],clicks:m.clicks,impressions:m.impressions,ctr:m.ctr,position:m.position})),rowCount:c.rows?.length||0}})),g.get("/seo/pages",r.defineEventHandler(async e=>{const{accessToken:n,siteUrl:o}=await l(e);if(!o)throw r.createError({statusCode:400,statusMessage:"Search Console Site URL is not configured."});const t=r.getQuery(e),s=d(t.startDate||"30daysAgo"),a=d(t.endDate||"today"),i=Math.min(parseInt(t.limit)||50,100),c=await y(n,o,{startDate:s,endDate:a,dimensions:["page"],rowLimit:i});return{rows:(c.rows||[]).map(m=>({page:m.keys[0],clicks:m.clicks,impressions:m.impressions,ctr:m.ctr,position:m.position})),rowCount:c.rows?.length||0}})),g.get("/seo/trends",r.defineEventHandler(async e=>{const{accessToken:n,siteUrl:o}=await l(e);if(!o)throw r.createError({statusCode:400,statusMessage:"Search Console Site URL is not configured."});const t=r.getQuery(e),s=d(t.startDate||"30daysAgo"),a=d(t.endDate||"today"),c=((await y(n,o,{startDate:s,endDate:a,dimensions:["date"],rowLimit:500})).rows||[]).map(p=>({date:p.keys[0],clicks:p.clicks,impressions:p.impressions,ctr:p.ctr,position:p.position})).sort((p,w)=>p.date.localeCompare(w.date)),m=c.reduce((p,w)=>({clicks:p.clicks+w.clicks,impressions:p.impressions+w.impressions}),{clicks:0,impressions:0});return m.ctr=m.impressions>0?m.clicks/m.impressions:0,m.avgPosition=c.length>0?c.reduce((p,w)=>p+w.position,0)/c.length:0,{rows:c,totals:m,rowCount:c.length}})),g.get("/seo/query-pages",r.defineEventHandler(async e=>{const{accessToken:n,siteUrl:o}=await l(e);if(!o)throw r.createError({statusCode:400,statusMessage:"Search Console Site URL is not configured."});const t=r.getQuery(e),s=d(t.startDate||"30daysAgo"),a=d(t.endDate||"today"),i=await y(n,o,{startDate:s,endDate:a,dimensions:["query","page"],rowLimit:100});return{rows:(i.rows||[]).map(c=>({query:c.keys[0],page:c.keys[1],clicks:c.clicks,impressions:c.impressions,ctr:c.ctr,position:c.position})),rowCount:i.rows?.length||0}})),g.handler}function b(f,E=!0){const D=(f.metricHeaders||[]).map(s=>s.name),l=(f.dimensionHeaders||[]).map(s=>s.name).indexOf("date"),u=[];(f.rows||[]).forEach(s=>{const a=l>=0?s.dimensionValues[l]?.value:s.dimensionValues[0]?.value;if(!a||a.length<8)return;const c={date:`${a.slice(0,4)}-${a.slice(4,6)}-${a.slice(6,8)}`};D.forEach((m,p)=>{c[m]=parseFloat(s.metricValues[p]?.value||"0")}),u.push(c)});const d={},y={};f.totals&&f.totals.length>=2?D.forEach((s,a)=>{d[s]=parseFloat(f.totals[0]?.metricValues?.[a]?.value||"0"),y[s]=parseFloat(f.totals[1]?.metricValues?.[a]?.value||"0")}):f.totals&&f.totals.length===1&&D.forEach((s,a)=>{d[s]=parseFloat(f.totals[0]?.metricValues?.[a]?.value||"0")});const e={};D.forEach(s=>{const a=d[s]||0,i=y[s];i!==void 0&&i!==0?e[s]=(a-i)/i*100:e[s]=null});const n=new Map;for(const s of u)n.has(s.date)||n.set(s.date,s);const o=Array.from(n.values()).sort((s,a)=>s.date.localeCompare(a.date)),t=E&&f.totals&&f.totals.length>=2?o.slice(-Math.ceil(o.length/2)):o;return{rows:t,totals:d,previousTotals:y,changes:e,rowCount:t.length}}function C(f,E){const D=(f.metricHeaders||[]).map(l=>l.name),g=(f.rows||[]).map(l=>{const u={[E]:l.dimensionValues[0].value};return D.forEach((d,y)=>{u[d]=parseFloat(l.metricValues[y].value)}),u});return{rows:g,rowCount:f.rowCount||g.length}}function k(f,E){const D=(f.metricHeaders||[]).map(l=>l.name),g=(f.rows||[]).map(l=>{const u={};return E.forEach((d,y)=>{u[d]=l.dimensionValues[y]?.value||""}),D.forEach((d,y)=>{u[d]=parseFloat(l.metricValues[y].value)}),u});return{rows:g,rowCount:f.rowCount||g.length}}exports.appointments=T;exports.googleAnalytics=U;exports.products=M;
|