@wix/agent-skills 1.33.1 → 1.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/package.json +1 -1
- package/skills/wix-export/SKILL.md +83 -0
- package/skills/wix-harmony-editor/.publish-manifest.json +8 -0
- package/skills/wix-harmony-editor/COPY-SITE.md +494 -0
- package/skills/wix-harmony-editor/SKILL.md +317 -0
- package/skills/wix-harmony-editor/scripts/copy/build-description.mjs +249 -0
- package/skills/wix-harmony-editor/scripts/copy/check-description.mjs +225 -0
- package/skills/wix-harmony-editor/scripts/copy/check-mirror.mjs +89 -0
- package/skills/wix-harmony-editor/scripts/copy/compare-preview.mjs +76 -0
- package/skills/wix-harmony-editor/scripts/copy/deploy-description.mjs +212 -0
- package/skills/wix-harmony-editor/scripts/copy/desc-hash.mjs +44 -0
- package/skills/wix-harmony-editor/scripts/copy/editor-run.mjs +45 -0
- package/skills/wix-harmony-editor/scripts/copy/export-page.mjs +53 -0
- package/skills/wix-harmony-editor/scripts/copy/find-interactions.mjs +76 -0
- package/skills/wix-harmony-editor/scripts/copy/hide-scrollbars.mjs +16 -0
- package/skills/wix-harmony-editor/scripts/copy/import-media.mjs +150 -0
- package/skills/wix-harmony-editor/scripts/copy/link-url.mjs +27 -0
- package/skills/wix-harmony-editor/scripts/copy/lint-api.mjs +56 -0
- package/skills/wix-harmony-editor/scripts/copy/measure-source.mjs +211 -0
- package/skills/wix-harmony-editor/scripts/copy/merge-mirrors.mjs +29 -0
- package/skills/wix-harmony-editor/scripts/copy/mirror-site.mjs +92 -0
- package/skills/wix-harmony-editor/scripts/copy/mobile-stage.mjs +56 -0
- package/skills/wix-harmony-editor/scripts/copy/preview-widths.mjs +73 -0
- package/skills/wix-harmony-editor/scripts/copy/render-plate.mjs +67 -0
- package/skills/wix-harmony-editor/scripts/copy/serve-mirror.mjs +102 -0
- package/skills/wix-harmony-editor/scripts/copy/snapshot-capabilities.mjs +40 -0
- package/skills/wix-harmony-editor/scripts/copy/split-sections.mjs +191 -0
- package/skills/wix-harmony-editor/scripts/copy/upload-media-manager.mjs +61 -0
- package/skills/wix-harmony-editor/scripts/launch.sh +359 -0
- package/skills/wix-headless/SKILL.md +7 -2
- package/skills/wix-headless/references/CAPABILITIES.md +6 -1
- package/skills/wix-headless/references/DISCOVERY.md +2 -1
- package/skills/wix-headless/references/SDK_HANDOFF.md +6 -1
- package/skills/wix-headless/references/SEED.md +3 -2
- package/skills/wix-headless/references/SETUP.md +1 -0
- package/skills/wix-headless/references/inline-recipes/experience-donations.md +102 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-donations.md +146 -0
- package/skills/wix-headless/references/inline-recipes/setup-donations.md +15 -0
- package/skills/wix-headless/references/managed/CREATE.md +1 -1
- package/skills/wix-headless-kit/SKILL.md +110 -21
- package/skills/wix-headless-kit/guides/api-run.md +15 -13
- package/skills/wix-headless-kit/guides/existing-site.md +31 -0
- package/skills/wix-headless-kit/guides/migration.md +49 -17
- package/skills/wix-headless-kit/install/agents-md.mjs +1 -1
- package/skills/wix-headless-kit/install/context.mjs +61 -6
- package/skills/wix-headless-kit/install/pins.json +1 -1
- package/skills/wix-headless-kit/install/setup.mjs +107 -12
- package/skills/wix-headless-replatform/.publish-manifest.json +8 -0
- package/skills/wix-headless-replatform/SKILL.md +116 -0
- package/skills/wix-headless-replatform/agents/openai.yaml +6 -0
- package/skills/wix-headless-replatform/references/control-and-visual-fidelity-contract.md +43 -0
- package/skills/wix-headless-replatform/references/extraction-schema.md +187 -0
- package/skills/wix-headless-replatform/references/interaction-runtime-contract.md +137 -0
- package/skills/wix-headless-replatform/references/layout-blueprint-contract.md +41 -0
- package/skills/wix-headless-replatform/references/output-contract.md +93 -0
- package/skills/wix-headless-replatform/references/post-build-gap-contract.md +125 -0
- package/skills/wix-headless-replatform/references/qa-checklist.md +83 -0
- package/skills/wix-headless-replatform/references/safety.md +19 -0
- package/skills/wix-headless-replatform/references/ui-normalization-contract.md +70 -0
- package/skills/wix-headless-replatform/references/workflow.md +157 -0
- package/skills/wix-headless-replatform/registry/README.md +20 -0
- package/skills/wix-headless-replatform/registry/approvals/button/shadcn-default-ac60ef5.json +28 -0
- package/skills/wix-headless-replatform/registry/items/button/shadcn-default-ac60ef5/button.tsx +54 -0
- package/skills/wix-headless-replatform/registry/items/button/shadcn-default-ac60ef5/capabilities.json +60 -0
- package/skills/wix-headless-replatform/registry/items/button/shadcn-default-ac60ef5/contract.md +48 -0
- package/skills/wix-headless-replatform/registry/licenses/shadcn-ui-ac60ef5-MIT.txt +21 -0
- package/skills/wix-headless-replatform/registry/registry.json +36 -0
- package/skills/wix-headless-replatform/resources/rp-facelift/SKILL.md +32 -0
- package/skills/wix-headless-replatform/resources/rp-project-context/SKILL.md +62 -0
- package/skills/wix-headless-replatform/resources/rp-qa-gap-loop/SKILL.md +64 -0
- package/skills/wix-headless-replatform/resources/rp-source-evidence/SKILL.md +42 -0
- package/skills/wix-headless-replatform/resources/rp-ui-implementation/SKILL.md +73 -0
- package/skills/wix-headless-replatform/schemas/build-plan.schema.json +10 -0
- package/skills/wix-headless-replatform/schemas/candidate.schema.json +19 -0
- package/skills/wix-headless-replatform/schemas/common.schema.json +33 -0
- package/skills/wix-headless-replatform/schemas/decision-patch.schema.json +10 -0
- package/skills/wix-headless-replatform/schemas/decision-request.schema.json +10 -0
- package/skills/wix-headless-replatform/schemas/extraction-gap.schema.json +28 -0
- package/skills/wix-headless-replatform/schemas/extraction-manifest.schema.json +34 -0
- package/skills/wix-headless-replatform/schemas/final-report.schema.json +10 -0
- package/skills/wix-headless-replatform/schemas/foundation.schema.json +11 -0
- package/skills/wix-headless-replatform/schemas/metadata.schema.json +11 -0
- package/skills/wix-headless-replatform/schemas/observation-packet.schema.json +17 -0
- package/skills/wix-headless-replatform/schemas/page-capture.schema.json +11 -0
- package/skills/wix-headless-replatform/schemas/page-resolution.schema.json +33 -0
- package/skills/wix-headless-replatform/schemas/shared-chrome.schema.json +11 -0
- package/skills/wix-headless-replatform/schemas/unit.schema.json +40 -0
- package/skills/wix-headless-replatform/scripts/assemble-extraction.mjs +844 -0
- package/skills/wix-headless-replatform/scripts/benchmark-extraction.mjs +163 -0
- package/skills/wix-headless-replatform/scripts/browser-extraction-preflight.mjs +42 -0
- package/skills/wix-headless-replatform/scripts/build-extracted-homepage.mjs +228 -0
- package/skills/wix-headless-replatform/scripts/clear-wix-starter.mjs +87 -0
- package/skills/wix-headless-replatform/scripts/create-wix-project.mjs +505 -0
- package/skills/wix-headless-replatform/scripts/discover-urls.mjs +142 -0
- package/skills/wix-headless-replatform/scripts/extract-assets.mjs +140 -0
- package/skills/wix-headless-replatform/scripts/extract-design-system.mjs +637 -0
- package/skills/wix-headless-replatform/scripts/extract-interactions.mjs +1903 -0
- package/skills/wix-headless-replatform/scripts/extract-page.mjs +2461 -0
- package/skills/wix-headless-replatform/scripts/extract-seo.mjs +25 -0
- package/skills/wix-headless-replatform/scripts/extract-tokens.mjs +63 -0
- package/skills/wix-headless-replatform/scripts/finalize-extraction-report.mjs +126 -0
- package/skills/wix-headless-replatform/scripts/finalize-gap-review.mjs +180 -0
- package/skills/wix-headless-replatform/scripts/finalize-gap-review.test.mjs +98 -0
- package/skills/wix-headless-replatform/scripts/finalize-migration-website.mjs +103 -0
- package/skills/wix-headless-replatform/scripts/generate-control-state-contract.mjs +176 -0
- package/skills/wix-headless-replatform/scripts/generate-design-md.mjs +261 -0
- package/skills/wix-headless-replatform/scripts/generate-extraction-validators.mjs +25 -0
- package/skills/wix-headless-replatform/scripts/generate-invoice-download-backend.mjs +342 -0
- package/skills/wix-headless-replatform/scripts/generate-layout-blueprint.mjs +140 -0
- package/skills/wix-headless-replatform/scripts/generate-repeater-cms.mjs +22 -0
- package/skills/wix-headless-replatform/scripts/generate-route-plan.mjs +143 -0
- package/skills/wix-headless-replatform/scripts/generate-scene-contract.mjs +288 -0
- package/skills/wix-headless-replatform/scripts/generate-ui-normalization.mjs +266 -0
- package/skills/wix-headless-replatform/scripts/generate-visual-assets.mjs +111 -0
- package/skills/wix-headless-replatform/scripts/lib/browser-tooling.mjs +570 -0
- package/skills/wix-headless-replatform/scripts/lib/common.mjs +329 -0
- package/skills/wix-headless-replatform/scripts/lib/component-capabilities.mjs +121 -0
- package/skills/wix-headless-replatform/scripts/lib/component-registry.mjs +282 -0
- package/skills/wix-headless-replatform/scripts/lib/content-boundary.mjs +61 -0
- package/skills/wix-headless-replatform/scripts/lib/extraction-contract.mjs +374 -0
- package/skills/wix-headless-replatform/scripts/lib/extraction-detectors.mjs +243 -0
- package/skills/wix-headless-replatform/scripts/lib/extraction-validators.generated.mjs +1139 -0
- package/skills/wix-headless-replatform/scripts/lib/font-contract.mjs +326 -0
- package/skills/wix-headless-replatform/scripts/lib/frontend-automation-state.mjs +184 -0
- package/skills/wix-headless-replatform/scripts/lib/gap-analysis.mjs +396 -0
- package/skills/wix-headless-replatform/scripts/lib/html-extract.mjs +168 -0
- package/skills/wix-headless-replatform/scripts/lib/interaction-bootstrap.mjs +10 -0
- package/skills/wix-headless-replatform/scripts/lib/interaction-runtime.mjs +194 -0
- package/skills/wix-headless-replatform/scripts/lib/interaction-timeline.mjs +348 -0
- package/skills/wix-headless-replatform/scripts/lib/layout-blueprint/classifiers.mjs +141 -0
- package/skills/wix-headless-replatform/scripts/lib/layout-blueprint/geometry.mjs +43 -0
- package/skills/wix-headless-replatform/scripts/lib/layout-blueprint/vocabulary.mjs +18 -0
- package/skills/wix-headless-replatform/scripts/lib/ui-normalization.css +64 -0
- package/skills/wix-headless-replatform/scripts/optimize-svg.mjs +31 -0
- package/skills/wix-headless-replatform/scripts/post-build-gap.mjs +358 -0
- package/skills/wix-headless-replatform/scripts/provision-repeater-cms.mjs +25 -0
- package/skills/wix-headless-replatform/scripts/record-gap-decision.mjs +39 -0
- package/skills/wix-headless-replatform/scripts/replay-extraction.mjs +107 -0
- package/skills/wix-headless-replatform/scripts/resolve-home-page.mjs +96 -0
- package/skills/wix-headless-replatform/scripts/site-clone.mjs +658 -0
- package/skills/wix-headless-replatform/scripts/validate-font-contract.mjs +29 -0
- package/skills/wix-headless-replatform/scripts/verify-interactions.mjs +669 -0
- package/skills/wix-headless-replatform/scripts/visual-qa.mjs +370 -0
- package/skills/wix-headless-templates/donations/INSTRUCTIONS.md +37 -24
- package/skills/wix-headless-templates/donations/app/components/donations/DonateForm.tsx +49 -23
- package/skills/wix-headless-templates/donations/app/components/donations/DonationReceipt.tsx +6 -5
- package/skills/wix-headless-templates/donations/app/components/donations/GoalProgress.tsx +5 -5
- package/skills/wix-headless-templates/donations/app/wix/donations/campaigns.ts +4 -4
- package/skills/wix-headless-templates/donations/app/wix/donations/donate.ts +7 -3
- package/skills/wix-headless-templates/donations/app/wix/donations/donation-store.ts +2 -2
- package/skills/wix-headless-templates/donations/app/wix/donations/donations-core.ts +12 -9
- package/skills/wix-headless-templates/donations/project/src/components/donations/DonateForm.tsx +49 -23
- package/skills/wix-headless-templates/donations/project/src/components/donations/DonationReceipt.tsx +6 -5
- package/skills/wix-headless-templates/donations/project/src/components/donations/GoalProgress.tsx +5 -5
- package/skills/wix-headless-templates/donations/project/src/wix/donations/campaigns.ts +4 -4
- package/skills/wix-headless-templates/donations/project/src/wix/donations/donate.ts +7 -3
- package/skills/wix-headless-templates/donations/project/src/wix/donations/donation-store.ts +2 -2
- package/skills/wix-headless-templates/donations/project/src/wix/donations/donations-core.ts +12 -9
- package/skills/wix-headless-templates/donations/rest/campaigns.ts +4 -4
- package/skills/wix-headless-templates/donations/rest/donate.ts +7 -3
- package/skills/wix-headless-templates/donations/seed/SEED.md +12 -7
- package/skills/wix-headless-templates/donations/tests/donation-contract.test.mjs +71 -0
- package/skills/wix-headless-templates/donations/tests/donation-form.test.cjs +137 -0
- package/skills/wix-headless-templates/restaurants/INSTRUCTIONS.md +28 -14
- package/skills/wix-headless-templates/restaurants/app/components/restaurants/OrderCartDrawer.tsx +87 -5
- package/skills/wix-headless-templates/restaurants/app/hooks/restaurants/useOrderCart.ts +9 -1
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/order-store.ts +33 -4
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/ordering-core.ts +100 -5
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/ordering.ts +101 -15
- package/skills/wix-headless-templates/restaurants/app/wix/restaurants/types.ts +35 -1
- package/skills/wix-headless-templates/restaurants/project/src/components/restaurants/OrderCartDrawer.tsx +87 -5
- package/skills/wix-headless-templates/restaurants/project/src/hooks/restaurants/useOrderCart.ts +9 -1
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/order-store.ts +33 -4
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/ordering-core.ts +100 -5
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/ordering.ts +101 -15
- package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/types.ts +35 -1
- package/skills/wix-headless-templates/restaurants/rest/ordering.ts +91 -14
- package/skills/wix-import/SKILL.md +90 -0
- package/skills/wix-manage/SKILL.md +13 -3
- package/skills/wix-manage/references/dashboard-navigation/dashboard-navigation.md +2 -1
- package/skills/wix-manage/references/dashboard-navigation/routes.json +249 -0
- package/skills/wix-manage/references/donations/create-and-update-donation-campaigns.md +139 -0
- package/skills/wix-manage/references/events/events-dashboard-navigation.md +81 -0
- package/skills/wix-manage/references/sites/manage-oauth-apps.md +1 -0
- package/skills/wix-manage/references/sites/upload-static-site.md +127 -8
- package/skills/wix-replatform/.publish-manifest.json +5 -5
- package/skills/wix-replatform/CLI.md +162 -0
- package/skills/wix-replatform/README.md +52 -0
- package/skills/wix-replatform/SKILL.md +229 -684
- package/skills/wix-replatform/console/account.css +1 -0
- package/skills/wix-replatform/console/app.css +1 -0
- package/skills/wix-replatform/console/app.js +117 -0
- package/skills/wix-replatform/console/index.html +4 -0
- package/skills/wix-replatform/console/json.css +11 -0
- package/skills/wix-replatform/lib/agent-adapters/index.js +71 -0
- package/skills/wix-replatform/lib/app-page-routing.js +75 -0
- package/skills/wix-replatform/lib/artifact-freshness.js +11 -1
- package/skills/wix-replatform/lib/blocked-data-requests.js +427 -0
- package/skills/wix-replatform/lib/census-reconciliation.js +426 -0
- package/skills/wix-replatform/lib/completion-report.js +1393 -13
- package/skills/wix-replatform/lib/config-env.js +85 -11
- package/skills/wix-replatform/lib/confirmed-pictures.js +212 -0
- package/skills/wix-replatform/lib/dependency-readiness.js +423 -0
- package/skills/wix-replatform/lib/dependency-recovery.js +21 -0
- package/skills/wix-replatform/lib/destination-choice.js +163 -0
- package/skills/wix-replatform/lib/destination-handoff.js +62 -0
- package/skills/wix-replatform/lib/destination-http.js +81 -0
- package/skills/wix-replatform/lib/destination-route.js +98 -0
- package/skills/wix-replatform/lib/destination.js +919 -0
- package/skills/wix-replatform/lib/discovered-census.js +231 -0
- package/skills/wix-replatform/lib/discovered-set-status.js +255 -0
- package/skills/wix-replatform/lib/document-url-guard.js +203 -0
- package/skills/wix-replatform/lib/entity-qa-attestation.js +339 -0
- package/skills/wix-replatform/lib/entity-verification.js +18 -0
- package/skills/wix-replatform/lib/execution-capability.js +120 -0
- package/skills/wix-replatform/lib/execution-log.js +170 -0
- package/skills/wix-replatform/lib/execution-manifest.js +20 -2
- package/skills/wix-replatform/lib/execution-state.js +22 -0
- package/skills/wix-replatform/lib/expectations-ledger.js +96 -0
- package/skills/wix-replatform/lib/generated-plugin-handoff.js +140 -0
- package/skills/wix-replatform/lib/import-readiness-contract.js +23 -0
- package/skills/wix-replatform/lib/import-recovery.js +800 -6
- package/skills/wix-replatform/lib/imported-redirect-targets.js +608 -0
- package/skills/wix-replatform/lib/internal-link-reconciliation.js +166 -0
- package/skills/wix-replatform/lib/link-audit.js +173 -0
- package/skills/wix-replatform/lib/link-census.js +194 -0
- package/skills/wix-replatform/lib/link-plan.js +148 -0
- package/skills/wix-replatform/lib/link-verification.js +274 -0
- package/skills/wix-replatform/lib/link-write-journal.js +42 -0
- package/skills/wix-replatform/lib/local-state.js +869 -30
- package/skills/wix-replatform/lib/member-completion.js +658 -0
- package/skills/wix-replatform/lib/member-crosswalk.js +69 -0
- package/skills/wix-replatform/lib/member-outcome-registry.js +265 -0
- package/skills/wix-replatform/lib/migration-completion.js +311 -0
- package/skills/wix-replatform/lib/operator-identity.js +47 -0
- package/skills/wix-replatform/lib/orchestration-decisions.js +248 -0
- package/skills/wix-replatform/lib/orchestration-preflight.js +401 -19
- package/skills/wix-replatform/lib/orchestration-router.js +608 -32
- package/skills/wix-replatform/lib/orchestration-state.js +188 -12
- package/skills/wix-replatform/lib/order-reference-readiness.js +30 -0
- package/skills/wix-replatform/lib/payments-outcome-registry.js +200 -0
- package/skills/wix-replatform/lib/plugin-cms-fallback.js +618 -0
- package/skills/wix-replatform/lib/preservation-approval-stamp.js +54 -0
- package/skills/wix-replatform/lib/product-media-deferral.js +96 -0
- package/skills/wix-replatform/lib/progress-log.js +19 -3
- package/skills/wix-replatform/lib/read-back-approval.js +184 -0
- package/skills/wix-replatform/lib/read-back-comparison.js +136 -0
- package/skills/wix-replatform/lib/read-back-contract.js +243 -0
- package/skills/wix-replatform/lib/read-back-extract.js +118 -0
- package/skills/wix-replatform/lib/read-back-gate.js +734 -0
- package/skills/wix-replatform/lib/read-back-reads.js +94 -0
- package/skills/wix-replatform/lib/read-back-state.js +107 -0
- package/skills/wix-replatform/lib/read-back-summary.js +81 -0
- package/skills/wix-replatform/lib/rerun-conflicts.js +334 -0
- package/skills/wix-replatform/lib/run-controller.js +401 -0
- package/skills/wix-replatform/lib/seo-outcome-registry.js +45 -0
- package/skills/wix-replatform/lib/setup-verification.js +148 -0
- package/skills/wix-replatform/lib/source-access.js +231 -0
- package/skills/wix-replatform/lib/source-coverage.js +1130 -0
- package/skills/wix-replatform/lib/source-secrets.js +277 -0
- package/skills/wix-replatform/lib/structured-link-patch.js +59 -0
- package/skills/wix-replatform/lib/task-state.js +110 -0
- package/skills/wix-replatform/lib/url-preservation-report.js +319 -0
- package/skills/wix-replatform/lib/url-preservation-state.js +349 -1
- package/skills/wix-replatform/lib/url-redirect-plan.js +728 -0
- package/skills/wix-replatform/lib/url-verification.js +315 -0
- package/skills/wix-replatform/lib/user-action-effects.js +42 -0
- package/skills/wix-replatform/lib/user-actions.js +264 -0
- package/skills/wix-replatform/lib/website-handoff.js +1220 -0
- package/skills/wix-replatform/lib/wix-client-callers.js +54 -0
- package/skills/wix-replatform/lib/wix-dashboard-url.js +35 -0
- package/skills/wix-replatform/lib/write-verification-state.js +92 -0
- package/skills/wix-replatform/lib/write-verification.js +274 -0
- package/skills/wix-replatform/resources/rp-destination/SKILL.md +137 -0
- package/skills/wix-replatform/resources/rp-discovery/SKILL.md +189 -16
- package/skills/wix-replatform/resources/rp-discovery/scripts/promote-source-coverage.js +47 -0
- package/skills/wix-replatform/resources/rp-execute-import/SKILL.md +869 -29
- package/skills/wix-replatform/resources/rp-execute-import/scripts/shipping-estimate-audit.js +70 -0
- package/skills/wix-replatform/resources/rp-execute-setup/SKILL.md +195 -29
- package/skills/wix-replatform/resources/rp-execute-setup/scripts/execute-setup.js +442 -0
- package/skills/wix-replatform/resources/rp-execution-policy/SKILL.md +112 -0
- package/skills/wix-replatform/resources/rp-execution-policy/lib/coupon-currency-plan-report.js +143 -0
- package/skills/wix-replatform/resources/rp-execution-policy/lib/payments-report.js +244 -0
- package/skills/wix-replatform/resources/rp-import-codegen/SKILL.md +2082 -38
- package/skills/wix-replatform/resources/rp-mapper/SKILL.md +528 -11
- package/skills/wix-replatform/resources/rp-mapper/lib/structure-bridge-planning.js +303 -0
- package/skills/wix-replatform/resources/rp-mapper/scripts/coverage-reconcile.js +88 -0
- package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +6 -5
- package/skills/wix-replatform/resources/rp-preflight/SKILL.md +40 -0
- package/skills/wix-replatform/resources/rp-project-intake/SKILL.md +55 -0
- package/skills/wix-replatform/resources/rp-quick-runtime/SKILL.md +60 -0
- package/skills/wix-replatform/resources/rp-quick-runtime/lib/import-progress.js +89 -0
- package/skills/wix-replatform/resources/rp-quick-runtime/lib/limit-recovery.js +36 -0
- package/skills/wix-replatform/resources/rp-quick-shopify/SKILL.md +123 -0
- package/skills/wix-replatform/resources/rp-quick-shopify/quick-mode.json +124 -0
- package/skills/wix-replatform/resources/rp-quick-shopify/scripts/quick-mode.js +522 -0
- package/skills/wix-replatform/resources/rp-quick-woocommerce/SKILL.md +56 -0
- package/skills/wix-replatform/resources/rp-quick-woocommerce/quick-mode.json +91 -0
- package/skills/wix-replatform/resources/rp-quick-woocommerce/scripts/quick-mode.js +255 -0
- package/skills/wix-replatform/resources/rp-setup-discovery/SKILL.md +80 -10
- package/skills/wix-replatform/resources/rp-setup-discovery/scripts/quick-setup-plan.js +44 -0
- package/skills/wix-replatform/resources/rp-source-csv/SKILL.md +3 -0
- package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fileset.js +0 -0
- package/skills/wix-replatform/resources/rp-source-csv/scripts/csv-discovery.js +21 -1
- package/skills/wix-replatform/resources/rp-source-inputs/SKILL.md +66 -0
- package/skills/wix-replatform/resources/rp-source-sfcc/SKILL.md +153 -0
- package/skills/wix-replatform/resources/rp-source-shopify/SKILL.md +394 -0
- package/skills/wix-replatform/resources/rp-source-shopify/lib/discovery-reads.js +200 -0
- package/skills/wix-replatform/resources/rp-source-shopify/lib/import-findings.js +34 -0
- package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-bulk-sqlite-worker.js +44 -0
- package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-bulk.js +1470 -0
- package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-cli.js +446 -0
- package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-gift-cards.js +474 -0
- package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-protected-fields.js +879 -0
- package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-session.js +426 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/articles.graphql +24 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/blogs.graphql +18 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/collections.graphql +40 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/customers.graphql +76 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/delivery-profiles.graphql +51 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/discounts.graphql +35 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/files.graphql +20 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/gift-cards.graphql +18 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/inventory.graphql +31 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/locations.graphql +21 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/menus.graphql +21 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/metaobjects.graphql +30 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/orders-core.graphql +150 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/orders-fulfillments.graphql +36 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/orders-refunds.graphql +48 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/pages.graphql +20 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-address.graphql +8 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-email.graphql +6 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-name.graphql +8 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-phone.graphql +8 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-address.graphql +12 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-email.graphql +6 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-name.graphql +13 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-phone.graphql +13 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/products.graphql +73 -0
- package/skills/wix-replatform/resources/rp-source-shopify/queries/url-redirects.graphql +13 -0
- package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-discovery.js +693 -0
- package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-extract.js +283 -0
- package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-gift-card-remedy.js +191 -0
- package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-session-check.js +115 -0
- package/skills/wix-replatform/resources/rp-source-shopify/source-schema.example.json +201 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/PLUGIN-READ-PLANS.md +146 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/SKILL.md +736 -22
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/blocked-data-handlers.js +73 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/checkout-field-csv-parser.js +115 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/checkout-field-csv-parser.test-fixture.js +91 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/coupon-discovery.js +440 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/currency-gate.js +125 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/gateway-source-keys.js +252 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/gateway-source-keys.json +183 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/gateway-summary.mjs +333 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/invoice-discovery.js +426 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/plugin-disposition.js +400 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/plugin-entity-read-plan.js +633 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/plugin-knowledge.js +1127 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/refund-corroboration.js +194 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/refund-corroboration.json +100 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/sampled-ids-batch.js +157 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/secret-value-guard.js +234 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/store-currency.js +101 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/structure-bridge-reader.js +755 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/wix-wp-plugin-v2-client.js +1074 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/wix-wp-plugin-v2-client.test-fixture.js +149 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/woo-inventory.js +25 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-http.js +204 -9
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-image-url.js +186 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-plugin-detect.js +1422 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-redirect-sources.js +343 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-route-classifier.js +262 -26
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/yoast-product-seo-evidence.js +272 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/README.md +373 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/advanced-custom-fields.json +101 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/back-in-stock-notifier-for-woocommerce.json +81 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/capabilities-pending-decision.json +128 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/cms-fallback-eligible.json +18 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/contact-form-7.json +104 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/facebook-for-woocommerce.json +44 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/fingerprint-aliases.json +49 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/free-gifts-for-woocommerce.json +94 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/index.json +863 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/mailpoet.json +52 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/membership-for-woocommerce.json +161 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/mwb-bookings-for-woocommerce.json +180 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/no-migration-needed.json +286 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/pricing-deals-for-woocommerce.json +79 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/product-extras-for-woocommerce.json +120 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/pw-woocommerce-gift-cards.json +128 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/requires-development.json +88 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/seo-by-rank-math.json +80 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/seriously-simple-podcasting.json +46 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/strong-testimonials.json +55 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/subscriptions-for-woocommerce.json +99 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/tablepress.json +55 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/the-events-calendar.json +160 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/ti-woocommerce-wishlist.json +81 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woo-checkout-field-editor-pro.json +60 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woo-discount-rules.json +74 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woo-product-bundle.json +75 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-gift-cards.json +60 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-other-payment-gateway.json +44 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-pdf-invoices-packing-slips.json +57 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-product-addon.json +141 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-progressive-discounts.json +54 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/wordpress-seo.json +158 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/wpc-composite-products.json +97 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/plugins/wpforms-lite.json +86 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/scripts/capture-store-settings.js +90 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/scripts/plugin-knowledge-validate.js +51 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/scripts/plugin-knowledge.js +103 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/scripts/wp-discovery.js +1668 -33
- package/skills/wix-replatform/resources/rp-source-wordpress/scripts/wp-plugin-inventory.js +273 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/secret-value-patterns.v1.json +11 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/sub-parts.json +13 -0
- package/skills/wix-replatform/resources/rp-target-wix/SKILL.md +446 -32
- package/skills/wix-replatform/resources/rp-target-wix/app-page-routing-capabilities.json +36 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/README.md +38 -2
- package/skills/wix-replatform/resources/rp-target-wix/domains/SERVICE-PLUGINS.md +322 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/docs-survey.json +70 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/domain.json +19 -9
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/category.json +42 -8
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/comment.json +54 -8
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/post.json +66 -10
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/tag.json +38 -7
- package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/docs-survey.json +332 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/domain.json +75 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/entities/booking.json +181 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/entities/service-add-on.json +130 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/entities/service.json +180 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/cms/docs-survey.json +161 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/cms/domain.json +15 -4
- package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/collection.json +39 -7
- package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/data-item.json +47 -8
- package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/reference.json +7 -1
- package/skills/wix-replatform/resources/rp-target-wix/domains/crm/docs-survey.json +204 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/crm/domain.json +17 -4
- package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/contact.json +159 -15
- package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/email-subscription.json +80 -12
- package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/label.json +48 -8
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/docs-survey.json +306 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/domain.json +30 -7
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/delivery-profile.json +171 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/discount-rule.json +182 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-applied-discount.json +129 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-invoice-document.json +192 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-line-item-options.json +123 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-line-item.json +60 -12
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-merchant-note.json +112 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-payment.json +191 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-refund.json +140 -13
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order.json +383 -18
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/pickup-location.json +122 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/shipping-option.json +98 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/wishlist-item.json +86 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/events/docs-survey.json +128 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/events/domain.json +38 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/category.json +73 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/event.json +107 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/registration-form.json +89 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/rsvp.json +118 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/ticket-definition.json +93 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/forms/docs-survey.json +86 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/forms/domain.json +56 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/forms/entities/form-submission.json +121 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/forms/entities/form.json +134 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/docs-survey.json +41 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/domain.json +50 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/entities/gift-card-product.json +87 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/entities/gift-card.json +130 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/index.json +914 -24
- package/skills/wix-replatform/resources/rp-target-wix/domains/media/docs-survey.json +41 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/media/domain.json +14 -4
- package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-file.json +45 -8
- package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-folder.json +41 -7
- package/skills/wix-replatform/resources/rp-target-wix/domains/members/docs-survey.json +119 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/members/domain.json +13 -3
- package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/badge.json +41 -7
- package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/custom-field.json +82 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/member-about.json +77 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/member.json +165 -13
- package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/docs-survey.json +41 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/domain.json +46 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/entities/plan-order.json +137 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/entities/plan.json +133 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/docs-survey.json +7 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/domain.json +36 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/amazon-shop-connect.json +71 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/ebay-shop-connect.json +67 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/google-youtube-connect.json +72 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/meta-catalog-connect.json +74 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/pinterest-catalog-connect.json +69 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/tiktok-catalog-connect.json +61 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/schema.json +28 -1
- package/skills/wix-replatform/resources/rp-target-wix/domains/seo/docs-survey.json +109 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/seo/domain.json +73 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/seo/entities/item-seo-tags.json +148 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/seo/entities/seo-pattern.json +91 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/seo/entities/site-seo-tags.json +79 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/site/docs-survey.json +32 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/site/domain.json +49 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/site/entities/business-contact.json +103 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/docs-survey.json +203 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/domain.json +27 -10
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/back-in-stock-request.json +119 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/brand.json +111 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/category.json +52 -8
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/coupon.json +214 -10
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/inventory-item.json +93 -13
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product-customization.json +111 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product-tag.json +52 -10
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product.json +145 -14
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/promotion.json +84 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/review.json +178 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/subscription-product.json +87 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/tax/docs-survey.json +106 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/tax/domain.json +64 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/manual-tax-mapping.json +119 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/tax-group.json +94 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/tax-region.json +113 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/tax-settings.json +65 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/blog-author-attribution.js +165 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-client.js +60 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-duplicates.js +201 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-ledger.js +306 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-report.js +229 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-stage.js +55 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build.js +715 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-media.js +567 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/bulk-results.js +73 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/contact-extended-fields.js +194 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/contact-import.js +133 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/contract-ledger.js +13 -4
- package/skills/wix-replatform/resources/rp-target-wix/lib/coupon-redemption-drift.js +491 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/customer-member.js +104 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/data-extension-schema.js +673 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/domain-knowledge.js +453 -2
- package/skills/wix-replatform/resources/rp-target-wix/lib/gift-card-balance-reconciliation.js +119 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/gift-card-build.js +566 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/gift-card-redemption-build.js +249 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/order-applied-discount-build.js +63 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/order-buyer.js +187 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/order-channel-build.js +64 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/order-history.js +1027 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/order-invoice-contract.js +90 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/order-payment-mapping.js +420 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/pricing-plan-definition.js +177 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/product-import.js +151 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/product-seo.js +723 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/seo-redirects.js +353 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/shipping-build.js +1437 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/shipping-option-stage.js +354 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/store-config-build.js +134 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/stores-category-attach.js +221 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/stores-inventory.js +248 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/stores-verification.js +86 -3
- package/skills/wix-replatform/resources/rp-target-wix/lib/tax-build.js +231 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/url-mapper-transport.js +28 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/value-utils.js +14 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/variant-correlation.js +34 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/wix-build.js +166 -15
- package/skills/wix-replatform/resources/rp-target-wix/lib/wix-target-spec.js +19 -2
- package/skills/wix-replatform/resources/rp-target-wix/lib/wix-writers.js +4079 -257
- package/skills/wix-replatform/resources/rp-target-wix/lib/write-verification.js +3 -0
- package/skills/wix-replatform/resources/rp-target-wix/scripts/docs-survey-sync.js +150 -0
- package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge-validate.js +40 -2
- package/skills/wix-replatform/resources/rp-target-wix/scripts/verify-stores.js +6 -1
- package/skills/wix-replatform/resources/rp-telemetry/SKILL.md +148 -8
- package/skills/wix-replatform/resources/rp-telemetry/lib/bi-sink.js +83 -15
- package/skills/wix-replatform/resources/rp-telemetry/lib/telemetry-recorder.js +1119 -215
- package/skills/wix-replatform/resources/rp-telemetry/lib/transcript-digest.js +318 -0
- package/skills/wix-replatform/resources/rp-telemetry/scripts/meter-from-audit.js +2 -2
- package/skills/wix-replatform/resources/rp-telemetry/scripts/rp-telemetry.js +106 -4
- package/skills/wix-replatform/resources/rp-website-continuation/SKILL.md +94 -0
- package/skills/wix-replatform/scripts/census-reconciliation.js +25 -0
- package/skills/wix-replatform/scripts/cms-fallback.js +89 -0
- package/skills/wix-replatform/scripts/discovered-census.js +26 -0
- package/skills/wix-replatform/scripts/discovered-set-status.js +33 -0
- package/skills/wix-replatform/scripts/entity-qa-attestation.js +130 -0
- package/skills/wix-replatform/scripts/execution-health-check.js +415 -0
- package/skills/wix-replatform/scripts/execution-manifest-validate.js +1 -1
- package/skills/wix-replatform/scripts/execution-state-prepare.js +1 -1
- package/skills/wix-replatform/scripts/expectations-ledger.js +44 -0
- package/skills/wix-replatform/scripts/import-contract-verify.js +183 -0
- package/skills/wix-replatform/scripts/internal-link-audit.js +90 -0
- package/skills/wix-replatform/scripts/item-seo-tags-verify.js +205 -0
- package/skills/wix-replatform/scripts/migration-completion.js +76 -0
- package/skills/wix-replatform/scripts/orchestration-preflight.js +21 -2
- package/skills/wix-replatform/scripts/orchestration-route.js +32 -1
- package/skills/wix-replatform/scripts/orchestration-state.js +146 -10
- package/skills/wix-replatform/scripts/read-back-gate.js +175 -0
- package/skills/wix-replatform/scripts/replatform-console.js +146 -0
- package/skills/wix-replatform/scripts/replatform.js +436 -0
- package/skills/wix-replatform/scripts/source-secrets.js +77 -0
- package/skills/wix-replatform/scripts/url-redirects.js +286 -0
- package/skills/wix-replatform/scripts/user-action.js +58 -0
- package/skills/wix-replatform/scripts/website-handoff-generate.js +64 -0
- package/skills/wix-replatform/scripts/wix-dashboard-url.js +54 -0
- package/skills/wix-replatform/scripts/wix-destination.js +143 -0
- package/skills/wix-replatform/scripts/wix-headless-scaffold.js +762 -0
- package/skills/wix-vibe-headless/SKILL.md +7 -3
- package/skills/wix-vibe-headless/install/deploy.cjs +61 -34
- package/skills/wix-vibe-headless/platforms/base44.md +1 -0
- package/skills/wix-vibe-headless/references/donations/INSTRUCTIONS.md +88 -0
- package/skills/wix-vibe-headless/references/donations/app/rest/wix-donations.js +112 -0
- package/skills/wix-vibe-headless/references/donations/seed/SEED.md +11 -0
- package/skills/wix-vibe-headless/references/donations/tests/donations.test.mjs +258 -0
- package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +5 -2
- package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +4 -1
- package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-ordering.js +67 -3
- package/skills/wix-vibe-headless/references/shared/app/rest/wix-client.js +4 -3
- package/skills/wix-replatform/resources/rp-target-wix/SPEC-product-reviews-and-blog-authorship.md +0 -330
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// rp-target-wix — blog post media: the cover (WordPress `featured_media`) and inline images.
|
|
4
|
+
//
|
|
5
|
+
// A blog importer that never resolves a WordPress image reference to a Wix file id ships posts
|
|
6
|
+
// with no cover and inline images still hot-linked to the old site. This module is the one
|
|
7
|
+
// place that does it, so no generated importer re-derives it.
|
|
8
|
+
//
|
|
9
|
+
// FAILURE POLICY (human-approved): when a post's cover or any inline image cannot be imported,
|
|
10
|
+
// THAT POST STAYS PENDING AND RECOVERABLE; other posts continue. Nothing is written to Wix for
|
|
11
|
+
// it — no draft, no publish, no crosswalk row — until every medium is confirmed READY. Do NOT
|
|
12
|
+
// add a partial-post fallback (import the text, drop a failed cover, keep a source URL for a
|
|
13
|
+
// failed inline image): that option was offered and not approved.
|
|
14
|
+
//
|
|
15
|
+
// Why the post waits for READY although a PENDING file id is already referenceable in blog
|
|
16
|
+
// content: that fact (see wix-writers.js, media import section) is true, but the policy needs
|
|
17
|
+
// failure discovery BEFORE the post ships, and only a settled file can say it failed.
|
|
18
|
+
//
|
|
19
|
+
// Caller shape (the generated blog importer):
|
|
20
|
+
//
|
|
21
|
+
// const richContent = await convertHtmlToRichContent(wix, post.contentHtml); // no media option
|
|
22
|
+
// const media = await importAndConfirmPostMedia(wix, { post, richContent, state, fetchFeaturedMedia });
|
|
23
|
+
// if (!media.allReady) continue; // nothing written; the state file already says why
|
|
24
|
+
// applyPostMedia(richContent, media); // rewrites the SAME document: no second conversion
|
|
25
|
+
// // createDraftPost(wix, { ..., richContent, heroImageId: media.heroImageId }), crosswalk row, then
|
|
26
|
+
// await state.markResolved(post.id, { targetPostId, runId, resumed: media.resumed });
|
|
27
|
+
//
|
|
28
|
+
// and on the crosswalk-gate path (the post is already written):
|
|
29
|
+
//
|
|
30
|
+
// await state.closeIfCrosswalked(post.id, { targetPostId, runId });
|
|
31
|
+
//
|
|
32
|
+
// Both close the record AND own the recovery-log entry for a post that had been pending, so
|
|
33
|
+
// no caller ordering can lose it (see "Recovery-log entry" below).
|
|
34
|
+
//
|
|
35
|
+
// Inline identity. rewriteInlineMedia replaces an image only when its `imageData.image.src.url`
|
|
36
|
+
// EXACTLY equals a map key. So keys are collected from the converted Ricos document, never from
|
|
37
|
+
// raw HTML: the collection key and the rewrite key are the same string by construction, with no
|
|
38
|
+
// canonicalizer to drift from the converter's own entity decoding and encoding.
|
|
39
|
+
//
|
|
40
|
+
// Out of scope here: images the converter does not emit as a Ricos image node (lazy-load markup
|
|
41
|
+
// with the URL only in data-src/srcset), and inline video/audio.
|
|
42
|
+
|
|
43
|
+
const crypto = require('node:crypto');
|
|
44
|
+
const fs = require('node:fs/promises');
|
|
45
|
+
const path = require('node:path');
|
|
46
|
+
const writers = require('./wix-writers.js');
|
|
47
|
+
const { resolveImageUrl } = require('../../rp-source-wordpress/lib/wp-image-url.js');
|
|
48
|
+
|
|
49
|
+
const SCHEMA_VERSION = 1;
|
|
50
|
+
const STATE_FILE = 'pending-blog-media.ndjson';
|
|
51
|
+
const OUTCOMES = ['imported', 'ready', 'fetch-failed', 'unresolvable-url', 'import-rejected', 'failed', 'not-ready', 'status-unknown'];
|
|
52
|
+
// A medium whose last row carries a file id in one of these outcomes is resumed, never
|
|
53
|
+
// re-imported: `ready` is reused as-is, the others are polled again.
|
|
54
|
+
const RESUMABLE = new Set(['imported', 'ready', 'not-ready', 'status-unknown']);
|
|
55
|
+
|
|
56
|
+
function postStableKey(postOrId) {
|
|
57
|
+
const id = postOrId && typeof postOrId === 'object' ? postOrId.id : postOrId;
|
|
58
|
+
if (id === undefined || id === null || id === '') throw new Error('blog-post-media: a post id is required');
|
|
59
|
+
return `wordpress:post:${String(id)}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function postTitle(post) {
|
|
63
|
+
const t = post && post.title;
|
|
64
|
+
if (typeof t === 'string') return t;
|
|
65
|
+
if (t && typeof t.rendered === 'string') return t.rendered;
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// --- collection --------------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
function collectRewriteKeys(richContent) {
|
|
72
|
+
const keys = [];
|
|
73
|
+
const visit = (node) => {
|
|
74
|
+
if (!node || typeof node !== 'object') return;
|
|
75
|
+
const url = node.imageData && node.imageData.image && node.imageData.image.src && node.imageData.image.src.url;
|
|
76
|
+
if (typeof url === 'string' && url !== '') keys.push(url);
|
|
77
|
+
(node.nodes || []).forEach(visit);
|
|
78
|
+
};
|
|
79
|
+
((richContent && richContent.nodes) || []).forEach(visit);
|
|
80
|
+
return keys;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// The import URL for one rewrite key: WHATWG resolution against the post's permalink, so
|
|
84
|
+
// relative and protocol-relative sources become absolute. Anything that is not http(s) after
|
|
85
|
+
// that (data:, blob:, a relative key with no permalink, malformed) is unresolvable.
|
|
86
|
+
function resolveImportUrl(key, base) {
|
|
87
|
+
let url;
|
|
88
|
+
try {
|
|
89
|
+
url = base ? new URL(key, base) : new URL(key);
|
|
90
|
+
} catch {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
return url.protocol === 'http:' || url.protocol === 'https:' ? url.toString() : null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// What this post needs imported. Inline media are deduped by import URL: every rewrite key that
|
|
97
|
+
// resolves to the same URL (the same string twice, or a relative and an absolute form) shares one
|
|
98
|
+
// import and one file id. An unresolvable key is its own medium, already failed.
|
|
99
|
+
function collectPostMedia({ post, richContent }) {
|
|
100
|
+
const media = [];
|
|
101
|
+
const featuredId = post && post.featured_media;
|
|
102
|
+
if (featuredId !== undefined && featuredId !== null && String(featuredId) !== '' && String(featuredId) !== '0') {
|
|
103
|
+
media.push({ mediaKey: `featured:${String(featuredId)}`, kind: 'featured', wpMediaId: String(featuredId), sourceUrl: null, rewriteKeys: [] });
|
|
104
|
+
}
|
|
105
|
+
const byMediaKey = new Map();
|
|
106
|
+
for (const key of collectRewriteKeys(richContent)) {
|
|
107
|
+
const importUrl = resolveImportUrl(key, post && post.link);
|
|
108
|
+
const mediaKey = `inline:${importUrl || key}`;
|
|
109
|
+
let item = byMediaKey.get(mediaKey);
|
|
110
|
+
if (!item) {
|
|
111
|
+
item = { mediaKey, kind: 'inline', wpMediaId: null, sourceUrl: importUrl, rewriteKeys: [] };
|
|
112
|
+
if (!importUrl) item.unresolvable = true;
|
|
113
|
+
byMediaKey.set(mediaKey, item);
|
|
114
|
+
media.push(item);
|
|
115
|
+
}
|
|
116
|
+
if (!item.rewriteKeys.includes(key)) item.rewriteKeys.push(key);
|
|
117
|
+
}
|
|
118
|
+
return media;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// --- pending-media state (append-only, authoritative recovery record) -------------------
|
|
122
|
+
//
|
|
123
|
+
// migrations/<project>/state/crosswalk/pending-blog-media.ndjson. One row per state change; for a
|
|
124
|
+
// (sourceStableKey, mediaKey) the last row wins. A `resolved` row closes the post and later
|
|
125
|
+
// media rows for it are ignored. Crash discipline matches the pending-invoice file: split on the
|
|
126
|
+
// byte; a torn tail is truncated on disk before the next append; a complete unterminated last
|
|
127
|
+
// row is kept and terminated first; an unparsable line anywhere else throws as corruption.
|
|
128
|
+
//
|
|
129
|
+
// Recovery-log entry. A post that a rerun resolves after it had been pending owes one standard
|
|
130
|
+
// recovery-log entry. The `resolved` row records that debt (`recoveryOwed`) with a recoveryId and
|
|
131
|
+
// timestamp fixed at that moment; a later `recoveryLogged` row pays it. Until then every run that
|
|
132
|
+
// meets the post — normally through the crosswalk gate — re-checks the recovery log for that
|
|
133
|
+
// recoveryId and appends only if it is absent, then writes `recoveryLogged`. A crash (or a failed
|
|
134
|
+
// append) anywhere between the crosswalk row and `recoveryLogged` is therefore repaired by the
|
|
135
|
+
// next run, and never produces a second entry.
|
|
136
|
+
//
|
|
137
|
+
// `recovery` defaults to skills/wix-replatform/lib/import-recovery.js; tests may inject one with
|
|
138
|
+
// the same { loadRecoveryLog, appendRecoveryLogEntry } shape.
|
|
139
|
+
function createPendingBlogMediaState({ projectDir, recovery } = {}) {
|
|
140
|
+
if (!projectDir) throw new Error('createPendingBlogMediaState needs the migration projectDir');
|
|
141
|
+
const recoveryApi = () => recovery || require('../../../lib/import-recovery.js');
|
|
142
|
+
const filePath = path.join(projectDir, 'state', 'crosswalk', STATE_FILE);
|
|
143
|
+
let droppedPartialLine = null;
|
|
144
|
+
|
|
145
|
+
async function readRows() {
|
|
146
|
+
let buffer;
|
|
147
|
+
try {
|
|
148
|
+
buffer = await fs.readFile(filePath);
|
|
149
|
+
} catch (error) {
|
|
150
|
+
if (error && error.code === 'ENOENT') return { rows: [], needsTerminator: false };
|
|
151
|
+
throw error;
|
|
152
|
+
}
|
|
153
|
+
const lastNewline = buffer.lastIndexOf(0x0a);
|
|
154
|
+
const completeBytes = lastNewline === -1 ? 0 : lastNewline + 1;
|
|
155
|
+
const complete = completeBytes > 0 ? buffer.subarray(0, completeBytes).toString('utf8').split('\n') : [];
|
|
156
|
+
if (complete.length > 0) complete.pop();
|
|
157
|
+
const rows = [];
|
|
158
|
+
complete.forEach((raw, i) => {
|
|
159
|
+
const line = raw.replace(/\r$/, '').trim();
|
|
160
|
+
if (!line) return;
|
|
161
|
+
try { rows.push(JSON.parse(line)); } catch (error) { throw new Error(`${filePath}:${i + 1} invalid NDJSON: ${error.message}`); }
|
|
162
|
+
});
|
|
163
|
+
const tail = buffer.subarray(completeBytes).toString('utf8');
|
|
164
|
+
let needsTerminator = false;
|
|
165
|
+
if (tail.trim()) {
|
|
166
|
+
let row = null;
|
|
167
|
+
try { row = JSON.parse(tail.trim()); } catch { row = null; }
|
|
168
|
+
if (row) {
|
|
169
|
+
rows.push(row);
|
|
170
|
+
needsTerminator = true;
|
|
171
|
+
} else {
|
|
172
|
+
await fs.truncate(filePath, completeBytes);
|
|
173
|
+
droppedPartialLine = { line: complete.length + 1, length: tail.length };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return { rows, needsTerminator };
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async function append(row) {
|
|
180
|
+
const { needsTerminator } = await readRows(); // repair first, so this append starts a clean line
|
|
181
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
182
|
+
if (needsTerminator) await fs.appendFile(filePath, '\n', 'utf8');
|
|
183
|
+
await fs.appendFile(filePath, `${JSON.stringify({ schemaVersion: SCHEMA_VERSION, ...row, updatedAt: new Date().toISOString() })}\n`, 'utf8');
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Fold the file into { sourceStableKey -> { title, resolved, targetPostId, media: Map } }.
|
|
187
|
+
async function fold() {
|
|
188
|
+
const { rows } = await readRows();
|
|
189
|
+
const posts = new Map();
|
|
190
|
+
for (const row of rows) {
|
|
191
|
+
if (!row || typeof row.sourceStableKey !== 'string') continue;
|
|
192
|
+
let post = posts.get(row.sourceStableKey);
|
|
193
|
+
if (!post) {
|
|
194
|
+
post = {
|
|
195
|
+
sourceStableKey: row.sourceStableKey, title: null, resolved: false, targetPostId: null, media: new Map(),
|
|
196
|
+
recoveryOwed: false, recoveryId: null, resolvedAt: null, resolvedRunId: null, recoveryLogged: false,
|
|
197
|
+
};
|
|
198
|
+
posts.set(row.sourceStableKey, post);
|
|
199
|
+
}
|
|
200
|
+
if (row.recoveryLogged === true) {
|
|
201
|
+
if (post.resolved && row.recoveryId === post.recoveryId) post.recoveryLogged = true;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
if (post.resolved) continue; // closed: later media rows are ignored
|
|
205
|
+
if (row.resolved === true) {
|
|
206
|
+
post.resolved = true;
|
|
207
|
+
post.targetPostId = row.targetPostId || null;
|
|
208
|
+
post.recoveryOwed = row.recoveryOwed === true;
|
|
209
|
+
post.recoveryId = row.recoveryId || null;
|
|
210
|
+
post.resolvedAt = row.resolvedAt || null;
|
|
211
|
+
post.resolvedRunId = row.resolvedRunId || null;
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (typeof row.mediaKey !== 'string') continue;
|
|
215
|
+
if (row.title) post.title = row.title;
|
|
216
|
+
post.media.set(row.mediaKey, row);
|
|
217
|
+
}
|
|
218
|
+
return posts;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
async function postRecord(postOrId) {
|
|
222
|
+
return (await fold()).get(postStableKey(postOrId)) || null;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Pay an owed recovery-log entry, idempotently: the entry is rebuilt from the `resolved` row,
|
|
226
|
+
// so its recoveryId is stable and an entry already in the log is not appended again.
|
|
227
|
+
async function settleRecoveryLog(record) {
|
|
228
|
+
if (!record || !record.resolved || !record.recoveryOwed || record.recoveryLogged) return false;
|
|
229
|
+
const api = recoveryApi();
|
|
230
|
+
const existing = api.recoveryEntriesOf ? api.recoveryEntriesOf(await api.loadRecoveryLog(projectDir)) : await api.loadRecoveryLog(projectDir);
|
|
231
|
+
if (!existing.some((entry) => entry && entry.recoveryId === record.recoveryId)) {
|
|
232
|
+
await api.appendRecoveryLogEntry(projectDir, buildBlogMediaRecoveryEntry({
|
|
233
|
+
runId: record.resolvedRunId,
|
|
234
|
+
sourceStableKey: record.sourceStableKey,
|
|
235
|
+
targetPostId: record.targetPostId,
|
|
236
|
+
recoveryId: record.recoveryId,
|
|
237
|
+
timestamp: record.resolvedAt,
|
|
238
|
+
}));
|
|
239
|
+
}
|
|
240
|
+
await append({ sourceStableKey: record.sourceStableKey, recoveryLogged: true, recoveryId: record.recoveryId });
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async function close(postOrId, { targetPostId = null, runId = null, recoveryOwed = false } = {}) {
|
|
245
|
+
const key = postStableKey(postOrId);
|
|
246
|
+
let record = await postRecord(postOrId);
|
|
247
|
+
if (!record) return { closed: false, recoveryLogged: false }; // no media: never had a record
|
|
248
|
+
let closed = false;
|
|
249
|
+
if (!record.resolved) {
|
|
250
|
+
if (recoveryOwed && (typeof runId !== 'string' || runId === '')) {
|
|
251
|
+
throw new Error(`blog-post-media: closing ${key} owes a recovery-log entry, so a runId is required`);
|
|
252
|
+
}
|
|
253
|
+
const resolvedAt = new Date().toISOString();
|
|
254
|
+
const recoveryId = recoveryOwed
|
|
255
|
+
? `recovery-blog-media-${crypto.createHash('sha256').update(`${key}|${resolvedAt}`).digest('hex').slice(0, 12)}`
|
|
256
|
+
: null;
|
|
257
|
+
await append({
|
|
258
|
+
sourceStableKey: key,
|
|
259
|
+
resolved: true,
|
|
260
|
+
targetPostId: targetPostId == null ? null : String(targetPostId),
|
|
261
|
+
recoveryOwed: Boolean(recoveryOwed),
|
|
262
|
+
recoveryId,
|
|
263
|
+
resolvedAt,
|
|
264
|
+
resolvedRunId: recoveryOwed ? runId : null,
|
|
265
|
+
});
|
|
266
|
+
closed = true;
|
|
267
|
+
record = await postRecord(postOrId);
|
|
268
|
+
}
|
|
269
|
+
return { closed, recoveryLogged: await settleRecoveryLog(record) };
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
path: filePath,
|
|
274
|
+
readRows,
|
|
275
|
+
fold,
|
|
276
|
+
postRecord,
|
|
277
|
+
appendMedia: (row) => append(row),
|
|
278
|
+
// After the post write and its crosswalk row. `resumed` is importAndConfirmPostMedia's flag:
|
|
279
|
+
// a post that had been pending before this run owes a recovery-log entry, appended here.
|
|
280
|
+
markResolved: (postOrId, { targetPostId = null, runId = null, resumed = false } = {}) =>
|
|
281
|
+
close(postOrId, { targetPostId, runId, recoveryOwed: Boolean(resumed) }),
|
|
282
|
+
// The crosswalk gate skipped this post: it is written, but an earlier run stopped before
|
|
283
|
+
// closing its record or before paying its recovery-log entry. No media calls. An open record
|
|
284
|
+
// closed here is a rerun resolving a pending post, so it owes the entry.
|
|
285
|
+
closeIfCrosswalked: (postOrId, { targetPostId = null, runId = null } = {}) =>
|
|
286
|
+
close(postOrId, { targetPostId, runId, recoveryOwed: true }),
|
|
287
|
+
droppedPartialLine: () => droppedPartialLine,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// --- import and confirm ------------------------------------------------------------------
|
|
292
|
+
|
|
293
|
+
function mediaRow(post, item, outcome, { fileId = null, reason = null, sizeInBytes = null } = {}) {
|
|
294
|
+
if (!OUTCOMES.includes(outcome)) throw new Error(`blog-post-media: unknown outcome ${outcome}`);
|
|
295
|
+
return {
|
|
296
|
+
sourceStableKey: postStableKey(post),
|
|
297
|
+
title: postTitle(post),
|
|
298
|
+
mediaKey: item.mediaKey,
|
|
299
|
+
kind: item.kind,
|
|
300
|
+
wpMediaId: item.wpMediaId,
|
|
301
|
+
sourceUrl: item.sourceUrl,
|
|
302
|
+
rewriteKeys: item.rewriteKeys,
|
|
303
|
+
fileId: fileId == null ? null : String(fileId),
|
|
304
|
+
...(sizeInBytes == null ? {} : { sizeInBytes: String(sizeInBytes) }),
|
|
305
|
+
outcome,
|
|
306
|
+
reason: reason == null ? null : String(reason).slice(0, 300),
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function errorText(error) {
|
|
311
|
+
if (!error) return 'unknown error';
|
|
312
|
+
const status = error.status ? `${error.status} ` : '';
|
|
313
|
+
return `${status}${error.message || String(error)}`;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Import every distinct medium of one post, settle every file in parallel, record each step.
|
|
317
|
+
// Returns { allReady, heroImageId, inlineBySourceUrl, items, resumed }. `resumed` is true when the
|
|
318
|
+
// post already had an open record from an earlier run (the caller's recovery-log trigger).
|
|
319
|
+
//
|
|
320
|
+
// Options: `state` from createPendingBlogMediaState; `fetchFeaturedMedia(id)` returns the
|
|
321
|
+
// WordPress `wp/v2/media/{id}` record (or a URL string, or null); `settle` is passed to
|
|
322
|
+
// waitUntilFileReady as { tries, delayMs }; `displayName` is optional.
|
|
323
|
+
async function importAndConfirmPostMedia(wix, { post, richContent, state, fetchFeaturedMedia, settle } = {}) {
|
|
324
|
+
if (!state) throw new Error('importAndConfirmPostMedia needs the pending-media state');
|
|
325
|
+
if (typeof fetchFeaturedMedia !== 'function') throw new Error('importAndConfirmPostMedia needs fetchFeaturedMedia(id)');
|
|
326
|
+
const record = await state.postRecord(post);
|
|
327
|
+
if (record && record.resolved) {
|
|
328
|
+
// Closed as written to `targetPostId`, yet the caller's crosswalk gate let it through. That is
|
|
329
|
+
// an inconsistency between two state files, not a media failure; guessing would either
|
|
330
|
+
// duplicate the post or write it without media. Stop and let the operator decide.
|
|
331
|
+
throw Object.assign(
|
|
332
|
+
new Error(`${postStableKey(post)} is recorded as written (Wix post ${record.targetPostId}) but is not in the crosswalk; repair the crosswalk before importing it again`),
|
|
333
|
+
{ code: 'BLOG_MEDIA_STATE_INCONSISTENT' },
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
const prior = record ? record.media : new Map();
|
|
337
|
+
const items = collectPostMedia({ post, richContent });
|
|
338
|
+
const toSettle = [];
|
|
339
|
+
|
|
340
|
+
for (const item of items) {
|
|
341
|
+
const last = prior.get(item.mediaKey);
|
|
342
|
+
if (last && last.fileId && RESUMABLE.has(last.outcome)) {
|
|
343
|
+
if (item.kind === 'featured' && last.sourceUrl) item.sourceUrl = last.sourceUrl;
|
|
344
|
+
item.fileId = last.fileId;
|
|
345
|
+
if (last.outcome === 'ready' && (item.kind !== 'featured' || Number(last.sizeInBytes) > 0)) {
|
|
346
|
+
item.outcome = 'ready'; continue;
|
|
347
|
+
}
|
|
348
|
+
toSettle.push(item);
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
if (item.unresolvable) {
|
|
352
|
+
item.outcome = 'unresolvable-url';
|
|
353
|
+
item.reason = post && post.link ? 'not an http(s) URL' : 'relative URL and the post has no link to resolve it against';
|
|
354
|
+
await state.appendMedia(mediaRow(post, item, item.outcome, { reason: item.reason }));
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
if (item.kind === 'featured') {
|
|
358
|
+
let resolved = null;
|
|
359
|
+
try {
|
|
360
|
+
const got = await fetchFeaturedMedia(item.wpMediaId);
|
|
361
|
+
resolved = typeof got === 'string' ? got : (got ? resolveImageUrl(got) : null);
|
|
362
|
+
if (!resolved) item.reason = 'WordPress media record has no usable image URL';
|
|
363
|
+
} catch (error) {
|
|
364
|
+
item.reason = `fetching WordPress media ${item.wpMediaId} failed: ${errorText(error)}`;
|
|
365
|
+
}
|
|
366
|
+
const absolute = resolved ? resolveImportUrl(resolved, post && post.link) : null;
|
|
367
|
+
if (!absolute) {
|
|
368
|
+
item.outcome = 'fetch-failed';
|
|
369
|
+
if (resolved) item.reason = 'WordPress media URL is not an http(s) URL';
|
|
370
|
+
await state.appendMedia(mediaRow(post, item, item.outcome, { reason: item.reason }));
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
item.sourceUrl = absolute;
|
|
374
|
+
}
|
|
375
|
+
let file;
|
|
376
|
+
try {
|
|
377
|
+
file = await writers.importMedia(wix, {
|
|
378
|
+
sourceUrl: item.sourceUrl,
|
|
379
|
+
displayName: displayNameFor(item.sourceUrl),
|
|
380
|
+
mediaType: 'IMAGE',
|
|
381
|
+
wpId: item.wpMediaId != null ? item.wpMediaId : undefined,
|
|
382
|
+
});
|
|
383
|
+
} catch (error) {
|
|
384
|
+
item.outcome = 'import-rejected';
|
|
385
|
+
item.reason = errorText(error);
|
|
386
|
+
await state.appendMedia(mediaRow(post, item, item.outcome, { reason: item.reason }));
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
if (!file || !file.id) {
|
|
390
|
+
item.outcome = 'import-rejected';
|
|
391
|
+
item.reason = 'import response carried no file id';
|
|
392
|
+
await state.appendMedia(mediaRow(post, item, item.outcome, { reason: item.reason }));
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
item.fileId = String(file.id);
|
|
396
|
+
// Checkpoint BEFORE polling: a crash from here on resumes this id instead of importing again.
|
|
397
|
+
await state.appendMedia(mediaRow(post, item, 'imported', { fileId: item.fileId }));
|
|
398
|
+
toSettle.push(item);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const settled = await Promise.all(toSettle.map(async (item) => {
|
|
402
|
+
try {
|
|
403
|
+
const ready = await writers.waitUntilFileReady(wix, item.fileId, settle || {});
|
|
404
|
+
if (ready && (item.kind !== 'featured' || Number(ready.sizeInBytes) > 0))
|
|
405
|
+
return { item, outcome: 'ready', sizeInBytes: ready.sizeInBytes };
|
|
406
|
+
if (ready && item.kind === 'featured')
|
|
407
|
+
return { item, outcome: 'not-ready', reason: 'cover is READY but has no non-zero sizeInBytes' };
|
|
408
|
+
return { item, outcome: 'not-ready', reason: 'still PENDING when the settle window ended' };
|
|
409
|
+
} catch (error) {
|
|
410
|
+
if (error && error.code === 'MEDIA_IMPORT_FAILED') return { item, outcome: 'failed', reason: 'Wix reported the import FAILED' };
|
|
411
|
+
return { item, outcome: 'status-unknown', reason: `reading the file status failed: ${errorText(error)}` };
|
|
412
|
+
}
|
|
413
|
+
}));
|
|
414
|
+
for (const { item, outcome, reason, sizeInBytes } of settled) {
|
|
415
|
+
item.outcome = outcome;
|
|
416
|
+
item.reason = reason || null;
|
|
417
|
+
if (outcome === 'failed') item.fileId = null; // a FAILED file is imported afresh next time
|
|
418
|
+
await state.appendMedia(mediaRow(post, item, outcome,
|
|
419
|
+
{ fileId: item.fileId, reason: item.reason, sizeInBytes }));
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
const allReady = items.every((item) => item.outcome === 'ready');
|
|
423
|
+
const featured = items.find((item) => item.kind === 'featured');
|
|
424
|
+
const inlineBySourceUrl = new Map();
|
|
425
|
+
for (const item of items) {
|
|
426
|
+
if (item.kind === 'inline' && item.outcome === 'ready') {
|
|
427
|
+
for (const key of item.rewriteKeys) inlineBySourceUrl.set(key, item.fileId);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
return {
|
|
431
|
+
allReady,
|
|
432
|
+
heroImageId: featured && featured.outcome === 'ready' ? featured.fileId : null,
|
|
433
|
+
inlineBySourceUrl,
|
|
434
|
+
items: items.map(({ unresolvable, ...rest }) => ({ ...rest, fileId: rest.fileId || null, reason: rest.reason || null })),
|
|
435
|
+
resumed: Boolean(record),
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function displayNameFor(url) {
|
|
440
|
+
try {
|
|
441
|
+
const last = new URL(url).pathname.split('/').filter(Boolean).pop();
|
|
442
|
+
return last ? decodeURIComponent(last) : undefined;
|
|
443
|
+
} catch {
|
|
444
|
+
return undefined;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// Rewrite the inline images of the SAME converted document. Only for an allReady result: a
|
|
449
|
+
// partial rewrite is the unapproved fallback.
|
|
450
|
+
function applyPostMedia(richContent, result) {
|
|
451
|
+
if (!result || !result.allReady) throw new Error('applyPostMedia: only an allReady media result may be applied to a post');
|
|
452
|
+
return writers.rewriteInlineMedia(richContent, result.inlineBySourceUrl);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Crosswalk hits must still enter the build runner for legacy reconciliation, but
|
|
456
|
+
// must not re-import media or close pending state before Wix identity is checked.
|
|
457
|
+
// Prefer the existing media ledger; a pre-ledger import supplies its local media
|
|
458
|
+
// crosswalk through resolveFromCrosswalk without making a new Wix media write.
|
|
459
|
+
async function existingPostMedia({ post, richContent, state, resolveFromCrosswalk } = {}) {
|
|
460
|
+
if (!state) throw new Error('existingPostMedia needs pending-media state');
|
|
461
|
+
const needed = collectPostMedia({ post, richContent });
|
|
462
|
+
if (!needed.length) return { allReady: true, heroImageId: null,
|
|
463
|
+
inlineBySourceUrl: new Map(), resumed: false, items: [] };
|
|
464
|
+
const record = await state.postRecord(post);
|
|
465
|
+
const local = record?.media;
|
|
466
|
+
const resolved = [];
|
|
467
|
+
for (const item of needed) {
|
|
468
|
+
let row = local?.get(item.mediaKey);
|
|
469
|
+
if ((!row || row.outcome !== 'ready' || !row.fileId ||
|
|
470
|
+
item.kind === 'featured' && !(Number(row.sizeInBytes) > 0)) &&
|
|
471
|
+
typeof resolveFromCrosswalk === 'function') row = await resolveFromCrosswalk(post, item);
|
|
472
|
+
if (!row || row.outcome !== 'ready' || !row.fileId ||
|
|
473
|
+
item.kind === 'featured' && !(Number(row.sizeInBytes) > 0)) {
|
|
474
|
+
throw Object.assign(
|
|
475
|
+
new Error(`blog legacy crosswalk ${postStableKey(post)} lacks confirmed READY media ${item.mediaKey}`),
|
|
476
|
+
{ code: 'BLOG_LEGACY_MEDIA_UNRESOLVED' });
|
|
477
|
+
}
|
|
478
|
+
resolved.push({ ...item, fileId: String(row.fileId), outcome: 'ready' });
|
|
479
|
+
}
|
|
480
|
+
const inlineBySourceUrl = new Map();
|
|
481
|
+
for (const item of resolved.filter(value => value.kind === 'inline'))
|
|
482
|
+
for (const key of item.rewriteKeys) inlineBySourceUrl.set(key, item.fileId);
|
|
483
|
+
return { allReady: true,
|
|
484
|
+
heroImageId: resolved.find(item => item.kind === 'featured')?.fileId || null,
|
|
485
|
+
inlineBySourceUrl, resumed: Boolean(record && !record.resolved), items: resolved };
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// --- report ------------------------------------------------------------------------------
|
|
489
|
+
|
|
490
|
+
function isCrosswalked(crosswalk, key) {
|
|
491
|
+
if (!crosswalk) return false;
|
|
492
|
+
if (typeof crosswalk === 'function') return Boolean(crosswalk(key));
|
|
493
|
+
if (typeof crosswalk.has === 'function') return crosswalk.has(key);
|
|
494
|
+
return false;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// Derived from the state file, never kept as a separate list. A post is pending when its record
|
|
498
|
+
// is open and it is not in the crosswalk — including when every medium is already READY but the
|
|
499
|
+
// post write was never recorded (`awaitingWrite`: a run stopped between the last READY row and
|
|
500
|
+
// the crosswalk row). `recoveryLogOwed` lists written posts whose recovery-log entry is not yet
|
|
501
|
+
// confirmed; the next run's crosswalk gate pays it. `crosswalk` is a Set/Map of sourceStableKeys
|
|
502
|
+
// or a function(sourceStableKey) -> truthy.
|
|
503
|
+
async function summarizePendingBlogMedia({ state, crosswalk } = {}) {
|
|
504
|
+
if (!state) throw new Error('summarizePendingBlogMedia needs the pending-media state');
|
|
505
|
+
const pending = [];
|
|
506
|
+
const recoveryLogOwed = [];
|
|
507
|
+
for (const post of (await state.fold()).values()) {
|
|
508
|
+
if (post.resolved) {
|
|
509
|
+
if (post.recoveryOwed && !post.recoveryLogged) recoveryLogOwed.push({ sourceStableKey: post.sourceStableKey, targetPostId: post.targetPostId, recoveryId: post.recoveryId });
|
|
510
|
+
continue;
|
|
511
|
+
}
|
|
512
|
+
if (isCrosswalked(crosswalk, post.sourceStableKey)) continue;
|
|
513
|
+
const media = [...post.media.values()]
|
|
514
|
+
.filter((row) => row.outcome !== 'ready')
|
|
515
|
+
.map((row) => ({ mediaKey: row.mediaKey, kind: row.kind, outcome: row.outcome, reason: row.reason || null, wpMediaId: row.wpMediaId || null, sourceUrl: row.sourceUrl || null, fileId: row.fileId || null }));
|
|
516
|
+
const awaitingWrite = media.length === 0;
|
|
517
|
+
pending.push({
|
|
518
|
+
sourceStableKey: post.sourceStableKey,
|
|
519
|
+
title: post.title,
|
|
520
|
+
awaitingWrite,
|
|
521
|
+
reason: awaitingWrite ? 'every medium is READY; the post write was not recorded — the next run writes it' : null,
|
|
522
|
+
media,
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
return { pendingMedia: pending.length, pending, recoveryLogOwed, statePath: 'state/crosswalk/pending-blog-media.ndjson' };
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// The standard recovery-log entry for a post a rerun resolved after it had been pending. The
|
|
529
|
+
// state's markResolved / closeIfCrosswalked append it; callers do not.
|
|
530
|
+
function buildBlogMediaRecoveryEntry({ runId, post, sourceStableKey, targetPostId, recoveryId, timestamp, crosswalkChanges = { added: 1, updated: 0 } }) {
|
|
531
|
+
const key = sourceStableKey || postStableKey(post);
|
|
532
|
+
return {
|
|
533
|
+
...(recoveryId ? { recoveryId } : {}),
|
|
534
|
+
...(timestamp ? { timestamp } : {}),
|
|
535
|
+
runId,
|
|
536
|
+
mode: 'resumed',
|
|
537
|
+
status: 'complete',
|
|
538
|
+
reason: 'blog_post_media_resolved',
|
|
539
|
+
selectionFilters: { entity: 'blog-post', sourceStableKey: key },
|
|
540
|
+
recordsSelected: 1,
|
|
541
|
+
recordsAttempted: 1,
|
|
542
|
+
imported: 1,
|
|
543
|
+
alreadyPresent: 0,
|
|
544
|
+
failed: 0,
|
|
545
|
+
deferred: 0,
|
|
546
|
+
unresolved: 0,
|
|
547
|
+
crosswalkChanges,
|
|
548
|
+
summaryChanges: { blogPostsPendingMedia: -1, blogPostsImported: 1 },
|
|
549
|
+
outcome: `blog post ${key} resolved as Wix post ${targetPostId} after its media reached READY`,
|
|
550
|
+
logs: ['state/crosswalk/pending-blog-media.ndjson'],
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
module.exports = {
|
|
555
|
+
SCHEMA_VERSION,
|
|
556
|
+
STATE_FILE,
|
|
557
|
+
OUTCOMES,
|
|
558
|
+
postStableKey,
|
|
559
|
+
collectPostMedia,
|
|
560
|
+
resolveImportUrl,
|
|
561
|
+
createPendingBlogMediaState,
|
|
562
|
+
importAndConfirmPostMedia,
|
|
563
|
+
applyPostMedia,
|
|
564
|
+
existingPostMedia,
|
|
565
|
+
summarizePendingBlogMedia,
|
|
566
|
+
buildBlogMediaRecoveryEntry,
|
|
567
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { opaqueId, contactId } = require('../../../lib/entity-verification');
|
|
4
|
+
// These selectors belong to inspected endpoint contracts, not to bulk APIs in general.
|
|
5
|
+
const selectors = { index: r => r?.itemMetadata?.originalIndex, success: r => r?.itemMetadata?.success };
|
|
6
|
+
const adapters = Object.freeze({
|
|
7
|
+
contacts: { ...selectors, envelope: r => r, validId: contactId },
|
|
8
|
+
products: { ...selectors, envelope: r => r?.productResults, validId: opaqueId },
|
|
9
|
+
inventory: { ...selectors, envelope: r => r, validId: null },
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
function correlateBulk(response, inputs, adapter) {
|
|
13
|
+
if (!adapter || !Object.values(adapters).includes(adapter)) throw new Error('An inspected endpoint adapter is required');
|
|
14
|
+
const envelope = adapter.envelope(response);
|
|
15
|
+
const defects = [];
|
|
16
|
+
const raw = Array.isArray(envelope?.results) ? envelope.results : [];
|
|
17
|
+
if (!Array.isArray(envelope?.results)) defects.push('invalid-envelope');
|
|
18
|
+
const meta = envelope?.bulkActionMetadata;
|
|
19
|
+
if (meta != null && (typeof meta !== 'object' || Array.isArray(meta))) defects.push('invalid-metadata');
|
|
20
|
+
const indexes = new Map(), ids = new Map();
|
|
21
|
+
for (const r of raw) {
|
|
22
|
+
const index = adapter.index(r);
|
|
23
|
+
indexes.set(index, (indexes.get(index) || 0) + 1);
|
|
24
|
+
if (adapter.success(r) === true && r?.itemMetadata?.id) ids.set(r.itemMetadata.id, (ids.get(r.itemMetadata.id) || 0) + 1);
|
|
25
|
+
}
|
|
26
|
+
const reportedSuccesses = raw.filter(r => adapter.success(r) === true).length;
|
|
27
|
+
const reportedFailures = raw.filter(r => adapter.success(r) === false).length;
|
|
28
|
+
for (const key of ['totalSuccesses', 'totalFailures', 'undetailedFailures']) {
|
|
29
|
+
if (meta?.[key] !== undefined && (!Number.isInteger(meta[key]) || meta[key] < 0 || meta[key] > inputs.length)) defects.push(`invalid-${key}`);
|
|
30
|
+
}
|
|
31
|
+
const undetailedFailures = Number.isInteger(meta?.undetailedFailures) && meta.undetailedFailures >= 0 ? meta.undetailedFailures : 0;
|
|
32
|
+
if (meta?.totalSuccesses !== undefined && meta.totalSuccesses !== reportedSuccesses) defects.push('inconsistent-successes');
|
|
33
|
+
if (meta?.totalFailures !== undefined && meta.totalFailures !== reportedFailures + undetailedFailures) defects.push('inconsistent-failures');
|
|
34
|
+
if (raw.length + undetailedFailures > inputs.length) defects.push('excess-results');
|
|
35
|
+
const globalInvalid = defects.length > 0;
|
|
36
|
+
const results = raw.map(r => {
|
|
37
|
+
const index = adapter.index(r), metadata = r?.itemMetadata || {};
|
|
38
|
+
const errors = [];
|
|
39
|
+
if (!Number.isInteger(index) || index < 0 || index >= inputs.length) errors.push('invalid-index');
|
|
40
|
+
else if (indexes.get(index) !== 1) errors.push('duplicate-index');
|
|
41
|
+
if (typeof adapter.success(r) !== 'boolean') errors.push('invalid-success');
|
|
42
|
+
if (adapter.validId && adapter.success(r) === true) {
|
|
43
|
+
if (!adapter.validId(metadata.id) || r?.item?._dryRunPlaceholder) errors.push('invalid-id');
|
|
44
|
+
if (r?.item?.id !== undefined && r.item.id !== metadata.id) errors.push('conflicting-id');
|
|
45
|
+
if (ids.get(metadata.id) > 1) errors.push('duplicate-target-id');
|
|
46
|
+
}
|
|
47
|
+
const correlated = !globalInvalid && errors.length === 0;
|
|
48
|
+
defects.push(...errors.map(code => `${code}:${String(index)}`));
|
|
49
|
+
return { index, input: Number.isInteger(index) ? inputs[index] : undefined, raw: r,
|
|
50
|
+
correlated, success: correlated && adapter.success(r) === true,
|
|
51
|
+
errorCode: errors[0] || (globalInvalid ? 'invalid-bulk-metadata' : metadata.error?.code) || null,
|
|
52
|
+
errorDescription: metadata.error?.description || null };
|
|
53
|
+
});
|
|
54
|
+
const accounted = new Set(results.filter(r => r.correlated).map(r => r.index));
|
|
55
|
+
const unresolvedIndexes = inputs.map((_, i) => i).filter(i => !accounted.has(i));
|
|
56
|
+
return { results, defects, unresolvedIndexes, unaccounted: unresolvedIndexes.length, undetailedFailures,
|
|
57
|
+
totalSuccesses: reportedSuccesses, totalFailures: reportedFailures + undetailedFailures };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function normalizeBulk(response, inputs, kind) {
|
|
61
|
+
const out = correlateBulk(response, inputs, adapters[kind]);
|
|
62
|
+
const contact = kind === 'contacts';
|
|
63
|
+
out.results = out.results.map(({ raw, input, ...r }) => ({ ...r,
|
|
64
|
+
[contact ? 'inputContact' : 'inputProduct']: input,
|
|
65
|
+
[contact ? 'contactId' : 'productId']: raw?.itemMetadata?.id || null,
|
|
66
|
+
[contact ? 'contact' : 'product']: raw?.item || null,
|
|
67
|
+
...(contact ? { action: raw?.action || null } : { revision: raw?.item?.revision || null }),
|
|
68
|
+
}));
|
|
69
|
+
out.succeeded = out.results.filter(r => r.success);
|
|
70
|
+
out.failed = out.results.filter(r => !r.success);
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
module.exports = { adapters, correlateBulk, normalizeBulk, opaqueId, contactId };
|