@simplens/onboard 1.0.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 (94) hide show
  1. package/README.md +214 -0
  2. package/dist/__tests__/errors.test.d.ts +2 -0
  3. package/dist/__tests__/errors.test.d.ts.map +1 -0
  4. package/dist/__tests__/errors.test.js +125 -0
  5. package/dist/__tests__/errors.test.js.map +1 -0
  6. package/dist/__tests__/utils.test.d.ts +2 -0
  7. package/dist/__tests__/utils.test.d.ts.map +1 -0
  8. package/dist/__tests__/utils.test.js +105 -0
  9. package/dist/__tests__/utils.test.js.map +1 -0
  10. package/dist/__tests__/validators.test.d.ts +2 -0
  11. package/dist/__tests__/validators.test.d.ts.map +1 -0
  12. package/dist/__tests__/validators.test.js +148 -0
  13. package/dist/__tests__/validators.test.js.map +1 -0
  14. package/dist/config/constants.d.ts +69 -0
  15. package/dist/config/constants.d.ts.map +1 -0
  16. package/dist/config/constants.js +79 -0
  17. package/dist/config/constants.js.map +1 -0
  18. package/dist/config/index.d.ts +2 -0
  19. package/dist/config/index.d.ts.map +1 -0
  20. package/dist/config/index.js +2 -0
  21. package/dist/config/index.js.map +1 -0
  22. package/dist/env-config.d.ts +33 -0
  23. package/dist/env-config.d.ts.map +1 -0
  24. package/dist/env-config.js +285 -0
  25. package/dist/env-config.js.map +1 -0
  26. package/dist/index.d.ts +3 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +153 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/infra.d.ts +31 -0
  31. package/dist/infra.d.ts.map +1 -0
  32. package/dist/infra.js +267 -0
  33. package/dist/infra.js.map +1 -0
  34. package/dist/plugins.d.ts +35 -0
  35. package/dist/plugins.d.ts.map +1 -0
  36. package/dist/plugins.js +164 -0
  37. package/dist/plugins.js.map +1 -0
  38. package/dist/services.d.ts +52 -0
  39. package/dist/services.d.ts.map +1 -0
  40. package/dist/services.js +158 -0
  41. package/dist/services.js.map +1 -0
  42. package/dist/templates.d.ts +3 -0
  43. package/dist/templates.d.ts.map +1 -0
  44. package/dist/templates.js +202 -0
  45. package/dist/templates.js.map +1 -0
  46. package/dist/types/domain.d.ts +119 -0
  47. package/dist/types/domain.d.ts.map +1 -0
  48. package/dist/types/domain.js +5 -0
  49. package/dist/types/domain.js.map +1 -0
  50. package/dist/types/errors.d.ts +69 -0
  51. package/dist/types/errors.d.ts.map +1 -0
  52. package/dist/types/errors.js +129 -0
  53. package/dist/types/errors.js.map +1 -0
  54. package/dist/types/index.d.ts +3 -0
  55. package/dist/types/index.d.ts.map +1 -0
  56. package/dist/types/index.js +3 -0
  57. package/dist/types/index.js.map +1 -0
  58. package/dist/utils/index.d.ts +2 -0
  59. package/dist/utils/index.d.ts.map +1 -0
  60. package/dist/utils/index.js +2 -0
  61. package/dist/utils/index.js.map +1 -0
  62. package/dist/utils/logger.d.ts +54 -0
  63. package/dist/utils/logger.d.ts.map +1 -0
  64. package/dist/utils/logger.js +92 -0
  65. package/dist/utils/logger.js.map +1 -0
  66. package/dist/utils.d.ts +32 -0
  67. package/dist/utils.d.ts.map +1 -0
  68. package/dist/utils.js +79 -0
  69. package/dist/utils.js.map +1 -0
  70. package/dist/validators.d.ts +93 -0
  71. package/dist/validators.d.ts.map +1 -0
  72. package/dist/validators.js +180 -0
  73. package/dist/validators.js.map +1 -0
  74. package/package.json +45 -0
  75. package/src/__tests__/errors.test.ts +187 -0
  76. package/src/__tests__/utils.test.ts +142 -0
  77. package/src/__tests__/validators.test.ts +195 -0
  78. package/src/config/constants.ts +86 -0
  79. package/src/config/index.ts +1 -0
  80. package/src/env-config.ts +320 -0
  81. package/src/index.ts +203 -0
  82. package/src/infra.ts +300 -0
  83. package/src/plugins.ts +190 -0
  84. package/src/services.ts +190 -0
  85. package/src/templates.ts +203 -0
  86. package/src/types/domain.ts +127 -0
  87. package/src/types/errors.ts +173 -0
  88. package/src/types/index.ts +2 -0
  89. package/src/utils/index.ts +1 -0
  90. package/src/utils/logger.ts +118 -0
  91. package/src/utils.ts +105 -0
  92. package/src/validators.ts +192 -0
  93. package/tsconfig.json +19 -0
  94. package/vitest.config.ts +20 -0
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Application configuration constants
3
+ */
4
+ /**
5
+ * Service port mappings
6
+ */
7
+ export declare const SERVICE_PORTS: {
8
+ readonly API: 3000;
9
+ readonly DASHBOARD: 3002;
10
+ readonly GRAFANA: 3001;
11
+ readonly KAFKA_UI: 8080;
12
+ readonly MONGO: 27017;
13
+ readonly KAFKA: 9092;
14
+ readonly REDIS: 6379;
15
+ readonly LOKI: 3100;
16
+ };
17
+ /**
18
+ * Health check configuration
19
+ */
20
+ export declare const HEALTH_CHECK: {
21
+ readonly MAX_RETRIES: 30;
22
+ readonly RETRY_DELAY_MS: 2000;
23
+ readonly TIMEOUT_MS: 60000;
24
+ };
25
+ /**
26
+ * Docker command timeouts
27
+ */
28
+ export declare const DOCKER_TIMEOUTS: {
29
+ readonly START_MS: 30000;
30
+ readonly STOP_MS: 15000;
31
+ readonly BUILD_MS: 300000;
32
+ };
33
+ /**
34
+ * Critical environment variables that always need user input
35
+ */
36
+ export declare const CRITICAL_ENV_KEYS: string[];
37
+ /**
38
+ * Validation constraints
39
+ */
40
+ export declare const VALIDATION: {
41
+ readonly MIN_PASSWORD_LENGTH: 8;
42
+ readonly MIN_API_KEY_LENGTH: 8;
43
+ readonly PORT_MIN: 1;
44
+ readonly PORT_MAX: 65535;
45
+ };
46
+ /**
47
+ * File paths
48
+ */
49
+ export declare const FILES: {
50
+ readonly DOCKER_COMPOSE_INFRA: "docker-compose.infra.yaml";
51
+ readonly DOCKER_COMPOSE_APP: "docker-compose.yaml";
52
+ readonly ENV_FILE: ".env";
53
+ readonly CONFIG_FILE: "simplens.config.yaml";
54
+ readonly ERROR_LOG: "onboard-error.log";
55
+ };
56
+ /**
57
+ * URL templates for service access
58
+ */
59
+ export declare function getServiceURL(service: keyof typeof SERVICE_PORTS, host?: string): string;
60
+ /**
61
+ * Docker compose file paths
62
+ */
63
+ export declare const DOCKER_COMPOSE_COMMANDS: {
64
+ readonly UP: readonly ["up", "-d"];
65
+ readonly DOWN: readonly ["down"];
66
+ readonly LOGS: readonly ["logs", "-f"];
67
+ readonly PS: readonly ["ps"];
68
+ };
69
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/config/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;;;;;CAShB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,eAAe;;;;CAIlB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,iBAAiB,UAQ7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;CAKb,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,KAAK;;;;;;CAMR,CAAC;AAEX;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,OAAO,aAAa,EAAE,IAAI,GAAE,MAAoB,GAAG,MAAM,CAErG;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;CAK1B,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Application configuration constants
3
+ */
4
+ /**
5
+ * Service port mappings
6
+ */
7
+ export const SERVICE_PORTS = {
8
+ API: 3000,
9
+ DASHBOARD: 3002,
10
+ GRAFANA: 3001,
11
+ KAFKA_UI: 8080,
12
+ MONGO: 27017,
13
+ KAFKA: 9092,
14
+ REDIS: 6379,
15
+ LOKI: 3100,
16
+ };
17
+ /**
18
+ * Health check configuration
19
+ */
20
+ export const HEALTH_CHECK = {
21
+ MAX_RETRIES: 30,
22
+ RETRY_DELAY_MS: 2000,
23
+ TIMEOUT_MS: 60000,
24
+ };
25
+ /**
26
+ * Docker command timeouts
27
+ */
28
+ export const DOCKER_TIMEOUTS = {
29
+ START_MS: 30000,
30
+ STOP_MS: 15000,
31
+ BUILD_MS: 300000,
32
+ };
33
+ /**
34
+ * Critical environment variables that always need user input
35
+ */
36
+ export const CRITICAL_ENV_KEYS = [
37
+ 'NS_API_KEY',
38
+ 'MONGO_URI',
39
+ 'BROKERS',
40
+ 'REDIS_URL',
41
+ 'AUTH_SECRET',
42
+ 'ADMIN_PASSWORD',
43
+ 'LOKI_URL',
44
+ ];
45
+ /**
46
+ * Validation constraints
47
+ */
48
+ export const VALIDATION = {
49
+ MIN_PASSWORD_LENGTH: 8,
50
+ MIN_API_KEY_LENGTH: 8,
51
+ PORT_MIN: 1,
52
+ PORT_MAX: 65535,
53
+ };
54
+ /**
55
+ * File paths
56
+ */
57
+ export const FILES = {
58
+ DOCKER_COMPOSE_INFRA: 'docker-compose.infra.yaml',
59
+ DOCKER_COMPOSE_APP: 'docker-compose.yaml',
60
+ ENV_FILE: '.env',
61
+ CONFIG_FILE: 'simplens.config.yaml',
62
+ ERROR_LOG: 'onboard-error.log',
63
+ };
64
+ /**
65
+ * URL templates for service access
66
+ */
67
+ export function getServiceURL(service, host = 'localhost') {
68
+ return `http://${host}:${SERVICE_PORTS[service]}`;
69
+ }
70
+ /**
71
+ * Docker compose file paths
72
+ */
73
+ export const DOCKER_COMPOSE_COMMANDS = {
74
+ UP: ['up', '-d'],
75
+ DOWN: ['down'],
76
+ LOGS: ['logs', '-f'],
77
+ PS: ['ps'],
78
+ };
79
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/config/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IACzB,GAAG,EAAE,IAAI;IACT,SAAS,EAAE,IAAI;IACf,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,IAAI;IACd,KAAK,EAAE,KAAK;IACZ,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,IAAI;IACX,IAAI,EAAE,IAAI;CACJ,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IACxB,WAAW,EAAE,EAAE;IACf,cAAc,EAAE,IAAI;IACpB,UAAU,EAAE,KAAK;CACX,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC3B,QAAQ,EAAE,KAAK;IACf,OAAO,EAAE,KAAK;IACd,QAAQ,EAAE,MAAM;CACV,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC7B,YAAY;IACZ,WAAW;IACX,SAAS;IACT,WAAW;IACX,aAAa;IACb,gBAAgB;IAChB,UAAU;CACb,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACtB,mBAAmB,EAAE,CAAC;IACtB,kBAAkB,EAAE,CAAC;IACrB,QAAQ,EAAE,CAAC;IACX,QAAQ,EAAE,KAAK;CACT,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG;IACjB,oBAAoB,EAAE,2BAA2B;IACjD,kBAAkB,EAAE,qBAAqB;IACzC,QAAQ,EAAE,MAAM;IAChB,WAAW,EAAE,sBAAsB;IACnC,SAAS,EAAE,mBAAmB;CACxB,CAAC;AAEX;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAmC,EAAE,OAAe,WAAW;IACzF,OAAO,UAAU,IAAI,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACnC,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;IAChB,IAAI,EAAE,CAAC,MAAM,CAAC;IACd,IAAI,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC;IACpB,EAAE,EAAE,CAAC,IAAI,CAAC;CACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './constants.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './constants.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { EnvVariable } from './types/domain.js';
2
+ /**
3
+ * Load and parse .env.example from embedded template
4
+ */
5
+ export declare function loadEnvExample(): Promise<EnvVariable[]>;
6
+ /**
7
+ * Prompts user for environment variable values based on the selected mode.
8
+ *
9
+ * @param mode - 'default' prompts only for critical vars, 'interactive' prompts for all
10
+ * @param infraServices - List of selected infrastructure service IDs
11
+ * @param infraHost - Host for infrastructure services
12
+ * @returns Map of environment variable keys to values
13
+ *
14
+ * @remarks
15
+ * Critical variables (always prompted): NS_API_KEY, MONGO_URI, BROKERS, etc.
16
+ * Interactive mode prompts for all variables including optional ones.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * const envVars = await promptEnvVariables('default', ['mongo', 'kafka'], 'localhost');
21
+ * // Prompts only for critical variables
22
+ * ```
23
+ */
24
+ export declare function promptEnvVariables(mode: 'default' | 'interactive', infraServices: string[], infraHost: string): Promise<Map<string, string>>;
25
+ /**
26
+ * Generate .env file from variables
27
+ */
28
+ export declare function generateEnvFile(targetDir: string, envVars: Map<string, string>): Promise<void>;
29
+ /**
30
+ * Append plugin credentials to .env file
31
+ */
32
+ export declare function appendPluginEnv(targetDir: string, pluginEnvVars: Map<string, string>): Promise<void>;
33
+ //# sourceMappingURL=env-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-config.d.ts","sourceRoot":"","sources":["../src/env-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAuG7D;AA0CD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,kBAAkB,CACpC,IAAI,EAAE,SAAS,GAAG,aAAa,EAC/B,aAAa,EAAE,MAAM,EAAE,EACvB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAmF9B;AAkBD;;GAEG;AACH,wBAAsB,eAAe,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;GAEG;AACH,wBAAsB,eAAe,CACjC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,OAAO,CAAC,IAAI,CAAC,CAgBf"}
@@ -0,0 +1,285 @@
1
+ import inquirer from 'inquirer';
2
+ import { writeFile, appendFile, logInfo, logSuccess } from './utils.js';
3
+ import path from 'path';
4
+ import { CRITICAL_ENV_KEYS } from './config/constants.js';
5
+ /**
6
+ * Load and parse .env.example from embedded template
7
+ */
8
+ export async function loadEnvExample() {
9
+ // Embedded .env template - always available regardless of installation
10
+ const envTemplate = `
11
+ # ============================================
12
+ # INFRASTRUCTURE HOST CONFIGURATION
13
+ # ============================================
14
+ INFRA_HOST=host.docker.internal
15
+
16
+ # ============================================
17
+ # CONNECTION URLS
18
+ # ============================================
19
+ NODE_ENV=production
20
+ # ============================================
21
+ # API SERVER
22
+ # ============================================
23
+ NS_API_KEY=
24
+ PORT=3000
25
+ MAX_BATCH_REQ_LIMIT=1000
26
+
27
+ # ============================================
28
+ # DATABASE
29
+ # ============================================
30
+ MONGO_URI=
31
+
32
+ # ============================================
33
+ # KAFKA
34
+ # ============================================
35
+ BROKERS=
36
+
37
+ # Kafka Topic Partitions (Core Topics)
38
+ DELAYED_PARTITION=1
39
+ NOTIFICATION_STATUS_PARTITION=1
40
+
41
+ # ============================================
42
+ # REDIS
43
+ # ============================================
44
+ REDIS_URL=
45
+
46
+ # ============================================
47
+ # PLUGIN SYSTEM
48
+ # ============================================
49
+ SIMPLENS_CONFIG_PATH=./simplens.config.yaml
50
+ PROCESSOR_CHANNEL=all
51
+
52
+ # ============================================
53
+ # BACKGROUND WORKER
54
+ # ============================================
55
+ OUTBOX_POLL_INTERVAL_MS=5000
56
+ OUTBOX_CLEANUP_INTERVAL_MS=60000
57
+ OUTBOX_BATCH_SIZE=100
58
+ OUTBOX_RETENTION_MS=300000
59
+ OUTBOX_CLAIM_TIMEOUT_MS=30000
60
+
61
+ # ============================================
62
+ # RETRY & IDEMPOTENCY
63
+ # ============================================
64
+ IDEMPOTENCY_TTL_SECONDS=86400
65
+ MAX_RETRY_COUNT=5
66
+ PROCESSING_TTL_SECONDS=120
67
+
68
+ # ============================================
69
+ # DELAYED NOTIFICATIONS
70
+ # ============================================
71
+ DELAYED_POLL_INTERVAL_MS=1000
72
+ DELAYED_BATCH_SIZE=10
73
+ MAX_POLLER_RETRIES=3
74
+
75
+ # ============================================
76
+ # RECOVERY SERVICE
77
+ # ============================================
78
+ RECOVERY_POLL_INTERVAL_MS=60000
79
+ PROCESSING_STUCK_THRESHOLD_MS=300000
80
+ PENDING_STUCK_THRESHOLD_MS=300000
81
+ RECOVERY_BATCH_SIZE=50
82
+ RECOVERY_CLAIM_TIMEOUT_MS=60000
83
+
84
+ # ============================================
85
+ # CLEANUP
86
+ # ============================================
87
+ CLEANUP_RESOLVED_ALERTS_RETENTION_MS=86400000
88
+ CLEANUP_PROCESSED_STATUS_OUTBOX_RETENTION_MS=86400000
89
+
90
+ # ============================================
91
+ # LOGGING
92
+ # ============================================
93
+ LOKI_URL=
94
+ LOG_LEVEL=info
95
+ LOG_TO_FILE=true
96
+
97
+ # ============================================
98
+ # ADMIN DASHBOARD
99
+ # ============================================
100
+ AUTH_SECRET=
101
+ ADMIN_USERNAME=admin
102
+ ADMIN_PASSWORD=
103
+ AUTH_TRUST_HOST=true
104
+ API_BASE_URL=http://api:3000
105
+ WEBHOOK_HOST=dashboard
106
+ WEBHOOK_PORT=3002
107
+ DASHBOARD_PORT=3002
108
+ `;
109
+ return parseEnvContent(envTemplate);
110
+ }
111
+ /**
112
+ * Parse .env content into structured format
113
+ */
114
+ function parseEnvContent(content) {
115
+ const lines = content.split('\n');
116
+ const variables = [];
117
+ let currentComment = '';
118
+ for (const line of lines) {
119
+ const trimmed = line.trim();
120
+ // Capture comments as descriptions
121
+ if (trimmed.startsWith('#') && !trimmed.includes('====')) {
122
+ currentComment = trimmed.replace(/^#\s*/, '');
123
+ continue;
124
+ }
125
+ // Skip empty lines and section dividers
126
+ if (!trimmed || trimmed.includes('====')) {
127
+ currentComment = '';
128
+ continue;
129
+ }
130
+ // Parse key=value pairs
131
+ const match = trimmed.match(/^([A-Z_]+)=(.*)$/);
132
+ if (match) {
133
+ const [, key, value] = match;
134
+ variables.push({
135
+ key,
136
+ value: value || '',
137
+ description: currentComment || undefined,
138
+ required: CRITICAL_ENV_KEYS.includes(key) || !value,
139
+ });
140
+ currentComment = '';
141
+ }
142
+ }
143
+ return variables;
144
+ }
145
+ /**
146
+ * Prompts user for environment variable values based on the selected mode.
147
+ *
148
+ * @param mode - 'default' prompts only for critical vars, 'interactive' prompts for all
149
+ * @param infraServices - List of selected infrastructure service IDs
150
+ * @param infraHost - Host for infrastructure services
151
+ * @returns Map of environment variable keys to values
152
+ *
153
+ * @remarks
154
+ * Critical variables (always prompted): NS_API_KEY, MONGO_URI, BROKERS, etc.
155
+ * Interactive mode prompts for all variables including optional ones.
156
+ *
157
+ * @example
158
+ * ```ts
159
+ * const envVars = await promptEnvVariables('default', ['mongo', 'kafka'], 'localhost');
160
+ * // Prompts only for critical variables
161
+ * ```
162
+ */
163
+ export async function promptEnvVariables(mode, infraServices, infraHost) {
164
+ logInfo('Configuring environment variables...');
165
+ const envVars = await loadEnvExample();
166
+ const result = new Map();
167
+ // Auto-fill infra connection URLs based on selected services and host
168
+ const autoInfraUrls = {
169
+ MONGO_URI: infraServices.includes('mongo')
170
+ ? (infraHost === "host.docker.internal" ? `mongodb://mongo:27017/simplens?replicaSet=rs0` : `mongodb://${infraHost}:27017/simplens?replicaSet=rs0`)
171
+ : '',
172
+ BROKERS: infraServices.includes('kafka')
173
+ ? (infraHost === "host.docker.internal" ? "kafka:9093" : `${infraHost}:9092`)
174
+ : '',
175
+ REDIS_URL: infraServices.includes('redis')
176
+ ? (infraHost === "host.docker.internal" ? "redis://redis:6379" : `redis://${infraHost}:6379`)
177
+ : '',
178
+ LOKI_URL: infraServices.includes('loki')
179
+ ? (infraHost === "host.docker.internal" ? "http://loki:3100" : `http://${infraHost}:3100`)
180
+ : '',
181
+ };
182
+ if (mode === 'default') {
183
+ // Use defaults, only prompt for critical values
184
+ for (const envVar of envVars) {
185
+ // Use auto-filled infra URLs
186
+ if (autoInfraUrls[envVar.key]) {
187
+ result.set(envVar.key, autoInfraUrls[envVar.key]);
188
+ continue;
189
+ }
190
+ // Use default value if available
191
+ if (envVar.value && !CRITICAL_ENV_KEYS.includes(envVar.key)) {
192
+ result.set(envVar.key, envVar.value);
193
+ continue;
194
+ }
195
+ // Prompt for critical values (only if not auto-filled)
196
+ if (CRITICAL_ENV_KEYS.includes(envVar.key)) {
197
+ const answer = await inquirer.prompt([
198
+ {
199
+ type: envVar.key.includes('PASSWORD') ? 'password' : 'input',
200
+ name: 'value',
201
+ message: `${envVar.key}${envVar.description ? ` (${envVar.description})` : ''}:`,
202
+ default: getSuggestedValue(envVar.key),
203
+ validate: (input) => {
204
+ if (!input && envVar.required) {
205
+ return `${envVar.key} is required`;
206
+ }
207
+ return true;
208
+ },
209
+ },
210
+ ]);
211
+ result.set(envVar.key, answer.value);
212
+ }
213
+ }
214
+ }
215
+ else {
216
+ // Interactive mode: prompt for everything
217
+ logInfo('Interactive mode: You will be prompted for each environment variable.');
218
+ for (const envVar of envVars) {
219
+ const defaultValue = autoInfraUrls[envVar.key] || envVar.value || getSuggestedValue(envVar.key);
220
+ const answer = await inquirer.prompt([
221
+ {
222
+ type: envVar.key.includes('PASSWORD') ? 'password' : 'input',
223
+ name: 'value',
224
+ message: `${envVar.key}${envVar.description ? ` (${envVar.description})` : ''}:`,
225
+ default: defaultValue,
226
+ validate: (input) => {
227
+ if (!input && envVar.required) {
228
+ return `${envVar.key} is required`;
229
+ }
230
+ return true;
231
+ },
232
+ },
233
+ ]);
234
+ result.set(envVar.key, answer.value);
235
+ }
236
+ }
237
+ logSuccess('Environment variables configured');
238
+ return result;
239
+ }
240
+ /**
241
+ * Get suggested value for specific keys
242
+ */
243
+ function getSuggestedValue(key) {
244
+ if (key === 'NS_API_KEY' || key === 'AUTH_SECRET') {
245
+ return `Replace with: openssl rand -base64 32`;
246
+ }
247
+ if (key === 'NODE_ENV') {
248
+ return 'production';
249
+ }
250
+ if (key === 'ADMIN_USERNAME') {
251
+ return 'admin';
252
+ }
253
+ return '';
254
+ }
255
+ /**
256
+ * Generate .env file from variables
257
+ */
258
+ export async function generateEnvFile(targetDir, envVars) {
259
+ const envPath = path.join(targetDir, '.env');
260
+ let content = '# SimpleNS Environment Configuration\n';
261
+ content += '# Generated by @simplens/onboard\n\n';
262
+ for (const [key, value] of envVars.entries()) {
263
+ content += `${key}=${value}\n`;
264
+ }
265
+ await writeFile(envPath, content);
266
+ logSuccess('Generated .env file');
267
+ }
268
+ /**
269
+ * Append plugin credentials to .env file
270
+ */
271
+ export async function appendPluginEnv(targetDir, pluginEnvVars) {
272
+ // Only append if there are actually credentials to add
273
+ if (pluginEnvVars.size === 0) {
274
+ logInfo('No plugin credentials to add');
275
+ return;
276
+ }
277
+ const envPath = path.join(targetDir, '.env');
278
+ let content = '\n# Plugin Credentials\n';
279
+ for (const [key, value] of pluginEnvVars.entries()) {
280
+ content += `${key}=${value}\n`;
281
+ }
282
+ await appendFile(envPath, content);
283
+ logSuccess('Added plugin credentials to .env');
284
+ }
285
+ //# sourceMappingURL=env-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-config.js","sourceRoot":"","sources":["../src/env-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import path from 'path';
4
+ import inquirer from 'inquirer';
5
+ import { displayBanner, logSuccess, logInfo, initLogger, logDebug } from './utils.js';
6
+ import { validatePrerequisites } from './validators.js';
7
+ import { promptInfraServices, generateInfraCompose, writeAppCompose, } from './infra.js';
8
+ import { promptEnvVariables, generateEnvFile, appendPluginEnv, } from './env-config.js';
9
+ import { fetchAvailablePlugins, promptPluginSelection, generatePluginConfig, parseConfigCredentials, promptPluginCredentials, } from './plugins.js';
10
+ import { promptStartServices, startInfraServices, waitForInfraHealth, startAppServices, displayServiceStatus, } from './services.js';
11
+ const program = new Command();
12
+ program
13
+ .name('@simplens/onboard')
14
+ .description('A CLI tool to setup a SimpleNS instance on your machine/server')
15
+ .version('1.0.0')
16
+ .option('--infra', 'Setup infrastructure services (MongoDB, Kafka, Redis, etc.)')
17
+ .option('--env <mode>', 'Environment setup mode: "default" or "interactive"')
18
+ .option('--dir <path>', 'Target directory for setup')
19
+ .parse(process.argv);
20
+ const options = program.opts();
21
+ /**
22
+ * Prompt for setup options if not provided via CLI args
23
+ */
24
+ async function promptSetupOptions() {
25
+ const answers = await inquirer.prompt([
26
+ {
27
+ type: 'confirm',
28
+ name: 'infra',
29
+ message: 'Do you want to setup infrastructure services (MongoDB, Kafka, Redis, etc.)?',
30
+ default: true,
31
+ when: () => options.infra === undefined,
32
+ },
33
+ {
34
+ type: 'list',
35
+ name: 'envMode',
36
+ message: 'Select environment configuration mode:',
37
+ choices: [
38
+ { name: 'Default (use preset values, prompt only for critical)', value: 'default' },
39
+ { name: 'Interactive (prompt for all variables)', value: 'interactive' },
40
+ ],
41
+ default: 'default',
42
+ when: () => !options.env,
43
+ },
44
+ {
45
+ type: 'input',
46
+ name: 'targetDir',
47
+ message: 'Target directory for setup:',
48
+ default: process.cwd(),
49
+ when: () => !options.dir,
50
+ },
51
+ ]);
52
+ return {
53
+ infra: options.infra !== undefined ? options.infra : answers.infra,
54
+ envMode: options.env || answers.envMode || 'default',
55
+ targetDir: options.dir || answers.targetDir || process.cwd(),
56
+ };
57
+ }
58
+ /**
59
+ * Main onboarding workflow
60
+ */
61
+ async function main() {
62
+ try {
63
+ // Display banner
64
+ displayBanner();
65
+ // Initialize logger based on CLI flags
66
+ const opts = program.opts();
67
+ initLogger({
68
+ verbose: opts.verbose || false,
69
+ debug: opts.debug || false,
70
+ logFile: opts.debug ? path.join(process.cwd(), 'onboard-debug.log') : undefined,
71
+ });
72
+ logDebug('Logger initialized');
73
+ logDebug(`CLI options: ${JSON.stringify(opts)}`);
74
+ // Prompt for setup options if not provided
75
+ const setupOptions = await promptSetupOptions();
76
+ // Get target directory
77
+ const targetDir = path.resolve(setupOptions.targetDir);
78
+ logInfo(`Target directory: ${targetDir}`);
79
+ logDebug(`Resolved target directory: ${targetDir}`);
80
+ // Step 1: Validate prerequisites
81
+ await validatePrerequisites();
82
+ // Step 2: Infrastructure setup (if --infra flag is provided)
83
+ let selectedInfraServices = [];
84
+ let infraHost = 'host.docker.internal';
85
+ if (setupOptions.infra) {
86
+ logInfo('\n🏗️ Infrastructure Setup\n');
87
+ selectedInfraServices = await promptInfraServices();
88
+ infraHost = await generateInfraCompose(targetDir, selectedInfraServices);
89
+ }
90
+ else {
91
+ logInfo('\n⏭️ Skipping infrastructure setup (use --infra to enable)');
92
+ }
93
+ // Always write app docker-compose
94
+ logInfo('\n📦 Application Services Setup\n');
95
+ await writeAppCompose(targetDir);
96
+ // Step 3: Environment configuration
97
+ logInfo('\n⚙️ Environment Configuration\n');
98
+ const envMode = setupOptions.envMode;
99
+ const envVars = await promptEnvVariables(envMode, selectedInfraServices, infraHost);
100
+ await generateEnvFile(targetDir, envVars);
101
+ // Step 4: Plugin installation
102
+ logInfo('\n🔌 Plugin Installation\n');
103
+ const availablePlugins = await fetchAvailablePlugins();
104
+ const selectedPlugins = await promptPluginSelection(availablePlugins);
105
+ if (selectedPlugins.length > 0) {
106
+ await generatePluginConfig(targetDir, selectedPlugins);
107
+ // Extract and prompt for plugin credentials
108
+ const configPath = path.join(targetDir, 'simplens.config.yaml');
109
+ const credentialKeys = await parseConfigCredentials(configPath);
110
+ if (credentialKeys.length > 0) {
111
+ const pluginCreds = await promptPluginCredentials(credentialKeys);
112
+ await appendPluginEnv(targetDir, pluginCreds);
113
+ }
114
+ }
115
+ // Step 5: Service orchestration
116
+ logInfo('\n🚀 Service Orchestration\n');
117
+ const shouldStart = await promptStartServices();
118
+ if (shouldStart) {
119
+ // Start infra services first (if --infra was used)
120
+ if (setupOptions.infra && selectedInfraServices.length > 0) {
121
+ await startInfraServices(targetDir);
122
+ await waitForInfraHealth(targetDir);
123
+ }
124
+ // Start app services
125
+ await startAppServices(targetDir);
126
+ // Display service status
127
+ await displayServiceStatus();
128
+ }
129
+ else {
130
+ logInfo('Services not started. You can start them later with:');
131
+ if (setupOptions.infra) {
132
+ console.log(' docker-compose -f docker-compose.infra.yaml up -d');
133
+ }
134
+ console.log(' docker-compose up -d\n');
135
+ }
136
+ // Final success message
137
+ logSuccess('\n🎉 SimpleNS onboarding completed successfully!\n');
138
+ }
139
+ catch (error) {
140
+ // Import at top of file
141
+ const { formatErrorForUser } = await import('./types/errors.js');
142
+ console.log('\n' + formatErrorForUser(error));
143
+ // Log full error to stderr for debugging
144
+ if (process.env.DEBUG) {
145
+ console.error('\nFull error details:');
146
+ console.error(error);
147
+ }
148
+ process.exit(1);
149
+ }
150
+ }
151
+ // Run main function
152
+ main();
153
+ //# sourceMappingURL=index.js.map