@akinon/projectzero 2.0.0-beta.12 → 2.0.0-beta.13
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/CHANGELOG.md +100 -23
- package/app-template/.env.example +1 -0
- package/app-template/.github/instructions/account.instructions.md +749 -0
- package/app-template/.github/instructions/checkout.instructions.md +678 -0
- package/app-template/.github/instructions/default.instructions.md +279 -0
- package/app-template/.github/instructions/edge-cases.instructions.md +73 -0
- package/app-template/.github/instructions/routing.instructions.md +603 -0
- package/app-template/.github/instructions/settings.instructions.md +338 -0
- package/app-template/.gitignore +3 -0
- package/app-template/AGENTS.md +7 -0
- package/app-template/CHANGELOG.md +1348 -310
- package/app-template/Procfile +1 -1
- package/app-template/akinon.json +0 -3
- package/app-template/build.sh +10 -0
- package/app-template/docs/advanced-usage.md +101 -0
- package/app-template/docs/sentry-usage.md +35 -0
- package/app-template/next-env.d.ts +1 -0
- package/app-template/{next.config.ts → next.config.mjs} +6 -6
- package/app-template/package.json +58 -51
- package/app-template/postcss.config.mjs +1 -4
- package/app-template/public/locales/en/checkout.json +6 -0
- package/app-template/public/locales/en/common.json +50 -1
- package/app-template/public/locales/en/product.json +62 -1
- package/app-template/public/locales/tr/checkout.json +6 -0
- package/app-template/public/locales/tr/common.json +50 -1
- package/app-template/public/locales/tr/product.json +63 -0
- package/app-template/public/masterpass-javascript-sdk-web.min.js +1 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/[...prettyurl]/page.tsx +9 -9
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/layout.tsx +2 -2
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/cancellation/page.tsx +6 -6
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/page.tsx +6 -6
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/page.tsx +1 -1
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/profile/page.tsx +2 -2
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/address/stores/page.tsx +2 -2
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/page.tsx +1 -1
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket/page.tsx +2 -2
- package/app-template/src/app/[pz]/category/[pk]/page.tsx +27 -0
- package/app-template/src/app/[pz]/flat-page/[pk]/page.tsx +23 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/forms/[pk]/generate/page.tsx +2 -3
- package/app-template/src/app/[pz]/group-product/[pk]/page.tsx +93 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/landing-page/[pk]/page.tsx +2 -4
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/layout.tsx +3 -10
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/list/page.tsx +2 -4
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/not-found.tsx +5 -7
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/page.tsx +6 -4
- package/app-template/src/app/[pz]/product/[pk]/page.tsx +102 -0
- package/app-template/src/app/[pz]/special-page/[pk]/page.tsx +35 -0
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/email-set-primary/[[...id]]/page.tsx +3 -4
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/registration/account-confirm-email/[[...id]]/page.tsx +3 -3
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/reset/[[...id]]/page.tsx +6 -12
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/xml-sitemap/[node]/route.ts +2 -2
- package/app-template/src/app/api/auth/[...nextauth]/route.ts +3 -0
- package/app-template/src/app/api/form/[...id]/route.ts +1 -7
- package/app-template/src/app/api/image-proxy/route.ts +1 -0
- package/app-template/src/app/api/product-categories/route.ts +1 -0
- package/app-template/src/app/api/similar-product-list/route.ts +1 -0
- package/app-template/src/app/api/similar-products/route.ts +1 -0
- package/app-template/src/app/api/virtual-try-on/limited-categories/route.ts +1 -0
- package/app-template/src/app/api/virtual-try-on/route.ts +1 -0
- package/app-template/src/assets/globals.scss +4 -133
- package/app-template/src/auth.ts +3 -0
- package/app-template/src/components/__tests__/badge.test.tsx +2 -2
- package/app-template/src/components/__tests__/link.test.tsx +2 -0
- package/app-template/src/components/accordion.tsx +23 -20
- package/app-template/src/components/button.tsx +1 -1
- package/app-template/src/components/carousel-core.tsx +4 -11
- package/app-template/src/components/checkbox.tsx +1 -1
- package/app-template/src/components/currency-select.tsx +1 -0
- package/app-template/src/components/file-input.tsx +27 -7
- package/app-template/src/components/generate-form-fields.tsx +49 -10
- package/app-template/src/components/input.tsx +11 -5
- package/app-template/src/components/modal.tsx +32 -16
- package/app-template/src/components/pagination.tsx +1 -0
- package/app-template/src/components/price.tsx +1 -1
- package/app-template/src/components/pwa-tags.tsx +1 -0
- package/app-template/src/components/select.tsx +39 -27
- package/app-template/src/components/shimmer.tsx +1 -1
- package/app-template/src/components/types/index.ts +25 -1
- package/app-template/src/hooks/use-fav-button.tsx +4 -8
- package/app-template/src/hooks/use-product-cart.ts +77 -0
- package/app-template/src/hooks/use-stock-alert.ts +74 -0
- package/app-template/src/plugins.js +12 -2
- package/app-template/src/redux/middlewares/category.ts +5 -4
- package/app-template/src/redux/store.ts +21 -1
- package/app-template/src/routes/index.ts +2 -1
- package/app-template/src/settings.js +3 -1
- package/app-template/src/types/index.ts +74 -3
- package/app-template/src/types/next-auth.d.ts +2 -2
- package/app-template/src/utils/variant-validation.ts +41 -0
- package/app-template/src/views/account/address-form.tsx +8 -4
- package/app-template/src/views/account/contact-form.tsx +2 -2
- package/app-template/src/views/account/content-header.tsx +4 -3
- package/app-template/src/views/account/faq/faq-tabs.tsx +8 -2
- package/app-template/src/views/account/order.tsx +1 -1
- package/app-template/src/views/account/orders/order-cancellation-item.tsx +1 -1
- package/app-template/src/views/anonymous-tracking/order-detail/index.tsx +1 -1
- package/app-template/src/views/basket/basket-item.tsx +6 -1
- package/app-template/src/views/basket/summary.tsx +16 -0
- package/app-template/src/views/breadcrumb.tsx +2 -2
- package/app-template/src/views/category/category-info.tsx +2 -1
- package/app-template/src/views/category/filters/index.tsx +1 -1
- package/app-template/src/views/checkout/auth.tsx +1 -1
- package/app-template/src/views/checkout/layout/header.tsx +1 -1
- package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +1 -1
- package/app-template/src/views/checkout/steps/payment/options/store-credit.tsx +121 -0
- package/app-template/src/views/checkout/steps/payment/payment-option-buttons.tsx +4 -4
- package/app-template/src/views/checkout/steps/shipping/address-box.tsx +3 -3
- package/app-template/src/views/checkout/steps/shipping/addresses.tsx +1 -1
- package/app-template/src/views/checkout/summary.tsx +12 -2
- package/app-template/src/views/find-in-store/index.tsx +2 -2
- package/app-template/src/views/header/action-menu.tsx +2 -6
- package/app-template/src/views/header/band.tsx +2 -2
- package/app-template/src/views/header/index.tsx +1 -1
- package/app-template/src/views/header/mini-basket.tsx +2 -2
- package/app-template/src/views/header/mobile-menu.tsx +6 -6
- package/app-template/src/views/header/navbar.tsx +1 -1
- package/app-template/src/views/header/pwa-back-button.tsx +1 -1
- package/app-template/src/views/header/search/index.tsx +13 -3
- package/app-template/src/views/header/search/results.tsx +1 -1
- package/app-template/src/views/header/user-menu.tsx +1 -3
- package/app-template/src/views/login/index.tsx +14 -13
- package/app-template/src/views/otp-login/index.tsx +11 -6
- package/app-template/src/views/product/layout.tsx +15 -1
- package/app-template/src/views/product/product-actions.tsx +165 -0
- package/app-template/src/views/product/product-info.tsx +69 -261
- package/app-template/src/views/product/product-share.tsx +56 -0
- package/app-template/src/views/product/product-variants.tsx +26 -0
- package/app-template/src/views/product/slider.tsx +22 -1
- package/app-template/src/views/product-pointer-banner-item.tsx +1 -1
- package/app-template/src/views/register/index.tsx +17 -21
- package/app-template/src/views/sales-contract-modal/index.tsx +17 -17
- package/app-template/src/widgets/footer-info.tsx +1 -1
- package/app-template/src/widgets/footer-menu.tsx +7 -3
- package/app-template/src/widgets/footer-subscription/index.tsx +1 -1
- package/app-template/src/widgets/home-stories-eng.tsx +43 -35
- package/app-template/tailwind.config.js +129 -1
- package/app-template/tsconfig.json +29 -11
- package/codemods/migrate-segments/index.js +591 -0
- package/commands/plugins.ts +62 -14
- package/dist/commands/plugins.js +62 -14
- package/package.json +1 -1
- package/app-template/src/app/[commerce]/[locale]/[currency]/category/[pk]/page.tsx +0 -22
- package/app-template/src/app/[commerce]/[locale]/[currency]/flat-page/[pk]/page.tsx +0 -20
- package/app-template/src/app/[commerce]/[locale]/[currency]/group-product/[pk]/page.tsx +0 -74
- package/app-template/src/app/[commerce]/[locale]/[currency]/product/[pk]/page.tsx +0 -84
- package/app-template/src/app/[commerce]/[locale]/[currency]/special-page/[pk]/page.tsx +0 -27
- package/app-template/src/pages/api/auth/[...nextauth].ts +0 -3
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/address/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-email/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-password/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/contact/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/coupons/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/email-verification/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/faq/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/favourite-products/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/my-quotations/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/layout.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/anonymous-tracking/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/oauth-login/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket-b2b/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/category/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/client-root.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/contact-us/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/error.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/flat-page/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/group-product/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/landing-page/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/list/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/checkout/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/layout.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/special-page/[pk]/loading.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/template.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/password/reset/page.tsx +0 -0
- /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/xml-sitemap/route.ts +0 -0
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const green = (msg) => `\x1b[32m${msg}\x1b[0m`;
|
|
5
|
+
const red = (msg) => `\x1b[31m${msg}\x1b[0m`;
|
|
6
|
+
const yellow = (msg) => `\x1b[33m${msg}\x1b[0m`;
|
|
7
|
+
const bold = (msg) => `\x1b[1m${msg}\x1b[0m`;
|
|
8
|
+
|
|
9
|
+
const BUILTIN_SEGMENTS = ['commerce', 'locale', 'currency', 'url'];
|
|
10
|
+
|
|
11
|
+
function copyDirRecursive(src, dest) {
|
|
12
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
13
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
14
|
+
const srcPath = path.join(src, entry.name);
|
|
15
|
+
const destPath = path.join(dest, entry.name);
|
|
16
|
+
if (entry.isDirectory()) {
|
|
17
|
+
copyDirRecursive(srcPath, destPath);
|
|
18
|
+
} else {
|
|
19
|
+
fs.copyFileSync(srcPath, destPath);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function countEntries(dir) {
|
|
25
|
+
let count = 0;
|
|
26
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
27
|
+
count++;
|
|
28
|
+
if (entry.isDirectory()) {
|
|
29
|
+
count += countEntries(path.join(dir, entry.name));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return count;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Walks down from [commerce]/ through nested dynamic segments,
|
|
37
|
+
* collecting segment names and the directories at each level.
|
|
38
|
+
*
|
|
39
|
+
* Handles intermediate content (e.g. layout.tsx at [locale]/ level)
|
|
40
|
+
* by continuing to descend as long as a single-bracket dynamic child exists.
|
|
41
|
+
*
|
|
42
|
+
* Example:
|
|
43
|
+
* [commerce]/[locale]/[currency]/[url]/...
|
|
44
|
+
* → segments: ['locale', 'currency', 'url']
|
|
45
|
+
* → levels: [{ dir: '[locale]/', segmentChild: '[currency]' }, ...]
|
|
46
|
+
* → contentDir: the deepest level with route content
|
|
47
|
+
*/
|
|
48
|
+
function detectSegments(commerceDir) {
|
|
49
|
+
const segments = [];
|
|
50
|
+
const levels = []; // { dir, segmentChildName } for each intermediate level
|
|
51
|
+
let currentDir = commerceDir;
|
|
52
|
+
|
|
53
|
+
while (true) {
|
|
54
|
+
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
55
|
+
|
|
56
|
+
// Find single-bracket dynamic segment dirs (not catch-all [...])
|
|
57
|
+
const dynamicDirs = entries.filter(
|
|
58
|
+
(e) =>
|
|
59
|
+
e.isDirectory() &&
|
|
60
|
+
e.name.startsWith('[') &&
|
|
61
|
+
e.name.endsWith(']') &&
|
|
62
|
+
!e.name.startsWith('[...')
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
if (dynamicDirs.length === 1) {
|
|
66
|
+
const segName = dynamicDirs[0].name.slice(1, -1);
|
|
67
|
+
segments.push(segName);
|
|
68
|
+
levels.push({ dir: currentDir, segmentChildName: dynamicDirs[0].name });
|
|
69
|
+
currentDir = path.join(currentDir, dynamicDirs[0].name);
|
|
70
|
+
} else {
|
|
71
|
+
// No more single dynamic segment children — this is the deepest content level
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return { segments, levels, contentDir: currentDir };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Copies non-segment content from each intermediate level into dest,
|
|
81
|
+
* then copies the deepest content level on top (deeper wins on conflict).
|
|
82
|
+
*/
|
|
83
|
+
function mergeContentIntoPz(levels, contentDir, pzDir) {
|
|
84
|
+
// First: copy non-segment content from each intermediate level (shallowest first)
|
|
85
|
+
for (const { dir, segmentChildName } of levels) {
|
|
86
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
87
|
+
for (const entry of entries) {
|
|
88
|
+
// Skip the segment child directory itself
|
|
89
|
+
if (entry.name === segmentChildName) continue;
|
|
90
|
+
|
|
91
|
+
const srcPath = path.join(dir, entry.name);
|
|
92
|
+
const destPath = path.join(pzDir, entry.name);
|
|
93
|
+
if (entry.isDirectory()) {
|
|
94
|
+
copyDirRecursive(srcPath, destPath);
|
|
95
|
+
} else {
|
|
96
|
+
fs.mkdirSync(pzDir, { recursive: true });
|
|
97
|
+
fs.copyFileSync(srcPath, destPath);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Last: copy deepest content level (overwrites conflicts from shallower levels)
|
|
103
|
+
copyDirRecursive(contentDir, pzDir);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Reads middleware.ts and extracts the expression used to build
|
|
108
|
+
* the URL rewrite for each custom segment.
|
|
109
|
+
*
|
|
110
|
+
* Looks for patterns like:
|
|
111
|
+
* url.pathname = '/' + <expression> + url.pathname
|
|
112
|
+
* url.pathname = `/${<expression>}${url.pathname}`
|
|
113
|
+
*
|
|
114
|
+
* Then maps that expression into a resolve function.
|
|
115
|
+
*/
|
|
116
|
+
function analyzeMiddleware(workingDir, customSegments) {
|
|
117
|
+
const hints = {};
|
|
118
|
+
|
|
119
|
+
const middlewarePath = path.join(workingDir, 'src', 'middleware.ts');
|
|
120
|
+
if (!fs.existsSync(middlewarePath)) return hints;
|
|
121
|
+
|
|
122
|
+
const content = fs.readFileSync(middlewarePath, 'utf-8');
|
|
123
|
+
|
|
124
|
+
// Extract the rewrite expression from url.pathname assignment
|
|
125
|
+
// Pattern 1: url.pathname = '/' + <expr> + url.pathname
|
|
126
|
+
const concatMatch = content.match(
|
|
127
|
+
/url\.pathname\s*=\s*['"`]\/['"`]\s*\+\s*(.+?)\s*\+\s*url\.pathname/
|
|
128
|
+
);
|
|
129
|
+
// Pattern 2: url.pathname = `/${<expr>}${url.pathname}`
|
|
130
|
+
const templateMatch = content.match(
|
|
131
|
+
/url\.pathname\s*=\s*`\/\$\{(.+?)\}\$\{url\.pathname\}`/
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
const rewriteExpression = concatMatch?.[1]?.trim() || templateMatch?.[1]?.trim();
|
|
135
|
+
|
|
136
|
+
for (const seg of customSegments) {
|
|
137
|
+
// If we found a rewrite expression in middleware, use it directly
|
|
138
|
+
if (rewriteExpression) {
|
|
139
|
+
hints[seg] = {
|
|
140
|
+
source: 'middleware-rewrite',
|
|
141
|
+
code: `({ req }) => ${rewriteExpression}`
|
|
142
|
+
};
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Check for cookie pattern: req.cookies.get('pz-{seg}') or similar
|
|
147
|
+
const cookieRegex = new RegExp(
|
|
148
|
+
`cookies\\.get\\(['"\`](?:pz-)?${seg}['"\`]\\)`,
|
|
149
|
+
'i'
|
|
150
|
+
);
|
|
151
|
+
if (cookieRegex.test(content)) {
|
|
152
|
+
hints[seg] = {
|
|
153
|
+
source: 'cookie',
|
|
154
|
+
code: `({ req }) => req.cookies.get('pz-${seg}')?.value ?? ''`
|
|
155
|
+
};
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Check for header pattern: req.headers.get('x-{seg}')
|
|
160
|
+
const headerRegex = new RegExp(
|
|
161
|
+
`headers\\.get\\(['"\`](?:x-)?${seg}['"\`]\\)`,
|
|
162
|
+
'i'
|
|
163
|
+
);
|
|
164
|
+
if (headerRegex.test(content)) {
|
|
165
|
+
hints[seg] = {
|
|
166
|
+
source: 'header',
|
|
167
|
+
code: `({ req }) => req.headers.get('x-${seg}') ?? ''`
|
|
168
|
+
};
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// No hint found
|
|
173
|
+
hints[seg] = {
|
|
174
|
+
source: 'unknown',
|
|
175
|
+
code: null
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return hints;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Removes the rewrite block from middleware.ts since resolve now handles it.
|
|
184
|
+
* Strips: url clone, url.pathname assignment, NextResponse.rewrite with pz-override-response.
|
|
185
|
+
* Leaves the middleware function body empty (or with remaining custom logic).
|
|
186
|
+
*/
|
|
187
|
+
function cleanupMiddleware(workingDir) {
|
|
188
|
+
const middlewarePath = path.join(workingDir, 'src', 'middleware.ts');
|
|
189
|
+
if (!fs.existsSync(middlewarePath)) return false;
|
|
190
|
+
|
|
191
|
+
let content = fs.readFileSync(middlewarePath, 'utf-8');
|
|
192
|
+
|
|
193
|
+
if (!content.includes('pz-override-response')) return false;
|
|
194
|
+
|
|
195
|
+
// Remove: const url = req.nextUrl.clone();
|
|
196
|
+
content = content.replace(
|
|
197
|
+
/\n?\s*const url = req\.nextUrl\.clone\(\);\s*\n?/,
|
|
198
|
+
'\n'
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
// Remove: url.pathname = ... + url.pathname;
|
|
202
|
+
content = content.replace(
|
|
203
|
+
/\s*url\.pathname\s*=\s*.+?url\.pathname.*;\s*\n?/,
|
|
204
|
+
''
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
// Replace NextResponse.rewrite(url, { headers: { 'pz-override-response': ... } })
|
|
208
|
+
// with empty return (or no return)
|
|
209
|
+
content = content.replace(
|
|
210
|
+
/\s*return\s+NextResponse\.rewrite\(url,\s*\{[\s\S]*?'pz-override-response'[\s\S]*?\}\s*\);\s*/,
|
|
211
|
+
'\n'
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
// Clean up empty lines left behind
|
|
215
|
+
content = content.replace(/\n{3,}/g, '\n\n');
|
|
216
|
+
|
|
217
|
+
fs.writeFileSync(middlewarePath, content);
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Replaces old segment path references in project files (tsconfig, imports, etc.)
|
|
223
|
+
* e.g. ./app/[commerce]/[locale]/[currency]/[url]/ → ./app/[pz]/
|
|
224
|
+
*/
|
|
225
|
+
function updatePathReferences(workingDir, segments) {
|
|
226
|
+
// Build old path patterns from detected segments in different formats
|
|
227
|
+
// Bracket format: [commerce]/[locale]/[currency]/[url]
|
|
228
|
+
const bracketPath = ['[commerce]', ...segments.map((s) => `[${s}]`)].join(
|
|
229
|
+
'/'
|
|
230
|
+
);
|
|
231
|
+
// Colon format (Next.js rewrites): :commerce/:locale/:currency/:url
|
|
232
|
+
const colonPath = [':commerce', ...segments.map((s) => `:${s}`)].join('/');
|
|
233
|
+
|
|
234
|
+
const replacements = [
|
|
235
|
+
{ from: bracketPath, to: '[pz]' },
|
|
236
|
+
{ from: colonPath, to: ':pz' }
|
|
237
|
+
];
|
|
238
|
+
|
|
239
|
+
const extensions = ['.json', '.js', '.mjs', '.ts', '.tsx'];
|
|
240
|
+
let updatedFiles = [];
|
|
241
|
+
|
|
242
|
+
function walkAndReplace(dir) {
|
|
243
|
+
let entries;
|
|
244
|
+
try {
|
|
245
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
246
|
+
} catch {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
for (const entry of entries) {
|
|
251
|
+
if (entry.name === 'node_modules' || entry.name === '.next') continue;
|
|
252
|
+
// Skip the app directory itself (already handled by directory migration)
|
|
253
|
+
if (entry.name === 'app' && dir === path.join(workingDir, 'src')) continue;
|
|
254
|
+
|
|
255
|
+
const fullPath = path.join(dir, entry.name);
|
|
256
|
+
|
|
257
|
+
if (entry.isDirectory()) {
|
|
258
|
+
walkAndReplace(fullPath);
|
|
259
|
+
} else if (extensions.some((ext) => entry.name.endsWith(ext))) {
|
|
260
|
+
let content;
|
|
261
|
+
try {
|
|
262
|
+
content = fs.readFileSync(fullPath, 'utf-8');
|
|
263
|
+
} catch {
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
let changed = false;
|
|
268
|
+
for (const { from, to } of replacements) {
|
|
269
|
+
if (content.includes(from)) {
|
|
270
|
+
content = content.split(from).join(to);
|
|
271
|
+
changed = true;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (changed) {
|
|
276
|
+
fs.writeFileSync(fullPath, content);
|
|
277
|
+
updatedFiles.push(path.relative(workingDir, fullPath));
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
walkAndReplace(workingDir);
|
|
284
|
+
return updatedFiles;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function updateParamsUsage(workingDir) {
|
|
288
|
+
const extensions = ['.ts', '.tsx'];
|
|
289
|
+
const updatedFiles = [];
|
|
290
|
+
|
|
291
|
+
// Patterns to replace inline
|
|
292
|
+
const replacements = [
|
|
293
|
+
// decodeURIComponent(params.url) → parsePzParams(params, settings).url
|
|
294
|
+
{
|
|
295
|
+
pattern: /decodeURIComponent\(params\.url\)/g,
|
|
296
|
+
replacement: 'parsePzParams(params, settings).url'
|
|
297
|
+
},
|
|
298
|
+
// params.locale → parsePzParams(params, settings).locale
|
|
299
|
+
{
|
|
300
|
+
pattern: /params\.locale/g,
|
|
301
|
+
replacement: 'parsePzParams(params, settings).locale'
|
|
302
|
+
},
|
|
303
|
+
// params.currency → parsePzParams(params, settings).currency
|
|
304
|
+
{
|
|
305
|
+
pattern: /params\.currency/g,
|
|
306
|
+
replacement: 'parsePzParams(params, settings).currency'
|
|
307
|
+
},
|
|
308
|
+
// params.url (standalone, not already wrapped) → parsePzParams(params, settings).url
|
|
309
|
+
{
|
|
310
|
+
pattern: /params\.url/g,
|
|
311
|
+
replacement: 'parsePzParams(params, settings).url'
|
|
312
|
+
}
|
|
313
|
+
];
|
|
314
|
+
|
|
315
|
+
function walk(dir) {
|
|
316
|
+
let entries;
|
|
317
|
+
try {
|
|
318
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
319
|
+
} catch {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
for (const entry of entries) {
|
|
324
|
+
if (entry.name === 'node_modules' || entry.name === '.next') continue;
|
|
325
|
+
const fullPath = path.join(dir, entry.name);
|
|
326
|
+
|
|
327
|
+
if (entry.isDirectory()) {
|
|
328
|
+
walk(fullPath);
|
|
329
|
+
} else if (extensions.some((ext) => entry.name.endsWith(ext))) {
|
|
330
|
+
let content;
|
|
331
|
+
try {
|
|
332
|
+
content = fs.readFileSync(fullPath, 'utf-8');
|
|
333
|
+
} catch {
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Check if file has any params.locale/currency/url usage
|
|
338
|
+
if (!/params\.(locale|currency|url)/.test(content)) continue;
|
|
339
|
+
|
|
340
|
+
let updated = content;
|
|
341
|
+
for (const { pattern, replacement } of replacements) {
|
|
342
|
+
updated = updated.replace(pattern, replacement);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (updated !== content) {
|
|
346
|
+
// Add import if not already present
|
|
347
|
+
if (!updated.includes('parsePzParams')) {
|
|
348
|
+
// This shouldn't happen since we just added it, but safety check
|
|
349
|
+
}
|
|
350
|
+
if (
|
|
351
|
+
!updated.includes("from '@akinon/next/utils'") &&
|
|
352
|
+
!updated.includes("from '@akinon/next/utils/pz-segments'")
|
|
353
|
+
) {
|
|
354
|
+
// Add import at the top after last import
|
|
355
|
+
const lastImportIdx = updated.lastIndexOf('\nimport ');
|
|
356
|
+
if (lastImportIdx !== -1) {
|
|
357
|
+
const lineEnd = updated.indexOf('\n', lastImportIdx + 1);
|
|
358
|
+
updated =
|
|
359
|
+
updated.slice(0, lineEnd + 1) +
|
|
360
|
+
"import { parsePzParams } from '@akinon/next/utils';\n" +
|
|
361
|
+
updated.slice(lineEnd + 1);
|
|
362
|
+
} else {
|
|
363
|
+
updated =
|
|
364
|
+
"import { parsePzParams } from '@akinon/next/utils';\n" +
|
|
365
|
+
updated;
|
|
366
|
+
}
|
|
367
|
+
} else {
|
|
368
|
+
// File already imports from @akinon/next/utils, add parsePzParams to existing import
|
|
369
|
+
const importRegex =
|
|
370
|
+
/import\s*\{([^}]*)\}\s*from\s*['"]@akinon\/next\/utils['"]/;
|
|
371
|
+
const match = updated.match(importRegex);
|
|
372
|
+
if (match && !match[1].includes('parsePzParams')) {
|
|
373
|
+
updated = updated.replace(
|
|
374
|
+
importRegex,
|
|
375
|
+
`import {${match[1]}, parsePzParams } from '@akinon/next/utils'`
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Ensure settings import exists (check for any settings import: 'settings', '@theme/settings', './settings', etc.)
|
|
381
|
+
const hasSettingsImport = /import\s+settings\s+from\s+['"]/.test(updated);
|
|
382
|
+
if (!hasSettingsImport) {
|
|
383
|
+
const lastImportIdx = updated.lastIndexOf('\nimport ');
|
|
384
|
+
if (lastImportIdx !== -1) {
|
|
385
|
+
const lineEnd = updated.indexOf('\n', lastImportIdx + 1);
|
|
386
|
+
updated =
|
|
387
|
+
updated.slice(0, lineEnd + 1) +
|
|
388
|
+
"import settings from 'settings';\n" +
|
|
389
|
+
updated.slice(lineEnd + 1);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
fs.writeFileSync(fullPath, updated);
|
|
394
|
+
updatedFiles.push(path.relative(workingDir, fullPath));
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
walk(path.join(workingDir, 'src'));
|
|
401
|
+
return updatedFiles;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function generatePzSegmentsConfig(segments, resolveHints) {
|
|
405
|
+
const lines = segments.map((name) => {
|
|
406
|
+
const hint = resolveHints[name];
|
|
407
|
+
if (hint && hint.code) {
|
|
408
|
+
return ` { name: '${name}', resolve: ${hint.code} }`;
|
|
409
|
+
}
|
|
410
|
+
if (hint && hint.source === 'unknown') {
|
|
411
|
+
return ` { name: '${name}', resolve: ({ req }) => '' /* TODO: return ${name} value */ }`;
|
|
412
|
+
}
|
|
413
|
+
return ` { name: '${name}' }`;
|
|
414
|
+
});
|
|
415
|
+
return `pzSegments: {\n segments: [\n${lines.join(',\n')}\n ]\n }`;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const transform = () => {
|
|
419
|
+
const workingDir = path.resolve(process.cwd());
|
|
420
|
+
const appDir = path.join(workingDir, 'src', 'app');
|
|
421
|
+
const settingsPath = path.join(workingDir, 'src', 'settings.js');
|
|
422
|
+
|
|
423
|
+
if (!fs.existsSync(appDir)) {
|
|
424
|
+
console.error(red('Error: src/app/ directory not found.'));
|
|
425
|
+
process.exit(1);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const pzDir = path.join(appDir, '[pz]');
|
|
429
|
+
if (fs.existsSync(pzDir)) {
|
|
430
|
+
console.log(
|
|
431
|
+
yellow(
|
|
432
|
+
'[pz] directory already exists. Migration may have already been done.'
|
|
433
|
+
)
|
|
434
|
+
);
|
|
435
|
+
process.exit(0);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
const commerceDir = path.join(appDir, '[commerce]');
|
|
439
|
+
if (!fs.existsSync(commerceDir)) {
|
|
440
|
+
console.error(red('Error: [commerce] directory not found in src/app/.'));
|
|
441
|
+
process.exit(1);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Detect all segments by walking down the directory tree
|
|
445
|
+
const { segments, levels, contentDir } = detectSegments(commerceDir);
|
|
446
|
+
|
|
447
|
+
const customSegments = segments.filter(
|
|
448
|
+
(s) => !BUILTIN_SEGMENTS.includes(s)
|
|
449
|
+
);
|
|
450
|
+
const segmentPath = ['[commerce]', ...segments.map((s) => `[${s}]`)].join(
|
|
451
|
+
'/'
|
|
452
|
+
);
|
|
453
|
+
|
|
454
|
+
// Count entries across all levels that will be merged
|
|
455
|
+
let totalEntries = countEntries(contentDir);
|
|
456
|
+
for (const { dir, segmentChildName } of levels) {
|
|
457
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
458
|
+
if (entry.name === segmentChildName) continue;
|
|
459
|
+
totalEntries++;
|
|
460
|
+
if (entry.isDirectory()) {
|
|
461
|
+
totalEntries += countEntries(path.join(dir, entry.name));
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
console.log(bold('\nPZ Segment Migration'));
|
|
467
|
+
console.log('====================\n');
|
|
468
|
+
console.log(`Detected: ${yellow(segmentPath + '/')}`);
|
|
469
|
+
console.log(`Segments: ${segments.join(', ')}`);
|
|
470
|
+
if (customSegments.length > 0) {
|
|
471
|
+
console.log(
|
|
472
|
+
`Custom: ${yellow(customSegments.join(', '))} (will be added to pzSegments)`
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
if (levels.some(({ dir, segmentChildName }) =>
|
|
476
|
+
fs.readdirSync(dir).some((f) => f !== segmentChildName)
|
|
477
|
+
)) {
|
|
478
|
+
console.log(`Note: Intermediate levels have content, will be merged`);
|
|
479
|
+
}
|
|
480
|
+
console.log(`Target: ${yellow('[pz]/')}`);
|
|
481
|
+
console.log(`Entries: ${totalEntries}\n`);
|
|
482
|
+
|
|
483
|
+
// Merge all levels into [pz]/
|
|
484
|
+
console.log('Merging content into [pz]/...');
|
|
485
|
+
mergeContentIntoPz(levels, contentDir, pzDir);
|
|
486
|
+
|
|
487
|
+
// Remove legacy [commerce]/ tree
|
|
488
|
+
console.log('Removing legacy directories...');
|
|
489
|
+
fs.rmSync(commerceDir, { recursive: true, force: true });
|
|
490
|
+
|
|
491
|
+
// Update settings.js
|
|
492
|
+
if (fs.existsSync(settingsPath)) {
|
|
493
|
+
let content = fs.readFileSync(settingsPath, 'utf-8');
|
|
494
|
+
|
|
495
|
+
// Add usePzSegment: true
|
|
496
|
+
if (!content.includes('usePzSegment')) {
|
|
497
|
+
content = content.replace(/(\n};\s*$)/, ',\n usePzSegment: true$1');
|
|
498
|
+
|
|
499
|
+
if (!content.includes('usePzSegment')) {
|
|
500
|
+
content = content.replace(/(};\s*$)/, ' usePzSegment: true,\n$1');
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// Add pzSegments config if custom segments were found
|
|
505
|
+
if (customSegments.length > 0 && !content.includes('pzSegments')) {
|
|
506
|
+
const resolveHints = analyzeMiddleware(workingDir, customSegments);
|
|
507
|
+
const orderedSegments = segments.filter((s) => s !== 'commerce');
|
|
508
|
+
const pzSegmentsBlock = generatePzSegmentsConfig(
|
|
509
|
+
orderedSegments,
|
|
510
|
+
resolveHints
|
|
511
|
+
);
|
|
512
|
+
|
|
513
|
+
content = content.replace(
|
|
514
|
+
/(\n};\s*$)/,
|
|
515
|
+
`,\n ${pzSegmentsBlock}$1`
|
|
516
|
+
);
|
|
517
|
+
|
|
518
|
+
if (!content.includes('pzSegments')) {
|
|
519
|
+
content = content.replace(
|
|
520
|
+
/(};\s*$)/,
|
|
521
|
+
` ${pzSegmentsBlock},\n$1`
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
fs.writeFileSync(settingsPath, content);
|
|
527
|
+
|
|
528
|
+
console.log('Updated settings.js:');
|
|
529
|
+
console.log(' - usePzSegment: true');
|
|
530
|
+
if (customSegments.length > 0) {
|
|
531
|
+
const resolveHints = analyzeMiddleware(workingDir, customSegments);
|
|
532
|
+
console.log(
|
|
533
|
+
` - pzSegments with segments: [${segments.filter((s) => s !== 'commerce').join(', ')}]`
|
|
534
|
+
);
|
|
535
|
+
for (const seg of customSegments) {
|
|
536
|
+
const hint = resolveHints[seg];
|
|
537
|
+
if (hint && hint.source !== 'unknown') {
|
|
538
|
+
console.log(
|
|
539
|
+
` ${bold(seg)}: resolve from ${hint.source}`
|
|
540
|
+
);
|
|
541
|
+
} else {
|
|
542
|
+
console.log(
|
|
543
|
+
yellow(
|
|
544
|
+
` ${seg}: resolve source unknown — fill in the resolve function manually`
|
|
545
|
+
)
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
} else {
|
|
551
|
+
console.log(
|
|
552
|
+
yellow(
|
|
553
|
+
'Warning: settings.js not found. Add usePzSegment: true manually.'
|
|
554
|
+
)
|
|
555
|
+
);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Clean up middleware.ts rewrite block since url is now a built-in segment
|
|
559
|
+
if (segments.includes('url') || customSegments.length > 0) {
|
|
560
|
+
const cleaned = cleanupMiddleware(workingDir);
|
|
561
|
+
if (cleaned) {
|
|
562
|
+
console.log('Cleaned middleware.ts: removed rewrite block (now handled by built-in url segment)');
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// Update path references in tsconfig, imports, etc.
|
|
567
|
+
const updatedFiles = updatePathReferences(workingDir, segments);
|
|
568
|
+
if (updatedFiles.length > 0) {
|
|
569
|
+
console.log(`Updated path references in ${updatedFiles.length} file(s):`);
|
|
570
|
+
updatedFiles.forEach((f) => console.log(` - ${f}`));
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// Update params.locale/currency/url usages to parsePzParams
|
|
574
|
+
const paramsUpdated = updateParamsUsage(workingDir);
|
|
575
|
+
if (paramsUpdated.length > 0) {
|
|
576
|
+
console.log(
|
|
577
|
+
`Updated params usage in ${paramsUpdated.length} file(s):`
|
|
578
|
+
);
|
|
579
|
+
paramsUpdated.forEach((f) => console.log(` - ${f}`));
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
console.log(green('\nMigration completed successfully!\n'));
|
|
583
|
+
console.log('Next steps:');
|
|
584
|
+
console.log(` 1. Review changes with ${bold('git diff')}`);
|
|
585
|
+
console.log(` 2. Build with ${bold('yarn build')}`);
|
|
586
|
+
console.log('');
|
|
587
|
+
};
|
|
588
|
+
|
|
589
|
+
module.exports = {
|
|
590
|
+
transform
|
|
591
|
+
};
|
package/commands/plugins.ts
CHANGED
|
@@ -69,45 +69,65 @@ export default async () => {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
const definedPlugins = [
|
|
72
|
+
{
|
|
73
|
+
name: 'Akifast',
|
|
74
|
+
value: 'pz-akifast'
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'Apple Pay',
|
|
78
|
+
value: 'pz-apple-pay'
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'B2B',
|
|
82
|
+
value: 'pz-b2b'
|
|
83
|
+
},
|
|
72
84
|
{
|
|
73
85
|
name: 'Basket Gift Pack',
|
|
74
86
|
value: 'pz-basket-gift-pack'
|
|
75
87
|
},
|
|
76
88
|
{
|
|
77
|
-
name: '
|
|
78
|
-
value: 'pz-
|
|
89
|
+
name: 'BKM Express',
|
|
90
|
+
value: 'pz-bkm'
|
|
79
91
|
},
|
|
80
92
|
{
|
|
81
93
|
name: 'Checkout Gift Pack',
|
|
82
94
|
value: 'pz-checkout-gift-pack'
|
|
83
95
|
},
|
|
84
96
|
{
|
|
85
|
-
name: '
|
|
86
|
-
value: 'pz-
|
|
97
|
+
name: 'Click & Collect',
|
|
98
|
+
value: 'pz-click-collect'
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'Credit Payment',
|
|
102
|
+
value: 'pz-credit-payment'
|
|
87
103
|
},
|
|
88
104
|
{
|
|
89
105
|
name: 'Garanti Pay',
|
|
90
106
|
value: 'pz-gpay'
|
|
91
107
|
},
|
|
92
108
|
{
|
|
93
|
-
name: '
|
|
94
|
-
value: 'pz-
|
|
109
|
+
name: 'Masterpass',
|
|
110
|
+
value: 'pz-masterpass'
|
|
95
111
|
},
|
|
96
112
|
{
|
|
97
|
-
name: '
|
|
98
|
-
value: 'pz-
|
|
113
|
+
name: 'Multi Basket',
|
|
114
|
+
value: 'pz-multi-basket'
|
|
99
115
|
},
|
|
100
116
|
{
|
|
101
|
-
name: '
|
|
102
|
-
value: 'pz-
|
|
117
|
+
name: 'One Click Checkout',
|
|
118
|
+
value: 'pz-one-click-checkout'
|
|
103
119
|
},
|
|
104
120
|
{
|
|
105
|
-
name: '
|
|
106
|
-
value: 'pz-
|
|
121
|
+
name: 'Otp',
|
|
122
|
+
value: 'pz-otp'
|
|
107
123
|
},
|
|
108
124
|
{
|
|
109
|
-
name: '
|
|
110
|
-
value: 'pz-
|
|
125
|
+
name: 'Pay On Delivery',
|
|
126
|
+
value: 'pz-pay-on-delivery'
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: 'Saved Card',
|
|
130
|
+
value: 'pz-saved-card'
|
|
111
131
|
},
|
|
112
132
|
{
|
|
113
133
|
name: 'Tabby Payment Extension',
|
|
@@ -116,6 +136,34 @@ export default async () => {
|
|
|
116
136
|
{
|
|
117
137
|
name: 'Tamara Payment Extension',
|
|
118
138
|
value: 'pz-tamara-extension'
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: 'Hepsipay',
|
|
142
|
+
value: 'pz-hepsipay'
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: 'Flow Payment',
|
|
146
|
+
value: 'pz-flow-payment'
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: 'Virtual Try-On',
|
|
150
|
+
value: 'pz-virtual-try-on'
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: 'Masterpass Rest',
|
|
154
|
+
value: 'pz-masterpass-rest'
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: 'Similar Products',
|
|
158
|
+
value: 'pz-similar-products'
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: 'Haso Payment Gateway',
|
|
162
|
+
value: 'pz-haso'
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: 'Google Pay',
|
|
166
|
+
value: 'pz-google-pay'
|
|
119
167
|
}
|
|
120
168
|
];
|
|
121
169
|
|