@happyvertical/smrt-planner 0.0.0-stage → 0.0.1
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/LICENSE +21 -0
- package/README.md +170 -2
- package/app/404.html +80 -0
- package/app/_app/immutable/assets/0.B5zXkXe_.css +1 -0
- package/app/_app/immutable/assets/10.hpcnxvK1.css +1 -0
- package/app/_app/immutable/assets/11.D7zoXfVV.css +1 -0
- package/app/_app/immutable/assets/12.CPobm1ED.css +1 -0
- package/app/_app/immutable/assets/2.CyaWdRdI.css +1 -0
- package/app/_app/immutable/assets/3.BlPQOes8.css +1 -0
- package/app/_app/immutable/assets/8.2gQeKBp_.css +1 -0
- package/app/_app/immutable/assets/9.HOPT4xtg.css +1 -0
- package/app/_app/immutable/assets/AiSetup.Cb22AigN.css +1 -0
- package/app/_app/immutable/assets/Button.DkP0qkG9.css +1 -0
- package/app/_app/immutable/assets/ConnectTools.BgIJOOGW.css +1 -0
- package/app/_app/immutable/assets/FieldMapForm.BCU-4pO4.css +1 -0
- package/app/_app/immutable/assets/ModelPage.Dd3LcMta.css +1 -0
- package/app/_app/immutable/assets/SectionActions.CTkVuNMF.css +1 -0
- package/app/_app/immutable/assets/SectionIcons.5Udq9vN-.css +1 -0
- package/app/_app/immutable/assets/SegmentedControl.B8SrQacd.css +1 -0
- package/app/_app/immutable/assets/dist.C5nHBk_O.css +1 -0
- package/app/_app/immutable/assets/feedback.BVKAwFck.css +1 -0
- package/app/_app/immutable/assets/forms.BChZ2RWM.css +1 -0
- package/app/_app/immutable/assets/inter-latin-ext.B_-bZUTo.woff2 +0 -0
- package/app/_app/immutable/assets/inter-latin.8kRkwJBP.woff2 +0 -0
- package/app/_app/immutable/assets/jetbrains-mono-latin-ext.Bnd2h4Br.woff2 +0 -0
- package/app/_app/immutable/assets/jetbrains-mono-latin.Db4Uuiha.woff2 +0 -0
- package/app/_app/immutable/assets/ort-wasm-simd-threaded.asyncify.CxOG5pUO.wasm +0 -0
- package/app/_app/immutable/assets/percent.LH0z-ozZ.css +1 -0
- package/app/_app/immutable/assets/space-grotesk-latin-ext.wJGaI8U0.woff2 +0 -0
- package/app/_app/immutable/assets/space-grotesk-latin.DPT1xrvW.woff2 +0 -0
- package/app/_app/immutable/assets/store.CGDwHkkF.css +1 -0
- package/app/_app/immutable/assets/ui.B1A1Zl2p.css +1 -0
- package/app/_app/immutable/assets/workspace.BIMkuZDb.css +1 -0
- package/app/_app/immutable/chunks/1okeBSoq.js +1 -0
- package/app/_app/immutable/chunks/B32EWqI8.js +9 -0
- package/app/_app/immutable/chunks/B4Kevpe0.js +1 -0
- package/app/_app/immutable/chunks/BJfAXhak.js +3 -0
- package/app/_app/immutable/chunks/BKwRT_1p.js +1 -0
- package/app/_app/immutable/chunks/BQxY8kkL.js +1 -0
- package/app/_app/immutable/chunks/BS4h9ES-.js +1 -0
- package/app/_app/immutable/chunks/BWPhGFHl.js +1 -0
- package/app/_app/immutable/chunks/BYcBM-fh.js +1 -0
- package/app/_app/immutable/chunks/BYde9M_U.js +1 -0
- package/app/_app/immutable/chunks/BegKiy2G.js +1 -0
- package/app/_app/immutable/chunks/Bjy-W4x2.js +81 -0
- package/app/_app/immutable/chunks/C7zBd-pD.js +1 -0
- package/app/_app/immutable/chunks/CA-A9Ngs.js +1 -0
- package/app/_app/immutable/chunks/CMhpRMKg.js +1 -0
- package/app/_app/immutable/chunks/CPRHZZeW.js +1 -0
- package/app/_app/immutable/chunks/CRQ1Pmzr.js +1 -0
- package/app/_app/immutable/chunks/CV-2zt0K.js +2 -0
- package/app/_app/immutable/chunks/CWtfVMDz.js +1 -0
- package/app/_app/immutable/chunks/CgAkqYsL.js +1 -0
- package/app/_app/immutable/chunks/Chyo8rdT.js +3 -0
- package/app/_app/immutable/chunks/CmmuWmp6.js +2 -0
- package/app/_app/immutable/chunks/CrFNLK0f.js +1 -0
- package/app/_app/immutable/chunks/CrO3W89x.js +1 -0
- package/app/_app/immutable/chunks/CyUMm_Wp.js +1 -0
- package/app/_app/immutable/chunks/CygC84VT.js +2 -0
- package/app/_app/immutable/chunks/D0VgZnk1.js +1 -0
- package/app/_app/immutable/chunks/D333l2GL.js +2 -0
- package/app/_app/immutable/chunks/D71UrO5c.js +1 -0
- package/app/_app/immutable/chunks/D7hhQvDO.js +1 -0
- package/app/_app/immutable/chunks/DD7gpKb2.js +1 -0
- package/app/_app/immutable/chunks/DJtH-lRi.js +3 -0
- package/app/_app/immutable/chunks/DNRgqfTx.js +1 -0
- package/app/_app/immutable/chunks/DRByVC-c.js +1 -0
- package/app/_app/immutable/chunks/DVRKjN-E.js +1 -0
- package/app/_app/immutable/chunks/D_J_XtJy.js +846 -0
- package/app/_app/immutable/chunks/Dbjm4OuC.js +1 -0
- package/app/_app/immutable/chunks/Dc4q22LH.js +42 -0
- package/app/_app/immutable/chunks/Dd_uD5pT.js +1 -0
- package/app/_app/immutable/chunks/Dp9GVO-9.js +1 -0
- package/app/_app/immutable/chunks/DqcD-WtP.js +1 -0
- package/app/_app/immutable/chunks/Dt-HX3Vu.js +1 -0
- package/app/_app/immutable/chunks/DyGfbRG-.js +1 -0
- package/app/_app/immutable/chunks/FbOxj-PF.js +69 -0
- package/app/_app/immutable/chunks/OJ_lLTHH.js +1 -0
- package/app/_app/immutable/chunks/QukgIHDX.js +1 -0
- package/app/_app/immutable/chunks/WxSPP8QW.js +4 -0
- package/app/_app/immutable/chunks/iET62IRm.js +2 -0
- package/app/_app/immutable/chunks/leQCwW2d.js +1 -0
- package/app/_app/immutable/chunks/p6bgzXiY.js +1 -0
- package/app/_app/immutable/chunks/uBIymjUX.js +1 -0
- package/app/_app/immutable/chunks/ufuM4XBq.js +33 -0
- package/app/_app/immutable/chunks/xihTtKlq.js +1 -0
- package/app/_app/immutable/entry/app.D5JJain6.js +2 -0
- package/app/_app/immutable/entry/start.CH9DJLgI.js +1 -0
- package/app/_app/immutable/nodes/0.CL1MxOva.js +10 -0
- package/app/_app/immutable/nodes/1.BO731RRg.js +1 -0
- package/app/_app/immutable/nodes/10.1nQxyH9H.js +4 -0
- package/app/_app/immutable/nodes/11.Cw0JnQF3.js +1 -0
- package/app/_app/immutable/nodes/12.BmZyLHbM.js +1 -0
- package/app/_app/immutable/nodes/2.BEw046av.js +17 -0
- package/app/_app/immutable/nodes/3.DvwpTAQA.js +1 -0
- package/app/_app/immutable/nodes/4.qrT4bnmS.js +1 -0
- package/app/_app/immutable/nodes/5.DDLa2uhV.js +1 -0
- package/app/_app/immutable/nodes/6.DN0QTY6z.js +1 -0
- package/app/_app/immutable/nodes/7.C_8N82Wq.js +1 -0
- package/app/_app/immutable/nodes/8.D2Mszsua.js +3 -0
- package/app/_app/immutable/nodes/9.CLYsywul.js +1 -0
- package/app/_app/immutable/workers/assets/ort-wasm-simd-threaded.asyncify-CxOG5pUO.wasm +0 -0
- package/app/_app/immutable/workers/llm.worker-wfCOG_uk.js +69 -0
- package/app/_app/immutable/workers/local-speech.worker-DWbfmFUk.js +51 -0
- package/app/_app/version.json +1 -0
- package/app/ai/index.html +89 -0
- package/app/blueprint/index.html +87 -0
- package/app/cookbook/index.html +87 -0
- package/app/index.html +103 -0
- package/app/m/ads/AdDeliveryTier/index.html +96 -0
- package/app/m/ads/AdEvent/index.html +96 -0
- package/app/m/ads/AdFormat/index.html +96 -0
- package/app/m/ads/AdGroup/index.html +96 -0
- package/app/m/ads/AdVariation/index.html +96 -0
- package/app/m/analytics/AnalyticsDataStream/index.html +96 -0
- package/app/m/analytics/AnalyticsEvent/index.html +96 -0
- package/app/m/analytics/AnalyticsProperty/index.html +96 -0
- package/app/m/analytics/AnalyticsReport/index.html +96 -0
- package/app/m/approvals/ApprovalEvent/index.html +96 -0
- package/app/m/approvals/ApprovalPolicy/index.html +96 -0
- package/app/m/approvals/ApprovalRequest/index.html +96 -0
- package/app/m/assets/Asset/index.html +96 -0
- package/app/m/assets/AssetAssociation/index.html +97 -0
- package/app/m/assets/AssetMetafield/index.html +96 -0
- package/app/m/assets/AssetStatus/index.html +96 -0
- package/app/m/assets/AssetType/index.html +96 -0
- package/app/m/assets/Folder/index.html +96 -0
- package/app/m/chat/AgentSession/index.html +96 -0
- package/app/m/chat/ChatMessage/index.html +97 -0
- package/app/m/chat/ChatParticipant/index.html +97 -0
- package/app/m/chat/ChatReaction/index.html +96 -0
- package/app/m/chat/ChatRoom/index.html +96 -0
- package/app/m/chat/ChatThread/index.html +97 -0
- package/app/m/chat/VoiceGatewayTurn/index.html +96 -0
- package/app/m/chat/VoiceSession/index.html +96 -0
- package/app/m/commerce/Agreement/index.html +96 -0
- package/app/m/commerce/Cart/index.html +96 -0
- package/app/m/commerce/Contract/index.html +96 -0
- package/app/m/commerce/ContractLineItem/index.html +97 -0
- package/app/m/commerce/Customer/index.html +96 -0
- package/app/m/commerce/Estimate/index.html +96 -0
- package/app/m/commerce/Fulfillment/index.html +96 -0
- package/app/m/commerce/FulfillmentLineItem/index.html +97 -0
- package/app/m/commerce/Invoice/index.html +96 -0
- package/app/m/commerce/InvoiceLineItem/index.html +97 -0
- package/app/m/commerce/Lease/index.html +96 -0
- package/app/m/commerce/LicenseSale/index.html +96 -0
- package/app/m/commerce/Order/index.html +96 -0
- package/app/m/commerce/Payment/index.html +96 -0
- package/app/m/commerce/PaymentAllocation/index.html +97 -0
- package/app/m/commerce/PaymentInstrument/index.html +96 -0
- package/app/m/commerce/PaymentIntent/index.html +96 -0
- package/app/m/commerce/Payout/index.html +96 -0
- package/app/m/commerce/ProductionOrder/index.html +96 -0
- package/app/m/commerce/PurchaseOrder/index.html +96 -0
- package/app/m/commerce/Vendor/index.html +96 -0
- package/app/m/commerce/WholesaleOrder/index.html +96 -0
- package/app/m/content/Content/index.html +96 -0
- package/app/m/content/ContentContribution/index.html +96 -0
- package/app/m/content/ContentContributionAttachment/index.html +96 -0
- package/app/m/content/ContentContributionRevision/index.html +96 -0
- package/app/m/content/ContentContributionType/index.html +96 -0
- package/app/m/content/ContentContributor/index.html +96 -0
- package/app/m/content/ContentCorrection/index.html +96 -0
- package/app/m/content/ContentFeedSource/index.html +96 -0
- package/app/m/content/ContentGovernanceAssignment/index.html +96 -0
- package/app/m/content/ContentGovernancePolicy/index.html +96 -0
- package/app/m/content/ContentGovernanceProfile/index.html +96 -0
- package/app/m/content/ContentReference/index.html +96 -0
- package/app/m/content/ContentReview/index.html +96 -0
- package/app/m/content/ContentVersion/index.html +96 -0
- package/app/m/content/Contents/index.html +96 -0
- package/app/m/events/Event/index.html +96 -0
- package/app/m/events/EventParticipant/index.html +97 -0
- package/app/m/events/EventSeries/index.html +96 -0
- package/app/m/events/EventType/index.html +96 -0
- package/app/m/facts/Fact/index.html +96 -0
- package/app/m/facts/FactContent/index.html +96 -0
- package/app/m/facts/FactEvidence/index.html +96 -0
- package/app/m/facts/FactSource/index.html +96 -0
- package/app/m/facts/FactSubject/index.html +96 -0
- package/app/m/facts/FactTag/index.html +96 -0
- package/app/m/fields/FieldPolicy/index.html +96 -0
- package/app/m/fields/FieldPolicySuggestion/index.html +96 -0
- package/app/m/fields/FieldUsageCounter/index.html +96 -0
- package/app/m/images/Image/index.html +96 -0
- package/app/m/inventory/InventoryLocation/index.html +96 -0
- package/app/m/inventory/StockLevel/index.html +96 -0
- package/app/m/inventory/StockMovement/index.html +96 -0
- package/app/m/ledgers/Account/index.html +96 -0
- package/app/m/ledgers/Journal/index.html +96 -0
- package/app/m/ledgers/JournalEntry/index.html +97 -0
- package/app/m/manufacturing/Assembly/index.html +96 -0
- package/app/m/manufacturing/BillOfMaterials/index.html +96 -0
- package/app/m/manufacturing/BomLine/index.html +96 -0
- package/app/m/manufacturing/Operation/index.html +96 -0
- package/app/m/manufacturing/ProductionRun/index.html +96 -0
- package/app/m/manufacturing/ProductionRunCompletion/index.html +96 -0
- package/app/m/manufacturing/RoutingStep/index.html +96 -0
- package/app/m/marketing/Campaign/index.html +96 -0
- package/app/m/marketing/CampaignChannel/index.html +96 -0
- package/app/m/marketing/CampaignMetricSnapshot/index.html +96 -0
- package/app/m/messages/Account/index.html +96 -0
- package/app/m/messages/Attachment/index.html +96 -0
- package/app/m/messages/Blacklist/index.html +96 -0
- package/app/m/messages/Email/failed-sends/index.html +96 -0
- package/app/m/messages/Email/index.html +96 -0
- package/app/m/messages/Email/mailbox/index.html +96 -0
- package/app/m/messages/EmailAccount/index.html +96 -0
- package/app/m/messages/EmailFolder/index.html +96 -0
- package/app/m/messages/Message/index.html +96 -0
- package/app/m/messages/MessagingEndpoint/index.html +96 -0
- package/app/m/messages/PersonaMessageRoute/index.html +96 -0
- package/app/m/messages/SlackAccount/index.html +96 -0
- package/app/m/messages/SlackMessage/index.html +96 -0
- package/app/m/messages/TelegramAccount/index.html +96 -0
- package/app/m/messages/Tweet/index.html +96 -0
- package/app/m/messages/TwitterAccount/index.html +96 -0
- package/app/m/messages/Whitelist/index.html +96 -0
- package/app/m/messages/ZulipAccount/index.html +96 -0
- package/app/m/places/Place/index.html +96 -0
- package/app/m/places/PlaceType/index.html +96 -0
- package/app/m/preferences/UiPreferenceRecord/index.html +96 -0
- package/app/m/products/Category/index.html +96 -0
- package/app/m/products/Material/index.html +96 -0
- package/app/m/products/Product/index.html +96 -0
- package/app/m/products/Product/ingredients/index.html +96 -0
- package/app/m/products/ProductVariant/index.html +97 -0
- package/app/m/products/Sku/index.html +97 -0
- package/app/m/profiles/ApiKey/index.html +96 -0
- package/app/m/profiles/Bot/index.html +96 -0
- package/app/m/profiles/MagicLinkToken/index.html +96 -0
- package/app/m/profiles/NostrIdentity/index.html +96 -0
- package/app/m/profiles/OidcIdentity/index.html +96 -0
- package/app/m/profiles/Organization/index.html +96 -0
- package/app/m/profiles/Person/index.html +96 -0
- package/app/m/profiles/Profile/index.html +96 -0
- package/app/m/profiles/ProfileMetadata/index.html +96 -0
- package/app/m/profiles/ProfileMetafield/index.html +96 -0
- package/app/m/profiles/ProfileRelationship/index.html +96 -0
- package/app/m/profiles/ProfileRelationshipTerm/index.html +96 -0
- package/app/m/profiles/ProfileRelationshipType/index.html +96 -0
- package/app/m/profiles/ProfileType/index.html +96 -0
- package/app/m/projects/Comment/index.html +97 -0
- package/app/m/projects/Issue/index.html +96 -0
- package/app/m/projects/Label/index.html +96 -0
- package/app/m/projects/Project/index.html +96 -0
- package/app/m/projects/ProjectIntegration/index.html +96 -0
- package/app/m/projects/PullRequest/index.html +96 -0
- package/app/m/projects/Repository/index.html +96 -0
- package/app/m/properties/Property/index.html +96 -0
- package/app/m/properties/Zone/index.html +96 -0
- package/app/m/reports/RuntimeReport/index.html +96 -0
- package/app/m/reports/SmrtPrincipalReportRefreshTask/index.html +96 -0
- package/app/m/reports/SmrtReportLock/index.html +96 -0
- package/app/m/reports/SmrtReportRefreshTask/index.html +96 -0
- package/app/m/reports/SmrtReportRun/index.html +96 -0
- package/app/m/reports/SmrtReportSchedule/index.html +96 -0
- package/app/m/reports/SmrtReportWatermark/index.html +96 -0
- package/app/m/sales/AttributionException/index.html +96 -0
- package/app/m/sales/AttributionPolicy/index.html +96 -0
- package/app/m/sales/Commission/index.html +96 -0
- package/app/m/sales/CommissionAdjustment/index.html +96 -0
- package/app/m/sales/CommissionPayout/index.html +96 -0
- package/app/m/sales/CommissionPlan/index.html +96 -0
- package/app/m/sales/Earner/index.html +96 -0
- package/app/m/sales/EarnerSourceAttribution/index.html +96 -0
- package/app/m/sales/EarningEvent/index.html +96 -0
- package/app/m/sales/ExecutedAgreement/index.html +96 -0
- package/app/m/sales/Lead/index.html +96 -0
- package/app/m/sales/Opportunity/index.html +96 -0
- package/app/m/sales/OpportunityConversion/index.html +96 -0
- package/app/m/sales/PipelineDefinition/index.html +96 -0
- package/app/m/sales/PipelineStage/index.html +97 -0
- package/app/m/sales/Referral/index.html +96 -0
- package/app/m/sales/ReferralAgreement/index.html +96 -0
- package/app/m/sales/ReferralLink/index.html +96 -0
- package/app/m/sales/ReferralProgram/index.html +96 -0
- package/app/m/sales/ReferralTermSnapshot/index.html +96 -0
- package/app/m/sales/ReferralTouch/index.html +96 -0
- package/app/m/sales/Referrer/index.html +96 -0
- package/app/m/sales/SalesActivity/index.html +96 -0
- package/app/m/sales/SalesRepresentative/index.html +96 -0
- package/app/m/sites/Site/index.html +96 -0
- package/app/m/sites/SiteAgentBinding/index.html +96 -0
- package/app/m/social/OAuthState/index.html +96 -0
- package/app/m/social/SocialAccount/index.html +96 -0
- package/app/m/social/SocialPost/index.html +96 -0
- package/app/m/social/SocialPostAnalyticsSnapshot/index.html +96 -0
- package/app/m/subscriptions/BillingAdjustment/index.html +96 -0
- package/app/m/subscriptions/ClientCharge/index.html +96 -0
- package/app/m/subscriptions/CreditGrant/index.html +96 -0
- package/app/m/subscriptions/PricingRule/index.html +96 -0
- package/app/m/subscriptions/RetailCharge/index.html +96 -0
- package/app/m/subscriptions/SpendingPolicy/index.html +96 -0
- package/app/m/subscriptions/SubscriptionPlan/index.html +96 -0
- package/app/m/subscriptions/TenantSubscription/index.html +96 -0
- package/app/m/subscriptions/TenantUsageMetric/index.html +96 -0
- package/app/m/support/ServiceTimeEntry/index.html +96 -0
- package/app/m/support/SupportAiRun/index.html +96 -0
- package/app/m/support/SupportAvailability/index.html +96 -0
- package/app/m/support/SupportCase/index.html +96 -0
- package/app/m/support/SupportCaseEvent/index.html +96 -0
- package/app/m/support/SupportChannelBinding/index.html +96 -0
- package/app/m/support/SupportCharge/index.html +96 -0
- package/app/m/support/SupportCompensation/index.html +96 -0
- package/app/m/support/SupportCompensationPlan/index.html +96 -0
- package/app/m/support/SupportEscalation/index.html +96 -0
- package/app/m/support/SupportInteraction/index.html +96 -0
- package/app/m/support/SupportPlan/index.html +96 -0
- package/app/m/support/SupportPolicy/index.html +96 -0
- package/app/m/support/SupportQualification/index.html +96 -0
- package/app/m/support/SupportServiceTarget/index.html +96 -0
- package/app/m/support/SupportSpecialist/index.html +96 -0
- package/app/m/support/SupportWorkLink/index.html +96 -0
- package/app/m/tags/Tag/index.html +96 -0
- package/app/m/tags/TagAlias/index.html +96 -0
- package/app/m/timesheets/AttendanceBreak/index.html +96 -0
- package/app/m/timesheets/AttendancePunch/index.html +96 -0
- package/app/m/timesheets/ServiceChargeSnapshot/index.html +96 -0
- package/app/m/timesheets/ServiceCompensationSnapshot/index.html +96 -0
- package/app/m/timesheets/ServiceTimeEntry/index.html +96 -0
- package/app/m/users/AccessRequest/index.html +96 -0
- package/app/m/users/Group/index.html +96 -0
- package/app/m/users/GroupMember/index.html +96 -0
- package/app/m/users/GroupRole/index.html +96 -0
- package/app/m/users/Membership/index.html +97 -0
- package/app/m/users/MembershipOverride/index.html +96 -0
- package/app/m/users/Permission/index.html +96 -0
- package/app/m/users/ResourceGrant/index.html +96 -0
- package/app/m/users/Role/index.html +96 -0
- package/app/m/users/RolePermission/index.html +96 -0
- package/app/m/users/Session/index.html +96 -0
- package/app/m/users/Tenant/index.html +96 -0
- package/app/m/users/TenantIntegration/index.html +96 -0
- package/app/m/users/TenantPermissionOverride/index.html +96 -0
- package/app/m/users/User/index.html +96 -0
- package/app/m/users/UsersCliAuthRequest/index.html +96 -0
- package/app/m/users/UsersMagicLinkToken/index.html +96 -0
- package/app/m/video/Character/index.html +96 -0
- package/app/m/video/CharacterAsset/index.html +96 -0
- package/app/m/video/CompositeJob/index.html +96 -0
- package/app/m/video/Performer/index.html +96 -0
- package/app/m/video/PerformerAsset/index.html +96 -0
- package/app/m/video/Scene/index.html +96 -0
- package/app/m/video/SceneAsset/index.html +96 -0
- package/app/m/video/VideoComposition/index.html +96 -0
- package/app/m/video/VideoCompositionAsset/index.html +96 -0
- package/app/m/video/VideoSequence/index.html +96 -0
- package/app/m/video/VideoSequenceAsset/index.html +96 -0
- package/app/m/video/VideoShot/index.html +96 -0
- package/app/m/video/VideoShotAsset/index.html +96 -0
- package/app/m/video/VideoShotCharacter/index.html +96 -0
- package/app/m/video/VideoWorkflow/index.html +96 -0
- package/app/m/voice/VoiceOutput/index.html +96 -0
- package/app/m/voice/VoiceProfile/index.html +96 -0
- package/app/m/voice/VoiceSample/index.html +96 -0
- package/app/packages/ads/index.html +92 -0
- package/app/packages/analytics/index.html +92 -0
- package/app/packages/approvals/index.html +92 -0
- package/app/packages/assets/index.html +92 -0
- package/app/packages/chat/index.html +92 -0
- package/app/packages/comments/index.html +92 -0
- package/app/packages/commerce/index.html +92 -0
- package/app/packages/content/index.html +92 -0
- package/app/packages/events/index.html +92 -0
- package/app/packages/expenses/index.html +92 -0
- package/app/packages/facts/index.html +92 -0
- package/app/packages/fields/index.html +92 -0
- package/app/packages/human-resources/index.html +92 -0
- package/app/packages/images/index.html +92 -0
- package/app/packages/index.html +90 -0
- package/app/packages/inventory/index.html +92 -0
- package/app/packages/ledgers/index.html +92 -0
- package/app/packages/manufacturing/index.html +92 -0
- package/app/packages/marketing/index.html +92 -0
- package/app/packages/messages/index.html +92 -0
- package/app/packages/places/index.html +92 -0
- package/app/packages/preferences/index.html +92 -0
- package/app/packages/products/index.html +92 -0
- package/app/packages/profiles/index.html +92 -0
- package/app/packages/projects/index.html +92 -0
- package/app/packages/properties/index.html +92 -0
- package/app/packages/reports/index.html +92 -0
- package/app/packages/sales/index.html +92 -0
- package/app/packages/sites/index.html +92 -0
- package/app/packages/social/index.html +92 -0
- package/app/packages/subscriptions/index.html +92 -0
- package/app/packages/support/index.html +92 -0
- package/app/packages/tags/index.html +92 -0
- package/app/packages/timesheets/index.html +92 -0
- package/app/packages/users/index.html +92 -0
- package/app/packages/video/index.html +92 -0
- package/app/packages/voice/index.html +92 -0
- package/app/recipes/account-access/help/index.html +93 -0
- package/app/recipes/account-access/index.html +95 -0
- package/app/recipes/activity/help/index.html +93 -0
- package/app/recipes/activity/index.html +94 -0
- package/app/recipes/agreements/help/index.html +93 -0
- package/app/recipes/agreements/index.html +96 -0
- package/app/recipes/analytics.reports/help/index.html +93 -0
- package/app/recipes/analytics.reports/index.html +94 -0
- package/app/recipes/assets/help/index.html +93 -0
- package/app/recipes/assets/index.html +95 -0
- package/app/recipes/billing/help/index.html +93 -0
- package/app/recipes/billing/index.html +95 -0
- package/app/recipes/chat.assistant/help/index.html +93 -0
- package/app/recipes/chat.assistant/index.html +94 -0
- package/app/recipes/comments/help/index.html +93 -0
- package/app/recipes/comments/index.html +94 -0
- package/app/recipes/commerce.customers/help/index.html +93 -0
- package/app/recipes/commerce.customers/index.html +94 -0
- package/app/recipes/commerce.estimates/help/index.html +93 -0
- package/app/recipes/commerce.estimates/index.html +94 -0
- package/app/recipes/commerce.purchases/help/index.html +93 -0
- package/app/recipes/commerce.purchases/index.html +94 -0
- package/app/recipes/commerce.sales/help/index.html +93 -0
- package/app/recipes/commerce.sales/index.html +94 -0
- package/app/recipes/commerce.vendors/help/index.html +93 -0
- package/app/recipes/commerce.vendors/index.html +94 -0
- package/app/recipes/commerce.wholesale/help/index.html +93 -0
- package/app/recipes/commerce.wholesale/index.html +94 -0
- package/app/recipes/events.calendar/help/index.html +93 -0
- package/app/recipes/events.calendar/index.html +94 -0
- package/app/recipes/fields.form-customization/help/index.html +93 -0
- package/app/recipes/fields.form-customization/index.html +94 -0
- package/app/recipes/inventory.stock/help/index.html +93 -0
- package/app/recipes/inventory.stock/index.html +94 -0
- package/app/recipes/ledgers.bookkeeping/help/index.html +93 -0
- package/app/recipes/ledgers.bookkeeping/index.html +94 -0
- package/app/recipes/messages/help/index.html +93 -0
- package/app/recipes/messages/index.html +95 -0
- package/app/recipes/products/help/index.html +93 -0
- package/app/recipes/products/index.html +96 -0
- package/app/recipes/projects.tracker/help/index.html +93 -0
- package/app/recipes/projects.tracker/index.html +94 -0
- package/app/recipes/reports.materialized/help/index.html +93 -0
- package/app/recipes/reports.materialized/index.html +94 -0
- package/app/recipes/sales.pipeline/help/index.html +93 -0
- package/app/recipes/sales.pipeline/index.html +94 -0
- package/app/recipes/tags.taxonomy/help/index.html +93 -0
- package/app/recipes/tags.taxonomy/index.html +94 -0
- package/app/recipes/team-collaboration/help/index.html +93 -0
- package/app/recipes/team-collaboration/index.html +94 -0
- package/app/s/custom-billing/index.html +89 -0
- package/app/s/custom-buying/index.html +89 -0
- package/app/s/custom-classes/index.html +89 -0
- package/app/s/custom-jobs/index.html +89 -0
- package/app/s/custom-kitchen/index.html +89 -0
- package/app/s/custom-material/index.html +89 -0
- package/app/s/custom-members/index.html +89 -0
- package/app/s/custom-parts/index.html +89 -0
- package/app/s/custom-schedule/index.html +89 -0
- package/app/s/custom-shop/index.html +89 -0
- package/app/s/custom-wholesale/index.html +89 -0
- package/app/s/section-access-control/index.html +89 -0
- package/app/s/section-account-security/index.html +89 -0
- package/app/s/section-accounting/index.html +89 -0
- package/app/s/section-activity/index.html +89 -0
- package/app/s/section-agreements/index.html +89 -0
- package/app/s/section-analytics/index.html +89 -0
- package/app/s/section-assets/index.html +89 -0
- package/app/s/section-billing/index.html +89 -0
- package/app/s/section-calendar/index.html +89 -0
- package/app/s/section-catalog/index.html +89 -0
- package/app/s/section-chat.assistant/index.html +89 -0
- package/app/s/section-comments/index.html +89 -0
- package/app/s/section-fields.form-customization/index.html +89 -0
- package/app/s/section-messages/index.html +89 -0
- package/app/s/section-more/index.html +89 -0
- package/app/s/section-operations/index.html +89 -0
- package/app/s/section-projects/index.html +89 -0
- package/app/s/section-purchasing/index.html +89 -0
- package/app/s/section-reports.materialized/index.html +89 -0
- package/app/s/section-sales/index.html +89 -0
- package/app/s/section-taxonomy/index.html +89 -0
- package/app/s/section-team/index.html +89 -0
- package/dist/ai/echo-gate.d.ts +13 -0
- package/dist/ai/echo-gate.js +21 -0
- package/dist/ai/icons.d.ts +9 -0
- package/dist/ai/icons.js +9 -0
- package/dist/ai/instance.d.ts +3 -0
- package/dist/ai/instance.js +25 -0
- package/dist/ai/state.svelte.d.ts +125 -0
- package/dist/ai/state.svelte.js +286 -0
- package/dist/ai/status.d.ts +67 -0
- package/dist/ai/status.js +117 -0
- package/dist/assets/smrt-mark.svg +38 -0
- package/dist/assistant/change.d.ts +101 -0
- package/dist/assistant/change.js +209 -0
- package/dist/assistant/engine.d.ts +20 -0
- package/dist/assistant/engine.js +43 -0
- package/dist/assistant/llm.worker.d.ts +1 -0
- package/dist/assistant/llm.worker.js +7 -0
- package/dist/assistant/match.d.ts +59 -0
- package/dist/assistant/match.js +271 -0
- package/dist/assistant/models.d.ts +38 -0
- package/dist/assistant/models.js +57 -0
- package/dist/assistant/offers.svelte.d.ts +36 -0
- package/dist/assistant/offers.svelte.js +59 -0
- package/dist/assistant/prefs.d.ts +14 -0
- package/dist/assistant/prefs.js +32 -0
- package/dist/assistant/prompt.d.ts +23 -0
- package/dist/assistant/prompt.js +163 -0
- package/dist/assistant/session.svelte.d.ts +73 -0
- package/dist/assistant/session.svelte.js +163 -0
- package/dist/assistant/theme-undo.svelte.d.ts +38 -0
- package/dist/assistant/theme-undo.svelte.js +50 -0
- package/dist/assistant/transport.d.ts +73 -0
- package/dist/assistant/transport.js +231 -0
- package/dist/assistant/voice-host.d.ts +10 -0
- package/dist/assistant/voice-host.js +17 -0
- package/dist/assistant/voice.svelte.d.ts +107 -0
- package/dist/assistant/voice.svelte.js +261 -0
- package/dist/catalog/catalog.json +89663 -0
- package/dist/catalog/generate/build.d.ts +33 -0
- package/dist/catalog/generate/build.js +131 -0
- package/dist/catalog/generate/exclusions.d.ts +18 -0
- package/dist/catalog/generate/exclusions.js +33 -0
- package/dist/catalog/generate/extract.d.ts +90 -0
- package/dist/catalog/generate/extract.js +326 -0
- package/dist/catalog/generate/local.d.ts +8 -0
- package/dist/catalog/generate/local.js +45 -0
- package/dist/catalog/generate/recipe-demo.d.ts +11 -0
- package/dist/catalog/generate/recipe-demo.js +29 -0
- package/dist/catalog/generate/recipe-metadata.d.ts +12 -0
- package/dist/catalog/generate/recipe-metadata.js +138 -0
- package/dist/catalog/generate/registry.d.ts +14 -0
- package/dist/catalog/generate/registry.js +83 -0
- package/dist/catalog/index.d.ts +21 -0
- package/dist/catalog/index.js +53 -0
- package/dist/catalog/types.d.ts +141 -0
- package/dist/catalog/types.js +8 -0
- package/dist/components/AiSetup.svelte +499 -0
- package/dist/components/AiSetup.svelte.d.ts +8 -0
- package/dist/components/AiStatusIcons.svelte +86 -0
- package/dist/components/AiStatusIcons.svelte.d.ts +18 -0
- package/dist/components/AppSettings.svelte +100 -0
- package/dist/components/AppSettings.svelte.d.ts +10 -0
- package/dist/components/BrowserAssistant.svelte +314 -0
- package/dist/components/BrowserAssistant.svelte.d.ts +8 -0
- package/dist/components/ChildRecords.svelte +331 -0
- package/dist/components/ChildRecords.svelte.d.ts +15 -0
- package/dist/components/ConnectTools.svelte +145 -0
- package/dist/components/ConnectTools.svelte.d.ts +8 -0
- package/dist/components/CookbooksPanel.svelte +308 -0
- package/dist/components/CookbooksPanel.svelte.d.ts +3 -0
- package/dist/components/ExportPanel.svelte +217 -0
- package/dist/components/ExportPanel.svelte.d.ts +3 -0
- package/dist/components/FeatureCard.svelte +197 -0
- package/dist/components/FeatureCard.svelte.d.ts +13 -0
- package/dist/components/FeaturesPanel.svelte +155 -0
- package/dist/components/FeaturesPanel.svelte.d.ts +3 -0
- package/dist/components/FieldInput.svelte +307 -0
- package/dist/components/FieldInput.svelte.d.ts +24 -0
- package/dist/components/FieldMapForm.svelte +173 -0
- package/dist/components/FieldMapForm.svelte.d.ts +18 -0
- package/dist/components/FormWorkspace.svelte +274 -0
- package/dist/components/FormWorkspace.svelte.d.ts +19 -0
- package/dist/components/HelpView.svelte +129 -0
- package/dist/components/HelpView.svelte.d.ts +12 -0
- package/dist/components/ModelOptions.svelte +239 -0
- package/dist/components/ModelOptions.svelte.d.ts +12 -0
- package/dist/components/ModelPage.svelte +295 -0
- package/dist/components/ModelPage.svelte.d.ts +9 -0
- package/dist/components/ModelWorkspace.svelte +488 -0
- package/dist/components/ModelWorkspace.svelte.d.ts +32 -0
- package/dist/components/PlannerEditBridge.svelte +36 -0
- package/dist/components/PlannerEditBridge.svelte.d.ts +3 -0
- package/dist/components/PlannerPalette.svelte +38 -0
- package/dist/components/PlannerPalette.svelte.d.ts +18 -0
- package/dist/components/RecipeCards.svelte +145 -0
- package/dist/components/RecipeCards.svelte.d.ts +3 -0
- package/dist/components/RecipeHelp.svelte +54 -0
- package/dist/components/RecipeHelp.svelte.d.ts +9 -0
- package/dist/components/RecipeOptions.svelte +160 -0
- package/dist/components/RecipeOptions.svelte.d.ts +9 -0
- package/dist/components/RecordFeatures.svelte +240 -0
- package/dist/components/RecordFeatures.svelte.d.ts +3 -0
- package/dist/components/RelationField.svelte +175 -0
- package/dist/components/RelationField.svelte.d.ts +16 -0
- package/dist/components/SectionActions.svelte +91 -0
- package/dist/components/SectionActions.svelte.d.ts +12 -0
- package/dist/components/SectionIcons.svelte +98 -0
- package/dist/components/SectionIcons.svelte.d.ts +15 -0
- package/dist/components/SectionOverview.svelte +65 -0
- package/dist/components/SectionOverview.svelte.d.ts +14 -0
- package/dist/components/SectionPage.svelte +230 -0
- package/dist/components/SectionPage.svelte.d.ts +7 -0
- package/dist/components/SettingsPanel.svelte +60 -0
- package/dist/components/SettingsPanel.svelte.d.ts +7 -0
- package/dist/components/ThemeBridge.svelte +56 -0
- package/dist/components/ThemeBridge.svelte.d.ts +3 -0
- package/dist/components/ThemeSection.svelte +167 -0
- package/dist/components/ThemeSection.svelte.d.ts +11 -0
- package/dist/components/VariantGridForm.svelte +309 -0
- package/dist/components/VariantGridForm.svelte.d.ts +12 -0
- package/dist/components/VoiceTyping.svelte +108 -0
- package/dist/components/VoiceTyping.svelte.d.ts +7 -0
- package/dist/cookbook/assemble.d.ts +16 -0
- package/dist/cookbook/assemble.js +29 -0
- package/dist/cookbook/file.d.ts +7 -0
- package/dist/cookbook/file.js +25 -0
- package/dist/cookbook/legacy.d.ts +9 -0
- package/dist/cookbook/legacy.js +87 -0
- package/dist/cookbook/migrate.d.ts +22 -0
- package/dist/cookbook/migrate.js +106 -0
- package/dist/cookbook/parse.d.ts +16 -0
- package/dist/cookbook/parse.js +246 -0
- package/dist/cookbook/storage.d.ts +45 -0
- package/dist/cookbook/storage.js +98 -0
- package/dist/cookbook/store.svelte.d.ts +94 -0
- package/dist/cookbook/store.svelte.js +231 -0
- package/dist/cookbook/types.d.ts +76 -0
- package/dist/cookbook/types.js +11 -0
- package/dist/cookbook/validate.d.ts +14 -0
- package/dist/cookbook/validate.js +29 -0
- package/dist/core/app.d.ts +12 -0
- package/dist/core/app.js +15 -0
- package/dist/core/catalog.d.ts +19 -0
- package/dist/core/catalog.js +9 -0
- package/dist/core/headless.d.ts +52 -0
- package/dist/core/headless.js +39 -0
- package/dist/core/index.d.ts +28 -0
- package/dist/core/index.js +28 -0
- package/dist/core/prompt.d.ts +38 -0
- package/dist/core/prompt.js +95 -0
- package/dist/core/reply.d.ts +60 -0
- package/dist/core/reply.js +89 -0
- package/dist/core/request.d.ts +15 -0
- package/dist/core/request.js +55 -0
- package/dist/data/children.d.ts +20 -0
- package/dist/data/children.js +80 -0
- package/dist/data/columns.d.ts +56 -0
- package/dist/data/columns.js +150 -0
- package/dist/data/context.d.ts +8 -0
- package/dist/data/context.js +19 -0
- package/dist/data/derived.d.ts +79 -0
- package/dist/data/derived.js +139 -0
- package/dist/data/display.d.ts +23 -0
- package/dist/data/display.js +84 -0
- package/dist/data/fakes.d.ts +52 -0
- package/dist/data/fakes.js +443 -0
- package/dist/data/format.d.ts +48 -0
- package/dist/data/format.js +121 -0
- package/dist/data/labels.d.ts +45 -0
- package/dist/data/labels.js +179 -0
- package/dist/data/packs.d.ts +95 -0
- package/dist/data/packs.js +830 -0
- package/dist/data/payments.d.ts +17 -0
- package/dist/data/payments.js +60 -0
- package/dist/data/planner-source.d.ts +7 -0
- package/dist/data/planner-source.js +32 -0
- package/dist/data/source.d.ts +119 -0
- package/dist/data/source.js +432 -0
- package/dist/features/catalogue.d.ts +96 -0
- package/dist/features/catalogue.js +225 -0
- package/dist/features/demo.d.ts +36 -0
- package/dist/features/demo.js +66 -0
- package/dist/features/palette.d.ts +39 -0
- package/dist/features/palette.js +53 -0
- package/dist/fields/address.d.ts +23 -0
- package/dist/fields/address.js +39 -0
- package/dist/fields/invalid.d.ts +2 -0
- package/dist/fields/invalid.js +8 -0
- package/dist/fields/modal.d.ts +7 -0
- package/dist/fields/modal.js +14 -0
- package/dist/fields/percent.d.ts +8 -0
- package/dist/fields/percent.js +16 -0
- package/dist/fields/renderer.d.ts +17 -0
- package/dist/fields/renderer.js +43 -0
- package/dist/forms/active.d.ts +16 -0
- package/dist/forms/active.js +24 -0
- package/dist/forms/fieldMap.d.ts +44 -0
- package/dist/forms/fieldMap.js +134 -0
- package/dist/forms/shared.d.ts +41 -0
- package/dist/forms/shared.js +138 -0
- package/dist/forms/stock.d.ts +28 -0
- package/dist/forms/stock.js +104 -0
- package/dist/forms/variantGrid.d.ts +83 -0
- package/dist/forms/variantGrid.js +283 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +16 -0
- package/dist/inference/byo.svelte.d.ts +86 -0
- package/dist/inference/byo.svelte.js +267 -0
- package/dist/inference/config.d.ts +70 -0
- package/dist/inference/config.js +149 -0
- package/dist/inference/host.d.ts +40 -0
- package/dist/inference/host.js +57 -0
- package/dist/inference/openai.d.ts +59 -0
- package/dist/inference/openai.js +202 -0
- package/dist/inference/presets.d.ts +5 -0
- package/dist/inference/presets.js +46 -0
- package/dist/kitchen/client.d.ts +39 -0
- package/dist/kitchen/client.js +109 -0
- package/dist/kitchen/fragment.d.ts +30 -0
- package/dist/kitchen/fragment.js +49 -0
- package/dist/kitchen/state.svelte.d.ts +26 -0
- package/dist/kitchen/state.svelte.js +45 -0
- package/dist/library/apply.d.ts +17 -0
- package/dist/library/apply.js +32 -0
- package/dist/library/document.d.ts +12 -0
- package/dist/library/document.js +27 -0
- package/dist/library/icons.d.ts +6 -0
- package/dist/library/icons.js +26 -0
- package/dist/library/index.d.ts +8 -0
- package/dist/library/index.js +12 -0
- package/dist/library/library.json +788 -0
- package/dist/library/menu.d.ts +18 -0
- package/dist/library/menu.js +72 -0
- package/dist/library/state.svelte.d.ts +10 -0
- package/dist/library/state.svelte.js +28 -0
- package/dist/library/types.d.ts +57 -0
- package/dist/library/types.js +1 -0
- package/dist/overviews/definitions.d.ts +24 -0
- package/dist/overviews/definitions.js +97 -0
- package/dist/overviews/page.d.ts +21 -0
- package/dist/overviews/page.js +36 -0
- package/dist/overviews/registry.d.ts +44 -0
- package/dist/overviews/registry.js +191 -0
- package/dist/overviews/validate.d.ts +32 -0
- package/dist/overviews/validate.js +91 -0
- package/dist/planner/Planner.svelte +204 -0
- package/dist/planner/Planner.svelte.d.ts +4 -0
- package/dist/planner/app.svelte.d.ts +6 -0
- package/dist/planner/app.svelte.js +23 -0
- package/dist/planner/assistant.d.ts +46 -0
- package/dist/planner/assistant.js +122 -0
- package/dist/planner/commands/adapter.d.ts +121 -0
- package/dist/planner/commands/adapter.js +597 -0
- package/dist/planner/commands/catalog.d.ts +19 -0
- package/dist/planner/commands/catalog.js +54 -0
- package/dist/planner/commands/controller.svelte.d.ts +13 -0
- package/dist/planner/commands/controller.svelte.js +77 -0
- package/dist/planner/commands/index.d.ts +15 -0
- package/dist/planner/commands/index.js +15 -0
- package/dist/planner/commands/schemas.d.ts +25 -0
- package/dist/planner/commands/schemas.js +67 -0
- package/dist/planner/commands/slices.d.ts +18 -0
- package/dist/planner/commands/slices.js +49 -0
- package/dist/planner/commands/types.d.ts +80 -0
- package/dist/planner/commands/types.js +18 -0
- package/dist/planner/create.d.ts +4 -0
- package/dist/planner/create.js +22 -0
- package/dist/planner/instance.d.ts +15 -0
- package/dist/planner/instance.js +22 -0
- package/dist/planner/query.d.ts +16 -0
- package/dist/planner/query.js +28 -0
- package/dist/planner/selection.d.ts +15 -0
- package/dist/planner/selection.js +38 -0
- package/dist/planner/selection.svelte.d.ts +29 -0
- package/dist/planner/selection.svelte.js +54 -0
- package/dist/planner/tab.svelte.d.ts +11 -0
- package/dist/planner/tab.svelte.js +22 -0
- package/dist/planner/types.d.ts +41 -0
- package/dist/planner/types.js +1 -0
- package/dist/recipes/cards.d.ts +55 -0
- package/dist/recipes/cards.js +80 -0
- package/dist/recipes/features.d.ts +53 -0
- package/dist/recipes/features.js +97 -0
- package/dist/recipes/help/descriptions.json +373 -0
- package/dist/recipes/help.d.ts +121 -0
- package/dist/recipes/help.js +262 -0
- package/dist/recipes/index.d.ts +65 -0
- package/dist/recipes/index.js +95 -0
- package/dist/recipes/merge.d.ts +26 -0
- package/dist/recipes/merge.js +21 -0
- package/dist/recipes/overlay.json +409 -0
- package/dist/recipes/plan-data.d.ts +41 -0
- package/dist/recipes/plan-data.js +97 -0
- package/dist/recipes/plumbing.d.ts +70 -0
- package/dist/recipes/plumbing.js +185 -0
- package/dist/recipes/policy.d.ts +118 -0
- package/dist/recipes/policy.js +268 -0
- package/dist/recipes/resolve.d.ts +19 -0
- package/dist/recipes/resolve.js +65 -0
- package/dist/recipes/scope.d.ts +25 -0
- package/dist/recipes/scope.js +31 -0
- package/dist/recipes/sections.d.ts +49 -0
- package/dist/recipes/sections.js +84 -0
- package/dist/recipes/state.svelte.d.ts +67 -0
- package/dist/recipes/state.svelte.js +112 -0
- package/dist/recipes/types.d.ts +322 -0
- package/dist/recipes/types.js +8 -0
- package/dist/sections/entries.d.ts +30 -0
- package/dist/sections/entries.js +57 -0
- package/dist/sections/info.d.ts +16 -0
- package/dist/sections/info.js +39 -0
- package/dist/sections/path.d.ts +12 -0
- package/dist/sections/path.js +18 -0
- package/dist/settings/app-settings.d.ts +44 -0
- package/dist/settings/app-settings.js +138 -0
- package/dist/settings/currencies.d.ts +2 -0
- package/dist/settings/currencies.js +8 -0
- package/dist/theme/runtime.d.ts +14 -0
- package/dist/theme/runtime.js +27 -0
- package/dist/theme/theme.d.ts +47 -0
- package/dist/theme/theme.js +122 -0
- package/dist/upstream/CustomerSelect.svelte +60 -0
- package/dist/upstream/CustomerSelect.svelte.d.ts +17 -0
- package/dist/upstream/VendorSelect.svelte +60 -0
- package/dist/upstream/VendorSelect.svelte.d.ts +17 -0
- package/dist/upstream/overlay.d.ts +10 -0
- package/dist/upstream/overlay.js +49 -0
- package/dist/upstream/partySelect.d.ts +8 -0
- package/dist/upstream/partySelect.js +21 -0
- package/dist/upstream/partyTypes.d.ts +64 -0
- package/dist/upstream/partyTypes.js +8 -0
- package/dist/upstream/relations.d.ts +2 -0
- package/dist/upstream/relations.js +24 -0
- package/dist/upstream/selects.d.ts +26 -0
- package/dist/upstream/selects.js +20 -0
- package/dist/upstream/widgets.d.ts +20 -0
- package/dist/upstream/widgets.js +30 -0
- package/package.json +80 -3
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { isMoneyField } from "../data/fakes.js";
|
|
2
|
+
import { isFractionRate } from "../data/format.js";
|
|
3
|
+
import { ADDRESS_FIELDS } from "../upstream/widgets.js";
|
|
4
|
+
/** A field that references another model, by manifest type or `related`. */
|
|
5
|
+
export function isRelation(field) {
|
|
6
|
+
return ((field.type === 'foreignKey' || field.type === 'crossPackageRef') &&
|
|
7
|
+
typeof field.related === 'string');
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* @param modelId the qualified name of the model that owns the field, which
|
|
11
|
+
* the address hint is keyed by (see `upstream/widgets.ts`).
|
|
12
|
+
*/
|
|
13
|
+
export function chooseRenderer(field, modelId) {
|
|
14
|
+
if (field.type === 'boolean')
|
|
15
|
+
return 'boolean';
|
|
16
|
+
if (isRelation(field))
|
|
17
|
+
return 'relation';
|
|
18
|
+
if (field.enum && field.enum.length > 0)
|
|
19
|
+
return 'enum';
|
|
20
|
+
if (field.ui?.widget)
|
|
21
|
+
return field.ui.widget;
|
|
22
|
+
if (field.type === 'json' &&
|
|
23
|
+
modelId !== undefined &&
|
|
24
|
+
(ADDRESS_FIELDS[modelId] ?? []).includes(field.name)) {
|
|
25
|
+
return 'address';
|
|
26
|
+
}
|
|
27
|
+
if (isMoneyField(field))
|
|
28
|
+
return 'money';
|
|
29
|
+
if (isFractionRate(field))
|
|
30
|
+
return 'percent';
|
|
31
|
+
switch (field.type) {
|
|
32
|
+
case 'datetime':
|
|
33
|
+
return 'datetime';
|
|
34
|
+
case 'integer':
|
|
35
|
+
return 'integer';
|
|
36
|
+
case 'decimal':
|
|
37
|
+
return 'decimal';
|
|
38
|
+
case 'json':
|
|
39
|
+
return 'json';
|
|
40
|
+
default:
|
|
41
|
+
return 'text';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FieldMapForm, Recipe, RecipeForm, RecipeFormExtension, VariantGridForm } from '../recipes/types.ts';
|
|
2
|
+
/** A form of an added recipe, with the extensions of the other added recipes. */
|
|
3
|
+
export interface ActiveForm<F extends RecipeForm = RecipeForm> {
|
|
4
|
+
recipeId: string;
|
|
5
|
+
form: F;
|
|
6
|
+
extensions: RecipeFormExtension[];
|
|
7
|
+
}
|
|
8
|
+
export declare function isFieldMap(active: ActiveForm): active is ActiveForm<FieldMapForm>;
|
|
9
|
+
export declare function isVariantGrid(active: ActiveForm): active is ActiveForm<VariantGridForm>;
|
|
10
|
+
/**
|
|
11
|
+
* The forms offered for a model by the recipes in `ids`, in the order the
|
|
12
|
+
* recipes are declared, each with the `extends` of every added recipe.
|
|
13
|
+
*/
|
|
14
|
+
export declare function activeForms(ids: readonly string[], recipes: readonly Recipe[], modelId: string): ActiveForm[];
|
|
15
|
+
/** Does any extension of the form bring in a row of this model? */
|
|
16
|
+
export declare function extendsWith(active: ActiveForm, modelId: string): boolean;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function isFieldMap(active) {
|
|
2
|
+
return active.form.kind === 'field-map';
|
|
3
|
+
}
|
|
4
|
+
export function isVariantGrid(active) {
|
|
5
|
+
return active.form.kind === 'variant-grid';
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The forms offered for a model by the recipes in `ids`, in the order the
|
|
9
|
+
* recipes are declared, each with the `extends` of every added recipe.
|
|
10
|
+
*/
|
|
11
|
+
export function activeForms(ids, recipes, modelId) {
|
|
12
|
+
const added = recipes.filter((recipe) => ids.includes(recipe.id));
|
|
13
|
+
return added.flatMap((recipe) => (recipe.forms ?? [])
|
|
14
|
+
.filter((form) => form.model === modelId)
|
|
15
|
+
.map((form) => ({
|
|
16
|
+
recipeId: recipe.id,
|
|
17
|
+
form,
|
|
18
|
+
extensions: added.flatMap((other) => (other.extends ?? []).filter((ext) => ext.form === form.id)),
|
|
19
|
+
})));
|
|
20
|
+
}
|
|
21
|
+
/** Does any extension of the form bring in a row of this model? */
|
|
22
|
+
export function extendsWith(active, modelId) {
|
|
23
|
+
return active.extensions.some((ext) => (ext.records ?? []).some((record) => record.model === modelId));
|
|
24
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { CatalogField } from '../catalog/types.ts';
|
|
2
|
+
import { type DataSource, type ModelRecord, type RecordWrite } from '../data/source.ts';
|
|
3
|
+
import type { FieldMapForm, RecipeFormField, RecipeFormRecord } from '../recipes/types.ts';
|
|
4
|
+
import type { ActiveForm } from './active.ts';
|
|
5
|
+
import { type ModelLookup } from './shared.ts';
|
|
6
|
+
/** The records and inputs of a field-map form once extensions are merged in. */
|
|
7
|
+
export declare function fieldMapParts(active: ActiveForm<FieldMapForm>): {
|
|
8
|
+
records: RecipeFormRecord[];
|
|
9
|
+
fields: RecipeFormField[];
|
|
10
|
+
};
|
|
11
|
+
/** Each input with the catalog field it maps onto, for rendering. */
|
|
12
|
+
export declare function fieldMapInputs(active: ActiveForm<FieldMapForm>, models: ModelLookup): {
|
|
13
|
+
field: RecipeFormField;
|
|
14
|
+
catalogField: CatalogField;
|
|
15
|
+
modelId: string;
|
|
16
|
+
}[];
|
|
17
|
+
/** Input values for a new row. */
|
|
18
|
+
export declare function blankFieldMap(active: ActiveForm<FieldMapForm>, models: ModelLookup): Record<string, unknown>;
|
|
19
|
+
/**
|
|
20
|
+
* The record the form edits by id: the one of the form's own `model` (a
|
|
21
|
+
* Customer form's Customer, though its Profile is written first), else the
|
|
22
|
+
* first.
|
|
23
|
+
*/
|
|
24
|
+
export declare function primaryIndex(active: ActiveForm<FieldMapForm>): number;
|
|
25
|
+
/** The rows an existing primary row's records point at, by alias. */
|
|
26
|
+
export declare function findFieldMapRows(source: DataSource, active: ActiveForm<FieldMapForm>, models: ModelLookup, id: string): Promise<Record<string, ModelRecord | undefined>>;
|
|
27
|
+
/**
|
|
28
|
+
* Load an existing row's input values, following the records' matches, with
|
|
29
|
+
* the rows found (hand them back to {@link planFieldMapSave}).
|
|
30
|
+
*/
|
|
31
|
+
export declare function loadFieldMapState(source: DataSource, active: ActiveForm<FieldMapForm>, models: ModelLookup, id: string): Promise<{
|
|
32
|
+
values: Record<string, unknown>;
|
|
33
|
+
rows: Record<string, ModelRecord | undefined>;
|
|
34
|
+
}>;
|
|
35
|
+
/** Load an existing row's input values. */
|
|
36
|
+
export declare function loadFieldMap(source: DataSource, active: ActiveForm<FieldMapForm>, models: ModelLookup, id: string): Promise<Record<string, unknown>>;
|
|
37
|
+
/**
|
|
38
|
+
* The related writes that save a field-map form: each record in order, found
|
|
39
|
+
* or created by its `match` and written with the inputs mapped to it. When
|
|
40
|
+
* editing (`id`), the primary record is updated by `id` and every record
|
|
41
|
+
* `rows` already holds (see {@link findFieldMapRows}) by its own id; the rest
|
|
42
|
+
* are found or created as on a new row. Pure; `apply` runs it.
|
|
43
|
+
*/
|
|
44
|
+
export declare function planFieldMapSave(active: ActiveForm<FieldMapForm>, models: ModelLookup, values: Readonly<Record<string, unknown>>, id?: string, rows?: Readonly<Record<string, ModelRecord | undefined>>, preset?: Readonly<Record<string, unknown>>): RecordWrite[];
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { isRecordRef, } from "../data/source.js";
|
|
2
|
+
import { contextFrom, findRows, mappedValues, parseTarget, scalar, startingValue, targetField, targetModelId, toWriteValues, } from "./shared.js";
|
|
3
|
+
/** The records and inputs of a field-map form once extensions are merged in. */
|
|
4
|
+
export function fieldMapParts(active) {
|
|
5
|
+
return {
|
|
6
|
+
records: [
|
|
7
|
+
...active.form.records,
|
|
8
|
+
...active.extensions.flatMap((ext) => ext.records ?? []),
|
|
9
|
+
],
|
|
10
|
+
fields: [
|
|
11
|
+
...active.form.fields,
|
|
12
|
+
...active.extensions.flatMap((ext) => ext.fields ?? []),
|
|
13
|
+
],
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** Each input with the catalog field it maps onto, for rendering. */
|
|
17
|
+
export function fieldMapInputs(active, models) {
|
|
18
|
+
const { records, fields } = fieldMapParts(active);
|
|
19
|
+
return fields.map((field) => ({
|
|
20
|
+
field,
|
|
21
|
+
catalogField: targetField(field, records, models),
|
|
22
|
+
modelId: targetModelId(field, records),
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
/** Input values for a new row. */
|
|
26
|
+
export function blankFieldMap(active, models) {
|
|
27
|
+
return Object.fromEntries(fieldMapInputs(active, models).map(({ field, catalogField }) => [
|
|
28
|
+
field.id,
|
|
29
|
+
startingValue(field, catalogField),
|
|
30
|
+
]));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The record the form edits by id: the one of the form's own `model` (a
|
|
34
|
+
* Customer form's Customer, though its Profile is written first), else the
|
|
35
|
+
* first.
|
|
36
|
+
*/
|
|
37
|
+
export function primaryIndex(active) {
|
|
38
|
+
const { records } = fieldMapParts(active);
|
|
39
|
+
const found = records.findIndex((r) => r.model === active.form.model);
|
|
40
|
+
return found < 0 ? 0 : found;
|
|
41
|
+
}
|
|
42
|
+
/** The rows an existing primary row's records point at, by alias. */
|
|
43
|
+
export async function findFieldMapRows(source, active, models, id) {
|
|
44
|
+
const { records } = fieldMapParts(active);
|
|
45
|
+
const primary = records[primaryIndex(active)];
|
|
46
|
+
if (!primary)
|
|
47
|
+
return {};
|
|
48
|
+
const row = await source.get(models(primary.model), id);
|
|
49
|
+
return findRows(source, records, { [primary.as]: row }, models);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Load an existing row's input values, following the records' matches, with
|
|
53
|
+
* the rows found (hand them back to {@link planFieldMapSave}).
|
|
54
|
+
*/
|
|
55
|
+
export async function loadFieldMapState(source, active, models, id) {
|
|
56
|
+
const { fields } = fieldMapParts(active);
|
|
57
|
+
const rows = await findFieldMapRows(source, active, models, id);
|
|
58
|
+
const blank = blankFieldMap(active, models);
|
|
59
|
+
const values = Object.fromEntries(fields.map((field) => {
|
|
60
|
+
const { alias, field: name } = parseTarget(field.to);
|
|
61
|
+
const value = rows[alias]?.[name];
|
|
62
|
+
return [field.id, value === undefined ? blank[field.id] : value];
|
|
63
|
+
}));
|
|
64
|
+
return { values, rows };
|
|
65
|
+
}
|
|
66
|
+
/** Load an existing row's input values. */
|
|
67
|
+
export async function loadFieldMap(source, active, models, id) {
|
|
68
|
+
return (await loadFieldMapState(source, active, models, id)).values;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The related writes that save a field-map form: each record in order, found
|
|
72
|
+
* or created by its `match` and written with the inputs mapped to it. When
|
|
73
|
+
* editing (`id`), the primary record is updated by `id` and every record
|
|
74
|
+
* `rows` already holds (see {@link findFieldMapRows}) by its own id; the rest
|
|
75
|
+
* are found or created as on a new row. Pure; `apply` runs it.
|
|
76
|
+
*/
|
|
77
|
+
export function planFieldMapSave(active, models, values, id, rows = {}, preset = {}) {
|
|
78
|
+
const { records, fields } = fieldMapParts(active);
|
|
79
|
+
const context = contextFrom(fields, values);
|
|
80
|
+
const primary = primaryIndex(active);
|
|
81
|
+
const written = new Set();
|
|
82
|
+
return records.map((record, index) => {
|
|
83
|
+
const mapped = mappedValues(fields, record.as, values);
|
|
84
|
+
// A page that lists a slice of rows (Ingredients) stamps new primary rows.
|
|
85
|
+
const createValues = {
|
|
86
|
+
...toWriteValues(record.values, context),
|
|
87
|
+
...(index === primary
|
|
88
|
+
? Object.fromEntries(Object.entries(preset).map(([key, v]) => [key, scalar(v)]))
|
|
89
|
+
: {}),
|
|
90
|
+
};
|
|
91
|
+
const model = models(record.model);
|
|
92
|
+
const existing = id !== undefined ? rows[record.as] : undefined;
|
|
93
|
+
try {
|
|
94
|
+
if (index === primary && id !== undefined) {
|
|
95
|
+
// Editing also (re)links a record created in this save, e.g. a
|
|
96
|
+
// Customer's Profile.
|
|
97
|
+
const links = Object.fromEntries(Object.entries(createValues).filter(([, v]) => isRecordRef(v)));
|
|
98
|
+
return {
|
|
99
|
+
op: 'save',
|
|
100
|
+
as: record.as,
|
|
101
|
+
model,
|
|
102
|
+
id,
|
|
103
|
+
values: { ...mapped, ...links },
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
if (existing) {
|
|
107
|
+
return {
|
|
108
|
+
op: 'save',
|
|
109
|
+
as: record.as,
|
|
110
|
+
model,
|
|
111
|
+
id: existing.id,
|
|
112
|
+
values: mapped,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
// A match naming a record that is written later only locates the row
|
|
116
|
+
// being edited; a new row has nothing to find.
|
|
117
|
+
const match = record.match ? toWriteValues(record.match, context) : {};
|
|
118
|
+
const later = Object.values(match).some((v) => isRecordRef(v) && !written.has(v.ref));
|
|
119
|
+
const usable = later ? {} : match;
|
|
120
|
+
const hasMatch = Object.keys(usable).length > 0;
|
|
121
|
+
return {
|
|
122
|
+
op: 'save',
|
|
123
|
+
as: record.as,
|
|
124
|
+
model,
|
|
125
|
+
...(hasMatch ? { match: usable } : {}),
|
|
126
|
+
onCreate: createValues,
|
|
127
|
+
values: mapped,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
written.add(record.as);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { CatalogField, CatalogModel } from '../catalog/types.ts';
|
|
2
|
+
import type { DataSource, ModelRecord, WriteValue } from '../data/source.ts';
|
|
3
|
+
import type { RecipeFormField, RecipeFormRecord, RecipeFormValue } from '../recipes/types.ts';
|
|
4
|
+
/** A catalog model by qualified name; a form naming a missing one is a bug. */
|
|
5
|
+
export type ModelLookup = (qualified: string) => CatalogModel;
|
|
6
|
+
export declare const catalogModels: ModelLookup;
|
|
7
|
+
/** What a template reads: `alias.field` to the value the form holds. */
|
|
8
|
+
export type TemplateContext = Readonly<Record<string, unknown>>;
|
|
9
|
+
/** `Blue Tee` to `BLUE-TEE`: upper-case letters and digits, joined by dashes. */
|
|
10
|
+
export declare function slug(value: unknown): string;
|
|
11
|
+
/** Fill `{alias.field}` and `{alias.field|slug}` in a string from the context. */
|
|
12
|
+
export declare function fillTemplate(text: string, context: TemplateContext): string;
|
|
13
|
+
/** A recipe value as a write value: templates filled, `{ref}` kept. */
|
|
14
|
+
export declare function toWriteValue(value: RecipeFormValue, context: TemplateContext, renameRef?: (alias: string) => string): WriteValue;
|
|
15
|
+
export declare function toWriteValues(values: Record<string, RecipeFormValue> | undefined, context: TemplateContext, renameRef?: (alias: string) => string): Record<string, WriteValue>;
|
|
16
|
+
/**
|
|
17
|
+
* An input's value as a write value: scalars and plain JSON objects (an
|
|
18
|
+
* Address) as they are, anything else null.
|
|
19
|
+
*/
|
|
20
|
+
export declare function scalar(value: unknown): WriteValue;
|
|
21
|
+
/** The inputs mapped to one record, as that record's field values. */
|
|
22
|
+
export declare function mappedValues(fields: readonly RecipeFormField[], alias: string, values: Readonly<Record<string, unknown>>): Record<string, WriteValue>;
|
|
23
|
+
/** `product.price` to `{ alias: 'product', field: 'price' }`. */
|
|
24
|
+
export declare function parseTarget(to: string): {
|
|
25
|
+
alias: string;
|
|
26
|
+
field: string;
|
|
27
|
+
};
|
|
28
|
+
/** The catalog field a form field maps onto. */
|
|
29
|
+
export declare function targetField(field: RecipeFormField, records: readonly RecipeFormRecord[], models: ModelLookup): CatalogField;
|
|
30
|
+
/** The qualified model a form field's record is of. */
|
|
31
|
+
export declare function targetModelId(field: RecipeFormField, records: readonly RecipeFormRecord[]): string;
|
|
32
|
+
/** The starting value of a field on a new row. */
|
|
33
|
+
export declare function startingValue(field: RecipeFormField, catalogField: CatalogField): unknown;
|
|
34
|
+
/** Context values (`alias.field`) from the form's field values. */
|
|
35
|
+
export declare function contextFrom(fields: readonly RecipeFormField[], values: Readonly<Record<string, unknown>>): Record<string, unknown>;
|
|
36
|
+
/**
|
|
37
|
+
* Rows a form's records currently point at: walk them in order, finding each
|
|
38
|
+
* by its (literal or `{ref}`) `match`. `seeded` rows (the one being edited)
|
|
39
|
+
* are taken as given. A record whose match cannot be resolved has no row.
|
|
40
|
+
*/
|
|
41
|
+
export declare function findRows(source: DataSource, records: readonly RecipeFormRecord[], seeded: Record<string, ModelRecord | undefined>, models: ModelLookup): Promise<Record<string, ModelRecord | undefined>>;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { getModelByQualifiedName } from "../catalog/index.js";
|
|
2
|
+
export const catalogModels = (qualified) => {
|
|
3
|
+
const found = getModelByQualifiedName(qualified);
|
|
4
|
+
if (!found)
|
|
5
|
+
throw new Error(`The catalog has no model ${qualified}`);
|
|
6
|
+
return found.model;
|
|
7
|
+
};
|
|
8
|
+
/** `Blue Tee` to `BLUE-TEE`: upper-case letters and digits, joined by dashes. */
|
|
9
|
+
export function slug(value) {
|
|
10
|
+
return String(value ?? '')
|
|
11
|
+
.toUpperCase()
|
|
12
|
+
.replace(/[^A-Z0-9]+/g, '-')
|
|
13
|
+
.replace(/^-+|-+$/g, '');
|
|
14
|
+
}
|
|
15
|
+
const PLACEHOLDER = /\{([A-Za-z_][\w]*\.[A-Za-z_][\w]*)(?:\|(slug))?\}/g;
|
|
16
|
+
/** Fill `{alias.field}` and `{alias.field|slug}` in a string from the context. */
|
|
17
|
+
export function fillTemplate(text, context) {
|
|
18
|
+
return text.replace(PLACEHOLDER, (_, key, filter) => {
|
|
19
|
+
const value = context[key];
|
|
20
|
+
const plain = value === null || value === undefined ? '' : String(value);
|
|
21
|
+
return filter === 'slug' ? slug(plain) : plain;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/** A recipe value as a write value: templates filled, `{ref}` kept. */
|
|
25
|
+
export function toWriteValue(value, context, renameRef = (alias) => alias) {
|
|
26
|
+
if (typeof value === 'string')
|
|
27
|
+
return fillTemplate(value, context);
|
|
28
|
+
if (value !== null && typeof value === 'object') {
|
|
29
|
+
return {
|
|
30
|
+
ref: renameRef(value.ref),
|
|
31
|
+
...(value.field ? { field: value.field } : {}),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
export function toWriteValues(values, context, renameRef) {
|
|
37
|
+
return Object.fromEntries(Object.entries(values ?? {}).map(([key, value]) => [
|
|
38
|
+
key,
|
|
39
|
+
toWriteValue(value, context, renameRef),
|
|
40
|
+
]));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* An input's value as a write value: scalars and plain JSON objects (an
|
|
44
|
+
* Address) as they are, anything else null.
|
|
45
|
+
*/
|
|
46
|
+
export function scalar(value) {
|
|
47
|
+
if (typeof value === 'string' ||
|
|
48
|
+
typeof value === 'number' ||
|
|
49
|
+
typeof value === 'boolean') {
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
53
|
+
? value
|
|
54
|
+
: null;
|
|
55
|
+
}
|
|
56
|
+
/** The inputs mapped to one record, as that record's field values. */
|
|
57
|
+
export function mappedValues(fields, alias, values) {
|
|
58
|
+
return Object.fromEntries(fields.flatMap((field) => {
|
|
59
|
+
const target = parseTarget(field.to);
|
|
60
|
+
return target.alias === alias
|
|
61
|
+
? [[target.field, scalar(values[field.id])]]
|
|
62
|
+
: [];
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
/** `product.price` to `{ alias: 'product', field: 'price' }`. */
|
|
66
|
+
export function parseTarget(to) {
|
|
67
|
+
const dot = to.indexOf('.');
|
|
68
|
+
if (dot < 1 || dot === to.length - 1) {
|
|
69
|
+
throw new Error(`A form field maps to "alias.field", got "${to}"`);
|
|
70
|
+
}
|
|
71
|
+
return { alias: to.slice(0, dot), field: to.slice(dot + 1) };
|
|
72
|
+
}
|
|
73
|
+
/** The catalog field a form field maps onto. */
|
|
74
|
+
export function targetField(field, records, models) {
|
|
75
|
+
const { alias, field: name } = parseTarget(field.to);
|
|
76
|
+
const record = records.find((r) => r.as === alias);
|
|
77
|
+
if (!record)
|
|
78
|
+
throw new Error(`Form field ${field.id} maps to unknown ${alias}`);
|
|
79
|
+
const found = models(record.model).fields.find((f) => f.name === name);
|
|
80
|
+
if (!found) {
|
|
81
|
+
throw new Error(`${record.model} has no field ${name} (form field ${field.id})`);
|
|
82
|
+
}
|
|
83
|
+
return found;
|
|
84
|
+
}
|
|
85
|
+
/** The qualified model a form field's record is of. */
|
|
86
|
+
export function targetModelId(field, records) {
|
|
87
|
+
const { alias } = parseTarget(field.to);
|
|
88
|
+
const record = records.find((r) => r.as === alias);
|
|
89
|
+
if (!record)
|
|
90
|
+
throw new Error(`Form field ${field.id} maps to unknown ${alias}`);
|
|
91
|
+
return record.model;
|
|
92
|
+
}
|
|
93
|
+
/** The starting value of a field on a new row. */
|
|
94
|
+
export function startingValue(field, catalogField) {
|
|
95
|
+
if (field.default !== undefined)
|
|
96
|
+
return field.default;
|
|
97
|
+
if (catalogField.default !== undefined)
|
|
98
|
+
return catalogField.default;
|
|
99
|
+
return catalogField.type === 'text' ? '' : null;
|
|
100
|
+
}
|
|
101
|
+
/** Context values (`alias.field`) from the form's field values. */
|
|
102
|
+
export function contextFrom(fields, values) {
|
|
103
|
+
return Object.fromEntries(fields.map((f) => [f.to, values[f.id]]));
|
|
104
|
+
}
|
|
105
|
+
const sameValue = (a, b) => a === b;
|
|
106
|
+
/**
|
|
107
|
+
* Rows a form's records currently point at: walk them in order, finding each
|
|
108
|
+
* by its (literal or `{ref}`) `match`. `seeded` rows (the one being edited)
|
|
109
|
+
* are taken as given. A record whose match cannot be resolved has no row.
|
|
110
|
+
*/
|
|
111
|
+
export async function findRows(source, records, seeded, models) {
|
|
112
|
+
const rows = { ...seeded };
|
|
113
|
+
for (const record of records) {
|
|
114
|
+
if (record.as in rows)
|
|
115
|
+
continue;
|
|
116
|
+
if (!record.match) {
|
|
117
|
+
rows[record.as] = undefined;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const wanted = {};
|
|
121
|
+
let resolvable = true;
|
|
122
|
+
for (const [key, value] of Object.entries(record.match)) {
|
|
123
|
+
if (value !== null && typeof value === 'object') {
|
|
124
|
+
const target = rows[value.ref];
|
|
125
|
+
if (!target)
|
|
126
|
+
resolvable = false;
|
|
127
|
+
wanted[key] = value.field ? target?.[value.field] : target?.id;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
wanted[key] = value;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
rows[record.as] = resolvable
|
|
134
|
+
? (await source.list(models(record.model))).find((row) => Object.entries(wanted).every(([k, v]) => sameValue(row[k], v)))
|
|
135
|
+
: undefined;
|
|
136
|
+
}
|
|
137
|
+
return rows;
|
|
138
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { MemoryDataSourceOptions, ModelRecord, RecordWrite } from '../data/source.ts';
|
|
2
|
+
import type { ModelLookup } from './shared.ts';
|
|
3
|
+
export declare const PRODUCT = "@happyvertical/smrt-products:Product";
|
|
4
|
+
export declare const VARIANT = "@happyvertical/smrt-products:ProductVariant";
|
|
5
|
+
export declare const SKU = "@happyvertical/smrt-products:Sku";
|
|
6
|
+
export declare const STOCK_LEVEL = "@happyvertical/smrt-inventory:StockLevel";
|
|
7
|
+
export declare const PROFILE_TYPE = "@happyvertical/smrt-profiles:ProfileType";
|
|
8
|
+
export declare const LOCATION = "@happyvertical/smrt-inventory:InventoryLocation";
|
|
9
|
+
/**
|
|
10
|
+
* Models the product forms write as children of a product. The demo data
|
|
11
|
+
* source starts them empty, so no sample row points at a product that is not
|
|
12
|
+
* there.
|
|
13
|
+
*/
|
|
14
|
+
export declare const SAVED_BY_FORMS: string[];
|
|
15
|
+
/**
|
|
16
|
+
* Sample locations (the active pack's), one SKU per sample product and a stock level for each SKU
|
|
17
|
+
* at the main location and (for about two in three) at the second, with a
|
|
18
|
+
* reorder point. The rows point at one another, so they are built together;
|
|
19
|
+
* a form still adds its own on top. Variants stay empty.
|
|
20
|
+
*/
|
|
21
|
+
export declare function stockSamples(models: ModelLookup): NonNullable<MemoryDataSourceOptions['samples']>;
|
|
22
|
+
/**
|
|
23
|
+
* Units on hand per product: each product's Skus' stock levels summed. A
|
|
24
|
+
* product with no stock row has no entry, so the list can show a dash.
|
|
25
|
+
*/
|
|
26
|
+
export declare function stockByProduct(skus: readonly ModelRecord[], levels: readonly ModelRecord[]): Map<string, number>;
|
|
27
|
+
/** Deletes for a product and everything the forms saved under it. */
|
|
28
|
+
export declare function planProductDelete(productId: string, skus: readonly ModelRecord[], models: ModelLookup): RecordWrite[];
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { fakeId, hashString } from "../data/fakes.js";
|
|
2
|
+
import { getSamplePack } from "../data/packs.js";
|
|
3
|
+
export const PRODUCT = '@happyvertical/smrt-products:Product';
|
|
4
|
+
export const VARIANT = '@happyvertical/smrt-products:ProductVariant';
|
|
5
|
+
export const SKU = '@happyvertical/smrt-products:Sku';
|
|
6
|
+
export const STOCK_LEVEL = '@happyvertical/smrt-inventory:StockLevel';
|
|
7
|
+
export const PROFILE_TYPE = '@happyvertical/smrt-profiles:ProfileType';
|
|
8
|
+
export const LOCATION = '@happyvertical/smrt-inventory:InventoryLocation';
|
|
9
|
+
/**
|
|
10
|
+
* Models the product forms write as children of a product. The demo data
|
|
11
|
+
* source starts them empty, so no sample row points at a product that is not
|
|
12
|
+
* there.
|
|
13
|
+
*/
|
|
14
|
+
export const SAVED_BY_FORMS = [VARIANT, SKU, STOCK_LEVEL, LOCATION];
|
|
15
|
+
/**
|
|
16
|
+
* Sample locations (the active pack's), one SKU per sample product and a stock level for each SKU
|
|
17
|
+
* at the main location and (for about two in three) at the second, with a
|
|
18
|
+
* reorder point. The rows point at one another, so they are built together;
|
|
19
|
+
* a form still adds its own on top. Variants stay empty.
|
|
20
|
+
*/
|
|
21
|
+
export function stockSamples(models) {
|
|
22
|
+
return {
|
|
23
|
+
[LOCATION]: {
|
|
24
|
+
from: [],
|
|
25
|
+
make: () => (getSamplePack().locations ?? []).map((l, i) => ({
|
|
26
|
+
id: fakeId(`${LOCATION}:sample:${i}`),
|
|
27
|
+
...l,
|
|
28
|
+
placeId: '',
|
|
29
|
+
active: true,
|
|
30
|
+
})),
|
|
31
|
+
},
|
|
32
|
+
[SKU]: {
|
|
33
|
+
from: [models(PRODUCT)],
|
|
34
|
+
make: ([products]) => (products ?? []).map((p, i) => ({
|
|
35
|
+
id: fakeId(`${SKU}:sample:${p.id}`),
|
|
36
|
+
productId: p.id,
|
|
37
|
+
code: `SKU-${String(i + 1).padStart(3, '0')}`,
|
|
38
|
+
barcode: '',
|
|
39
|
+
name: String(p.name ?? ''),
|
|
40
|
+
attributes: '',
|
|
41
|
+
parentSkuId: '',
|
|
42
|
+
active: true,
|
|
43
|
+
})),
|
|
44
|
+
},
|
|
45
|
+
[STOCK_LEVEL]: {
|
|
46
|
+
from: [models(SKU), models(LOCATION)],
|
|
47
|
+
make: ([skus, locations]) => {
|
|
48
|
+
const pack = getSamplePack();
|
|
49
|
+
const placed = new Map(pack.products.map((p) => [p.name, p.at]));
|
|
50
|
+
return (skus ?? []).flatMap((sku) => (locations ?? []).flatMap((location, j) => {
|
|
51
|
+
const h = hashString(`${sku.id}:${location.id}`);
|
|
52
|
+
// A pack may say where a product is counted; otherwise it is
|
|
53
|
+
// at the first location and, for two in three, the second.
|
|
54
|
+
const home = placed.get(String(sku.name));
|
|
55
|
+
if (home !== undefined) {
|
|
56
|
+
if (home !== j)
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
else if (j > 0 && h % 3 === 0)
|
|
60
|
+
return [];
|
|
61
|
+
const reorderPoint = 10 + (h % 4) * 5;
|
|
62
|
+
return [
|
|
63
|
+
{
|
|
64
|
+
id: fakeId(`${STOCK_LEVEL}:sample:${sku.id}:${location.id}`),
|
|
65
|
+
skuId: sku.id,
|
|
66
|
+
locationId: location.id,
|
|
67
|
+
state: 'available',
|
|
68
|
+
// Some rows sit at or under the reorder point.
|
|
69
|
+
qty: h % 5 === 0 ? reorderPoint - 3 : reorderPoint + (h % 40),
|
|
70
|
+
reorderPoint,
|
|
71
|
+
reorderQuantity: reorderPoint * 3,
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
}));
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Units on hand per product: each product's Skus' stock levels summed. A
|
|
81
|
+
* product with no stock row has no entry, so the list can show a dash.
|
|
82
|
+
*/
|
|
83
|
+
export function stockByProduct(skus, levels) {
|
|
84
|
+
const productOf = new Map(skus.map((sku) => [sku.id, sku.productId]));
|
|
85
|
+
const totals = new Map();
|
|
86
|
+
for (const level of levels) {
|
|
87
|
+
const productId = productOf.get(String(level.skuId));
|
|
88
|
+
if (typeof productId !== 'string')
|
|
89
|
+
continue;
|
|
90
|
+
totals.set(productId, (totals.get(productId) ?? 0) + Number(level.qty ?? 0));
|
|
91
|
+
}
|
|
92
|
+
return totals;
|
|
93
|
+
}
|
|
94
|
+
/** Deletes for a product and everything the forms saved under it. */
|
|
95
|
+
export function planProductDelete(productId, skus, models) {
|
|
96
|
+
return [
|
|
97
|
+
...skus.flatMap((sku) => [
|
|
98
|
+
{ op: 'delete', model: models(STOCK_LEVEL), match: { skuId: sku.id } },
|
|
99
|
+
{ op: 'delete', model: models(SKU), id: sku.id },
|
|
100
|
+
]),
|
|
101
|
+
{ op: 'delete', model: models(VARIANT), match: { productId } },
|
|
102
|
+
{ op: 'delete', model: models(PRODUCT), id: productId },
|
|
103
|
+
];
|
|
104
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { CatalogField } from '../catalog/types.ts';
|
|
2
|
+
import type { DataSource, ModelRecord, RecordWrite } from '../data/source.ts';
|
|
3
|
+
import type { RecipeFormField, RecipeFormRecord, VariantGridForm } from '../recipes/types.ts';
|
|
4
|
+
import type { ActiveForm } from './active.ts';
|
|
5
|
+
import { type ModelLookup } from './shared.ts';
|
|
6
|
+
/** One size x color (or whatever the axes are) combination. */
|
|
7
|
+
export interface GridCombo {
|
|
8
|
+
/** Stable key: the values in axis order, as JSON. */
|
|
9
|
+
key: string;
|
|
10
|
+
/** `{ size: 'M', color: 'navy' }`: what `Sku.attributes` pins. */
|
|
11
|
+
attributes: Record<string, string>;
|
|
12
|
+
/** The values in axis order, for labels. */
|
|
13
|
+
values: string[];
|
|
14
|
+
}
|
|
15
|
+
/** What a variant-grid form holds while it is open. */
|
|
16
|
+
export interface GridState {
|
|
17
|
+
/** Product inputs by form field id. */
|
|
18
|
+
values: Record<string, unknown>;
|
|
19
|
+
/** Values on offer per axis name, in the order shown. */
|
|
20
|
+
axes: Record<string, string[]>;
|
|
21
|
+
/** Per-cell extension inputs: cell key, then form field id. */
|
|
22
|
+
cells: Record<string, Record<string, unknown>>;
|
|
23
|
+
}
|
|
24
|
+
/** The rows a saved product already has, so a save can update and prune. */
|
|
25
|
+
export interface ExistingGrid {
|
|
26
|
+
productId: string;
|
|
27
|
+
variants: ModelRecord[];
|
|
28
|
+
skus: ModelRecord[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Split pasted lists on commas, trim, drop blanks and repeats
|
|
32
|
+
* (case-insensitively), keep the order.
|
|
33
|
+
*/
|
|
34
|
+
export declare function cleanValues(values: readonly string[]): string[];
|
|
35
|
+
/**
|
|
36
|
+
* Every combination of the axes' values, rows in axis order. An axis with no
|
|
37
|
+
* values is left out, so a product with only sizes still gets a cell per size;
|
|
38
|
+
* no values anywhere means no cells.
|
|
39
|
+
*/
|
|
40
|
+
export declare function combinations(axes: readonly {
|
|
41
|
+
name: string;
|
|
42
|
+
values: readonly string[];
|
|
43
|
+
}[]): GridCombo[];
|
|
44
|
+
/** The grid's combinations for its current state. */
|
|
45
|
+
export declare function gridCombos(form: VariantGridForm, state: Pick<GridState, 'axes'>): GridCombo[];
|
|
46
|
+
/** Product inputs plus the per-cell inputs the extensions add. */
|
|
47
|
+
export declare function gridParts(active: ActiveForm<VariantGridForm>): {
|
|
48
|
+
productFields: RecipeFormField[];
|
|
49
|
+
cellFields: RecipeFormField[];
|
|
50
|
+
cellRecords: RecipeFormRecord[];
|
|
51
|
+
};
|
|
52
|
+
/** Product inputs with the catalog field they map onto, for rendering. */
|
|
53
|
+
export declare function gridProductInputs(active: ActiveForm<VariantGridForm>, models: ModelLookup): {
|
|
54
|
+
field: RecipeFormField;
|
|
55
|
+
catalogField: CatalogField;
|
|
56
|
+
}[];
|
|
57
|
+
/** Cell inputs with the catalog field they map onto. */
|
|
58
|
+
export declare function gridCellInputs(active: ActiveForm<VariantGridForm>, models: ModelLookup): {
|
|
59
|
+
field: RecipeFormField;
|
|
60
|
+
catalogField: CatalogField;
|
|
61
|
+
}[];
|
|
62
|
+
/** An empty grid: starting values for the product inputs and every axis. */
|
|
63
|
+
export declare function blankGrid(active: ActiveForm<VariantGridForm>, models: ModelLookup): GridState;
|
|
64
|
+
/** The starting inputs of one cell. */
|
|
65
|
+
export declare function blankCell(active: ActiveForm<VariantGridForm>, models: ModelLookup): Record<string, unknown>;
|
|
66
|
+
/** Parse a JSON-string field (`allowedValues`, `attributes`), leniently. */
|
|
67
|
+
export declare function parseJson(value: unknown): unknown;
|
|
68
|
+
/** Load an existing product into a grid: its axes, then a cell per Sku. */
|
|
69
|
+
export declare function loadGrid(source: DataSource, active: ActiveForm<VariantGridForm>, models: ModelLookup, productId: string): Promise<{
|
|
70
|
+
state: GridState;
|
|
71
|
+
existing: ExistingGrid;
|
|
72
|
+
} | undefined>;
|
|
73
|
+
/** The Sku code of a new cell: product, then each value, upper-cased. */
|
|
74
|
+
export declare function skuCode(productName: unknown, combo: GridCombo): string;
|
|
75
|
+
/**
|
|
76
|
+
* The related writes that save a variant grid: the product, one
|
|
77
|
+
* `ProductVariant` per axis that has values (and a delete for one that no
|
|
78
|
+
* longer does), a `Sku` per combination with its `attributes` pinned (Skus of
|
|
79
|
+
* combinations that went away are deleted with the rows the extensions keep
|
|
80
|
+
* under them), then each extension's rows per cell. Pure; `apply` runs it
|
|
81
|
+
* all or nothing.
|
|
82
|
+
*/
|
|
83
|
+
export declare function planGridSave(active: ActiveForm<VariantGridForm>, models: ModelLookup, state: GridState, existing?: ExistingGrid): RecordWrite[];
|