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.
- package/LICENSE +21 -0
- package/README.md +129 -0
- package/dist/commands/init.d.ts +25 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +289 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/renew.d.ts +16 -0
- package/dist/commands/renew.d.ts.map +1 -0
- package/dist/commands/renew.js +54 -0
- package/dist/commands/renew.js.map +1 -0
- package/dist/commands/status.d.ts +13 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +140 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/sync.d.ts +13 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +111 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/config/trustlocal.d.ts +40 -0
- package/dist/config/trustlocal.d.ts.map +1 -0
- package/dist/config/trustlocal.js +54 -0
- package/dist/config/trustlocal.js.map +1 -0
- package/dist/detector/framework.d.ts +14 -0
- package/dist/detector/framework.d.ts.map +1 -0
- package/dist/detector/framework.js +89 -0
- package/dist/detector/framework.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -0
- package/dist/injectors/astHelper.d.ts +35 -0
- package/dist/injectors/astHelper.d.ts.map +1 -0
- package/dist/injectors/astHelper.js +192 -0
- package/dist/injectors/astHelper.js.map +1 -0
- package/dist/injectors/express.d.ts +22 -0
- package/dist/injectors/express.d.ts.map +1 -0
- package/dist/injectors/express.js +59 -0
- package/dist/injectors/express.js.map +1 -0
- package/dist/injectors/nextjs.d.ts +24 -0
- package/dist/injectors/nextjs.d.ts.map +1 -0
- package/dist/injectors/nextjs.js +116 -0
- package/dist/injectors/nextjs.js.map +1 -0
- package/dist/injectors/nginx.d.ts +23 -0
- package/dist/injectors/nginx.d.ts.map +1 -0
- package/dist/injectors/nginx.js +61 -0
- package/dist/injectors/nginx.js.map +1 -0
- package/dist/injectors/plain.d.ts +12 -0
- package/dist/injectors/plain.d.ts.map +1 -0
- package/dist/injectors/plain.js +36 -0
- package/dist/injectors/plain.js.map +1 -0
- package/dist/injectors/vite.d.ts +24 -0
- package/dist/injectors/vite.d.ts.map +1 -0
- package/dist/injectors/vite.js +125 -0
- package/dist/injectors/vite.js.map +1 -0
- package/dist/mkcert/check.d.ts +13 -0
- package/dist/mkcert/check.d.ts.map +1 -0
- package/dist/mkcert/check.js +38 -0
- package/dist/mkcert/check.js.map +1 -0
- package/dist/mkcert/generate.d.ts +26 -0
- package/dist/mkcert/generate.d.ts.map +1 -0
- package/dist/mkcert/generate.js +111 -0
- package/dist/mkcert/generate.js.map +1 -0
- package/dist/mkcert/install.d.ts +7 -0
- package/dist/mkcert/install.d.ts.map +1 -0
- package/dist/mkcert/install.js +75 -0
- package/dist/mkcert/install.js.map +1 -0
- package/dist/utils/backup.d.ts +7 -0
- package/dist/utils/backup.d.ts.map +1 -0
- package/dist/utils/backup.js +16 -0
- package/dist/utils/backup.js.map +1 -0
- package/dist/utils/logger.d.ts +17 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +38 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/os.d.ts +4 -0
- package/dist/utils/os.d.ts.map +1 -0
- package/dist/utils/os.js +24 -0
- package/dist/utils/os.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Lightweight AST helpers for reading JavaScript/TypeScript config files.
|
|
4
|
+
*
|
|
5
|
+
* Uses @babel/parser for parsing only — no @babel/generator dependency.
|
|
6
|
+
* Injection is done by precise string-slice insertion at AST-located positions,
|
|
7
|
+
* which preserves the original file's formatting.
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
+
var ownKeys = function(o) {
|
|
27
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
+
var ar = [];
|
|
29
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
+
return ar;
|
|
31
|
+
};
|
|
32
|
+
return ownKeys(o);
|
|
33
|
+
};
|
|
34
|
+
return function (mod) {
|
|
35
|
+
if (mod && mod.__esModule) return mod;
|
|
36
|
+
var result = {};
|
|
37
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
+
__setModuleDefault(result, mod);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.findNodes = findNodes;
|
|
44
|
+
exports.parseSource = parseSource;
|
|
45
|
+
exports.hasProperty = hasProperty;
|
|
46
|
+
exports.getObjectOpenBraceEnd = getObjectOpenBraceEnd;
|
|
47
|
+
exports.findTopLevelConfigObject = findTopLevelConfigObject;
|
|
48
|
+
exports.hasNestedProperty = hasNestedProperty;
|
|
49
|
+
const parser = __importStar(require("@babel/parser"));
|
|
50
|
+
function isNode(val) {
|
|
51
|
+
return typeof val === 'object' && val !== null && 'type' in val;
|
|
52
|
+
}
|
|
53
|
+
/** Shallow walk of direct children of a node. */
|
|
54
|
+
function childNodes(node) {
|
|
55
|
+
const children = [];
|
|
56
|
+
const record = node;
|
|
57
|
+
for (const key of Object.keys(record)) {
|
|
58
|
+
const val = record[key];
|
|
59
|
+
if (Array.isArray(val)) {
|
|
60
|
+
for (const item of val) {
|
|
61
|
+
if (isNode(item))
|
|
62
|
+
children.push(item);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else if (isNode(val)) {
|
|
66
|
+
children.push(val);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return children;
|
|
70
|
+
}
|
|
71
|
+
/** Deep-first search for nodes matching a predicate. */
|
|
72
|
+
function findNodes(root, predicate) {
|
|
73
|
+
const results = [];
|
|
74
|
+
const stack = [root];
|
|
75
|
+
while (stack.length) {
|
|
76
|
+
const node = stack.pop();
|
|
77
|
+
if (predicate(node))
|
|
78
|
+
results.push(node);
|
|
79
|
+
stack.push(...childNodes(node));
|
|
80
|
+
}
|
|
81
|
+
return results;
|
|
82
|
+
}
|
|
83
|
+
/** Parse a JS/TS source string into a Babel AST. */
|
|
84
|
+
function parseSource(source) {
|
|
85
|
+
return parser.parse(source, {
|
|
86
|
+
sourceType: 'module',
|
|
87
|
+
plugins: [
|
|
88
|
+
'typescript',
|
|
89
|
+
'jsx',
|
|
90
|
+
['decorators', { decoratorsBeforeExport: true }],
|
|
91
|
+
'classProperties',
|
|
92
|
+
],
|
|
93
|
+
errorRecovery: true,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/** Check if an ObjectExpression already has a direct property with the given key. */
|
|
97
|
+
function hasProperty(obj, key) {
|
|
98
|
+
return obj.properties.some((p) => p.type === 'ObjectProperty' &&
|
|
99
|
+
((p.key.type === 'Identifier' && p.key.name === key) ||
|
|
100
|
+
(p.key.type === 'StringLiteral' && p.key.value === key)));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get the character position immediately after the opening `{` of an
|
|
104
|
+
* ObjectExpression so we can insert properties at the top.
|
|
105
|
+
*/
|
|
106
|
+
function getObjectOpenBraceEnd(obj, source) {
|
|
107
|
+
if (obj.start === null || obj.start === undefined)
|
|
108
|
+
return -1;
|
|
109
|
+
// The opening `{` is always the first character of an ObjectExpression
|
|
110
|
+
const brace = source.indexOf('{', obj.start);
|
|
111
|
+
return brace + 1;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Find the top-level exported config ObjectExpression.
|
|
115
|
+
*
|
|
116
|
+
* Handles:
|
|
117
|
+
* - `export default { ... }`
|
|
118
|
+
* - `export default defineConfig({ ... })`
|
|
119
|
+
* - `module.exports = { ... }`
|
|
120
|
+
* - `const config = { ... }` (last top-level ObjectExpression as fallback)
|
|
121
|
+
*/
|
|
122
|
+
function findTopLevelConfigObject(ast) {
|
|
123
|
+
for (const node of ast.program.body) {
|
|
124
|
+
// export default { ... }
|
|
125
|
+
if (node.type === 'ExportDefaultDeclaration') {
|
|
126
|
+
const decl = node.declaration;
|
|
127
|
+
if (decl.type === 'ObjectExpression')
|
|
128
|
+
return decl;
|
|
129
|
+
// export default defineConfig({ ... }) — first arg is the config
|
|
130
|
+
if (decl.type === 'CallExpression') {
|
|
131
|
+
const call = decl;
|
|
132
|
+
const firstArg = call.arguments[0];
|
|
133
|
+
if (firstArg?.type === 'ObjectExpression')
|
|
134
|
+
return firstArg;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// module.exports = { ... } OR module.exports = defineConfig({ ... })
|
|
138
|
+
if (node.type === 'ExpressionStatement') {
|
|
139
|
+
const expr = node.expression;
|
|
140
|
+
if (expr.type === 'AssignmentExpression') {
|
|
141
|
+
const assign = expr;
|
|
142
|
+
const isModuleExports = assign.left.type === 'MemberExpression' &&
|
|
143
|
+
assign.left.object.type === 'Identifier' &&
|
|
144
|
+
assign.left.object.name === 'module' &&
|
|
145
|
+
assign.left.property.type === 'Identifier' &&
|
|
146
|
+
assign.left.property.name === 'exports';
|
|
147
|
+
if (isModuleExports) {
|
|
148
|
+
if (assign.right.type === 'ObjectExpression') {
|
|
149
|
+
return assign.right;
|
|
150
|
+
}
|
|
151
|
+
// module.exports = someFunc({ ... })
|
|
152
|
+
if (assign.right.type === 'CallExpression') {
|
|
153
|
+
const call = assign.right;
|
|
154
|
+
const firstArg = call.arguments[0];
|
|
155
|
+
if (firstArg?.type === 'ObjectExpression')
|
|
156
|
+
return firstArg;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// const nextConfig = { ... } / const config: NextConfig = { ... }
|
|
162
|
+
if (node.type === 'VariableDeclaration') {
|
|
163
|
+
for (const decl of node.declarations) {
|
|
164
|
+
if (decl.init?.type === 'ObjectExpression') {
|
|
165
|
+
return decl.init;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Check whether a nested path like `server.https` already exists inside an
|
|
174
|
+
* ObjectExpression. `path` is given as an array of key names.
|
|
175
|
+
*/
|
|
176
|
+
function hasNestedProperty(obj, path) {
|
|
177
|
+
if (path.length === 0)
|
|
178
|
+
return true;
|
|
179
|
+
const [head, ...tail] = path;
|
|
180
|
+
const prop = obj.properties.find((p) => p.type === 'ObjectProperty' &&
|
|
181
|
+
((p.key.type === 'Identifier' && p.key.name === head) ||
|
|
182
|
+
(p.key.type === 'StringLiteral' && p.key.value === head)));
|
|
183
|
+
if (!prop)
|
|
184
|
+
return false;
|
|
185
|
+
if (tail.length === 0)
|
|
186
|
+
return true;
|
|
187
|
+
if (prop.value.type === 'ObjectExpression') {
|
|
188
|
+
return hasNestedProperty(prop.value, tail);
|
|
189
|
+
}
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=astHelper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"astHelper.js","sourceRoot":"","sources":["../../src/injectors/astHelper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Express / Node injector
|
|
3
|
+
*
|
|
4
|
+
* Does NOT modify server.js — too risky, too variable.
|
|
5
|
+
* Instead:
|
|
6
|
+
* 1. Sets NODE_EXTRA_CA_CERTS in .env (pointing to mkcert's rootCA.pem)
|
|
7
|
+
* 2. Prints a code snippet showing how to add HTTPS to the server
|
|
8
|
+
*/
|
|
9
|
+
export declare const ENV_KEY = "NODE_EXTRA_CA_CERTS";
|
|
10
|
+
export declare const INJECTION_MARKER = "# trustlocal:NODE_EXTRA_CA_CERTS";
|
|
11
|
+
/**
|
|
12
|
+
* Ensure NODE_EXTRA_CA_CERTS is present in the .env file.
|
|
13
|
+
* Creates the file if it doesn't exist.
|
|
14
|
+
* Idempotent.
|
|
15
|
+
*
|
|
16
|
+
* @param envPath Absolute path to the .env file
|
|
17
|
+
* @param caRootPem Absolute path to the mkcert rootCA.pem (from `mkcert -CAROOT`)
|
|
18
|
+
*/
|
|
19
|
+
export declare function injectExpress(envPath: string, caRootPem: string): Promise<boolean>;
|
|
20
|
+
/** Print the manual HTTPS server snippet to the terminal. */
|
|
21
|
+
export declare function printExpressSnippet(certDir: string): void;
|
|
22
|
+
//# sourceMappingURL=express.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/injectors/express.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,eAAO,MAAM,OAAO,wBAAwB,CAAC;AAC7C,eAAO,MAAM,gBAAgB,qCAAqC,CAAC;AAEnE;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAmBxF;AAED,6DAA6D;AAC7D,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAczD"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Express / Node injector
|
|
4
|
+
*
|
|
5
|
+
* Does NOT modify server.js — too risky, too variable.
|
|
6
|
+
* Instead:
|
|
7
|
+
* 1. Sets NODE_EXTRA_CA_CERTS in .env (pointing to mkcert's rootCA.pem)
|
|
8
|
+
* 2. Prints a code snippet showing how to add HTTPS to the server
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.INJECTION_MARKER = exports.ENV_KEY = void 0;
|
|
12
|
+
exports.injectExpress = injectExpress;
|
|
13
|
+
exports.printExpressSnippet = printExpressSnippet;
|
|
14
|
+
const promises_1 = require("fs/promises");
|
|
15
|
+
const logger_1 = require("../utils/logger");
|
|
16
|
+
exports.ENV_KEY = 'NODE_EXTRA_CA_CERTS';
|
|
17
|
+
exports.INJECTION_MARKER = '# trustlocal:NODE_EXTRA_CA_CERTS';
|
|
18
|
+
/**
|
|
19
|
+
* Ensure NODE_EXTRA_CA_CERTS is present in the .env file.
|
|
20
|
+
* Creates the file if it doesn't exist.
|
|
21
|
+
* Idempotent.
|
|
22
|
+
*
|
|
23
|
+
* @param envPath Absolute path to the .env file
|
|
24
|
+
* @param caRootPem Absolute path to the mkcert rootCA.pem (from `mkcert -CAROOT`)
|
|
25
|
+
*/
|
|
26
|
+
async function injectExpress(envPath, caRootPem) {
|
|
27
|
+
let content = '';
|
|
28
|
+
try {
|
|
29
|
+
content = await (0, promises_1.readFile)(envPath, 'utf-8');
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// .env doesn't exist — we'll create it
|
|
33
|
+
}
|
|
34
|
+
// Idempotency check
|
|
35
|
+
if (content.includes(exports.INJECTION_MARKER) || content.includes(`${exports.ENV_KEY}=`)) {
|
|
36
|
+
return false; // already configured
|
|
37
|
+
}
|
|
38
|
+
const line = `${exports.INJECTION_MARKER}\n${exports.ENV_KEY}=${caRootPem}\n`;
|
|
39
|
+
const newContent = content ? `${content.trimEnd()}\n\n${line}` : line;
|
|
40
|
+
await (0, promises_1.writeFile)(envPath, newContent, 'utf-8');
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
/** Print the manual HTTPS server snippet to the terminal. */
|
|
44
|
+
function printExpressSnippet(certDir) {
|
|
45
|
+
logger_1.logger.blank();
|
|
46
|
+
logger_1.logger.info('Add HTTPS to your Express/Node server:');
|
|
47
|
+
logger_1.logger.blank();
|
|
48
|
+
logger_1.logger.info(" const https = require('https');");
|
|
49
|
+
logger_1.logger.info(" const fs = require('fs');");
|
|
50
|
+
logger_1.logger.info('');
|
|
51
|
+
logger_1.logger.info(' const server = https.createServer({');
|
|
52
|
+
logger_1.logger.info(` key: fs.readFileSync('${certDir}/localhost-key.pem'),`);
|
|
53
|
+
logger_1.logger.info(` cert: fs.readFileSync('${certDir}/localhost.pem'),`);
|
|
54
|
+
logger_1.logger.info(' }, app);');
|
|
55
|
+
logger_1.logger.info('');
|
|
56
|
+
logger_1.logger.info(' server.listen(443);');
|
|
57
|
+
logger_1.logger.blank();
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=express.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/injectors/express.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAgBH,sCAmBC;AAGD,kDAcC;AAlDD,0CAAkD;AAClD,4CAAyC;AAE5B,QAAA,OAAO,GAAG,qBAAqB,CAAC;AAChC,QAAA,gBAAgB,GAAG,kCAAkC,CAAC;AAEnE;;;;;;;GAOG;AACI,KAAK,UAAU,aAAa,CAAC,OAAe,EAAE,SAAiB;IACpE,IAAI,OAAO,GAAG,EAAE,CAAC;IAEjB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,uCAAuC;IACzC,CAAC;IAED,oBAAoB;IACpB,IAAI,OAAO,CAAC,QAAQ,CAAC,wBAAgB,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,eAAO,GAAG,CAAC,EAAE,CAAC;QAC1E,OAAO,KAAK,CAAC,CAAC,qBAAqB;IACrC,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,wBAAgB,KAAK,eAAO,IAAI,SAAS,IAAI,CAAC;IAC9D,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAEtE,MAAM,IAAA,oBAAS,EAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6DAA6D;AAC7D,SAAgB,mBAAmB,CAAC,OAAe;IACjD,eAAM,CAAC,KAAK,EAAE,CAAC;IACf,eAAM,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IACtD,eAAM,CAAC,KAAK,EAAE,CAAC;IACf,eAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IACjD,eAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IAC9C,eAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChB,eAAM,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IACrD,eAAM,CAAC,IAAI,CAAC,8BAA8B,OAAO,uBAAuB,CAAC,CAAC;IAC1E,eAAM,CAAC,IAAI,CAAC,8BAA8B,OAAO,mBAAmB,CAAC,CAAC;IACtE,eAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1B,eAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChB,eAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACrC,eAAM,CAAC,KAAK,EAAE,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js injector
|
|
3
|
+
*
|
|
4
|
+
* Adds `experimental.https` to next.config.js / next.config.ts using AST-based
|
|
5
|
+
* insertion. Never uses string concatenation on existing files.
|
|
6
|
+
*/
|
|
7
|
+
export declare const INJECTION_MARKER = "// trustlocal:https";
|
|
8
|
+
export interface InjectResult {
|
|
9
|
+
alreadyConfigured: boolean;
|
|
10
|
+
created: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Inject HTTPS config into a Next.js config file.
|
|
14
|
+
* Creates the file if it doesn't exist.
|
|
15
|
+
* Idempotent — safe to call multiple times.
|
|
16
|
+
*/
|
|
17
|
+
export declare function injectNextjs(configPath: string): Promise<InjectResult>;
|
|
18
|
+
/**
|
|
19
|
+
* Pure function: insert the HTTPS block into source code.
|
|
20
|
+
* Uses the AST to locate the config object opening brace,
|
|
21
|
+
* then does a string-slice insertion at that position.
|
|
22
|
+
*/
|
|
23
|
+
export declare function injectIntoSource(source: string): string | null;
|
|
24
|
+
//# sourceMappingURL=nextjs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../../src/injectors/nextjs.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,eAAO,MAAM,gBAAgB,wBAAwB,CAAC;AA+BtD,MAAM,WAAW,YAAY;IAC3B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAyC5E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmB9D"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Next.js injector
|
|
4
|
+
*
|
|
5
|
+
* Adds `experimental.https` to next.config.js / next.config.ts using AST-based
|
|
6
|
+
* insertion. Never uses string concatenation on existing files.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.INJECTION_MARKER = void 0;
|
|
10
|
+
exports.injectNextjs = injectNextjs;
|
|
11
|
+
exports.injectIntoSource = injectIntoSource;
|
|
12
|
+
const promises_1 = require("fs/promises");
|
|
13
|
+
const backup_1 = require("../utils/backup");
|
|
14
|
+
const astHelper_1 = require("./astHelper");
|
|
15
|
+
exports.INJECTION_MARKER = '// trustlocal:https';
|
|
16
|
+
const CERT_DIR = '.trustlocal';
|
|
17
|
+
function buildHttpsBlock(indent) {
|
|
18
|
+
return `
|
|
19
|
+
${indent}${exports.INJECTION_MARKER}
|
|
20
|
+
${indent}experimental: {
|
|
21
|
+
${indent} https: {
|
|
22
|
+
${indent} key: '${CERT_DIR}/localhost-key.pem',
|
|
23
|
+
${indent} cert: '${CERT_DIR}/localhost.pem',
|
|
24
|
+
${indent} },
|
|
25
|
+
${indent}},`;
|
|
26
|
+
}
|
|
27
|
+
function buildNewConfigFile() {
|
|
28
|
+
return `${exports.INJECTION_MARKER}
|
|
29
|
+
/** @type {import('next').NextConfig} */
|
|
30
|
+
const nextConfig = {
|
|
31
|
+
experimental: {
|
|
32
|
+
https: {
|
|
33
|
+
key: '${CERT_DIR}/localhost-key.pem',
|
|
34
|
+
cert: '${CERT_DIR}/localhost.pem',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
module.exports = nextConfig;
|
|
40
|
+
`;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Inject HTTPS config into a Next.js config file.
|
|
44
|
+
* Creates the file if it doesn't exist.
|
|
45
|
+
* Idempotent — safe to call multiple times.
|
|
46
|
+
*/
|
|
47
|
+
async function injectNextjs(configPath) {
|
|
48
|
+
let content;
|
|
49
|
+
// ── File does not exist → create it ──────────────────────────────────────
|
|
50
|
+
try {
|
|
51
|
+
content = await (0, promises_1.readFile)(configPath, 'utf-8');
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
await (0, promises_1.writeFile)(configPath, buildNewConfigFile(), 'utf-8');
|
|
55
|
+
return { alreadyConfigured: false, created: true };
|
|
56
|
+
}
|
|
57
|
+
// ── Already injected (idempotency check) ──────────────────────────────────
|
|
58
|
+
if (content.includes(exports.INJECTION_MARKER)) {
|
|
59
|
+
return { alreadyConfigured: true, created: false };
|
|
60
|
+
}
|
|
61
|
+
// Additional AST-based check: look for experimental.https already present
|
|
62
|
+
try {
|
|
63
|
+
const ast = (0, astHelper_1.parseSource)(content);
|
|
64
|
+
const configObj = (0, astHelper_1.findTopLevelConfigObject)(ast);
|
|
65
|
+
if (configObj && (0, astHelper_1.hasNestedProperty)(configObj, ['experimental', 'https'])) {
|
|
66
|
+
return { alreadyConfigured: true, created: false };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// If parse fails, proceed cautiously — the regex below will still guard us
|
|
71
|
+
}
|
|
72
|
+
// ── Back up before mutating ───────────────────────────────────────────────
|
|
73
|
+
await (0, backup_1.backupFile)(configPath);
|
|
74
|
+
// ── AST-based injection ───────────────────────────────────────────────────
|
|
75
|
+
const injected = injectIntoSource(content);
|
|
76
|
+
if (!injected) {
|
|
77
|
+
throw new Error(`trustlocal could not locate the config object in ${configPath}.\n` +
|
|
78
|
+
'Please add the experimental.https block manually.');
|
|
79
|
+
}
|
|
80
|
+
await (0, promises_1.writeFile)(configPath, injected, 'utf-8');
|
|
81
|
+
return { alreadyConfigured: false, created: false };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Pure function: insert the HTTPS block into source code.
|
|
85
|
+
* Uses the AST to locate the config object opening brace,
|
|
86
|
+
* then does a string-slice insertion at that position.
|
|
87
|
+
*/
|
|
88
|
+
function injectIntoSource(source) {
|
|
89
|
+
let ast;
|
|
90
|
+
try {
|
|
91
|
+
ast = (0, astHelper_1.parseSource)(source);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
const configObj = (0, astHelper_1.findTopLevelConfigObject)(ast);
|
|
97
|
+
if (!configObj)
|
|
98
|
+
return null;
|
|
99
|
+
const insertPos = (0, astHelper_1.getObjectOpenBraceEnd)(configObj, source);
|
|
100
|
+
if (insertPos < 0)
|
|
101
|
+
return null;
|
|
102
|
+
// Detect indentation: look at the first existing property
|
|
103
|
+
const indent = detectIndent(source, configObj);
|
|
104
|
+
const block = buildHttpsBlock(indent);
|
|
105
|
+
return source.slice(0, insertPos) + block + source.slice(insertPos);
|
|
106
|
+
}
|
|
107
|
+
function detectIndent(source, configObj) {
|
|
108
|
+
// Find the line after the opening brace and measure its leading whitespace
|
|
109
|
+
if (configObj.start === null || configObj.start === undefined)
|
|
110
|
+
return ' ';
|
|
111
|
+
const bracePos = source.indexOf('{', configObj.start);
|
|
112
|
+
const afterBrace = source.slice(bracePos + 1);
|
|
113
|
+
const nextLineMatch = /\n(\s+)/.exec(afterBrace);
|
|
114
|
+
return nextLineMatch?.[1] ?? ' ';
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=nextjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs.js","sourceRoot":"","sources":["../../src/injectors/nextjs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nginx injector
|
|
3
|
+
*
|
|
4
|
+
* Injects ssl_certificate / ssl_certificate_key directives into the
|
|
5
|
+
* server { } block of nginx.conf and adds `listen 443 ssl` if not present.
|
|
6
|
+
* Always backs up the file before mutating.
|
|
7
|
+
* Idempotent — checks for the injection marker before writing.
|
|
8
|
+
*/
|
|
9
|
+
export declare const INJECTION_MARKER = "# trustlocal:https";
|
|
10
|
+
export interface InjectResult {
|
|
11
|
+
alreadyConfigured: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Inject SSL directives into nginx.conf.
|
|
15
|
+
* Idempotent — safe to call multiple times.
|
|
16
|
+
*/
|
|
17
|
+
export declare function injectNginx(configPath: string): Promise<InjectResult>;
|
|
18
|
+
/**
|
|
19
|
+
* Pure function: inject SSL block into nginx.conf source.
|
|
20
|
+
* Finds the first `server {` block and inserts directives after its opening brace.
|
|
21
|
+
*/
|
|
22
|
+
export declare function injectIntoSource(source: string): string | null;
|
|
23
|
+
//# sourceMappingURL=nginx.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nginx.d.ts","sourceRoot":"","sources":["../../src/injectors/nginx.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,eAAO,MAAM,gBAAgB,uBAAuB,CAAC;AAarD,MAAM,WAAW,YAAY;IAC3B,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAoB3E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe9D"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Nginx injector
|
|
4
|
+
*
|
|
5
|
+
* Injects ssl_certificate / ssl_certificate_key directives into the
|
|
6
|
+
* server { } block of nginx.conf and adds `listen 443 ssl` if not present.
|
|
7
|
+
* Always backs up the file before mutating.
|
|
8
|
+
* Idempotent — checks for the injection marker before writing.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.INJECTION_MARKER = void 0;
|
|
12
|
+
exports.injectNginx = injectNginx;
|
|
13
|
+
exports.injectIntoSource = injectIntoSource;
|
|
14
|
+
const promises_1 = require("fs/promises");
|
|
15
|
+
const backup_1 = require("../utils/backup");
|
|
16
|
+
exports.INJECTION_MARKER = '# trustlocal:https';
|
|
17
|
+
const CERT_DIR = '.trustlocal';
|
|
18
|
+
function buildSslBlock(indent) {
|
|
19
|
+
return (`\n${indent}${exports.INJECTION_MARKER}\n` +
|
|
20
|
+
`${indent}listen 443 ssl;\n` +
|
|
21
|
+
`${indent}ssl_certificate ${CERT_DIR}/localhost.pem;\n` +
|
|
22
|
+
`${indent}ssl_certificate_key ${CERT_DIR}/localhost-key.pem;\n`);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Inject SSL directives into nginx.conf.
|
|
26
|
+
* Idempotent — safe to call multiple times.
|
|
27
|
+
*/
|
|
28
|
+
async function injectNginx(configPath) {
|
|
29
|
+
const content = await (0, promises_1.readFile)(configPath, 'utf-8');
|
|
30
|
+
// Idempotency check
|
|
31
|
+
if (content.includes(exports.INJECTION_MARKER)) {
|
|
32
|
+
return { alreadyConfigured: true };
|
|
33
|
+
}
|
|
34
|
+
await (0, backup_1.backupFile)(configPath);
|
|
35
|
+
const injected = injectIntoSource(content);
|
|
36
|
+
if (!injected) {
|
|
37
|
+
throw new Error(`trustlocal could not locate a server { } block in nginx.conf.\n` +
|
|
38
|
+
'Please add the ssl_certificate directives manually.');
|
|
39
|
+
}
|
|
40
|
+
await (0, promises_1.writeFile)(configPath, injected, 'utf-8');
|
|
41
|
+
return { alreadyConfigured: false };
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Pure function: inject SSL block into nginx.conf source.
|
|
45
|
+
* Finds the first `server {` block and inserts directives after its opening brace.
|
|
46
|
+
*/
|
|
47
|
+
function injectIntoSource(source) {
|
|
48
|
+
// Match `server {` with optional whitespace
|
|
49
|
+
const serverBlockMatch = /(\bserver\s*\{)/.exec(source);
|
|
50
|
+
if (!serverBlockMatch || serverBlockMatch.index === undefined)
|
|
51
|
+
return null;
|
|
52
|
+
// Position after the `{`
|
|
53
|
+
const insertPos = serverBlockMatch.index + serverBlockMatch[0].length;
|
|
54
|
+
// Detect indentation by looking at existing directives inside the server block
|
|
55
|
+
const afterBrace = source.slice(insertPos);
|
|
56
|
+
const indentMatch = /\n(\s+)/.exec(afterBrace);
|
|
57
|
+
const indent = indentMatch?.[1] ?? ' ';
|
|
58
|
+
const block = buildSslBlock(indent);
|
|
59
|
+
return source.slice(0, insertPos) + block + source.slice(insertPos);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=nginx.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nginx.js","sourceRoot":"","sources":["../../src/injectors/nginx.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AA0BH,kCAoBC;AAMD,4CAeC;AAjED,0CAAkD;AAClD,4CAA6C;AAEhC,QAAA,gBAAgB,GAAG,oBAAoB,CAAC;AAErD,MAAM,QAAQ,GAAG,aAAa,CAAC;AAE/B,SAAS,aAAa,CAAC,MAAc;IACnC,OAAO,CACL,KAAK,MAAM,GAAG,wBAAgB,IAAI;QAClC,GAAG,MAAM,mBAAmB;QAC5B,GAAG,MAAM,uBAAuB,QAAQ,mBAAmB;QAC3D,GAAG,MAAM,uBAAuB,QAAQ,uBAAuB,CAChE,CAAC;AACJ,CAAC;AAMD;;;GAGG;AACI,KAAK,UAAU,WAAW,CAAC,UAAkB;IAClD,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAEpD,oBAAoB;IACpB,IAAI,OAAO,CAAC,QAAQ,CAAC,wBAAgB,CAAC,EAAE,CAAC;QACvC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC;IACrC,CAAC;IAED,MAAM,IAAA,mBAAU,EAAC,UAAU,CAAC,CAAC;IAE7B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC3C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,iEAAiE;YAC/D,qDAAqD,CACxD,CAAC;IACJ,CAAC;IAED,MAAM,IAAA,oBAAS,EAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC/C,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,MAAc;IAC7C,4CAA4C;IAC5C,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxD,IAAI,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAE3E,yBAAyB;IACzB,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAEtE,+EAA+E;IAC/E,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC3C,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;IAE1C,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain fallback injector
|
|
3
|
+
*
|
|
4
|
+
* When no supported framework is detected:
|
|
5
|
+
* - Places certs in .trustlocal/
|
|
6
|
+
* - Prints cert paths and a short manual-wiring guide
|
|
7
|
+
* - Still writes trustlocal.json so teammates can run `sync`
|
|
8
|
+
*/
|
|
9
|
+
export declare const CERT_DIR = ".trustlocal";
|
|
10
|
+
/** Print usage instructions for the plain fallback. */
|
|
11
|
+
export declare function printPlainInstructions(certDir?: string): void;
|
|
12
|
+
//# sourceMappingURL=plain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plain.d.ts","sourceRoot":"","sources":["../../src/injectors/plain.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,eAAO,MAAM,QAAQ,gBAAgB,CAAC;AAEtC,uDAAuD;AACvD,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,MAAiB,GAAG,IAAI,CAmBvE"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Plain fallback injector
|
|
4
|
+
*
|
|
5
|
+
* When no supported framework is detected:
|
|
6
|
+
* - Places certs in .trustlocal/
|
|
7
|
+
* - Prints cert paths and a short manual-wiring guide
|
|
8
|
+
* - Still writes trustlocal.json so teammates can run `sync`
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.CERT_DIR = void 0;
|
|
12
|
+
exports.printPlainInstructions = printPlainInstructions;
|
|
13
|
+
const logger_1 = require("../utils/logger");
|
|
14
|
+
exports.CERT_DIR = '.trustlocal';
|
|
15
|
+
/** Print usage instructions for the plain fallback. */
|
|
16
|
+
function printPlainInstructions(certDir = exports.CERT_DIR) {
|
|
17
|
+
logger_1.logger.blank();
|
|
18
|
+
logger_1.logger.info('Certificates have been placed in:');
|
|
19
|
+
logger_1.logger.info(` ${certDir}/localhost.pem — certificate`);
|
|
20
|
+
logger_1.logger.info(` ${certDir}/localhost-key.pem — private key`);
|
|
21
|
+
logger_1.logger.blank();
|
|
22
|
+
logger_1.logger.info('Wire them into your server manually. Example (Node https module):');
|
|
23
|
+
logger_1.logger.blank();
|
|
24
|
+
logger_1.logger.info(" const https = require('https');");
|
|
25
|
+
logger_1.logger.info(" const fs = require('fs');");
|
|
26
|
+
logger_1.logger.info('');
|
|
27
|
+
logger_1.logger.info(' https.createServer({');
|
|
28
|
+
logger_1.logger.info(` key: fs.readFileSync('${certDir}/localhost-key.pem'),`);
|
|
29
|
+
logger_1.logger.info(` cert: fs.readFileSync('${certDir}/localhost.pem'),`);
|
|
30
|
+
logger_1.logger.info(' }, app).listen(443);');
|
|
31
|
+
logger_1.logger.blank();
|
|
32
|
+
logger_1.logger.info('For NODE_EXTRA_CA_CERTS add this to your .env:');
|
|
33
|
+
logger_1.logger.info(' NODE_EXTRA_CA_CERTS=<output of: mkcert -CAROOT>/rootCA.pem');
|
|
34
|
+
logger_1.logger.blank();
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=plain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plain.js","sourceRoot":"","sources":["../../src/injectors/plain.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAOH,wDAmBC;AAxBD,4CAAyC;AAE5B,QAAA,QAAQ,GAAG,aAAa,CAAC;AAEtC,uDAAuD;AACvD,SAAgB,sBAAsB,CAAC,UAAkB,gBAAQ;IAC/D,eAAM,CAAC,KAAK,EAAE,CAAC;IACf,eAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IACjD,eAAM,CAAC,IAAI,CAAC,KAAK,OAAO,oCAAoC,CAAC,CAAC;IAC9D,eAAM,CAAC,IAAI,CAAC,KAAK,OAAO,oCAAoC,CAAC,CAAC;IAC9D,eAAM,CAAC,KAAK,EAAE,CAAC;IACf,eAAM,CAAC,IAAI,CAAC,mEAAmE,CAAC,CAAC;IACjF,eAAM,CAAC,KAAK,EAAE,CAAC;IACf,eAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IACjD,eAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IAC9C,eAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChB,eAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACtC,eAAM,CAAC,IAAI,CAAC,8BAA8B,OAAO,uBAAuB,CAAC,CAAC;IAC1E,eAAM,CAAC,IAAI,CAAC,8BAA8B,OAAO,mBAAmB,CAAC,CAAC;IACtE,eAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACtC,eAAM,CAAC,KAAK,EAAE,CAAC;IACf,eAAM,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;IAC9D,eAAM,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;IAC5E,eAAM,CAAC,KAAK,EAAE,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite injector
|
|
3
|
+
*
|
|
4
|
+
* Adds `server.https` to vite.config.js / vite.config.ts using AST-based
|
|
5
|
+
* insertion. Uses fs.readFileSync in the injected code since Vite's
|
|
6
|
+
* server.https accepts https.ServerOptions (requires Buffer/string content,
|
|
7
|
+
* not file paths).
|
|
8
|
+
*/
|
|
9
|
+
export declare const INJECTION_MARKER = "// trustlocal:https";
|
|
10
|
+
export interface InjectResult {
|
|
11
|
+
alreadyConfigured: boolean;
|
|
12
|
+
created: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Inject HTTPS config into a Vite config file.
|
|
16
|
+
* Creates the file if it doesn't exist.
|
|
17
|
+
* Idempotent — safe to call multiple times.
|
|
18
|
+
*/
|
|
19
|
+
export declare function injectVite(configPath: string): Promise<InjectResult>;
|
|
20
|
+
/**
|
|
21
|
+
* Pure function: insert the HTTPS block into Vite config source.
|
|
22
|
+
*/
|
|
23
|
+
export declare function injectIntoSource(source: string): string | null;
|
|
24
|
+
//# sourceMappingURL=vite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../../src/injectors/vite.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,eAAO,MAAM,gBAAgB,wBAAwB,CAAC;AA0CtD,MAAM,WAAW,YAAY;IAC3B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAqC1E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAqB9D"}
|