@simplens/onboard 1.0.1 → 1.0.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.
Files changed (82) hide show
  1. package/README.md +331 -214
  2. package/dist/__tests__/env-config.test.d.ts +2 -0
  3. package/dist/__tests__/env-config.test.d.ts.map +1 -0
  4. package/dist/__tests__/env-config.test.js +23 -0
  5. package/dist/__tests__/env-config.test.js.map +1 -0
  6. package/dist/__tests__/infra-prompts.test.d.ts +2 -0
  7. package/dist/__tests__/infra-prompts.test.d.ts.map +1 -0
  8. package/dist/__tests__/infra-prompts.test.js +43 -0
  9. package/dist/__tests__/infra-prompts.test.js.map +1 -0
  10. package/dist/__tests__/infra.test.d.ts +2 -0
  11. package/dist/__tests__/infra.test.d.ts.map +1 -0
  12. package/dist/__tests__/infra.test.js +14 -0
  13. package/dist/__tests__/infra.test.js.map +1 -0
  14. package/dist/__tests__/nginx.test.d.ts +2 -0
  15. package/dist/__tests__/nginx.test.d.ts.map +1 -0
  16. package/dist/__tests__/nginx.test.js +16 -0
  17. package/dist/__tests__/nginx.test.js.map +1 -0
  18. package/dist/env-config.d.ts +27 -12
  19. package/dist/env-config.d.ts.map +1 -1
  20. package/dist/env-config.js +253 -128
  21. package/dist/env-config.js.map +1 -1
  22. package/dist/index.js +340 -69
  23. package/dist/index.js.map +1 -1
  24. package/dist/infra.d.ts +19 -8
  25. package/dist/infra.d.ts.map +1 -1
  26. package/dist/infra.js +267 -128
  27. package/dist/infra.js.map +1 -1
  28. package/dist/plugins.d.ts +5 -10
  29. package/dist/plugins.d.ts.map +1 -1
  30. package/dist/plugins.js +75 -44
  31. package/dist/plugins.js.map +1 -1
  32. package/dist/services.d.ts +1 -23
  33. package/dist/services.d.ts.map +1 -1
  34. package/dist/services.js +47 -62
  35. package/dist/services.js.map +1 -1
  36. package/dist/templates.d.ts +2 -1
  37. package/dist/templates.d.ts.map +1 -1
  38. package/dist/templates.js +203 -191
  39. package/dist/templates.js.map +1 -1
  40. package/dist/types/domain.d.ts +2 -0
  41. package/dist/types/domain.d.ts.map +1 -1
  42. package/dist/ui.d.ts +45 -0
  43. package/dist/ui.d.ts.map +1 -0
  44. package/dist/ui.js +93 -0
  45. package/dist/ui.js.map +1 -0
  46. package/dist/utils/logger.d.ts +1 -0
  47. package/dist/utils/logger.d.ts.map +1 -1
  48. package/dist/utils/logger.js +32 -7
  49. package/dist/utils/logger.js.map +1 -1
  50. package/dist/utils.d.ts +8 -0
  51. package/dist/utils.d.ts.map +1 -1
  52. package/dist/utils.js +66 -2
  53. package/dist/utils.js.map +1 -1
  54. package/dist/validators.d.ts +1 -52
  55. package/dist/validators.d.ts.map +1 -1
  56. package/dist/validators.js +10 -57
  57. package/dist/validators.js.map +1 -1
  58. package/package.json +3 -5
  59. package/src/__tests__/env-config.test.ts +28 -0
  60. package/src/__tests__/errors.test.ts +187 -187
  61. package/src/__tests__/infra-prompts.test.ts +54 -0
  62. package/src/__tests__/infra.test.ts +15 -0
  63. package/src/__tests__/utils.test.ts +142 -142
  64. package/src/__tests__/validators.test.ts +195 -195
  65. package/src/config/constants.ts +86 -86
  66. package/src/config/index.ts +1 -1
  67. package/src/env-config.ts +455 -311
  68. package/src/index.ts +534 -202
  69. package/src/infra.ts +404 -245
  70. package/src/plugins.ts +221 -190
  71. package/src/services.ts +175 -190
  72. package/src/templates.ts +209 -196
  73. package/src/types/domain.ts +129 -127
  74. package/src/types/errors.ts +173 -173
  75. package/src/types/index.ts +2 -2
  76. package/src/ui.ts +91 -0
  77. package/src/utils/index.ts +1 -1
  78. package/src/utils/logger.ts +144 -118
  79. package/src/utils.ts +183 -105
  80. package/src/validators.ts +145 -192
  81. package/tsconfig.json +18 -18
  82. package/vitest.config.ts +22 -22
package/dist/infra.js CHANGED
@@ -1,144 +1,162 @@
1
- import inquirer from 'inquirer';
2
- import { APP_COMPOSE_TEMPLATE } from './templates.js';
3
- import { writeFile, logInfo, logSuccess } from './utils.js';
1
+ import { APP_COMPOSE_TEMPLATE, APP_NGINX_SERVICE_TEMPLATE } from './templates.js';
2
+ import { writeFile } from './utils.js';
3
+ import { multiselect } from '@clack/prompts';
4
+ import { handleCancel, spinner } from './ui.js';
4
5
  import path from 'path';
5
6
  const INFRA_SERVICES = [
6
7
  { name: 'MongoDB (Database)', value: 'mongo', checked: true },
7
8
  { name: 'Kafka (Message Queue)', value: 'kafka', checked: true },
8
9
  { name: 'Kafka UI (Dashboard)', value: 'kafka-ui', checked: true },
9
10
  { name: 'Redis (Cache)', value: 'redis', checked: true },
11
+ { name: 'Nginx (Reverse Proxy)', value: 'nginx', checked: false },
10
12
  { name: 'Loki (Log Aggregation)', value: 'loki', checked: false },
11
13
  { name: 'Grafana (Observability Dashboard)', value: 'grafana', checked: false },
12
14
  ];
13
15
  /**
14
16
  * Prompts user to select which infrastructure services to deploy.
15
- * Services include MongoDB, Kafka, Redis, Loki, and Grafana.
16
17
  *
17
18
  * @returns Array of selected service IDs (e.g., ['mongo', 'kafka', 'redis'])
18
19
  * @throws Error if no services are selected
19
- *
20
- * @example
21
- * ```ts
22
- * const services = await promptInfraServices();
23
- * // Returns: ['mongo', 'kafka', 'kafka-ui', 'redis']
24
- * ```
25
20
  */
26
21
  export async function promptInfraServices() {
27
- const answer = await inquirer.prompt([
28
- {
29
- type: 'checkbox',
30
- name: 'services',
31
- message: 'Select infrastructure services to run:',
32
- choices: INFRA_SERVICES,
33
- validate: (input) => {
34
- if (input.length === 0) {
35
- return 'Please select at least one service';
36
- }
37
- return true;
38
- },
39
- },
40
- ]);
41
- return answer.services;
22
+ return promptInfraServicesWithBasePath({ allowNginx: true });
23
+ }
24
+ /**
25
+ * Prompts infrastructure services with optional nginx availability.
26
+ * If nginx is disabled, it is removed from choices and from result safety-check.
27
+ */
28
+ export async function promptInfraServicesWithBasePath(options) {
29
+ const choices = options.allowNginx
30
+ ? INFRA_SERVICES
31
+ : INFRA_SERVICES.filter(service => service.value !== 'nginx');
32
+ const message = options.allowNginx
33
+ ? 'Select infrastructure services to run (Space to select, Enter to confirm):'
34
+ : 'Select infrastructure services to run (Space to select, Enter to confirm) — nginx disabled:';
35
+ const selected = await multiselect({
36
+ message,
37
+ options: choices.map(s => ({
38
+ value: s.value,
39
+ label: s.name,
40
+ hint: s.checked ? 'recommended' : undefined,
41
+ })),
42
+ initialValues: choices.filter(s => s.checked).map(s => s.value),
43
+ required: true,
44
+ withGuide: true,
45
+ });
46
+ handleCancel(selected);
47
+ const result = selected;
48
+ if (options.allowNginx) {
49
+ return result;
50
+ }
51
+ return result.filter(service => service !== 'nginx');
42
52
  }
43
53
  /**
44
54
  * Service chunk definitions - each service as a complete block
45
55
  */
46
56
  const SERVICE_CHUNKS = {
47
- 'mongo': ` mongo:
48
- image: mongo:7.0
49
- container_name: mongo
50
- command: [ "--replSet", "rs0", "--bind_ip_all", "--port", "27017" ]
51
- ports:
52
- - 27017:27017
53
- healthcheck:
54
- test: echo "try { rs.status() } catch (err) { rs.initiate({_id:'rs0',members:[{_id:0,host:'mongo:27017'}]}) }" | mongosh --port 27017 --quiet
55
- interval: 5s
56
- timeout: 30s
57
- start_period: 0s
58
- start_interval: 1s
59
- retries: 30
60
- volumes:
61
- - "mongo_data:/data/db"
57
+ 'mongo': ` mongo:
58
+ image: mongo:7.0
59
+ container_name: mongo
60
+ command: [ "--replSet", "rs0", "--bind_ip_all", "--port", "27017" ]
61
+ ports:
62
+ - 27017:27017
63
+ healthcheck:
64
+ test: echo "try { rs.status() } catch (err) { rs.initiate({_id:'rs0',members:[{_id:0,host:'mongo:27017'}]}) }" | mongosh --port 27017 --quiet
65
+ interval: 5s
66
+ timeout: 30s
67
+ start_period: 0s
68
+ start_interval: 1s
69
+ retries: 30
70
+ volumes:
71
+ - "mongo_data:/data/db"
62
72
  - "mongo_config:/data/configdb"`,
63
- 'kafka': ` kafka:
64
- image: apache/kafka-native
65
- container_name: kafka
66
- ports:
67
- - "9092:9092"
68
- environment:
69
- # Configure listeners for both docker and host communication
70
- KAFKA_LISTENERS: CONTROLLER://localhost:9091,HOST://0.0.0.0:9092,DOCKER://0.0.0.0:9093
71
- KAFKA_ADVERTISED_LISTENERS: HOST://kafka:9092,DOCKER://kafka:9093
72
- KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,DOCKER:PLAINTEXT,HOST:PLAINTEXT
73
-
74
- # Settings required for KRaft mode
75
- KAFKA_NODE_ID: 1
76
- KAFKA_PROCESS_ROLES: broker,controller
77
- KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
78
- KAFKA_CONTROLLER_QUORUM_VOTERS: 1@localhost:9091
79
-
80
- # Listener to use for broker-to-broker communication
81
- KAFKA_INTER_BROKER_LISTENER_NAME: DOCKER
82
-
83
- # Required for a single node cluster
84
- KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
85
-
86
- # Disable auto-topic creation - API server will create topics with correct partitions
87
- KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
88
- volumes:
73
+ 'kafka': ` kafka:
74
+ image: apache/kafka-native
75
+ container_name: kafka
76
+ ports:
77
+ - "9092:9092"
78
+ environment:
79
+ # Configure listeners for both docker and host communication
80
+ KAFKA_LISTENERS: CONTROLLER://localhost:9091,HOST://0.0.0.0:9092,DOCKER://0.0.0.0:9093
81
+ KAFKA_ADVERTISED_LISTENERS: HOST://kafka:9092,DOCKER://kafka:9093
82
+ KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,DOCKER:PLAINTEXT,HOST:PLAINTEXT
83
+
84
+ # Settings required for KRaft mode
85
+ KAFKA_NODE_ID: 1
86
+ KAFKA_PROCESS_ROLES: broker,controller
87
+ KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
88
+ KAFKA_CONTROLLER_QUORUM_VOTERS: 1@localhost:9091
89
+
90
+ # Listener to use for broker-to-broker communication
91
+ KAFKA_INTER_BROKER_LISTENER_NAME: DOCKER
92
+
93
+ # Required for a single node cluster
94
+ KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
95
+
96
+ # Disable auto-topic creation - API server will create topics with correct partitions
97
+ KAFKA_AUTO_CREATE_TOPICS_ENABLE: "false"
98
+ volumes:
89
99
  - "kafka_data:/var/lib/kafka/data"`,
90
- 'kafka-ui': ` kafka-ui:
91
- image: kafbat/kafka-ui:main
92
- container_name: kafka-ui
93
- ports:
94
- - 8080:8080
95
- environment:
96
- DYNAMIC_CONFIG_ENABLED: "true"
97
- KAFKA_CLUSTERS_0_NAME: local
98
- KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9093
99
- depends_on:
100
+ 'kafka-ui': ` kafka-ui:
101
+ image: kafbat/kafka-ui:main
102
+ container_name: kafka-ui
103
+ ports:
104
+ - 8080:8080
105
+ environment:
106
+ DYNAMIC_CONFIG_ENABLED: "true"
107
+ KAFKA_CLUSTERS_0_NAME: local
108
+ KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9093
109
+ depends_on:
100
110
  - kafka`,
101
- 'redis': ` redis:
102
- image: redis:7-alpine
103
- container_name: redis
104
- ports:
105
- - "6379:6379"
106
- command: redis-server --appendonly yes
107
- volumes:
108
- - "redis_data:/data"
109
- healthcheck:
110
- test: [ "CMD", "redis-cli", "ping" ]
111
- interval: 5s
112
- timeout: 3s
111
+ 'redis': ` redis:
112
+ image: redis:7-alpine
113
+ container_name: redis
114
+ ports:
115
+ - "6379:6379"
116
+ command: redis-server --appendonly yes
117
+ volumes:
118
+ - "redis_data:/data"
119
+ healthcheck:
120
+ test: [ "CMD", "redis-cli", "ping" ]
121
+ interval: 5s
122
+ timeout: 3s
113
123
  retries: 5`,
114
- 'loki': ` loki:
115
- image: grafana/loki:2.9.0
116
- container_name: loki
117
- ports:
118
- - "3100:3100"
119
- command: -config.file=/etc/loki/local-config.yaml
120
- volumes:
121
- - "loki_data:/loki"
122
- healthcheck:
123
- test: [ "CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3100/ready || exit 1" ]
124
- interval: 10s
125
- timeout: 5s
124
+ 'loki': ` loki:
125
+ image: grafana/loki:2.9.0
126
+ container_name: loki
127
+ ports:
128
+ - "3100:3100"
129
+ command: -config.file=/etc/loki/local-config.yaml
130
+ volumes:
131
+ - "loki_data:/loki"
132
+ healthcheck:
133
+ test: [ "CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3100/ready || exit 1" ]
134
+ interval: 10s
135
+ timeout: 5s
126
136
  retries: 5`,
127
- 'grafana': ` grafana:
128
- image: grafana/grafana:10.2.0
129
- container_name: grafana
130
- ports:
131
- - "3001:3000"
132
- environment:
133
- - GF_PATHS_PROVISIONING=/etc/grafana/provisioning
134
- - GF_AUTH_ANONYMOUS_ENABLED=true
135
- - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
136
- - GF_SECURITY_ADMIN_PASSWORD=admin
137
- volumes:
138
- - "grafana_data:/var/lib/grafana"
139
- depends_on:
140
- loki:
137
+ 'grafana': ` grafana:
138
+ image: grafana/grafana:10.2.0
139
+ container_name: grafana
140
+ ports:
141
+ - "3001:3000"
142
+ environment:
143
+ - GF_PATHS_PROVISIONING=/etc/grafana/provisioning
144
+ - GF_AUTH_ANONYMOUS_ENABLED=true
145
+ - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
146
+ - GF_SECURITY_ADMIN_PASSWORD=admin
147
+ volumes:
148
+ - "grafana_data:/var/lib/grafana"
149
+ depends_on:
150
+ loki:
141
151
  condition: service_healthy`,
152
+ 'nginx': ` nginx:
153
+ image: nginx:alpine
154
+ container_name: nginx
155
+ ports:
156
+ - "80:80"
157
+ volumes:
158
+ - "./nginx.conf:/etc/nginx/conf.d/default.conf:ro"
159
+ restart: unless-stopped`,
142
160
  };
143
161
  /**
144
162
  * Service-to-volumes mapping
@@ -148,6 +166,7 @@ const SERVICE_VOLUMES = {
148
166
  'kafka': ['kafka_data'],
149
167
  'kafka-ui': [],
150
168
  'redis': ['redis_data'],
169
+ 'nginx': [],
151
170
  'loki': ['loki_data'],
152
171
  'grafana': ['grafana_data'],
153
172
  };
@@ -156,15 +175,15 @@ const SERVICE_VOLUMES = {
156
175
  */
157
176
  function buildInfraCompose(selectedServices) {
158
177
  // Header
159
- const header = `# ============================================
160
- # SimpleNS Infrastructure Services
161
- # All services use Docker service names for container-to-container communication.
162
- # This ensures cross-platform compatibility (Windows, Linux, macOS).
163
- # ============================================
164
-
165
- services:
166
- # ============================================
167
- # Infrastructure Services
178
+ const header = `# ============================================
179
+ # SimpleNS Infrastructure Services
180
+ # All services use Docker service names for container-to-container communication.
181
+ # This ensures cross-platform compatibility (Windows, Linux, macOS).
182
+ # ============================================
183
+
184
+ services:
185
+ # ============================================
186
+ # Infrastructure Services
168
187
  # ============================================`;
169
188
  // Assemble selected service chunks
170
189
  const serviceBlocks = [];
@@ -198,20 +217,140 @@ services:
198
217
  * Generate and write docker-compose.infra.yaml
199
218
  */
200
219
  export async function generateInfraCompose(targetDir, selectedServices) {
201
- logInfo('Generating docker-compose.infra.yaml...');
220
+ const s = spinner();
221
+ s.start('Generating docker-compose.infra.yaml...');
202
222
  // Build compose content from service chunks
203
223
  const infraContent = buildInfraCompose(selectedServices);
204
224
  // Write infrastructure compose file
205
225
  const infraPath = path.join(targetDir, 'docker-compose.infra.yaml');
206
226
  await writeFile(infraPath, infraContent);
207
- logSuccess('Generated docker-compose.infra.yaml');
227
+ s.stop('Generated docker-compose.infra.yaml');
228
+ }
229
+ /**
230
+ * Build app docker-compose content.
231
+ * Optionally inject nginx reverse-proxy service before the volumes section.
232
+ */
233
+ export function buildAppComposeContent(includeNginx) {
234
+ if (!includeNginx) {
235
+ return APP_COMPOSE_TEMPLATE;
236
+ }
237
+ const marker = '\nvolumes:';
238
+ if (!APP_COMPOSE_TEMPLATE.includes(marker)) {
239
+ return APP_COMPOSE_TEMPLATE;
240
+ }
241
+ return APP_COMPOSE_TEMPLATE.replace(marker, `\n${APP_NGINX_SERVICE_TEMPLATE}\n${marker}`);
208
242
  }
209
243
  /**
210
244
  * Write app docker-compose.yaml
211
245
  */
212
- export async function writeAppCompose(targetDir) {
246
+ export async function writeAppCompose(targetDir, options = {}) {
247
+ const s = spinner();
248
+ s.start('Generating docker-compose.yaml...');
213
249
  const appPath = path.join(targetDir, 'docker-compose.yaml');
214
- await writeFile(appPath, APP_COMPOSE_TEMPLATE);
215
- logSuccess('Generated docker-compose.yaml');
250
+ const appContent = buildAppComposeContent(options.includeNginx === true);
251
+ await writeFile(appPath, appContent);
252
+ s.stop('Generated docker-compose.yaml');
253
+ }
254
+ /**
255
+ * Generate nginx.conf based on basePath configuration
256
+ */
257
+ export async function generateNginxConfig(targetDir, basePath) {
258
+ const s = spinner();
259
+ s.start('Generating nginx.conf...');
260
+ // Normalize basePath (remove leading/trailing slashes for template)
261
+ const normalizedPath = basePath.trim().replace(/^\/|\/$/g, '');
262
+ const hasBasePath = normalizedPath.length > 0;
263
+ // Template for nginx.conf
264
+ const nginxTemplate = `server {
265
+ listen 80;
266
+ server_name localhost;
267
+
268
+ location /api/notification/ {
269
+ proxy_pass http://api:3000;
270
+ proxy_http_version 1.1;
271
+
272
+ proxy_set_header Host $host;
273
+ proxy_set_header X-Real-IP $remote_addr;
274
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
275
+ proxy_set_header X-Forwarded-Proto $scheme;
276
+ }
277
+
278
+ location = /runtime-config.js {
279
+ proxy_pass http://dashboard:3002/runtime-config.js;
280
+ proxy_http_version 1.1;
281
+
282
+ proxy_set_header Host $host;
283
+ proxy_set_header X-Real-IP $remote_addr;
284
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
285
+ proxy_set_header X-Forwarded-Proto $scheme;
286
+
287
+ # optional: prevent caching if config is dynamic
288
+ add_header Cache-Control "no-store";
289
+ }
290
+
291
+ location ^~ /_next/ {
292
+ proxy_pass http://dashboard:3002/_next/;
293
+ proxy_http_version 1.1;
294
+
295
+ proxy_set_header Host $host;
296
+ proxy_set_header X-Real-IP $remote_addr;
297
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
298
+ proxy_set_header X-Forwarded-Proto $scheme;
299
+
300
+ expires 1y;
301
+ add_header Cache-Control "public, immutable";
302
+ }
303
+ ${hasBasePath ? `
304
+ location ^~ /${normalizedPath}/_next/ {
305
+ proxy_pass http://dashboard:3002/_next/;
306
+ proxy_http_version 1.1;
307
+
308
+ proxy_set_header Host $host;
309
+ proxy_set_header X-Real-IP $remote_addr;
310
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
311
+ proxy_set_header X-Forwarded-Proto $scheme;
312
+
313
+ expires 1y;
314
+ add_header Cache-Control "public, immutable";
315
+ }
316
+ ` : ''}
317
+ location ~* \\.(png|jpg|jpeg|gif|ico|svg|webp|woff|woff2|ttf|eot)$ {
318
+ proxy_pass http://dashboard:3002;
319
+ proxy_http_version 1.1;
320
+
321
+ proxy_set_header Host $host;
322
+ proxy_set_header X-Real-IP $remote_addr;
323
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
324
+ proxy_set_header X-Forwarded-Proto $scheme;
325
+
326
+ expires 1y;
327
+ add_header Cache-Control "public, max-age=31536000";
328
+ }
329
+ ${hasBasePath ? `
330
+ location ^~ /${normalizedPath} {
331
+ proxy_pass http://dashboard:3002;
332
+ proxy_http_version 1.1;
333
+
334
+ proxy_set_header Host $host;
335
+ proxy_set_header X-Real-IP $remote_addr;
336
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
337
+ proxy_set_header X-Forwarded-Proto $scheme;
338
+ }
339
+ ` : `
340
+ location / {
341
+ proxy_pass http://dashboard:3002;
342
+ proxy_http_version 1.1;
343
+
344
+ proxy_set_header Host $host;
345
+ proxy_set_header X-Real-IP $remote_addr;
346
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
347
+ proxy_set_header X-Forwarded-Proto $scheme;
348
+ }
349
+ `}
350
+ }
351
+ `;
352
+ const nginxPath = path.join(targetDir, 'nginx.conf');
353
+ await writeFile(nginxPath, nginxTemplate);
354
+ s.stop(`Generated nginx.conf${hasBasePath ? ` with base path: /${normalizedPath}` : ' (root path)'}`);
216
355
  }
217
356
  //# sourceMappingURL=infra.js.map
package/dist/infra.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"infra.js","sourceRoot":"","sources":["../src/infra.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"infra.js","sourceRoot":"","sources":["../src/infra.ts"],"names":[],"mappings":"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"}
package/dist/plugins.d.ts CHANGED
@@ -4,16 +4,6 @@ import type { PluginInfo } from './types/domain.js';
4
4
  * Falls back to default plugins if fetching fails.
5
5
  *
6
6
  * @returns Array of available plugin information
7
- *
8
- * @remarks
9
- * Uses `npx @simplens/config-gen list --official` to fetch plugins.
10
- * Default fallback plugins: mock, nodemailer-gmail, resend
11
- *
12
- * @example
13
- * ```ts
14
- * const plugins = await fetchAvailablePlugins();
15
- * // Returns: [{ package: '@simplens/mock', name: 'Mock Provider', ... }, ...]
16
- * ```
17
7
  */
18
8
  export declare function fetchAvailablePlugins(): Promise<PluginInfo[]>;
19
9
  /**
@@ -28,6 +18,11 @@ export declare function generatePluginConfig(targetDir: string, selectedPlugins:
28
18
  * Parse simplens.config.yaml to extract credential keys
29
19
  */
30
20
  export declare function parseConfigCredentials(configPath: string): Promise<string[]>;
21
+ /**
22
+ * Generate default placeholder values for plugin credentials
23
+ * Used in --full mode for non-interactive setup
24
+ */
25
+ export declare function generateDefaultPluginCredentials(credentialKeys: string[]): Map<string, string>;
31
26
  /**
32
27
  * Prompt for plugin-specific credentials
33
28
  */
@@ -1 +1 @@
1
- {"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,mBAAmB,CAAC;AAEpE;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAwCnE;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,gBAAgB,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAoB7F;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACtC,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,EAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA4BlF;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA+BpG"}
1
+ {"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,mBAAmB,CAAC;AAEpE;;;;;GAKG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CA0CnE;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,gBAAgB,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAqB7F;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACtC,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,EAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA4BlF;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAoB9F;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA0CpG"}