trustlocal 0.1.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 (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +129 -0
  3. package/dist/commands/init.d.ts +25 -0
  4. package/dist/commands/init.d.ts.map +1 -0
  5. package/dist/commands/init.js +289 -0
  6. package/dist/commands/init.js.map +1 -0
  7. package/dist/commands/renew.d.ts +16 -0
  8. package/dist/commands/renew.d.ts.map +1 -0
  9. package/dist/commands/renew.js +54 -0
  10. package/dist/commands/renew.js.map +1 -0
  11. package/dist/commands/status.d.ts +13 -0
  12. package/dist/commands/status.d.ts.map +1 -0
  13. package/dist/commands/status.js +140 -0
  14. package/dist/commands/status.js.map +1 -0
  15. package/dist/commands/sync.d.ts +13 -0
  16. package/dist/commands/sync.d.ts.map +1 -0
  17. package/dist/commands/sync.js +111 -0
  18. package/dist/commands/sync.js.map +1 -0
  19. package/dist/config/trustlocal.d.ts +40 -0
  20. package/dist/config/trustlocal.d.ts.map +1 -0
  21. package/dist/config/trustlocal.js +54 -0
  22. package/dist/config/trustlocal.js.map +1 -0
  23. package/dist/detector/framework.d.ts +14 -0
  24. package/dist/detector/framework.d.ts.map +1 -0
  25. package/dist/detector/framework.js +89 -0
  26. package/dist/detector/framework.js.map +1 -0
  27. package/dist/index.d.ts +8 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +69 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/injectors/astHelper.d.ts +35 -0
  32. package/dist/injectors/astHelper.d.ts.map +1 -0
  33. package/dist/injectors/astHelper.js +192 -0
  34. package/dist/injectors/astHelper.js.map +1 -0
  35. package/dist/injectors/express.d.ts +22 -0
  36. package/dist/injectors/express.d.ts.map +1 -0
  37. package/dist/injectors/express.js +59 -0
  38. package/dist/injectors/express.js.map +1 -0
  39. package/dist/injectors/nextjs.d.ts +24 -0
  40. package/dist/injectors/nextjs.d.ts.map +1 -0
  41. package/dist/injectors/nextjs.js +116 -0
  42. package/dist/injectors/nextjs.js.map +1 -0
  43. package/dist/injectors/nginx.d.ts +23 -0
  44. package/dist/injectors/nginx.d.ts.map +1 -0
  45. package/dist/injectors/nginx.js +61 -0
  46. package/dist/injectors/nginx.js.map +1 -0
  47. package/dist/injectors/plain.d.ts +12 -0
  48. package/dist/injectors/plain.d.ts.map +1 -0
  49. package/dist/injectors/plain.js +36 -0
  50. package/dist/injectors/plain.js.map +1 -0
  51. package/dist/injectors/vite.d.ts +24 -0
  52. package/dist/injectors/vite.d.ts.map +1 -0
  53. package/dist/injectors/vite.js +125 -0
  54. package/dist/injectors/vite.js.map +1 -0
  55. package/dist/mkcert/check.d.ts +13 -0
  56. package/dist/mkcert/check.d.ts.map +1 -0
  57. package/dist/mkcert/check.js +38 -0
  58. package/dist/mkcert/check.js.map +1 -0
  59. package/dist/mkcert/generate.d.ts +26 -0
  60. package/dist/mkcert/generate.d.ts.map +1 -0
  61. package/dist/mkcert/generate.js +111 -0
  62. package/dist/mkcert/generate.js.map +1 -0
  63. package/dist/mkcert/install.d.ts +7 -0
  64. package/dist/mkcert/install.d.ts.map +1 -0
  65. package/dist/mkcert/install.js +75 -0
  66. package/dist/mkcert/install.js.map +1 -0
  67. package/dist/utils/backup.d.ts +7 -0
  68. package/dist/utils/backup.d.ts.map +1 -0
  69. package/dist/utils/backup.js +16 -0
  70. package/dist/utils/backup.js.map +1 -0
  71. package/dist/utils/logger.d.ts +17 -0
  72. package/dist/utils/logger.d.ts.map +1 -0
  73. package/dist/utils/logger.js +38 -0
  74. package/dist/utils/logger.js.map +1 -0
  75. package/dist/utils/os.d.ts +4 -0
  76. package/dist/utils/os.d.ts.map +1 -0
  77. package/dist/utils/os.js +24 -0
  78. package/dist/utils/os.js.map +1 -0
  79. package/package.json +55 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sahil Kashyap
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # trustlocal
2
+
3
+ > One command. HTTPS everywhere. Zero config.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/trustlocal)](https://www.npmjs.com/package/trustlocal)
6
+ [![npm downloads](https://img.shields.io/npm/dw/trustlocal)](https://www.npmjs.com/package/trustlocal)
7
+ [![license](https://img.shields.io/npm/l/trustlocal)](LICENSE)
8
+
9
+ `trustlocal` automates local HTTPS setup for web development projects. It uses [mkcert](https://github.com/FiloSottile/mkcert) to generate locally trusted certificates, then detects your framework and injects the correct SSL configuration — eliminating every manual step between *"I want HTTPS locally"* and *"it works."*
10
+
11
+ ---
12
+
13
+ ## Quick start
14
+
15
+ ```bash
16
+ npx trustlocal init
17
+ ```
18
+
19
+ That's it. `trustlocal` will:
20
+
21
+ 1. Install mkcert if not already present
22
+ 2. Register the local CA (prompts for sudo once)
23
+ 3. Detect your framework (Next.js, Vite, Express, Nginx, or plain)
24
+ 4. Generate trusted certificates for `localhost` and `127.0.0.1`
25
+ 5. Inject HTTPS config into your framework's config file
26
+ 6. Set `NODE_EXTRA_CA_CERTS` in `.env`
27
+ 7. Add `.trustlocal/` to `.gitignore`
28
+ 8. Write `trustlocal.json` so teammates can sync with one command
29
+
30
+ ---
31
+
32
+ ## Commands
33
+
34
+ ### `init` — First-time setup
35
+
36
+ ```bash
37
+ npx trustlocal init [--domains myapp.local] [--force] [--dry-run]
38
+ ```
39
+
40
+ | Flag | Description |
41
+ |------|-------------|
42
+ | `--domains <list>` | Comma-separated extra domains (e.g. `--domains myapp.local,api.local`) |
43
+ | `--force` | Re-initialise even if `trustlocal.json` already exists |
44
+ | `--dry-run` | Preview what would happen without writing any files |
45
+
46
+ ### `sync` — Onboard a new teammate
47
+
48
+ ```bash
49
+ npx trustlocal sync
50
+ ```
51
+
52
+ Reads `trustlocal.json`, generates fresh certs on the new machine (no private key sharing), injects config identically, and gets HTTPS working in under 30 seconds.
53
+
54
+ ### `renew` — Renew expiring certs
55
+
56
+ ```bash
57
+ npx trustlocal renew [--force]
58
+ ```
59
+
60
+ Certs expire after 2 years. Deletes old certs and generates fresh ones. Framework config files are **not** touched — cert paths stay the same.
61
+
62
+ ### `status` — Check your setup
63
+
64
+ ```bash
65
+ npx trustlocal status
66
+ ```
67
+
68
+ Shows framework, cert expiry, config injection status, `NODE_EXTRA_CA_CERTS`, and `.gitignore` — with coloured OK / WARNING / ERROR indicators.
69
+
70
+ ---
71
+
72
+ ## Supported frameworks
73
+
74
+ | Framework | Detection | Config target |
75
+ |-----------|-----------|---------------|
76
+ | **Next.js** | `next` in `package.json` | `next.config.js/ts` — `experimental.https` |
77
+ | **Vite** | `vite` in `package.json` | `vite.config.js/ts` — `server.https` |
78
+ | **Express / Node** | `express` in deps or `server.js` found | `.env` — `NODE_EXTRA_CA_CERTS` + printed snippet |
79
+ | **Nginx** | `nginx.conf` in project root | `nginx.conf` — `ssl_certificate` block |
80
+ | **Plain** | fallback | Certs placed in `.trustlocal/` with instructions |
81
+
82
+ ---
83
+
84
+ ## How it works
85
+
86
+ ```
87
+ npx trustlocal init
88
+
89
+ → Checking mkcert...
90
+ ✓ mkcert 1.4.4 found
91
+ → Detecting framework...
92
+ ✓ Detected: Next.js (next.config.ts)
93
+ → Generating certificates for: localhost, 127.0.0.1
94
+ ✓ Certificates generated → .trustlocal/
95
+ → Injecting HTTPS config into next.config.ts...
96
+ ✓ Config updated
97
+ → Updating .env...
98
+ ✓ NODE_EXTRA_CA_CERTS set
99
+ → Updating .gitignore...
100
+ ✓ .trustlocal/ added to .gitignore
101
+
102
+ ✓ Done! Open https://localhost:3000
103
+
104
+ Teammates: run npx trustlocal sync to get HTTPS on their machines.
105
+ Cert expires: 2028-03-31
106
+ ```
107
+
108
+ ---
109
+
110
+ ## Security
111
+
112
+ - `.trustlocal/` (containing `.pem` files) is automatically added to `.gitignore` — **private keys are never committed**
113
+ - `trustlocal.json` is safe to commit — it contains no keys, only config metadata
114
+ - All cert generation happens locally via `mkcert`. `trustlocal` never reads, stores, or transmits any private key
115
+
116
+ ---
117
+
118
+ ## Requirements
119
+
120
+ - Node.js 18+
121
+ - macOS or Linux (Windows support is post-v1)
122
+
123
+ ---
124
+
125
+ ## License
126
+
127
+ MIT © Sahil Kashyap
128
+
129
+ Built with [Claude Code](https://claude.ai/claude-code)
@@ -0,0 +1,25 @@
1
+ /**
2
+ * `npx trustlocal init`
3
+ *
4
+ * Full execution flow (per spec §5.1):
5
+ * 1. Check Node version >= 18
6
+ * 2. Check if trustlocal.json already exists (require --force to continue)
7
+ * 3. Check / install mkcert
8
+ * 4. Run mkcert -install
9
+ * 5. Detect framework
10
+ * 6. Prompt user to confirm / override
11
+ * 7. Collect domains
12
+ * 8. Create .trustlocal/ and generate certs
13
+ * 9. Backup + inject HTTPS config
14
+ * 10. Add NODE_EXTRA_CA_CERTS to .env
15
+ * 11. Add .trustlocal/ to .gitignore
16
+ * 12. Write trustlocal.json
17
+ * 13. Print success summary
18
+ */
19
+ export interface InitOptions {
20
+ domains?: string[];
21
+ force?: boolean;
22
+ dryRun?: boolean;
23
+ }
24
+ export declare function runInit(options?: InitOptions): Promise<void>;
25
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAmBH,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA+GD,wBAAsB,OAAO,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoItE"}
@@ -0,0 +1,289 @@
1
+ "use strict";
2
+ /**
3
+ * `npx trustlocal init`
4
+ *
5
+ * Full execution flow (per spec §5.1):
6
+ * 1. Check Node version >= 18
7
+ * 2. Check if trustlocal.json already exists (require --force to continue)
8
+ * 3. Check / install mkcert
9
+ * 4. Run mkcert -install
10
+ * 5. Detect framework
11
+ * 6. Prompt user to confirm / override
12
+ * 7. Collect domains
13
+ * 8. Create .trustlocal/ and generate certs
14
+ * 9. Backup + inject HTTPS config
15
+ * 10. Add NODE_EXTRA_CA_CERTS to .env
16
+ * 11. Add .trustlocal/ to .gitignore
17
+ * 12. Write trustlocal.json
18
+ * 13. Print success summary
19
+ */
20
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ var desc = Object.getOwnPropertyDescriptor(m, k);
23
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
24
+ desc = { enumerable: true, get: function() { return m[k]; } };
25
+ }
26
+ Object.defineProperty(o, k2, desc);
27
+ }) : (function(o, m, k, k2) {
28
+ if (k2 === undefined) k2 = k;
29
+ o[k2] = m[k];
30
+ }));
31
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
32
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
33
+ }) : function(o, v) {
34
+ o["default"] = v;
35
+ });
36
+ var __importStar = (this && this.__importStar) || (function () {
37
+ var ownKeys = function(o) {
38
+ ownKeys = Object.getOwnPropertyNames || function (o) {
39
+ var ar = [];
40
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
41
+ return ar;
42
+ };
43
+ return ownKeys(o);
44
+ };
45
+ return function (mod) {
46
+ if (mod && mod.__esModule) return mod;
47
+ var result = {};
48
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
49
+ __setModuleDefault(result, mod);
50
+ return result;
51
+ };
52
+ })();
53
+ Object.defineProperty(exports, "__esModule", { value: true });
54
+ exports.runInit = runInit;
55
+ const promises_1 = require("fs/promises");
56
+ const path_1 = require("path");
57
+ const readline = __importStar(require("readline"));
58
+ const logger_1 = require("../utils/logger");
59
+ const framework_1 = require("../detector/framework");
60
+ const check_1 = require("../mkcert/check");
61
+ const install_1 = require("../mkcert/install");
62
+ const generate_1 = require("../mkcert/generate");
63
+ const trustlocal_1 = require("../config/trustlocal");
64
+ const nextjs_1 = require("../injectors/nextjs");
65
+ const vite_1 = require("../injectors/vite");
66
+ const express_1 = require("../injectors/express");
67
+ const nginx_1 = require("../injectors/nginx");
68
+ const plain_1 = require("../injectors/plain");
69
+ const check_2 = require("../mkcert/check");
70
+ /** Prompt the user with a question and return their answer. */
71
+ async function prompt(question) {
72
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
73
+ return new Promise((resolve) => {
74
+ rl.question(` ${question} `, (answer) => {
75
+ rl.close();
76
+ resolve(answer.trim());
77
+ });
78
+ });
79
+ }
80
+ /** Collect extra .local domains from .env file */
81
+ async function collectEnvDomains(cwd) {
82
+ try {
83
+ const content = await (0, promises_1.readFile)((0, path_1.join)(cwd, '.env'), 'utf-8');
84
+ const matches = content.matchAll(/(?:HOST|DOMAIN|URL)[^=]*=\s*([a-zA-Z0-9.-]+\.local)/g);
85
+ return [...matches].map((m) => m[1]);
86
+ }
87
+ catch {
88
+ return [];
89
+ }
90
+ }
91
+ /** Add a path to .gitignore if not already present. */
92
+ async function ensureGitignore(cwd, entry) {
93
+ const gitignorePath = (0, path_1.join)(cwd, '.gitignore');
94
+ let content = '';
95
+ try {
96
+ content = await (0, promises_1.readFile)(gitignorePath, 'utf-8');
97
+ }
98
+ catch {
99
+ // File doesn't exist — create it
100
+ }
101
+ if (content.includes(entry))
102
+ return;
103
+ const newContent = content
104
+ ? `${content.trimEnd()}\n\n# trustlocal — local TLS certs (never commit private keys)\n${entry}/\n`
105
+ : `# trustlocal — local TLS certs (never commit private keys)\n${entry}/\n`;
106
+ await (0, promises_1.writeFile)(gitignorePath, newContent, 'utf-8');
107
+ }
108
+ /** Add NODE_EXTRA_CA_CERTS to .env */
109
+ async function ensureNodeExtraCA(cwd, caRootPem) {
110
+ const envPath = (0, path_1.join)(cwd, '.env');
111
+ let content = '';
112
+ try {
113
+ content = await (0, promises_1.readFile)(envPath, 'utf-8');
114
+ }
115
+ catch {
116
+ // File doesn't exist
117
+ }
118
+ if (content.includes('NODE_EXTRA_CA_CERTS'))
119
+ return;
120
+ const line = `\n# trustlocal — allow Node.js to trust the local CA\nNODE_EXTRA_CA_CERTS=${caRootPem}\n`;
121
+ await (0, promises_1.writeFile)(envPath, content + line, 'utf-8');
122
+ }
123
+ /** Run the appropriate injector for the detected framework. */
124
+ async function runInjector(framework, configFile, cwd, caRootPem) {
125
+ switch (framework) {
126
+ case 'nextjs': {
127
+ const configPath = (0, path_1.join)(cwd, configFile ?? 'next.config.js');
128
+ const result = await (0, nextjs_1.injectNextjs)(configPath);
129
+ if (result.alreadyConfigured) {
130
+ logger_1.logger.warn('HTTPS already configured in Next.js config — skipping injection.');
131
+ }
132
+ else {
133
+ logger_1.logger.success(`Config updated${result.created ? ' (new file created)' : ''}`);
134
+ }
135
+ break;
136
+ }
137
+ case 'vite': {
138
+ const configPath = (0, path_1.join)(cwd, configFile ?? 'vite.config.ts');
139
+ const result = await (0, vite_1.injectVite)(configPath);
140
+ if (result.alreadyConfigured) {
141
+ logger_1.logger.warn('HTTPS already configured in Vite config — skipping injection.');
142
+ }
143
+ else {
144
+ logger_1.logger.success(`Config updated${result.created ? ' (new file created)' : ''}`);
145
+ }
146
+ break;
147
+ }
148
+ case 'express': {
149
+ const envPath = (0, path_1.join)(cwd, '.env');
150
+ await (0, express_1.injectExpress)(envPath, caRootPem);
151
+ logger_1.logger.success('NODE_EXTRA_CA_CERTS set in .env');
152
+ (0, express_1.printExpressSnippet)(trustlocal_1.CERT_DIR);
153
+ break;
154
+ }
155
+ case 'nginx': {
156
+ const configPath = (0, path_1.join)(cwd, configFile ?? 'nginx.conf');
157
+ const result = await (0, nginx_1.injectNginx)(configPath);
158
+ if (result.alreadyConfigured) {
159
+ logger_1.logger.warn('HTTPS already configured in nginx.conf — skipping injection.');
160
+ }
161
+ else {
162
+ logger_1.logger.success('nginx.conf updated');
163
+ }
164
+ break;
165
+ }
166
+ case 'plain': {
167
+ (0, plain_1.printPlainInstructions)(trustlocal_1.CERT_DIR);
168
+ break;
169
+ }
170
+ }
171
+ }
172
+ async function runInit(options = {}) {
173
+ const cwd = process.cwd();
174
+ logger_1.logger.title('trustlocal init');
175
+ // ── 1. Node version check ─────────────────────────────────────────────────
176
+ const [major] = process.versions.node.split('.').map(Number);
177
+ if ((major ?? 0) < 18) {
178
+ logger_1.logger.error(`Node.js 18+ is required. You are running ${process.versions.node}.`);
179
+ process.exit(1);
180
+ }
181
+ // ── 2. Existing trustlocal.json ────────────────────────────────────────────
182
+ const existing = await (0, trustlocal_1.readConfig)(cwd);
183
+ if (existing && !options.force) {
184
+ logger_1.logger.warn('trustlocal.json already exists in this project.');
185
+ logger_1.logger.info('Run with --force to re-initialise, or use `npx trustlocal sync` instead.');
186
+ process.exit(0);
187
+ }
188
+ // ── 3. Check / install mkcert ──────────────────────────────────────────────
189
+ logger_1.logger.step('Checking mkcert...');
190
+ const mkcertInfo = (0, check_1.checkMkcert)();
191
+ if (!mkcertInfo.installed) {
192
+ logger_1.logger.warn('mkcert not found — attempting auto-install...');
193
+ (0, install_1.installMkcert)();
194
+ }
195
+ else {
196
+ logger_1.logger.success(`mkcert ${mkcertInfo.version ?? ''} found`);
197
+ }
198
+ // ── 4. mkcert -install (register local CA) ────────────────────────────────
199
+ logger_1.logger.step('Installing local CA (may prompt for sudo)...');
200
+ if (!options.dryRun) {
201
+ (0, generate_1.installCA)();
202
+ }
203
+ logger_1.logger.success('Local CA registered');
204
+ // ── 5. Detect framework ────────────────────────────────────────────────────
205
+ logger_1.logger.step('Detecting framework...');
206
+ let detection = await (0, framework_1.detectFramework)(cwd);
207
+ logger_1.logger.success(`Detected: ${(0, framework_1.frameworkDisplayName)(detection.framework)}${detection.configFile ? ` (${detection.configFile})` : ''}`);
208
+ // ── 6. Confirm / override ─────────────────────────────────────────────────
209
+ if (!options.dryRun) {
210
+ const answer = await prompt(`Use ${(0, framework_1.frameworkDisplayName)(detection.framework)}? [Y/n/override]`);
211
+ if (answer.toLowerCase() === 'n') {
212
+ logger_1.logger.info('Aborting. Run again to retry.');
213
+ process.exit(0);
214
+ }
215
+ const overrides = {
216
+ nextjs: 'nextjs', next: 'nextjs',
217
+ vite: 'vite',
218
+ express: 'express', node: 'express',
219
+ nginx: 'nginx',
220
+ plain: 'plain',
221
+ };
222
+ if (answer && answer.toLowerCase() !== 'y' && overrides[answer.toLowerCase()]) {
223
+ detection = { framework: overrides[answer.toLowerCase()] };
224
+ logger_1.logger.info(`Using ${(0, framework_1.frameworkDisplayName)(detection.framework)}`);
225
+ }
226
+ }
227
+ // ── 7. Collect domains ─────────────────────────────────────────────────────
228
+ const envDomains = await collectEnvDomains(cwd);
229
+ const extraDomains = options.domains ?? [];
230
+ const domains = ['localhost', '127.0.0.1', ...envDomains, ...extraDomains].filter((d, i, arr) => arr.indexOf(d) === i);
231
+ logger_1.logger.step(`Generating certificates for: ${domains.join(', ')}`);
232
+ // ── 8. Create .trustlocal/ and generate certs ─────────────────────────────
233
+ // .gitignore must be updated BEFORE writing cert files (per spec)
234
+ logger_1.logger.step('Updating .gitignore...');
235
+ if (!options.dryRun) {
236
+ await ensureGitignore(cwd, trustlocal_1.CERT_DIR);
237
+ }
238
+ logger_1.logger.success(`.trustlocal/ added to .gitignore`);
239
+ if (!options.dryRun) {
240
+ await (0, generate_1.generateCerts)(trustlocal_1.CERT_DIR, domains, cwd);
241
+ }
242
+ logger_1.logger.success(`Certificates generated → ${trustlocal_1.CERT_DIR}/`);
243
+ // ── 9. Inject HTTPS config ────────────────────────────────────────────────
244
+ logger_1.logger.step(`Injecting HTTPS config into ${detection.configFile ?? detection.framework}...`);
245
+ const caRootPem = mkcertInfo.caRoot
246
+ ? `${mkcertInfo.caRoot}/rootCA.pem`
247
+ : `${(0, check_2.getMkcertCARoot)()}/rootCA.pem`;
248
+ if (!options.dryRun) {
249
+ await runInjector(detection.framework, detection.configFile, cwd, caRootPem);
250
+ }
251
+ else {
252
+ logger_1.logger.success('Config updated (dry-run)');
253
+ }
254
+ // ── 10. NODE_EXTRA_CA_CERTS in .env ──────────────────────────────────────
255
+ logger_1.logger.step('Updating .env...');
256
+ if (!options.dryRun) {
257
+ await ensureNodeExtraCA(cwd, caRootPem);
258
+ }
259
+ logger_1.logger.success('NODE_EXTRA_CA_CERTS set');
260
+ // ── 12. Write trustlocal.json ─────────────────────────────────────────────
261
+ const config = (0, trustlocal_1.buildConfig)({
262
+ framework: detection.framework,
263
+ domains,
264
+ certDir: trustlocal_1.CERT_DIR,
265
+ configFiles: detection.configFile ? [detection.configFile] : [],
266
+ });
267
+ if (!options.dryRun) {
268
+ await (0, trustlocal_1.writeConfig)(cwd, config);
269
+ }
270
+ // ── 13. Success summary ────────────────────────────────────────────────────
271
+ const certPath = (0, path_1.join)(cwd, trustlocal_1.CERT_DIR, generate_1.CERT_FILENAME);
272
+ const expiry = await (async () => {
273
+ if (options.dryRun)
274
+ return new Date(Date.now() + 2 * 365 * 24 * 3600 * 1000);
275
+ try {
276
+ return (0, generate_1.getCertExpiry)(certPath);
277
+ }
278
+ catch {
279
+ return new Date(Date.now() + 2 * 365 * 24 * 3600 * 1000);
280
+ }
281
+ })();
282
+ logger_1.logger.blank();
283
+ logger_1.logger.success('Done! Open https://localhost:3000');
284
+ logger_1.logger.blank();
285
+ logger_1.logger.info('Teammates: run npx trustlocal sync to get HTTPS on their machines.');
286
+ logger_1.logger.info(`Cert expires: ${expiry.toISOString().split('T')[0]}`);
287
+ logger_1.logger.blank();
288
+ }
289
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `npx trustlocal renew`
3
+ *
4
+ * Execution flow (per spec §5.3):
5
+ * 1. Read trustlocal.json
6
+ * 2. Check cert expiry — warn if > 30 days remaining (require --force)
7
+ * 3. Delete old certs from .trustlocal/
8
+ * 4. Generate fresh certs
9
+ * 5. Print new expiry date
10
+ * (Config injection NOT repeated — cert file paths don't change)
11
+ */
12
+ export interface RenewOptions {
13
+ force?: boolean;
14
+ }
15
+ export declare function runRenew(options?: RenewOptions): Promise<void>;
16
+ //# sourceMappingURL=renew.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renew.d.ts","sourceRoot":"","sources":["../../src/commands/renew.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAID,wBAAsB,QAAQ,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0CxE"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ /**
3
+ * `npx trustlocal renew`
4
+ *
5
+ * Execution flow (per spec §5.3):
6
+ * 1. Read trustlocal.json
7
+ * 2. Check cert expiry — warn if > 30 days remaining (require --force)
8
+ * 3. Delete old certs from .trustlocal/
9
+ * 4. Generate fresh certs
10
+ * 5. Print new expiry date
11
+ * (Config injection NOT repeated — cert file paths don't change)
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.runRenew = runRenew;
15
+ const path_1 = require("path");
16
+ const logger_1 = require("../utils/logger");
17
+ const trustlocal_1 = require("../config/trustlocal");
18
+ const generate_1 = require("../mkcert/generate");
19
+ const DAYS_WARN_THRESHOLD = 30;
20
+ async function runRenew(options = {}) {
21
+ const cwd = process.cwd();
22
+ logger_1.logger.title('trustlocal renew');
23
+ // ── 1. Read trustlocal.json ───────────────────────────────────────────────
24
+ const config = await (0, trustlocal_1.readConfig)(cwd);
25
+ if (!config) {
26
+ logger_1.logger.error('trustlocal.json not found.');
27
+ logger_1.logger.info('Run `npx trustlocal init` first.');
28
+ process.exit(1);
29
+ }
30
+ // ── 2. Check cert expiry ──────────────────────────────────────────────────
31
+ const certPath = (0, path_1.join)(cwd, config.certDir, generate_1.CERT_FILENAME);
32
+ const expiry = (0, generate_1.getCertExpiry)(certPath);
33
+ const now = new Date();
34
+ const daysLeft = Math.floor((expiry.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
35
+ logger_1.logger.info(`Current cert expires: ${expiry.toISOString().split('T')[0]} (${daysLeft} days remaining)`);
36
+ if (daysLeft > DAYS_WARN_THRESHOLD && !options.force) {
37
+ logger_1.logger.warn(`Cert is still valid for ${daysLeft} days.`);
38
+ logger_1.logger.info('Use --force to renew anyway.');
39
+ process.exit(0);
40
+ }
41
+ // ── 3. Delete old certs ───────────────────────────────────────────────────
42
+ logger_1.logger.step('Removing old certificates...');
43
+ await (0, generate_1.deleteCerts)(config.certDir, cwd);
44
+ logger_1.logger.success('Old certificates removed');
45
+ // ── 4. Generate fresh certs ────────────────────────────────────────────────
46
+ logger_1.logger.step(`Generating new certificates for: ${config.domains.join(', ')}`);
47
+ await (0, generate_1.generateCerts)(config.certDir, config.domains, cwd);
48
+ const newExpiry = (0, generate_1.getCertExpiry)(certPath);
49
+ logger_1.logger.success(`Certificates renewed → ${config.certDir}/`);
50
+ logger_1.logger.blank();
51
+ logger_1.logger.success(`New cert expires: ${newExpiry.toISOString().split('T')[0]}`);
52
+ logger_1.logger.blank();
53
+ }
54
+ //# sourceMappingURL=renew.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renew.js","sourceRoot":"","sources":["../../src/commands/renew.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAcH,4BA0CC;AAtDD,+BAA4B;AAE5B,4CAAyC;AACzC,qDAAkD;AAClD,iDAA8F;AAM9F,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAExB,KAAK,UAAU,QAAQ,CAAC,UAAwB,EAAE;IACvD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAE1B,eAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAEjC,6EAA6E;IAC7E,MAAM,MAAM,GAAG,MAAM,IAAA,uBAAU,EAAC,GAAG,CAAC,CAAC;IACrC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,eAAM,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC3C,eAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,6EAA6E;IAC7E,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,GAAG,EAAE,MAAM,CAAC,OAAO,EAAE,wBAAa,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,IAAA,wBAAa,EAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IAExF,eAAM,CAAC,IAAI,CAAC,yBAAyB,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,kBAAkB,CAAC,CAAC;IAExG,IAAI,QAAQ,GAAG,mBAAmB,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACrD,eAAM,CAAC,IAAI,CAAC,2BAA2B,QAAQ,QAAQ,CAAC,CAAC;QACzD,eAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,6EAA6E;IAC7E,eAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAC5C,MAAM,IAAA,sBAAW,EAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACvC,eAAM,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;IAE3C,8EAA8E;IAC9E,eAAM,CAAC,IAAI,CAAC,oCAAoC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7E,MAAM,IAAA,wBAAa,EAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAEzD,MAAM,SAAS,GAAG,IAAA,wBAAa,EAAC,QAAQ,CAAC,CAAC;IAC1C,eAAM,CAAC,OAAO,CAAC,0BAA0B,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;IAE5D,eAAM,CAAC,KAAK,EAAE,CAAC;IACf,eAAM,CAAC,OAAO,CAAC,qBAAqB,SAAS,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC7E,eAAM,CAAC,KAAK,EAAE,CAAC;AACjB,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `npx trustlocal status`
3
+ *
4
+ * Execution flow (per spec §5.4):
5
+ * 1. Read trustlocal.json — show error if missing
6
+ * 2. Print: framework, domains, cert location, expiry, days until expiry
7
+ * 3. Check if config injection is still present in framework config file
8
+ * 4. Check if NODE_EXTRA_CA_CERTS is set in .env
9
+ * 5. Check if .trustlocal/ is in .gitignore
10
+ * 6. Print coloured status line for each check
11
+ */
12
+ export declare function runStatus(): Promise<void>;
13
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiDH,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAgF/C"}