apipay 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/banks/add.d.ts +1 -1
  3. package/dist/commands/banks/add.d.ts.map +1 -1
  4. package/dist/commands/banks/add.js +43 -43
  5. package/dist/commands/banks/add.js.map +1 -1
  6. package/dist/commands/banks/list.d.ts +1 -1
  7. package/dist/commands/banks/list.d.ts.map +1 -1
  8. package/dist/commands/banks/list.js +19 -17
  9. package/dist/commands/banks/list.js.map +1 -1
  10. package/dist/commands/banks/remove.d.ts +1 -1
  11. package/dist/commands/banks/remove.d.ts.map +1 -1
  12. package/dist/commands/banks/remove.js +19 -19
  13. package/dist/commands/banks/remove.js.map +1 -1
  14. package/dist/commands/banks/toggle.d.ts +1 -1
  15. package/dist/commands/banks/toggle.d.ts.map +1 -1
  16. package/dist/commands/banks/toggle.js +12 -12
  17. package/dist/commands/banks/toggle.js.map +1 -1
  18. package/dist/commands/config/get.d.ts +1 -1
  19. package/dist/commands/config/get.d.ts.map +1 -1
  20. package/dist/commands/config/get.js +15 -12
  21. package/dist/commands/config/get.js.map +1 -1
  22. package/dist/commands/config/reset.d.ts +1 -1
  23. package/dist/commands/config/reset.d.ts.map +1 -1
  24. package/dist/commands/config/reset.js +12 -12
  25. package/dist/commands/config/reset.js.map +1 -1
  26. package/dist/commands/config/set.d.ts +1 -1
  27. package/dist/commands/config/set.d.ts.map +1 -1
  28. package/dist/commands/config/set.js +14 -11
  29. package/dist/commands/config/set.js.map +1 -1
  30. package/dist/commands/keys/create.d.ts +1 -1
  31. package/dist/commands/keys/create.d.ts.map +1 -1
  32. package/dist/commands/keys/create.js +38 -32
  33. package/dist/commands/keys/create.js.map +1 -1
  34. package/dist/commands/keys/list.d.ts +1 -1
  35. package/dist/commands/keys/list.d.ts.map +1 -1
  36. package/dist/commands/keys/list.js +15 -15
  37. package/dist/commands/keys/list.js.map +1 -1
  38. package/dist/commands/keys/revoke.d.ts +1 -1
  39. package/dist/commands/keys/revoke.d.ts.map +1 -1
  40. package/dist/commands/keys/revoke.js +25 -22
  41. package/dist/commands/keys/revoke.js.map +1 -1
  42. package/dist/commands/login.d.ts +2 -2
  43. package/dist/commands/login.d.ts.map +1 -1
  44. package/dist/commands/login.js +66 -55
  45. package/dist/commands/login.js.map +1 -1
  46. package/dist/commands/logout.d.ts +1 -1
  47. package/dist/commands/logout.d.ts.map +1 -1
  48. package/dist/commands/logout.js +12 -12
  49. package/dist/commands/logout.js.map +1 -1
  50. package/dist/commands/metrics/summary.d.ts +1 -1
  51. package/dist/commands/metrics/summary.d.ts.map +1 -1
  52. package/dist/commands/metrics/summary.js +17 -17
  53. package/dist/commands/metrics/summary.js.map +1 -1
  54. package/dist/commands/metrics/transactions.d.ts +1 -1
  55. package/dist/commands/metrics/transactions.d.ts.map +1 -1
  56. package/dist/commands/metrics/transactions.js +23 -20
  57. package/dist/commands/metrics/transactions.js.map +1 -1
  58. package/dist/commands/{init.d.ts → setup.d.ts} +4 -4
  59. package/dist/commands/setup.d.ts.map +1 -0
  60. package/dist/commands/setup.js +192 -0
  61. package/dist/commands/setup.js.map +1 -0
  62. package/dist/commands/status.d.ts +1 -1
  63. package/dist/commands/status.d.ts.map +1 -1
  64. package/dist/commands/status.js +42 -38
  65. package/dist/commands/status.js.map +1 -1
  66. package/dist/commands/webhooks/add.d.ts +1 -1
  67. package/dist/commands/webhooks/add.d.ts.map +1 -1
  68. package/dist/commands/webhooks/add.js +34 -32
  69. package/dist/commands/webhooks/add.js.map +1 -1
  70. package/dist/commands/webhooks/history.d.ts +1 -1
  71. package/dist/commands/webhooks/history.d.ts.map +1 -1
  72. package/dist/commands/webhooks/history.js +19 -17
  73. package/dist/commands/webhooks/history.js.map +1 -1
  74. package/dist/commands/webhooks/list.d.ts +1 -1
  75. package/dist/commands/webhooks/list.d.ts.map +1 -1
  76. package/dist/commands/webhooks/list.js +20 -16
  77. package/dist/commands/webhooks/list.js.map +1 -1
  78. package/dist/commands/webhooks/remove.d.ts +1 -1
  79. package/dist/commands/webhooks/remove.d.ts.map +1 -1
  80. package/dist/commands/webhooks/remove.js +14 -14
  81. package/dist/commands/webhooks/remove.js.map +1 -1
  82. package/dist/commands/webhooks/resend.d.ts +1 -1
  83. package/dist/commands/webhooks/resend.d.ts.map +1 -1
  84. package/dist/commands/webhooks/resend.js +20 -11
  85. package/dist/commands/webhooks/resend.js.map +1 -1
  86. package/dist/commands/webhooks/toggle.d.ts +1 -1
  87. package/dist/commands/webhooks/toggle.d.ts.map +1 -1
  88. package/dist/commands/webhooks/toggle.js +12 -12
  89. package/dist/commands/webhooks/toggle.js.map +1 -1
  90. package/dist/commands/webhooks/update.d.ts +1 -1
  91. package/dist/commands/webhooks/update.d.ts.map +1 -1
  92. package/dist/commands/webhooks/update.js +17 -17
  93. package/dist/commands/webhooks/update.js.map +1 -1
  94. package/dist/commands/whoami.d.ts +1 -1
  95. package/dist/commands/whoami.d.ts.map +1 -1
  96. package/dist/commands/whoami.js +18 -18
  97. package/dist/commands/whoami.js.map +1 -1
  98. package/dist/index.d.ts +1 -1
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +1 -1
  101. package/dist/index.js.map +1 -1
  102. package/dist/lib/api-client.d.ts +1 -1
  103. package/dist/lib/api-client.d.ts.map +1 -1
  104. package/dist/lib/api-client.js +39 -34
  105. package/dist/lib/api-client.js.map +1 -1
  106. package/dist/lib/base-command.d.ts +3 -3
  107. package/dist/lib/base-command.d.ts.map +1 -1
  108. package/dist/lib/base-command.js +10 -10
  109. package/dist/lib/base-command.js.map +1 -1
  110. package/dist/lib/config.d.ts +2 -2
  111. package/dist/lib/config.d.ts.map +1 -1
  112. package/dist/lib/config.js +33 -34
  113. package/dist/lib/config.js.map +1 -1
  114. package/dist/lib/constants.js +11 -11
  115. package/dist/lib/constants.js.map +1 -1
  116. package/dist/lib/formatters.d.ts +2 -0
  117. package/dist/lib/formatters.d.ts.map +1 -1
  118. package/dist/lib/formatters.js +43 -37
  119. package/dist/lib/formatters.js.map +1 -1
  120. package/dist/lib/prompts.d.ts +1 -0
  121. package/dist/lib/prompts.d.ts.map +1 -1
  122. package/dist/lib/prompts.js +33 -18
  123. package/dist/lib/prompts.js.map +1 -1
  124. package/dist/lib/validators.d.ts +1 -0
  125. package/dist/lib/validators.d.ts.map +1 -1
  126. package/dist/lib/validators.js +49 -28
  127. package/dist/lib/validators.js.map +1 -1
  128. package/oclif.manifest.json +38 -38
  129. package/package.json +93 -82
  130. package/dist/commands/init.d.ts.map +0 -1
  131. package/dist/commands/init.js +0 -109
  132. package/dist/commands/init.js.map +0 -1
@@ -1,4 +1,3 @@
1
- import chalk from 'chalk';
2
1
  /**
3
2
  * Input validators for CLI prompts.
4
3
  * Each returns true if valid, or an error message string if invalid.
@@ -6,70 +5,84 @@ import chalk from 'chalk';
6
5
  export function validateEmail(input) {
7
6
  const trimmed = input.trim();
8
7
  if (!trimmed)
9
- return 'Email is required';
8
+ return "Email is required";
10
9
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
11
10
  if (!emailRegex.test(trimmed))
12
- return 'Please enter a valid email address';
11
+ return "Please enter a valid email address";
13
12
  return true;
14
13
  }
15
14
  export function validateAccountNumber(input, bankShortName) {
16
15
  const trimmed = input.trim();
17
16
  if (!trimmed)
18
- return 'Account number is required';
17
+ return "Account number is required";
19
18
  if (!/^\d+$/.test(trimmed))
20
- return 'Account number must contain only digits';
19
+ return "Account number must contain only digits";
21
20
  // Bank-specific length validation
22
- if (bankShortName === 'BIDV' && trimmed.length !== 14) {
23
- return 'BIDV account numbers must be 14 digits';
21
+ if (bankShortName === "BIDV" && trimmed.length !== 14) {
22
+ return "BIDV account numbers must be 14 digits";
24
23
  }
25
- if (bankShortName === 'MBB' && trimmed.length !== 13) {
26
- return 'MB Bank account numbers must be 13 digits';
24
+ if (bankShortName === "MBB" && trimmed.length !== 13) {
25
+ return "MB Bank account numbers must be 13 digits";
27
26
  }
28
27
  if (trimmed.length < 6 || trimmed.length > 20) {
29
- return 'Account number must be between 6 and 20 digits';
28
+ return "Account number must be between 6 and 20 digits";
30
29
  }
31
30
  return true;
32
31
  }
33
32
  export function validateOtp(input) {
34
33
  const trimmed = input.trim();
35
34
  if (!trimmed)
36
- return 'OTP is required';
35
+ return "OTP is required";
37
36
  if (!/^\d{4,8}$/.test(trimmed))
38
- return 'OTP must be 4-8 digits';
37
+ return "OTP must be 4-8 digits";
39
38
  return true;
40
39
  }
41
40
  export function validateWebhookUrl(input) {
42
41
  const trimmed = input.trim();
43
42
  if (!trimmed)
44
- return 'Webhook URL is required';
43
+ return "Webhook URL is required";
45
44
  try {
46
45
  const url = new URL(trimmed);
47
- if (url.protocol !== 'https:' && url.protocol !== 'http:') {
48
- return 'URL must use https:// (or http:// for local testing)';
49
- }
50
- // Block obvious private/internal addresses
51
46
  const hostname = url.hostname.toLowerCase();
52
- const blocked = ['localhost', '127.0.0.1', '0.0.0.0', '169.254.169.254', 'metadata.google.internal'];
53
- if (blocked.includes(hostname)) {
54
- return `${chalk.yellow('Warning:')} ${hostname} is a private address. Use a publicly reachable URL.`;
47
+ const isLocalhost = hostname === "localhost" || hostname === "127.0.0.1";
48
+ if (url.protocol === "http:") {
49
+ if (!isLocalhost) {
50
+ // HTTP is only safe for local dev — block for any real host
51
+ return "Webhook URL must use HTTPS to protect transaction data in transit. Use https:// (http:// is only allowed for localhost).";
52
+ }
53
+ // http://localhost is fine for local testing — allow through
54
+ }
55
+ else if (url.protocol !== "https:") {
56
+ return "URL must use https:// (or http://localhost for local testing).";
55
57
  }
56
- // Block private IP ranges
57
- if (/^(10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.)/.test(hostname)) {
58
- return `${chalk.yellow('Warning:')} Private IP addresses are not reachable from the server.`;
58
+ // Block dangerous/internal addresses for non-localhost
59
+ if (!isLocalhost) {
60
+ const blocked = [
61
+ "0.0.0.0",
62
+ "169.254.169.254",
63
+ "metadata.google.internal",
64
+ ];
65
+ if (blocked.includes(hostname)) {
66
+ return `${hostname} is not a valid webhook endpoint.`;
67
+ }
68
+ // Block private IP ranges
69
+ if (/^(10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.)/.test(hostname)) {
70
+ return "Private IP addresses are not reachable as webhook endpoints. Use a publicly reachable HTTPS URL.";
71
+ }
59
72
  }
60
73
  }
61
74
  catch {
62
- return 'Please enter a valid URL (e.g., https://example.com/webhook)';
75
+ return "Please enter a valid URL (e.g., https://example.com/webhook).";
63
76
  }
64
77
  return true;
65
78
  }
66
79
  export function validatePhoneNumber(input) {
67
80
  const trimmed = input.trim();
68
81
  if (!trimmed)
69
- return 'Phone number is required';
82
+ return "Phone number is required";
70
83
  // Vietnamese phone: 0xxx or +84xxx, 9-11 digits
71
84
  if (!/^(\+84|0)\d{8,10}$/.test(trimmed)) {
72
- return 'Please enter a valid Vietnamese phone number (e.g., 0912345678)';
85
+ return "Please enter a valid Vietnamese phone number (e.g., 0912345678)";
73
86
  }
74
87
  return true;
75
88
  }
@@ -83,9 +96,17 @@ export function validateRequired(fieldName) {
83
96
  export function validateApiKeyName(input) {
84
97
  const trimmed = input.trim();
85
98
  if (!trimmed)
86
- return 'API key name is required';
99
+ return "API key name is required";
87
100
  if (trimmed.length > 50)
88
- return 'Name must be 50 characters or less';
101
+ return "Name must be 50 characters or less";
102
+ return true;
103
+ }
104
+ export function validateAccountName(input) {
105
+ const trimmed = input.trim();
106
+ if (!trimmed)
107
+ return "Account holder name is required";
108
+ if (trimmed.length > 100)
109
+ return "Account holder name must be 100 characters or less";
89
110
  return true;
90
111
  }
91
112
  //# sourceMappingURL=validators.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/lib/validators.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/lib/validators.ts"],"names":[],"mappings":"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"}
@@ -1,42 +1,5 @@
1
1
  {
2
2
  "commands": {
3
- "init": {
4
- "aliases": [],
5
- "args": {},
6
- "description": "Set up ApiPay interactively — login, generate API key, add bank, register webhook",
7
- "examples": [
8
- "<%= config.bin %> init"
9
- ],
10
- "flags": {
11
- "json": {
12
- "description": "Output raw JSON (for scripting/CI)",
13
- "name": "json",
14
- "allowNo": false,
15
- "type": "boolean"
16
- },
17
- "quiet": {
18
- "char": "q",
19
- "description": "Suppress interactive output",
20
- "name": "quiet",
21
- "allowNo": false,
22
- "type": "boolean"
23
- }
24
- },
25
- "hasDynamicHelp": false,
26
- "hiddenAliases": [],
27
- "id": "init",
28
- "pluginAlias": "apipay",
29
- "pluginName": "apipay",
30
- "pluginType": "core",
31
- "strict": true,
32
- "enableJsonFlag": false,
33
- "isESM": true,
34
- "relativePath": [
35
- "dist",
36
- "commands",
37
- "init.js"
38
- ]
39
- },
40
3
  "login": {
41
4
  "aliases": [],
42
5
  "args": {},
@@ -134,6 +97,43 @@
134
97
  "logout.js"
135
98
  ]
136
99
  },
100
+ "setup": {
101
+ "aliases": [],
102
+ "args": {},
103
+ "description": "Set up ApiPay interactively — login, generate API key, add bank, register webhook",
104
+ "examples": [
105
+ "<%= config.bin %> setup"
106
+ ],
107
+ "flags": {
108
+ "json": {
109
+ "description": "Output raw JSON (for scripting/CI)",
110
+ "name": "json",
111
+ "allowNo": false,
112
+ "type": "boolean"
113
+ },
114
+ "quiet": {
115
+ "char": "q",
116
+ "description": "Suppress interactive output",
117
+ "name": "quiet",
118
+ "allowNo": false,
119
+ "type": "boolean"
120
+ }
121
+ },
122
+ "hasDynamicHelp": false,
123
+ "hiddenAliases": [],
124
+ "id": "setup",
125
+ "pluginAlias": "apipay",
126
+ "pluginName": "apipay",
127
+ "pluginType": "core",
128
+ "strict": true,
129
+ "enableJsonFlag": false,
130
+ "isESM": true,
131
+ "relativePath": [
132
+ "dist",
133
+ "commands",
134
+ "setup.js"
135
+ ]
136
+ },
137
137
  "status": {
138
138
  "aliases": [],
139
139
  "args": {},
@@ -998,5 +998,5 @@
998
998
  ]
999
999
  }
1000
1000
  },
1001
- "version": "0.1.0"
1001
+ "version": "0.2.0"
1002
1002
  }
package/package.json CHANGED
@@ -1,84 +1,95 @@
1
1
  {
2
- "name": "apipay",
3
- "version": "0.1.0",
4
- "description": "ApiPay CLI — Set up and manage your payment gateway from the terminal",
5
- "author": "ApiPay",
6
- "license": "MIT",
7
- "type": "module",
8
- "bin": {
9
- "apipay": "./bin/run.js"
10
- },
11
- "main": "dist/index.js",
12
- "types": "dist/index.d.ts",
13
- "files": [
14
- "bin/",
15
- "dist/",
16
- "oclif.manifest.json"
17
- ],
18
- "scripts": {
19
- "build": "tsc -b && node --loader ts-node/esm ./scripts/generate-manifest.ts 2>/dev/null || true",
20
- "dev": "node --loader ts-node/esm bin/dev.js",
21
- "lint": "eslint src/",
22
- "clean": "rimraf dist oclif.manifest.json",
23
- "prepublishOnly": "npm run clean && npm run build",
24
- "tsc": "tsc --noEmit"
25
- },
26
- "dependencies": {
27
- "@inquirer/prompts": "^7.5.0",
28
- "@oclif/core": "^4.2.10",
29
- "@oclif/plugin-autocomplete": "^3.2.20",
30
- "@oclif/plugin-help": "^6.2.25",
31
- "@oclif/plugin-not-found": "^3.2.35",
32
- "@oclif/plugin-warn-if-update-available": "^3.1.30",
33
- "chalk": "^5.4.1",
34
- "cli-table3": "^0.6.5",
35
- "conf": "^13.1.0",
36
- "open": "^10.1.2",
37
- "ora": "^8.2.0"
38
- },
39
- "devDependencies": {
40
- "@types/node": "^22.13.5",
41
- "rimraf": "^6.0.1",
42
- "ts-node": "^10.9.2",
43
- "typescript": "^5.7.3"
44
- },
45
- "engines": {
46
- "node": ">=18.0.0"
47
- },
48
- "oclif": {
49
- "bin": "apipay",
50
- "dirname": "apipay",
51
- "commands": {
52
- "strategy": "pattern",
53
- "target": "./dist/commands"
54
- },
55
- "topicSeparator": ":",
56
- "topics": {
57
- "keys": { "description": "Manage API keys" },
58
- "banks": { "description": "Manage bank accounts" },
59
- "webhooks": { "description": "Manage webhooks" },
60
- "metrics": { "description": "View transaction metrics" },
61
- "config": { "description": "Manage CLI configuration" }
62
- },
63
- "plugins": [
64
- "@oclif/plugin-help",
65
- "@oclif/plugin-autocomplete",
66
- "@oclif/plugin-not-found",
67
- "@oclif/plugin-warn-if-update-available"
68
- ],
69
- "warn-if-update-available": {
70
- "timeoutInDays": 7
71
- }
72
- },
73
- "publishConfig": {
74
- "access": "public"
75
- },
76
- "keywords": [
77
- "apipay",
78
- "payment",
79
- "gateway",
80
- "cli",
81
- "banking",
82
- "webhooks"
83
- ]
2
+ "name": "apipay",
3
+ "version": "0.2.0",
4
+ "description": "ApiPay CLI — Set up and manage your payment gateway from the terminal",
5
+ "author": "ApiPay",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "bin": {
9
+ "apipay": "./bin/run.js"
10
+ },
11
+ "main": "dist/index.js",
12
+ "types": "dist/index.d.ts",
13
+ "files": [
14
+ "bin/",
15
+ "dist/",
16
+ "oclif.manifest.json"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc -b && node --loader ts-node/esm ./scripts/generate-manifest.ts 2>/dev/null || true",
20
+ "dev": "node --loader ts-node/esm bin/dev.js",
21
+ "watch": "tsc -b --watch",
22
+ "lint": "eslint src/",
23
+ "clean": "rimraf dist oclif.manifest.json",
24
+ "prepublishOnly": "npm run clean && npm run build",
25
+ "tsc": "tsc --noEmit"
26
+ },
27
+ "dependencies": {
28
+ "@inquirer/prompts": "^7.5.0",
29
+ "@oclif/core": "^4.2.10",
30
+ "@oclif/plugin-autocomplete": "^3.2.20",
31
+ "@oclif/plugin-help": "^6.2.25",
32
+ "@oclif/plugin-not-found": "^3.2.35",
33
+ "@oclif/plugin-warn-if-update-available": "^3.1.30",
34
+ "chalk": "^5.4.1",
35
+ "cli-table3": "^0.6.5",
36
+ "conf": "^13.1.0",
37
+ "open": "^10.1.2",
38
+ "ora": "^8.2.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^22.13.5",
42
+ "rimraf": "^6.0.1",
43
+ "ts-node": "^10.9.2",
44
+ "typescript": "^5.7.3"
45
+ },
46
+ "engines": {
47
+ "node": ">=18.0.0"
48
+ },
49
+ "oclif": {
50
+ "bin": "apipay",
51
+ "dirname": "apipay",
52
+ "commands": {
53
+ "strategy": "pattern",
54
+ "target": "./dist/commands"
55
+ },
56
+ "topicSeparator": ":",
57
+ "topics": {
58
+ "keys": {
59
+ "description": "Manage API keys"
60
+ },
61
+ "banks": {
62
+ "description": "Manage bank accounts"
63
+ },
64
+ "webhooks": {
65
+ "description": "Manage webhooks"
66
+ },
67
+ "metrics": {
68
+ "description": "View transaction metrics"
69
+ },
70
+ "config": {
71
+ "description": "Manage CLI configuration"
72
+ }
73
+ },
74
+ "plugins": [
75
+ "@oclif/plugin-help",
76
+ "@oclif/plugin-autocomplete",
77
+ "@oclif/plugin-not-found",
78
+ "@oclif/plugin-warn-if-update-available"
79
+ ],
80
+ "warn-if-update-available": {
81
+ "timeoutInDays": 7
82
+ }
83
+ },
84
+ "publishConfig": {
85
+ "access": "public"
86
+ },
87
+ "keywords": [
88
+ "apipay",
89
+ "payment",
90
+ "gateway",
91
+ "cli",
92
+ "banking",
93
+ "webhooks"
94
+ ]
84
95
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAiBrD;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,WAAW;IAC3C,OAAgB,WAAW,SAC2D;IAEtF,OAAgB,QAAQ,WAA8B;IAEhD,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAgF1B,OAAO,CAAC,cAAc;CAevB"}
@@ -1,109 +0,0 @@
1
- import chalk from 'chalk';
2
- import { BaseCommand } from '../lib/base-command.js';
3
- import { isLoggedIn, getApiKey, getCompletedSteps, getNextIncompleteStep, } from '../lib/config.js';
4
- import { SETUP_STEPS } from '../lib/constants.js';
5
- import { banner, stepLabel, success, info } from '../lib/formatters.js';
6
- // Import command runners
7
- import Login from './login.js';
8
- import KeysCreate from './keys/create.js';
9
- import BanksAdd from './banks/add.js';
10
- import WebhooksAdd from './webhooks/add.js';
11
- /**
12
- * `apipay init` — Guided setup wizard.
13
- * Walks new users through the complete setup flow:
14
- * 1. Login (magic link or password)
15
- * 2. Generate API key
16
- * 3. Add bank account
17
- * 4. Register webhook
18
- *
19
- * Resumes from the last incomplete step automatically.
20
- */
21
- export default class Init extends BaseCommand {
22
- static description = 'Set up ApiPay interactively — login, generate API key, add bank, register webhook';
23
- static examples = ['<%= config.bin %> init'];
24
- async run() {
25
- banner();
26
- const completed = getCompletedSteps();
27
- const nextStep = getNextIncompleteStep();
28
- if (!nextStep) {
29
- this.printChecklist(completed);
30
- console.log('');
31
- success('Setup is already complete! You\'re ready to receive payments.');
32
- console.log('');
33
- info(`Run ${chalk.cyan('apipay status')} to see your current configuration.`);
34
- info(`Run ${chalk.cyan('apipay --help')} to explore all commands.`);
35
- console.log('');
36
- return;
37
- }
38
- if (completed.length > 0) {
39
- info(`Resuming setup from step ${completed.length + 1}/${SETUP_STEPS.length}...`);
40
- this.printChecklist(completed);
41
- console.log('');
42
- }
43
- const totalSteps = SETUP_STEPS.length;
44
- // Step 1: Login
45
- if (!completed.includes('login')) {
46
- console.log(stepLabel(1, totalSteps, 'Authenticate with ApiPay'));
47
- console.log(chalk.gray(' Sign in to your account or create a new one.\n'));
48
- await Login.run([]);
49
- console.log('');
50
- }
51
- // Step 2: API Key
52
- if (!completed.includes('api-key')) {
53
- if (!isLoggedIn()) {
54
- this.error('Login is required before proceeding. Run `apipay login` first.', { exit: 1 });
55
- }
56
- console.log(stepLabel(2, totalSteps, 'Generate API Key'));
57
- console.log(chalk.gray(' Create an API key to authenticate your integration.\n'));
58
- await KeysCreate.run([]);
59
- console.log('');
60
- }
61
- // Step 3: Add Bank
62
- if (!completed.includes('bank')) {
63
- if (!getApiKey()) {
64
- this.error('API key is required. Run `apipay keys:create` first.', { exit: 1 });
65
- }
66
- console.log(stepLabel(3, totalSteps, 'Add Bank Account'));
67
- console.log(chalk.gray(' Connect a bank account to start receiving payments.\n'));
68
- await BanksAdd.run([]);
69
- console.log('');
70
- }
71
- // Step 4: Add Webhook
72
- if (!completed.includes('webhook')) {
73
- if (!getApiKey()) {
74
- this.error('API key is required. Run `apipay keys:create` first.', { exit: 1 });
75
- }
76
- console.log(stepLabel(4, totalSteps, 'Register Webhook'));
77
- console.log(chalk.gray(' Set up a webhook to receive transaction notifications.\n'));
78
- await WebhooksAdd.run([]);
79
- console.log('');
80
- }
81
- // Final summary
82
- console.log('');
83
- console.log(chalk.green.bold(' ╔══════════════════════════════════════╗'));
84
- console.log(chalk.green.bold(' ║ ✓ Setup Complete! ║'));
85
- console.log(chalk.green.bold(' ╚══════════════════════════════════════╝'));
86
- console.log('');
87
- this.printChecklist(getCompletedSteps());
88
- console.log('');
89
- info(`Dashboard: ${chalk.underline.cyan('https://apipay.vn/dashboard')}`);
90
- info(`Docs: ${chalk.underline.cyan('https://apipay.vn/docs')}`);
91
- info(`Status: ${chalk.cyan('apipay status')}`);
92
- console.log('');
93
- }
94
- printChecklist(completed) {
95
- const labels = {
96
- login: 'Login',
97
- 'api-key': 'API Key',
98
- bank: 'Bank Account',
99
- webhook: 'Webhook',
100
- };
101
- for (const step of SETUP_STEPS) {
102
- const done = completed.includes(step);
103
- const icon = done ? chalk.green('✓') : chalk.gray('○');
104
- const label = done ? chalk.white(labels[step]) : chalk.gray(labels[step]);
105
- console.log(` ${icon} ${label}`);
106
- }
107
- }
108
- }
109
- //# sourceMappingURL=init.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}