@flopay/vue 0.0.0-stage → 1.13.2

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.
@@ -0,0 +1,156 @@
1
+ import * as vue from 'vue';
2
+ import { PropType, VNode } from 'vue';
3
+ import { ThemeId, VaultCardThemeColors, FloPayAppearance, ButtonsLayoutStyles } from '@flopay/shared';
4
+ import { a as FloPayCardSetupCompleteEvent, F as FloPayCardSetupCancelEvent, b as FloPayCardSetupDeclineEvent, c as FloPayCardSetupError } from './hosted-setup-jpaaXDFA.cjs';
5
+
6
+ /** Verified terminal result from saving any advertised payment method. */
7
+ type FloPayPaymentMethodSetupCompleteEvent = FloPayCardSetupCompleteEvent;
8
+ /** Provider-neutral terminal decline from saving a payment method. */
9
+ type FloPayPaymentMethodSetupDeclineEvent = FloPayCardSetupDeclineEvent;
10
+ /** Abandoned setup emitted when the surface unmounts before an outcome. */
11
+ type FloPayPaymentMethodSetupCancelEvent = FloPayCardSetupCancelEvent;
12
+ /** Props for {@link FloPayPaymentMethodSetup} (callbacks are emits). */
13
+ interface FloPayPaymentMethodSetupProps {
14
+ sessionId: string;
15
+ nonce: string;
16
+ billingApiUrl?: string;
17
+ telemetry?: boolean;
18
+ /**
19
+ * The same `ThemeId` bundle `FloPayCheckout` and `FloPayCardSetup` resolve,
20
+ * or raw `VaultCardThemeColors` for the hosted card widget. A preset also
21
+ * themes the Stripe wallets and APMs and the outcome overlay. Defaults to
22
+ * `'modern-light'`, which an unrecognized preset id also falls back to;
23
+ * pass `'classic'` for the historic FloPay look.
24
+ */
25
+ theme?: ThemeId | VaultCardThemeColors;
26
+ /**
27
+ * Inline styles for the hosted card-widget container, with the same
28
+ * precedence over the preset's pane surface (and a stored
29
+ * `buttonsStyles.cardFormContainer`) as `FloPayCardSetup`.
30
+ */
31
+ containerStyle?: Record<string, string | number>;
32
+ /**
33
+ * Appearance override, the same prop and type as `FloPayCheckout`'s and
34
+ * `FloPayCardSetup`'s (for example a client's saved embed theme
35
+ * `appearance`). It replaces the preset's appearance outright, as checkout
36
+ * does: its variables drive the hosted card fields and submit button, the
37
+ * Stripe Elements of every wallet and APM, and the outcome overlay. Ignored
38
+ * with raw `VaultCardThemeColors`; an empty `{}` is the same as omitting it.
39
+ */
40
+ appearance?: FloPayAppearance;
41
+ /**
42
+ * Buttons-layout style overrides, the same prop and type as
43
+ * `FloPayCheckout`'s and `FloPayCardSetup`'s (for example a client's saved
44
+ * embed theme `buttonsStyles`), merged over the preset's buttons layout the
45
+ * way checkout merges them. `submitButton` and the `cardInput*` members style
46
+ * the hosted card form, and `cardFormContainer` the pane around it and the
47
+ * outcome overlay's panel. Ignored with raw `VaultCardThemeColors`; an empty
48
+ * `{}` is the same as omitting it.
49
+ */
50
+ buttonsStyles?: ButtonsLayoutStyles;
51
+ }
52
+ /**
53
+ * Saves any payment method the setup session advertises: the hosted vault
54
+ * card, advertised Stripe wallets/APMs (each on the account the backend chose
55
+ * for it) and the PayPal vault flow. Takes only `sessionId` + `nonce`, never
56
+ * creates a session. Success is the backend's call, never the provider's: once
57
+ * a wallet, APM or PayPal is accepted, the session is re-read until the
58
+ * backend reports the method saved, and only then is `complete` emitted, once.
59
+ * A `decline` is never paired with a `complete`.
60
+ */
61
+ declare const FloPayPaymentMethodSetup: vue.DefineComponent<vue.ExtractPropTypes<{
62
+ sessionId: {
63
+ type: StringConstructor;
64
+ default: undefined;
65
+ };
66
+ nonce: {
67
+ type: StringConstructor;
68
+ default: undefined;
69
+ };
70
+ billingApiUrl: {
71
+ type: StringConstructor;
72
+ default: undefined;
73
+ };
74
+ telemetry: {
75
+ type: BooleanConstructor;
76
+ default: undefined;
77
+ };
78
+ theme: {
79
+ type: PropType<ThemeId | VaultCardThemeColors>;
80
+ default: string;
81
+ };
82
+ containerStyle: {
83
+ type: PropType<Record<string, string | number>>;
84
+ default: undefined;
85
+ };
86
+ appearance: {
87
+ type: PropType<FloPayAppearance>;
88
+ default: undefined;
89
+ };
90
+ buttonsStyles: {
91
+ type: PropType<ButtonsLayoutStyles>;
92
+ default: undefined;
93
+ };
94
+ }>, () => VNode<vue.RendererNode, vue.RendererElement, {
95
+ [key: string]: any;
96
+ }> | VNode<vue.RendererNode, vue.RendererElement, {
97
+ [key: string]: any;
98
+ }>[] | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
99
+ ready: () => true;
100
+ complete: (_event: FloPayPaymentMethodSetupCompleteEvent) => true;
101
+ cancel: (_event: FloPayPaymentMethodSetupCancelEvent) => true;
102
+ decline: (_event: FloPayPaymentMethodSetupDeclineEvent) => true;
103
+ validation: (_message: string | null) => true;
104
+ error: (_error: FloPayCardSetupError) => true;
105
+ }, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
106
+ sessionId: {
107
+ type: StringConstructor;
108
+ default: undefined;
109
+ };
110
+ nonce: {
111
+ type: StringConstructor;
112
+ default: undefined;
113
+ };
114
+ billingApiUrl: {
115
+ type: StringConstructor;
116
+ default: undefined;
117
+ };
118
+ telemetry: {
119
+ type: BooleanConstructor;
120
+ default: undefined;
121
+ };
122
+ theme: {
123
+ type: PropType<ThemeId | VaultCardThemeColors>;
124
+ default: string;
125
+ };
126
+ containerStyle: {
127
+ type: PropType<Record<string, string | number>>;
128
+ default: undefined;
129
+ };
130
+ appearance: {
131
+ type: PropType<FloPayAppearance>;
132
+ default: undefined;
133
+ };
134
+ buttonsStyles: {
135
+ type: PropType<ButtonsLayoutStyles>;
136
+ default: undefined;
137
+ };
138
+ }>> & Readonly<{
139
+ onComplete?: ((_event: FloPayCardSetupCompleteEvent) => any) | undefined;
140
+ onCancel?: ((_event: FloPayCardSetupCancelEvent) => any) | undefined;
141
+ onError?: ((_error: FloPayCardSetupError) => any) | undefined;
142
+ onReady?: (() => any) | undefined;
143
+ onDecline?: ((_event: FloPayCardSetupDeclineEvent) => any) | undefined;
144
+ onValidation?: ((_message: string | null) => any) | undefined;
145
+ }>, {
146
+ nonce: string;
147
+ sessionId: string;
148
+ billingApiUrl: string;
149
+ telemetry: boolean;
150
+ appearance: FloPayAppearance;
151
+ theme: VaultCardThemeColors | ThemeId;
152
+ containerStyle: Record<string, string | number>;
153
+ buttonsStyles: ButtonsLayoutStyles;
154
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
155
+
156
+ export { FloPayPaymentMethodSetup, type FloPayPaymentMethodSetupCancelEvent, type FloPayPaymentMethodSetupCompleteEvent, type FloPayPaymentMethodSetupDeclineEvent, type FloPayPaymentMethodSetupProps };
@@ -0,0 +1,156 @@
1
+ import * as vue from 'vue';
2
+ import { PropType, VNode } from 'vue';
3
+ import { ThemeId, VaultCardThemeColors, FloPayAppearance, ButtonsLayoutStyles } from '@flopay/shared';
4
+ import { a as FloPayCardSetupCompleteEvent, F as FloPayCardSetupCancelEvent, b as FloPayCardSetupDeclineEvent, c as FloPayCardSetupError } from './hosted-setup-jpaaXDFA.js';
5
+
6
+ /** Verified terminal result from saving any advertised payment method. */
7
+ type FloPayPaymentMethodSetupCompleteEvent = FloPayCardSetupCompleteEvent;
8
+ /** Provider-neutral terminal decline from saving a payment method. */
9
+ type FloPayPaymentMethodSetupDeclineEvent = FloPayCardSetupDeclineEvent;
10
+ /** Abandoned setup emitted when the surface unmounts before an outcome. */
11
+ type FloPayPaymentMethodSetupCancelEvent = FloPayCardSetupCancelEvent;
12
+ /** Props for {@link FloPayPaymentMethodSetup} (callbacks are emits). */
13
+ interface FloPayPaymentMethodSetupProps {
14
+ sessionId: string;
15
+ nonce: string;
16
+ billingApiUrl?: string;
17
+ telemetry?: boolean;
18
+ /**
19
+ * The same `ThemeId` bundle `FloPayCheckout` and `FloPayCardSetup` resolve,
20
+ * or raw `VaultCardThemeColors` for the hosted card widget. A preset also
21
+ * themes the Stripe wallets and APMs and the outcome overlay. Defaults to
22
+ * `'modern-light'`, which an unrecognized preset id also falls back to;
23
+ * pass `'classic'` for the historic FloPay look.
24
+ */
25
+ theme?: ThemeId | VaultCardThemeColors;
26
+ /**
27
+ * Inline styles for the hosted card-widget container, with the same
28
+ * precedence over the preset's pane surface (and a stored
29
+ * `buttonsStyles.cardFormContainer`) as `FloPayCardSetup`.
30
+ */
31
+ containerStyle?: Record<string, string | number>;
32
+ /**
33
+ * Appearance override, the same prop and type as `FloPayCheckout`'s and
34
+ * `FloPayCardSetup`'s (for example a client's saved embed theme
35
+ * `appearance`). It replaces the preset's appearance outright, as checkout
36
+ * does: its variables drive the hosted card fields and submit button, the
37
+ * Stripe Elements of every wallet and APM, and the outcome overlay. Ignored
38
+ * with raw `VaultCardThemeColors`; an empty `{}` is the same as omitting it.
39
+ */
40
+ appearance?: FloPayAppearance;
41
+ /**
42
+ * Buttons-layout style overrides, the same prop and type as
43
+ * `FloPayCheckout`'s and `FloPayCardSetup`'s (for example a client's saved
44
+ * embed theme `buttonsStyles`), merged over the preset's buttons layout the
45
+ * way checkout merges them. `submitButton` and the `cardInput*` members style
46
+ * the hosted card form, and `cardFormContainer` the pane around it and the
47
+ * outcome overlay's panel. Ignored with raw `VaultCardThemeColors`; an empty
48
+ * `{}` is the same as omitting it.
49
+ */
50
+ buttonsStyles?: ButtonsLayoutStyles;
51
+ }
52
+ /**
53
+ * Saves any payment method the setup session advertises: the hosted vault
54
+ * card, advertised Stripe wallets/APMs (each on the account the backend chose
55
+ * for it) and the PayPal vault flow. Takes only `sessionId` + `nonce`, never
56
+ * creates a session. Success is the backend's call, never the provider's: once
57
+ * a wallet, APM or PayPal is accepted, the session is re-read until the
58
+ * backend reports the method saved, and only then is `complete` emitted, once.
59
+ * A `decline` is never paired with a `complete`.
60
+ */
61
+ declare const FloPayPaymentMethodSetup: vue.DefineComponent<vue.ExtractPropTypes<{
62
+ sessionId: {
63
+ type: StringConstructor;
64
+ default: undefined;
65
+ };
66
+ nonce: {
67
+ type: StringConstructor;
68
+ default: undefined;
69
+ };
70
+ billingApiUrl: {
71
+ type: StringConstructor;
72
+ default: undefined;
73
+ };
74
+ telemetry: {
75
+ type: BooleanConstructor;
76
+ default: undefined;
77
+ };
78
+ theme: {
79
+ type: PropType<ThemeId | VaultCardThemeColors>;
80
+ default: string;
81
+ };
82
+ containerStyle: {
83
+ type: PropType<Record<string, string | number>>;
84
+ default: undefined;
85
+ };
86
+ appearance: {
87
+ type: PropType<FloPayAppearance>;
88
+ default: undefined;
89
+ };
90
+ buttonsStyles: {
91
+ type: PropType<ButtonsLayoutStyles>;
92
+ default: undefined;
93
+ };
94
+ }>, () => VNode<vue.RendererNode, vue.RendererElement, {
95
+ [key: string]: any;
96
+ }> | VNode<vue.RendererNode, vue.RendererElement, {
97
+ [key: string]: any;
98
+ }>[] | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
99
+ ready: () => true;
100
+ complete: (_event: FloPayPaymentMethodSetupCompleteEvent) => true;
101
+ cancel: (_event: FloPayPaymentMethodSetupCancelEvent) => true;
102
+ decline: (_event: FloPayPaymentMethodSetupDeclineEvent) => true;
103
+ validation: (_message: string | null) => true;
104
+ error: (_error: FloPayCardSetupError) => true;
105
+ }, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
106
+ sessionId: {
107
+ type: StringConstructor;
108
+ default: undefined;
109
+ };
110
+ nonce: {
111
+ type: StringConstructor;
112
+ default: undefined;
113
+ };
114
+ billingApiUrl: {
115
+ type: StringConstructor;
116
+ default: undefined;
117
+ };
118
+ telemetry: {
119
+ type: BooleanConstructor;
120
+ default: undefined;
121
+ };
122
+ theme: {
123
+ type: PropType<ThemeId | VaultCardThemeColors>;
124
+ default: string;
125
+ };
126
+ containerStyle: {
127
+ type: PropType<Record<string, string | number>>;
128
+ default: undefined;
129
+ };
130
+ appearance: {
131
+ type: PropType<FloPayAppearance>;
132
+ default: undefined;
133
+ };
134
+ buttonsStyles: {
135
+ type: PropType<ButtonsLayoutStyles>;
136
+ default: undefined;
137
+ };
138
+ }>> & Readonly<{
139
+ onComplete?: ((_event: FloPayCardSetupCompleteEvent) => any) | undefined;
140
+ onCancel?: ((_event: FloPayCardSetupCancelEvent) => any) | undefined;
141
+ onError?: ((_error: FloPayCardSetupError) => any) | undefined;
142
+ onReady?: (() => any) | undefined;
143
+ onDecline?: ((_event: FloPayCardSetupDeclineEvent) => any) | undefined;
144
+ onValidation?: ((_message: string | null) => any) | undefined;
145
+ }>, {
146
+ nonce: string;
147
+ sessionId: string;
148
+ billingApiUrl: string;
149
+ telemetry: boolean;
150
+ appearance: FloPayAppearance;
151
+ theme: VaultCardThemeColors | ThemeId;
152
+ containerStyle: Record<string, string | number>;
153
+ buttonsStyles: ButtonsLayoutStyles;
154
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
155
+
156
+ export { FloPayPaymentMethodSetup, type FloPayPaymentMethodSetupCancelEvent, type FloPayPaymentMethodSetupCompleteEvent, type FloPayPaymentMethodSetupDeclineEvent, type FloPayPaymentMethodSetupProps };
@@ -0,0 +1,7 @@
1
+ import {
2
+ FloPayPaymentMethodSetup
3
+ } from "./chunk-2PLBNCM6.mjs";
4
+ import "./chunk-W52CQTJI.mjs";
5
+ export {
6
+ FloPayPaymentMethodSetup
7
+ };
@@ -0,0 +1,148 @@
1
+ // src/payment-method-setup-paypal.ts
2
+ import { PaymentAPI } from "@flopay/js/card-setup";
3
+ import {
4
+ buildExternalMethodRecoveryMessage,
5
+ classifyExternalMethodFailure,
6
+ detectPayPalEnvironment,
7
+ FloPayError,
8
+ PAYPAL_VAULTED_PAYMENT_METHOD_TYPE
9
+ } from "@flopay/shared";
10
+ import { loadScript } from "@paypal/paypal-js";
11
+ import { defineComponent, h, onBeforeUnmount, onMounted, ref } from "vue";
12
+ var PayPalSetupMethod = defineComponent({
13
+ name: "FloPayPayPalSetupMethod",
14
+ props: {
15
+ clientId: { type: String, required: true },
16
+ environment: { type: String, default: void 0 },
17
+ /** The setup session's own currency, when the read carries one. A vault flow needs none. */
18
+ currency: { type: String, default: void 0 },
19
+ sessionId: { type: String, required: true },
20
+ nonce: { type: String, required: true },
21
+ billingApiUrl: { type: String, required: true },
22
+ telemetry: { type: Boolean, default: void 0 },
23
+ customer: { type: Object, required: true }
24
+ },
25
+ emits: {
26
+ /** The buyer started saving PayPal. */
27
+ submitting: () => true,
28
+ /** PayPal accepted the account and the billing API took the token. */
29
+ confirmed: () => true,
30
+ /** A technical failure; `retryable` says whether trying again can help. */
31
+ failed: (_error, _options) => true,
32
+ /** The buyer closed PayPal's window without an outcome (not a cancel). */
33
+ abandoned: () => true
34
+ },
35
+ setup(props, { emit }) {
36
+ const container = ref(null);
37
+ let active = true;
38
+ let close;
39
+ let api = null;
40
+ onMounted(() => {
41
+ const { inAppBrowser } = detectPayPalEnvironment();
42
+ const client = new PaymentAPI(props.billingApiUrl, { telemetry: props.telemetry });
43
+ api = client;
44
+ const { sessionId, nonce } = props;
45
+ const customer = {
46
+ userId: props.customer.userId,
47
+ email: props.customer.email
48
+ };
49
+ const environment = props.environment;
50
+ void (async () => {
51
+ try {
52
+ const paypal = await loadScript({
53
+ clientId: props.clientId,
54
+ ...props.currency ? { currency: props.currency.toUpperCase() } : {},
55
+ components: "buttons",
56
+ ...environment === "sandbox" || environment === "production" ? { environment } : {}
57
+ });
58
+ const target = container.value;
59
+ if (!active || !target) return;
60
+ if (!paypal?.Buttons) {
61
+ throw new FloPayError("PayPal could not be loaded.", "api_error", {
62
+ code: "paypal_unavailable"
63
+ });
64
+ }
65
+ const buttons = paypal.Buttons({
66
+ createVaultSetupToken: async () => {
67
+ emit("submitting");
68
+ const intent = await client.createSessionIntent(sessionId, nonce, {
69
+ provider: "paypal",
70
+ paymentMethodCategory: "wallet",
71
+ paymentMethodType: PAYPAL_VAULTED_PAYMENT_METHOD_TYPE,
72
+ paymentMethodId: null,
73
+ intentKind: "setup"
74
+ });
75
+ if (intent.provider !== "paypal" || intent.providerObjectType !== "setup_token") {
76
+ throw new FloPayError(
77
+ "The billing API did not return a PayPal setup token.",
78
+ "api_error",
79
+ { code: "InvalidSessionIntentResponse" }
80
+ );
81
+ }
82
+ return intent.providerObjectId;
83
+ },
84
+ onApprove: async (data) => {
85
+ const token = data.vaultSetupToken;
86
+ if (!token) {
87
+ throw new FloPayError("PayPal approved without a setup token.", "api_error", {
88
+ code: "paypal_setup_token_missing"
89
+ });
90
+ }
91
+ const response = await client.processPayment(customer.userId, {
92
+ sessionId,
93
+ nonce,
94
+ paymentMethodCategory: "paypal",
95
+ tokenizedData: {
96
+ id: token,
97
+ type: "paypal_setup_token",
98
+ isPaypal: true,
99
+ gateway: "paypal",
100
+ paymentMethodType: PAYPAL_VAULTED_PAYMENT_METHOD_TYPE
101
+ },
102
+ accountData: customer
103
+ });
104
+ if (!response.ok) {
105
+ throw new FloPayError("PayPal could not be saved.", "api_error", {
106
+ code: "paypal_setup_failed",
107
+ statusCode: response.status
108
+ });
109
+ }
110
+ if (active) emit("confirmed");
111
+ },
112
+ onCancel: () => {
113
+ if (active) emit("abandoned");
114
+ },
115
+ onError: (error) => {
116
+ if (!active) return;
117
+ const { popupBlocked } = classifyExternalMethodFailure(error, {
118
+ inAppBrowser,
119
+ handoffObserved: false
120
+ });
121
+ emit(
122
+ "failed",
123
+ popupBlocked ? new Error(buildExternalMethodRecoveryMessage("PayPal", true, inAppBrowser)) : error,
124
+ { code: popupBlocked ? "popup_blocked" : "paypal_setup_failed", retryable: true }
125
+ );
126
+ }
127
+ });
128
+ close = () => buttons.close();
129
+ await buttons.render(target);
130
+ } catch (error) {
131
+ if (!active) return;
132
+ emit("failed", error, { code: "paypal_unavailable", retryable: true });
133
+ }
134
+ })();
135
+ });
136
+ onBeforeUnmount(() => {
137
+ active = false;
138
+ void close?.().catch(() => {
139
+ });
140
+ api?.destroy();
141
+ api = null;
142
+ });
143
+ return () => h("div", { ref: container, "data-flopay-paypal-setup": "" });
144
+ }
145
+ });
146
+ export {
147
+ PayPalSetupMethod
148
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ StripePaymentMethods
3
+ } from "./chunk-VXYNYMHI.mjs";
4
+ export {
5
+ StripePaymentMethods
6
+ };
package/package.json CHANGED
@@ -1,6 +1,63 @@
1
1
  {
2
2
  "name": "@flopay/vue",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "1.13.2",
4
+ "type": "module",
5
+ "sideEffects": false,
6
+ "publishConfig": {
7
+ "registry": "https://registry.npmjs.org/",
8
+ "access": "public"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/TeamFloPay/sdk.git",
13
+ "directory": "packages/vue"
14
+ },
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.mjs",
19
+ "require": "./dist/index.cjs"
20
+ },
21
+ "./card-setup": {
22
+ "types": "./dist/card-setup-entry.d.ts",
23
+ "import": "./dist/card-setup-entry.mjs",
24
+ "require": "./dist/card-setup-entry.cjs"
25
+ },
26
+ "./payment-method-setup": {
27
+ "types": "./dist/payment-method-setup-entry.d.ts",
28
+ "import": "./dist/payment-method-setup-entry.mjs",
29
+ "require": "./dist/payment-method-setup-entry.cjs"
30
+ }
31
+ },
32
+ "main": "./dist/index.cjs",
33
+ "module": "./dist/index.mjs",
34
+ "types": "./dist/index.d.ts",
35
+ "files": [
36
+ "dist"
37
+ ],
38
+ "dependencies": {
39
+ "@paypal/paypal-js": "^10.1.0",
40
+ "@stripe/stripe-js": "^9.17.0",
41
+ "@flopay/js": "1.13.2",
42
+ "@flopay/shared": "1.13.2"
43
+ },
44
+ "peerDependencies": {
45
+ "vue": ">=3.3.0"
46
+ },
47
+ "devDependencies": {
48
+ "@vue/server-renderer": "3.5.44",
49
+ "@vue/test-utils": "^2.4.6",
50
+ "jsdom": "^29.1.1",
51
+ "tsup": "^8.3.0",
52
+ "typescript": "^6.0.3",
53
+ "vitest": "4.1.12",
54
+ "vue": "3.5.44"
55
+ },
56
+ "scripts": {
57
+ "build": "tsup",
58
+ "dev": "tsup --watch",
59
+ "typecheck": "tsc --noEmit",
60
+ "test": "vitest run",
61
+ "clean": "rm -rf dist"
62
+ }
6
63
  }