From 91d1159d892104a9c03776f79c646251094e74d7 Mon Sep 17 00:00:00 2001 From: Robin Kehl Date: Tue, 8 Oct 2024 13:37:00 +0200 Subject: [PATCH 1/9] feat: add `useScriptPaypal` --- package.json | 1 + .../third-parties/paypal/nuxt-scripts.vue | 8 ++ pnpm-lock.yaml | 118 ++++++++++++++++-- src/runtime/components/ScriptPayPal.vue | 95 ++++++++++++++ src/runtime/registry/paypal.ts | 94 ++++++++++++++ 5 files changed, 308 insertions(+), 8 deletions(-) create mode 100644 playground/pages/third-parties/paypal/nuxt-scripts.vue create mode 100644 src/runtime/components/ScriptPayPal.vue create mode 100644 src/runtime/registry/paypal.ts diff --git a/package.json b/package.json index b258324c..370c9ef2 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,7 @@ "@nuxt/eslint-config": "^0.5.7", "@nuxt/module-builder": "^0.8.4", "@nuxt/test-utils": "3.14.2", + "@paypal/paypal-js": "^8.1.2", "@types/semver": "^7.5.8", "@typescript-eslint/typescript-estree": "^8.7.0", "@unhead/schema": "1.11.6", diff --git a/playground/pages/third-parties/paypal/nuxt-scripts.vue b/playground/pages/third-parties/paypal/nuxt-scripts.vue new file mode 100644 index 00000000..590eb5e8 --- /dev/null +++ b/playground/pages/third-parties/paypal/nuxt-scripts.vue @@ -0,0 +1,8 @@ + + + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 58c655f6..59a7ae74 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -90,7 +90,7 @@ importers: version: 3.7.0 third-party-capital: specifier: 2.3.0 - version: 3.0.0 + version: 2.3.0 ufo: specifier: ^1.5.4 version: 1.5.4 @@ -116,6 +116,9 @@ importers: '@nuxt/test-utils': specifier: 3.14.2 version: 3.14.2(h3@1.12.0)(magicast@0.3.5)(nitropack@2.9.7(magicast@0.3.5)(webpack-sources@3.2.3))(playwright-core@1.47.2)(rollup@4.21.3)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(vitest@2.1.1(@types/node@22.7.3)(terser@5.34.0))(vue-router@4.4.5(vue@3.5.9(typescript@5.6.2)))(vue@3.5.9(typescript@5.6.2))(webpack-sources@3.2.3) + '@paypal/paypal-js': + specifier: ^8.1.2 + version: 8.1.2 '@types/semver': specifier: ^7.5.8 version: 7.5.8 @@ -175,7 +178,7 @@ importers: version: 1.5.1(magicast@0.3.5)(rollup@4.22.4)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(webpack-sources@3.2.3) '@nuxt/devtools-ui-kit': specifier: latest - version: 1.5.1(@nuxt/devtools@1.5.1(rollup@4.22.4)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(vue@3.5.9(typescript@5.6.2))(webpack-sources@3.2.3))(@unocss/webpack@0.62.4(rollup@4.22.4)(webpack@5.95.0(esbuild@0.23.1)))(@vue/compiler-core@3.5.9)(fuse.js@7.0.0)(magicast@0.3.5)(nuxt@3.13.2(@parcel/watcher@2.4.1)(@types/node@22.7.3)(eslint@9.11.1(jiti@2.0.0))(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.22.4)(terser@5.34.0)(typescript@5.6.2)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(webpack-sources@3.2.3))(postcss@8.4.47)(rollup@4.22.4)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(vue@3.5.9(typescript@5.6.2))(webpack-sources@3.2.3)(webpack@5.95.0(esbuild@0.23.1)) + version: 1.5.2(@nuxt/devtools@1.5.1(rollup@4.22.4)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(vue@3.5.9(typescript@5.6.2))(webpack-sources@3.2.3))(@unocss/webpack@0.62.4(rollup@4.22.4)(webpack@5.95.0(esbuild@0.23.1)))(@vue/compiler-core@3.5.9)(fuse.js@7.0.0)(magicast@0.3.5)(nuxt@3.13.2(@parcel/watcher@2.4.1)(@types/node@22.7.3)(eslint@9.11.1(jiti@2.0.0))(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.22.4)(terser@5.34.0)(typescript@5.6.2)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(webpack-sources@3.2.3))(postcss@8.4.47)(rollup@4.22.4)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(vue@3.5.9(typescript@5.6.2))(webpack-sources@3.2.3)(webpack@5.95.0(esbuild@0.23.1)) '@nuxt/kit': specifier: ^3.13.2 version: 3.13.2(magicast@0.3.5)(rollup@4.22.4)(webpack-sources@3.2.3) @@ -1333,11 +1336,21 @@ packages: peerDependencies: vite: '*' + '@nuxt/devtools-kit@1.5.2': + resolution: {integrity: sha512-IMbwflL/JLuK1JcM5yWKa+T5JGjwnCACZJw218/8bUTt/uTVgtkMueE+1/p9rhCWxvGQiT3xnCIXKhEg7xP58Q==} + peerDependencies: + vite: '*' + '@nuxt/devtools-ui-kit@1.5.1': resolution: {integrity: sha512-/1B2AYXuuPePWVuoHd/UGIKR3z3vO2bW73UAEszpHVLc/OwLA19K9f5o91sgyamAi2Qb5NymAMc/UZL0ijN8uA==} peerDependencies: '@nuxt/devtools': 1.5.1 + '@nuxt/devtools-ui-kit@1.5.2': + resolution: {integrity: sha512-J8rYJ3Pl6yZTybR6Wbq63RbsJMy3z4e2cQ/Ohiij2iCpZHEdqI22w0LALpmfH0mj1T/0903vWe+ce4jtyGO2zw==} + peerDependencies: + '@nuxt/devtools': 1.5.2 + '@nuxt/devtools-wizard@1.4.2': resolution: {integrity: sha512-TyhmPBg/xJKPOdnwR3DAh8KMUt6/0dUNABCxGVeY7PYbIiXt4msIGVJkBc4y+WwIJHOYPrSRClmZVsXQfRlB4A==} hasBin: true @@ -1554,6 +1567,9 @@ packages: resolution: {integrity: sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==} engines: {node: '>= 10.0.0'} + '@paypal/paypal-js@8.1.2': + resolution: {integrity: sha512-EKshGSWRxLWU1NyPB9P1TiOkPajVmpTo5I9HuZKoSv8y2uk0XIskXqMkAJ/Y9qAg9iJyP102Jb/atX63tTy24w==} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -2072,6 +2088,10 @@ packages: resolution: {integrity: sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.8.1': + resolution: {integrity: sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/type-utils@8.5.0': resolution: {integrity: sha512-N1K8Ix+lUM+cIDhL2uekVn/ZD7TZW+9/rwz8DclQpcQ9rk4sIL5CAlBC0CugWKREmDjBzI/kQqU4wkg46jWLYA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2089,6 +2109,10 @@ packages: resolution: {integrity: sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.8.1': + resolution: {integrity: sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.5.0': resolution: {integrity: sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2107,12 +2131,27 @@ packages: typescript: optional: true + '@typescript-eslint/typescript-estree@8.8.1': + resolution: {integrity: sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/utils@8.5.0': resolution: {integrity: sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 + '@typescript-eslint/utils@8.8.1': + resolution: {integrity: sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + '@typescript-eslint/visitor-keys@8.5.0': resolution: {integrity: sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2121,6 +2160,10 @@ packages: resolution: {integrity: sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.8.1': + resolution: {integrity: sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} @@ -5274,6 +5317,9 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} + promise-polyfill@8.3.0: + resolution: {integrity: sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==} + prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} @@ -5895,8 +5941,8 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - third-party-capital@3.0.0: - resolution: {integrity: sha512-zCrYkb4lnFTpsz0cyZ7c3q9aqQ5zX4po1Gy4utqOf8UkIV9Jx45P8ty6kpF1gLVvfkfNB36nEKv3isQhJv7Ftw==} + third-party-capital@2.3.0: + resolution: {integrity: sha512-p4rGOF4JCkI18HH3a1Vfd89Mg37TLlAsGmePBt20MA52frviYSBE6ToGOmTpqRC4EIlS5/4Owv6TpegFJUSkOg==} tiny-inflate@1.0.3: resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} @@ -7579,6 +7625,18 @@ snapshots: - supports-color - webpack-sources + '@nuxt/devtools-kit@1.5.2(magicast@0.3.5)(rollup@4.22.4)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(webpack-sources@3.2.3)': + dependencies: + '@nuxt/kit': 3.13.2(magicast@0.3.5)(rollup@4.22.4)(webpack-sources@3.2.3) + '@nuxt/schema': 3.13.2(rollup@4.22.4)(webpack-sources@3.2.3) + execa: 7.2.0 + vite: 5.4.5(@types/node@22.7.3)(terser@5.34.0) + transitivePeerDependencies: + - magicast + - rollup + - supports-color + - webpack-sources + '@nuxt/devtools-ui-kit@1.5.1(@nuxt/devtools@1.5.1(rollup@4.21.3)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(vue@3.5.9(typescript@5.6.2))(webpack-sources@3.2.3))(@unocss/webpack@0.62.4(rollup@4.21.3)(webpack@5.95.0(esbuild@0.23.1)))(@vue/compiler-core@3.5.9)(fuse.js@7.0.0)(magicast@0.3.5)(nuxt@3.13.2(@parcel/watcher@2.4.1)(@types/node@22.7.3)(eslint@9.11.1(jiti@2.0.0))(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.21.3)(terser@5.34.0)(typescript@5.6.2)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(webpack-sources@3.2.3))(postcss@8.4.47)(rollup@4.21.3)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(vue@3.5.9(typescript@5.6.2))(webpack-sources@3.2.3)(webpack@5.95.0(esbuild@0.23.1))': dependencies: '@iconify-json/carbon': 1.2.1 @@ -7627,14 +7685,14 @@ snapshots: - webpack - webpack-sources - '@nuxt/devtools-ui-kit@1.5.1(@nuxt/devtools@1.5.1(rollup@4.22.4)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(vue@3.5.9(typescript@5.6.2))(webpack-sources@3.2.3))(@unocss/webpack@0.62.4(rollup@4.22.4)(webpack@5.95.0(esbuild@0.23.1)))(@vue/compiler-core@3.5.9)(fuse.js@7.0.0)(magicast@0.3.5)(nuxt@3.13.2(@parcel/watcher@2.4.1)(@types/node@22.7.3)(eslint@9.11.1(jiti@2.0.0))(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.22.4)(terser@5.34.0)(typescript@5.6.2)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(webpack-sources@3.2.3))(postcss@8.4.47)(rollup@4.22.4)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(vue@3.5.9(typescript@5.6.2))(webpack-sources@3.2.3)(webpack@5.95.0(esbuild@0.23.1))': + '@nuxt/devtools-ui-kit@1.5.2(@nuxt/devtools@1.5.1(rollup@4.22.4)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(vue@3.5.9(typescript@5.6.2))(webpack-sources@3.2.3))(@unocss/webpack@0.62.4(rollup@4.22.4)(webpack@5.95.0(esbuild@0.23.1)))(@vue/compiler-core@3.5.9)(fuse.js@7.0.0)(magicast@0.3.5)(nuxt@3.13.2(@parcel/watcher@2.4.1)(@types/node@22.7.3)(eslint@9.11.1(jiti@2.0.0))(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.22.4)(terser@5.34.0)(typescript@5.6.2)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(webpack-sources@3.2.3))(postcss@8.4.47)(rollup@4.22.4)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(vue@3.5.9(typescript@5.6.2))(webpack-sources@3.2.3)(webpack@5.95.0(esbuild@0.23.1))': dependencies: '@iconify-json/carbon': 1.2.1 '@iconify-json/logos': 1.2.0 '@iconify-json/ri': 1.2.0 '@iconify-json/tabler': 1.2.3 '@nuxt/devtools': 1.5.1(rollup@4.22.4)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(vue@3.5.9(typescript@5.6.2))(webpack-sources@3.2.3) - '@nuxt/devtools-kit': 1.5.1(magicast@0.3.5)(rollup@4.22.4)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(webpack-sources@3.2.3) + '@nuxt/devtools-kit': 1.5.2(magicast@0.3.5)(rollup@4.22.4)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(webpack-sources@3.2.3) '@nuxt/kit': 3.13.2(magicast@0.3.5)(rollup@4.22.4)(webpack-sources@3.2.3) '@unocss/core': 0.62.4 '@unocss/nuxt': 0.62.4(magicast@0.3.5)(postcss@8.4.47)(rollup@4.22.4)(vite@5.4.5(@types/node@22.7.3)(terser@5.34.0))(webpack-sources@3.2.3)(webpack@5.95.0(esbuild@0.23.1)) @@ -8810,6 +8868,10 @@ snapshots: '@parcel/watcher-win32-ia32': 2.4.1 '@parcel/watcher-win32-x64': 2.4.1 + '@paypal/paypal-js@8.1.2': + dependencies: + promise-polyfill: 8.3.0 + '@pkgjs/parseargs@0.11.0': optional: true @@ -9190,7 +9252,7 @@ snapshots: '@stylistic/eslint-plugin@2.8.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: - '@typescript-eslint/utils': 8.5.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) + '@typescript-eslint/utils': 8.8.1(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2) eslint: 9.11.1(jiti@2.0.0) eslint-visitor-keys: 4.0.0 espree: 10.1.0 @@ -9322,6 +9384,11 @@ snapshots: '@typescript-eslint/types': 8.5.0 '@typescript-eslint/visitor-keys': 8.5.0 + '@typescript-eslint/scope-manager@8.8.1': + dependencies: + '@typescript-eslint/types': 8.8.1 + '@typescript-eslint/visitor-keys': 8.8.1 + '@typescript-eslint/type-utils@8.5.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: '@typescript-eslint/typescript-estree': 8.5.0(typescript@5.6.2) @@ -9338,6 +9405,8 @@ snapshots: '@typescript-eslint/types@8.7.0': {} + '@typescript-eslint/types@8.8.1': {} + '@typescript-eslint/typescript-estree@8.5.0(typescript@5.6.2)': dependencies: '@typescript-eslint/types': 8.5.0 @@ -9368,6 +9437,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.8.1(typescript@5.6.2)': + dependencies: + '@typescript-eslint/types': 8.8.1 + '@typescript-eslint/visitor-keys': 8.8.1 + debug: 4.3.7 + fast-glob: 3.3.2 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.6.2) + optionalDependencies: + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@8.5.0(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.1(jiti@2.0.0)) @@ -9379,6 +9463,17 @@ snapshots: - supports-color - typescript + '@typescript-eslint/utils@8.8.1(eslint@9.11.1(jiti@2.0.0))(typescript@5.6.2)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.1(jiti@2.0.0)) + '@typescript-eslint/scope-manager': 8.8.1 + '@typescript-eslint/types': 8.8.1 + '@typescript-eslint/typescript-estree': 8.8.1(typescript@5.6.2) + eslint: 9.11.1(jiti@2.0.0) + transitivePeerDependencies: + - supports-color + - typescript + '@typescript-eslint/visitor-keys@8.5.0': dependencies: '@typescript-eslint/types': 8.5.0 @@ -9389,6 +9484,11 @@ snapshots: '@typescript-eslint/types': 8.7.0 eslint-visitor-keys: 3.4.3 + '@typescript-eslint/visitor-keys@8.8.1': + dependencies: + '@typescript-eslint/types': 8.8.1 + eslint-visitor-keys: 3.4.3 + '@ungap/structured-clone@1.2.0': {} '@unhead/addons@1.11.2(rollup@4.22.4)(webpack-sources@3.2.3)': @@ -14002,6 +14102,8 @@ snapshots: process@0.11.10: {} + promise-polyfill@8.3.0: {} + prompts@2.4.2: dependencies: kleur: 3.0.3 @@ -14837,7 +14939,7 @@ snapshots: dependencies: any-promise: 1.3.0 - third-party-capital@3.0.0: + third-party-capital@2.3.0: dependencies: semver: 7.6.3 diff --git a/src/runtime/components/ScriptPayPal.vue b/src/runtime/components/ScriptPayPal.vue new file mode 100644 index 00000000..a585f337 --- /dev/null +++ b/src/runtime/components/ScriptPayPal.vue @@ -0,0 +1,95 @@ + + + diff --git a/src/runtime/registry/paypal.ts b/src/runtime/registry/paypal.ts new file mode 100644 index 00000000..a1cb287d --- /dev/null +++ b/src/runtime/registry/paypal.ts @@ -0,0 +1,94 @@ +import { withQuery } from 'ufo' +import type { PayPalNamespace } from '@paypal/paypal-js' +import { useRegistryScript } from '../utils' +import { object, string, optional, array, union, boolean } from '#nuxt-scripts-validator' +import type { RegistryScriptInput } from '#nuxt-scripts' + +export interface PaypalApi { + paypal: PayPalNamespace +} + +declare global { + interface Window extends PaypalApi { + } +} + +export const PaypalOptions = object({ + clientId: string(), + buyerCountry: optional(string()), + commit: optional(string()), + components: optional(union([string(), array(string())])), + currency: optional(string()), + debug: optional(union([string(), boolean()])), + disableFunding: optional(union([string(), array(string())])), + enableFunding: optional(union([string(), array(string())])), + integrationDate: optional(string()), + intent: optional(string()), + locale: optional(string()), + /** + * loadScript() supports an array for merchantId, even though + * merchant-id technically may not contain multiple values. + * For an array with a length of > 1 it automatically sets + * merchantId to "*" and moves the actual values to dataMerchantId + */ + merchantId: optional(union([string(), array(string())])), + vault: optional(union([string(), boolean()])), + // own props + sandbox: optional(boolean()), +}) + +export type PaypalInput = RegistryScriptInput + +export function useScriptPaypal(_options?: PaypalInput) { + return useRegistryScript('paypal', (options) => { + let dataMerchantId = undefined + + if (Array.isArray(options?.merchantId) && options?.merchantId.length > 1) { + dataMerchantId = JSON.stringify(options.merchantId) + options.merchantId = '*' + } + + if (Array.isArray(options?.components)) { + options.components = options.components.join(',') + } + + if (Array.isArray(options?.disableFunding)) { + options.disableFunding = options.disableFunding.join(',') + } + + if (Array.isArray(options?.enableFunding)) { + options.enableFunding = options.enableFunding.join(',') + } + + return { + scriptInput: { + // todo: default to sandbox if dev mode + src: withQuery(options.sandbox ? 'https://www.sandbox.paypal.com/sdk/js' : 'https://www.paypal.com/sdk/js', { + 'client-id': options.clientId, + 'buyer-country': options.buyerCountry, + 'commit': options.commit, + 'components': options.components, + 'currency': options.currency, + 'debug': options.debug, + 'disable-funding': options.disableFunding, + 'enable-funding': options.enableFunding, + 'integration-date': options.integrationDate, + 'intent': options.intent, + 'locale': options.locale, + 'merchant-id': options.merchantId, + 'vault': options.vault, + }), + dataMerchantId, + }, + schema: import.meta.dev ? PaypalOptions : undefined, + // trigger: 'client', + scriptOptions: { + use() { + return { + paypal: window.paypal, + } + }, + }, + } + }, _options) +} From b86f73712cd7b06f55feb6d48deaf756cd6b13a8 Mon Sep 17 00:00:00 2001 From: Robin Kehl Date: Mon, 18 Nov 2024 17:29:44 +0100 Subject: [PATCH 2/9] feat: add `ScriptPaypalButton.vue` component --- .../third-parties/paypal/nuxt-scripts.vue | 28 ++- src/runtime/components/ScriptPayPal.vue | 95 ---------- .../components/ScriptPaypalButtons.vue | 177 ++++++++++++++++++ src/runtime/registry/paypal.ts | 10 +- 4 files changed, 210 insertions(+), 100 deletions(-) delete mode 100644 src/runtime/components/ScriptPayPal.vue create mode 100644 src/runtime/components/ScriptPaypalButtons.vue diff --git a/playground/pages/third-parties/paypal/nuxt-scripts.vue b/playground/pages/third-parties/paypal/nuxt-scripts.vue index 590eb5e8..026a61cf 100644 --- a/playground/pages/third-parties/paypal/nuxt-scripts.vue +++ b/playground/pages/third-parties/paypal/nuxt-scripts.vue @@ -1,8 +1,30 @@ diff --git a/src/runtime/components/ScriptPayPal.vue b/src/runtime/components/ScriptPayPal.vue deleted file mode 100644 index a585f337..00000000 --- a/src/runtime/components/ScriptPayPal.vue +++ /dev/null @@ -1,95 +0,0 @@ - - - diff --git a/src/runtime/components/ScriptPaypalButtons.vue b/src/runtime/components/ScriptPaypalButtons.vue new file mode 100644 index 00000000..289d362b --- /dev/null +++ b/src/runtime/components/ScriptPaypalButtons.vue @@ -0,0 +1,177 @@ + + + diff --git a/src/runtime/registry/paypal.ts b/src/runtime/registry/paypal.ts index a1cb287d..b388c839 100644 --- a/src/runtime/registry/paypal.ts +++ b/src/runtime/registry/paypal.ts @@ -60,14 +60,20 @@ export function useScriptPaypal(_options?: PaypalInput) { options.enableFunding = options.enableFunding.join(',') } + if (options?.sandbox === undefined) { + // TODO: get dev from nuxt (?) + options.sandbox = import.meta.env.DEV + } + + const components = (options.components?.length ? options.components : ['buttons', 'messages', 'marks', 'card-fields', 'funding-eligibility']).join(',') + return { scriptInput: { - // todo: default to sandbox if dev mode src: withQuery(options.sandbox ? 'https://www.sandbox.paypal.com/sdk/js' : 'https://www.paypal.com/sdk/js', { 'client-id': options.clientId, 'buyer-country': options.buyerCountry, 'commit': options.commit, - 'components': options.components, + 'components': components, 'currency': options.currency, 'debug': options.debug, 'disable-funding': options.disableFunding, From 86562886cd911069603136a2c4e10e9d7233be2e Mon Sep 17 00:00:00 2001 From: Robin Kehl Date: Mon, 18 Nov 2024 17:51:06 +0100 Subject: [PATCH 3/9] feat: save button instance --- .../components/ScriptPaypalButtons.vue | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/runtime/components/ScriptPaypalButtons.vue b/src/runtime/components/ScriptPaypalButtons.vue index 289d362b..3bb5f13d 100644 --- a/src/runtime/components/ScriptPaypalButtons.vue +++ b/src/runtime/components/ScriptPaypalButtons.vue @@ -2,7 +2,6 @@ import { computed, type HTMLAttributes, onMounted, ref, type ReservedProps, shallowRef, watch } from 'vue' import { defu } from 'defu' import type { - PayPalButtonsComponentOptions, OnApproveActions, OnApproveData, OnCancelledActions, @@ -11,6 +10,8 @@ import type { OnShippingAddressChangeData, OnShippingOptionsChangeActions, OnShippingOptionsChangeData, + PayPalButtonsComponent, + PayPalButtonsComponentOptions, } from '@paypal/paypal-js' import type { OnInitActions } from '@paypal/paypal-js/types/components/buttons' import { onBeforeUnmount, resolveComponent, useScriptPaypal, useScriptTriggerElement } from '#imports' @@ -119,27 +120,30 @@ const options = computed(() => { watch(() => props.disabled, handleDisabled) +const buttonInst = shallowRef() + onMounted(() => { onLoaded(async ({ paypal }) => { if (!el.value) return - await paypal?.Buttons?.(options.value).render(el.value) + buttonInst.value = paypal?.Buttons?.(options.value) + await buttonInst.value?.render(el.value) ready.value = true - watch(() => options, () => { + watch(() => options.value, async (_options) => { if (!el.value) return - destroy() - paypal?.Buttons?.(options.value).render(el.value) + await buttonInst.value?.updateProps(_options) }) }) }) -function destroy() { - if (!el.value) return - el.value?.replaceChildren() +async function destroy() { + if (buttonInst.value) { + await buttonInst.value?.close() + } } -onBeforeUnmount(() => { - destroy() +onBeforeUnmount(async () => { + await destroy() }) const ScriptLoadingIndicator = resolveComponent('ScriptLoadingIndicator') From 5b012194d5337d9472a796dd0162115423933f9e Mon Sep 17 00:00:00 2001 From: Robin Kehl Date: Mon, 18 Nov 2024 17:56:42 +0100 Subject: [PATCH 4/9] chore: add correct aria label --- src/runtime/components/ScriptPaypalButtons.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/components/ScriptPaypalButtons.vue b/src/runtime/components/ScriptPaypalButtons.vue index 3bb5f13d..55a01495 100644 --- a/src/runtime/components/ScriptPaypalButtons.vue +++ b/src/runtime/components/ScriptPaypalButtons.vue @@ -156,8 +156,8 @@ const rootAttrs = computed(() => { 'aria-label': status.value === 'awaitingLoad' ? 'Paypal Script Placeholder' : status.value === 'loading' - ? 'Paypal Embed Loading' - : 'Paypal Embed', + ? 'Paypal Buttons Loading' + : 'Paypal Buttons', 'aria-live': 'polite', 'role': 'application', ...(trigger instanceof Promise ? trigger.ssrAttrs || {} : {}), From 61e4e9e0c3729be0da2f7860dc96b293bc573b2e Mon Sep 17 00:00:00 2001 From: Robin Kehl Date: Mon, 18 Nov 2024 18:00:29 +0100 Subject: [PATCH 5/9] feat: add `ScriptPaypalMarks` component --- .../third-parties/paypal/nuxt-scripts.vue | 3 + src/runtime/components/ScriptPaypalMarks.vue | 98 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 src/runtime/components/ScriptPaypalMarks.vue diff --git a/playground/pages/third-parties/paypal/nuxt-scripts.vue b/playground/pages/third-parties/paypal/nuxt-scripts.vue index 026a61cf..782589e9 100644 --- a/playground/pages/third-parties/paypal/nuxt-scripts.vue +++ b/playground/pages/third-parties/paypal/nuxt-scripts.vue @@ -1,5 +1,6 @@ diff --git a/src/runtime/components/ScriptPaypalMarks.vue b/src/runtime/components/ScriptPaypalMarks.vue new file mode 100644 index 00000000..82611e5a --- /dev/null +++ b/src/runtime/components/ScriptPaypalMarks.vue @@ -0,0 +1,98 @@ + + + From 8b1a22e7e432f51a4993402942b69899d6f78073 Mon Sep 17 00:00:00 2001 From: Robin Kehl Date: Mon, 18 Nov 2024 18:38:07 +0100 Subject: [PATCH 6/9] chore: minor adjustments --- src/runtime/registry/paypal.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/runtime/registry/paypal.ts b/src/runtime/registry/paypal.ts index b388c839..971d97da 100644 --- a/src/runtime/registry/paypal.ts +++ b/src/runtime/registry/paypal.ts @@ -32,6 +32,7 @@ export const PaypalOptions = object({ * merchantId to "*" and moves the actual values to dataMerchantId */ merchantId: optional(union([string(), array(string())])), + dataPartnerAttributionId: optional(string()), vault: optional(union([string(), boolean()])), // own props sandbox: optional(boolean()), @@ -65,11 +66,20 @@ export function useScriptPaypal(_options?: PaypalInput) { options.sandbox = import.meta.env.DEV } - const components = (options.components?.length ? options.components : ['buttons', 'messages', 'marks', 'card-fields', 'funding-eligibility']).join(',') + let components = ['buttons', 'messages', 'marks', 'card-fields', 'funding-eligibility'].join(',') + + if (options.components) { + if (Array.isArray(options.components)) { + components = options.components.join(',') + } + else { + components = options.components + } + } return { scriptInput: { - src: withQuery(options.sandbox ? 'https://www.sandbox.paypal.com/sdk/js' : 'https://www.paypal.com/sdk/js', { + 'src': withQuery(options.sandbox ? 'https://www.sandbox.paypal.com/sdk/js' : 'https://www.paypal.com/sdk/js', { 'client-id': options.clientId, 'buyer-country': options.buyerCountry, 'commit': options.commit, @@ -81,10 +91,10 @@ export function useScriptPaypal(_options?: PaypalInput) { 'integration-date': options.integrationDate, 'intent': options.intent, 'locale': options.locale, - 'merchant-id': options.merchantId, 'vault': options.vault, }), - dataMerchantId, + 'data-merchant-id': dataMerchantId, + 'data-partner-attribution-id': options.dataPartnerAttributionId, // TODO: maybe nuxt specific default }, schema: import.meta.dev ? PaypalOptions : undefined, // trigger: 'client', From 759b5f4025b8f658d72d0d7127d7a8b7c4f52476 Mon Sep 17 00:00:00 2001 From: Robin Kehl Date: Mon, 18 Nov 2024 19:08:20 +0100 Subject: [PATCH 7/9] feat: add `ScriptPaypalMessages` component --- .../third-parties/paypal/nuxt-scripts.vue | 2 + .../components/ScriptPaypalButtons.vue | 9 +- src/runtime/components/ScriptPaypalMarks.vue | 9 +- .../components/ScriptPaypalMessages.vue | 139 ++++++++++++++++++ src/runtime/registry/paypal.ts | 4 +- 5 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 src/runtime/components/ScriptPaypalMessages.vue diff --git a/playground/pages/third-parties/paypal/nuxt-scripts.vue b/playground/pages/third-parties/paypal/nuxt-scripts.vue index 782589e9..1a6caae6 100644 --- a/playground/pages/third-parties/paypal/nuxt-scripts.vue +++ b/playground/pages/third-parties/paypal/nuxt-scripts.vue @@ -12,6 +12,8 @@

Marks

+

Messages

+ diff --git a/src/runtime/components/ScriptPaypalButtons.vue b/src/runtime/components/ScriptPaypalButtons.vue index 55a01495..a086cf1c 100644 --- a/src/runtime/components/ScriptPaypalButtons.vue +++ b/src/runtime/components/ScriptPaypalButtons.vue @@ -14,7 +14,7 @@ import type { PayPalButtonsComponentOptions, } from '@paypal/paypal-js' import type { OnInitActions } from '@paypal/paypal-js/types/components/buttons' -import { onBeforeUnmount, resolveComponent, useScriptPaypal, useScriptTriggerElement } from '#imports' +import { onBeforeUnmount, type PaypalInput, resolveComponent, useScriptPaypal, useScriptTriggerElement } from '#imports' import type { ElementScriptTrigger } from '#nuxt-scripts' const el = ref(null) @@ -37,6 +37,10 @@ const props = withDefaults(defineProps<{ * The options for the paypal buttons. */ buttonOptions?: PayPalButtonsComponentOptions + /** + * The paypal script options. + */ + paypalScriptOptions?: Partial /** * Disables the paypal buttons. */ @@ -45,12 +49,15 @@ const props = withDefaults(defineProps<{ trigger: 'visible', clientId: 'test', disabled: false, + buttonOptions: () => ({}), + paypalScriptOptions: () => ({}), }) const ready = ref(false) const { onLoaded, status } = useScriptPaypal({ clientId: props.clientId, + ...props.paypalScriptOptions, }) const emit = defineEmits<{ diff --git a/src/runtime/components/ScriptPaypalMarks.vue b/src/runtime/components/ScriptPaypalMarks.vue index 82611e5a..a5d229bc 100644 --- a/src/runtime/components/ScriptPaypalMarks.vue +++ b/src/runtime/components/ScriptPaypalMarks.vue @@ -2,7 +2,7 @@ import { computed, type HTMLAttributes, onMounted, ref, type ReservedProps, shallowRef, watch } from 'vue' import { defu } from 'defu' import type { PayPalMarksComponent, PayPalMarksComponentOptions } from '@paypal/paypal-js' -import { onBeforeUnmount, resolveComponent, useScriptPaypal, useScriptTriggerElement } from '#imports' +import { onBeforeUnmount, type PaypalInput, resolveComponent, useScriptPaypal, useScriptTriggerElement } from '#imports' import type { ElementScriptTrigger } from '#nuxt-scripts' const el = ref(null) @@ -25,15 +25,22 @@ const props = withDefaults(defineProps<{ * The options for the paypal marks. */ marksOptions?: PayPalMarksComponentOptions + /** + * The paypal script options. + */ + paypalScriptOptions?: Partial }>(), { trigger: 'visible', clientId: 'test', + marksOptions: () => ({}), + paypalScriptOptions: () => ({}), }) const ready = ref(false) const { onLoaded, status } = useScriptPaypal({ clientId: props.clientId, + ...props.paypalScriptOptions, }) const marksInst = shallowRef() diff --git a/src/runtime/components/ScriptPaypalMessages.vue b/src/runtime/components/ScriptPaypalMessages.vue new file mode 100644 index 00000000..536f174f --- /dev/null +++ b/src/runtime/components/ScriptPaypalMessages.vue @@ -0,0 +1,139 @@ + + + diff --git a/src/runtime/registry/paypal.ts b/src/runtime/registry/paypal.ts index 971d97da..9ca5596b 100644 --- a/src/runtime/registry/paypal.ts +++ b/src/runtime/registry/paypal.ts @@ -32,7 +32,7 @@ export const PaypalOptions = object({ * merchantId to "*" and moves the actual values to dataMerchantId */ merchantId: optional(union([string(), array(string())])), - dataPartnerAttributionId: optional(string()), + partnerAttributionId: optional(string()), vault: optional(union([string(), boolean()])), // own props sandbox: optional(boolean()), @@ -94,7 +94,7 @@ export function useScriptPaypal(_options?: PaypalInput) { 'vault': options.vault, }), 'data-merchant-id': dataMerchantId, - 'data-partner-attribution-id': options.dataPartnerAttributionId, // TODO: maybe nuxt specific default + 'data-partner-attribution-id': options.partnerAttributionId, // TODO: maybe nuxt specific default }, schema: import.meta.dev ? PaypalOptions : undefined, // trigger: 'client', From 47fd43274306ff5316894829f433744c468e423f Mon Sep 17 00:00:00 2001 From: Robin Kehl Date: Mon, 18 Nov 2024 19:17:14 +0100 Subject: [PATCH 8/9] chore: dont remove messages --- playground/pages/third-parties/paypal/nuxt-scripts.vue | 2 +- src/runtime/components/ScriptPaypalMessages.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/playground/pages/third-parties/paypal/nuxt-scripts.vue b/playground/pages/third-parties/paypal/nuxt-scripts.vue index 1a6caae6..38d1cd0c 100644 --- a/playground/pages/third-parties/paypal/nuxt-scripts.vue +++ b/playground/pages/third-parties/paypal/nuxt-scripts.vue @@ -13,7 +13,7 @@

Marks

Messages

- + diff --git a/src/runtime/components/ScriptPaypalMessages.vue b/src/runtime/components/ScriptPaypalMessages.vue index 536f174f..4cbfebdc 100644 --- a/src/runtime/components/ScriptPaypalMessages.vue +++ b/src/runtime/components/ScriptPaypalMessages.vue @@ -88,7 +88,7 @@ onMounted(() => { watch(() => options.value, async (_options) => { if (!el.value) return - destroy() + // don't destroy the element messageInst.value = paypal?.Messages?.(_options) await messageInst.value?.render(el.value) }) From f3fc77d3dfd45f74edbfd1d667b8ce21f3f32eeb Mon Sep 17 00:00:00 2001 From: Robin Kehl Date: Mon, 18 Nov 2024 19:36:07 +0100 Subject: [PATCH 9/9] chore: update sandbox dev env --- src/runtime/registry/paypal.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/runtime/registry/paypal.ts b/src/runtime/registry/paypal.ts index 9ca5596b..7bafee8b 100644 --- a/src/runtime/registry/paypal.ts +++ b/src/runtime/registry/paypal.ts @@ -62,8 +62,7 @@ export function useScriptPaypal(_options?: PaypalInput) { } if (options?.sandbox === undefined) { - // TODO: get dev from nuxt (?) - options.sandbox = import.meta.env.DEV + options.sandbox = import.meta.dev } let components = ['buttons', 'messages', 'marks', 'card-fields', 'funding-eligibility'].join(',')