UNPKG

@varlock/vite-integration

Version:

Vite plugin to use varlock for .env file loading - adds validation, type-safety, and extra security features

1,510 lines (1,504 loc) 53.1 kB
import path from 'path'; import Debug from 'debug'; import { initVarlockEnv } from 'varlock/env'; import { patchGlobalConsole } from 'varlock/patch-console'; import { patchGlobalServerResponse } from 'varlock/patch-server-response'; import { patchGlobalResponse } from 'varlock/patch-response'; import { execSyncVarlock } from 'varlock/exec-sync-varlock'; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. __defProp(target, "default", { value: mod, enumerable: true }) , mod )); // ../../../node_modules/.pnpm/ast-matcher@1.2.0/node_modules/ast-matcher/index.js var require_ast_matcher = __commonJS({ "../../../node_modules/.pnpm/ast-matcher@1.2.0/node_modules/ast-matcher/index.js"(exports, module) { var STOP = false; var SKIP_BRANCH = 1; var IGNORED_KEYS = ["start", "end", "loc", "location", "locations", "line", "column", "range", "ranges", "raw", "extra"]; var _parser = function() { throw new Error("No parser set, you need to set parser before use astMatcher. For instance, astMatcher.setParser(esprima.parse)"); }; function setParser(p) { if (typeof p !== "function") { throw new Error("Input parser must be a function that takes JavaScript contents as input, produce a estree compliant syntax tree object."); } _parser = function(contents) { let node = p(contents); if (node.type === "File" && node.program) { node = node.program; } return node; }; } function traverse(object, visitor) { let child; if (!object) return; let r = visitor.call(null, object); if (r === STOP) return STOP; if (r === SKIP_BRANCH) return; for (let i = 0, keys = Object.keys(object); i < keys.length; i++) { let key = keys[i]; if (IGNORED_KEYS.indexOf(key) !== -1) continue; child = object[key]; if (typeof child === "object" && child !== null) { if (traverse(child, visitor) === STOP) { return STOP; } } } } var ANY = 1; var ANL = 2; var STR = 3; var ARR = 4; function matchTerm(pattern) { let possible; if (pattern.type === "Identifier") { possible = pattern.name.toString(); } else if (pattern.type === "ExpressionStatement" && pattern.expression.type === "Identifier") { possible = pattern.expression.name.toString(); } else if ((pattern.type === "FieldDefinition" || pattern.type === "ClassProperty") && pattern.key.type === "Identifier") { possible = pattern.key.name.toString(); } if (!possible || !possible.startsWith("__")) return; let type; if (possible === "__any" || possible.startsWith("__any_")) { type = ANY; } else if (possible === "__anl" || possible.startsWith("__anl_")) { type = ANL; } else if (possible === "__str" || possible.startsWith("__str_")) { type = STR; } else if (possible === "__arr" || possible.startsWith("__arr_")) { type = ARR; } if (type) return { type, name: possible.slice(6) }; } function extract(pattern, part) { if (!pattern) throw new Error("missing pattern"); if (!part) return STOP; let term = matchTerm(pattern); if (term) { if (term.type === ANY) { if (term.name) { let r = {}; r[term.name] = part; return r; } return {}; } else if (term.type === STR) { if (part.type === "Literal" || part.type === "StringLiteral") { if (term.name) { let r = {}; r[term.name] = part.value; return r; } return {}; } return STOP; } } if (Array.isArray(pattern)) { if (!Array.isArray(part)) return STOP; if (pattern.length === 1) { let arrTerm = matchTerm(pattern[0]); if (arrTerm) { if (arrTerm.type === ARR) { let arr = part.filter(function(it) { return it.type === "Literal" || it.type === "StringLiteral"; }).map(function(it) { return it.value; }); if (arr.length) { if (arrTerm.name) { let r = {}; r[arrTerm.name] = arr; return r; } return {}; } return STOP; } else if (arrTerm.type === ANL) { if (arrTerm.name) { let r = {}; r[arrTerm.name] = part; return r; } return {}; } } } if (pattern.length !== part.length) { return STOP; } } let allResult = {}; for (let i = 0, keys = Object.keys(pattern); i < keys.length; i++) { let key = keys[i]; if (IGNORED_KEYS.indexOf(key) !== -1) continue; let nextPattern = pattern[key]; let nextPart = part[key]; if (!nextPattern || typeof nextPattern !== "object") { if (nextPattern === nextPart) continue; return STOP; } const result = extract(nextPattern, nextPart); if (result === STOP) return STOP; if (result) Object.assign(allResult, result); } return allResult; } function compilePattern(pattern) { let exp = ensureParsed(pattern); if (exp.type !== "Program" || !exp.body) { throw new Error(`Not a valid expression: "${pattern}".`); } if (exp.body.length === 0) { throw new Error(`There is no statement in pattern "${pattern}".`); } if (exp.body.length > 1) { throw new Error(`Multiple statements is not supported "${pattern}".`); } exp = exp.body[0]; if (exp.type === "ExpressionStatement") exp = exp.expression; return exp; } function ensureParsed(codeOrNode) { if (codeOrNode && codeOrNode.type) { if (codeOrNode.type === "File" && codeOrNode.program) { return codeOrNode.program; } return codeOrNode; } return _parser(codeOrNode); } function astMatcher2(pattern) { let pat = compilePattern(pattern); return function(jsStr) { let node = ensureParsed(jsStr); let matches = []; traverse(node, function(n2) { let m = extract(pat, n2); if (m) { matches.push({ match: m, node: n2 // this is the full matching node }); } }); return matches.length ? matches : void 0; }; } function depFinder() { if (arguments.length === 0) { throw new Error("No patterns provided."); } let seed = 0; let patterns = Array.prototype.map.call(arguments, function(p) { return compilePattern(p.replace(/__dep(s?)/g, function(m, wantArr) { return (wantArr ? "__arr_" : "__str_") + ++seed; })); }); let len = patterns.length; return function(jsStr) { let node = ensureParsed(jsStr); let deps = []; traverse(node, function(n2) { for (let i = 0; i < len; i += 1) { let result = extract(patterns[i], n2); if (result) { Object.keys(result).forEach(function(k) { let d = result[k]; if (typeof d === "string") deps.push(d); else deps.push.apply(deps, d); }); break; } } }); return deps; }; } module.exports = astMatcher2; module.exports.setParser = setParser; module.exports.ensureParsed = ensureParsed; module.exports.extract = extract; module.exports.compilePattern = compilePattern; module.exports.depFinder = depFinder; module.exports.STOP = STOP; module.exports.SKIP_BRANCH = SKIP_BRANCH; module.exports.traverse = traverse; } }); // ../../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.5.0/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs var comma = ",".charCodeAt(0); var semicolon = ";".charCodeAt(0); var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var intToChar = new Uint8Array(64); var charToInt = new Uint8Array(128); for (let i = 0; i < chars.length; i++) { const c = chars.charCodeAt(i); intToChar[i] = c; charToInt[c] = i; } function encodeInteger(builder, num, relative) { let delta = num - relative; delta = delta < 0 ? -delta << 1 | 1 : delta << 1; do { let clamped = delta & 31; delta >>>= 5; if (delta > 0) clamped |= 32; builder.write(intToChar[clamped]); } while (delta > 0); return num; } var bufLength = 1024 * 16; var td = typeof TextDecoder !== "undefined" ? /* @__PURE__ */ new TextDecoder() : typeof Buffer !== "undefined" ? { decode(buf) { const out = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength); return out.toString(); } } : { decode(buf) { let out = ""; for (let i = 0; i < buf.length; i++) { out += String.fromCharCode(buf[i]); } return out; } }; var StringWriter = class { constructor() { this.pos = 0; this.out = ""; this.buffer = new Uint8Array(bufLength); } write(v) { const { buffer } = this; buffer[this.pos++] = v; if (this.pos === bufLength) { this.out += td.decode(buffer); this.pos = 0; } } flush() { const { buffer, out, pos } = this; return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out; } }; function encode(decoded) { const writer = new StringWriter(); let sourcesIndex = 0; let sourceLine = 0; let sourceColumn = 0; let namesIndex = 0; for (let i = 0; i < decoded.length; i++) { const line = decoded[i]; if (i > 0) writer.write(semicolon); if (line.length === 0) continue; let genColumn = 0; for (let j = 0; j < line.length; j++) { const segment = line[j]; if (j > 0) writer.write(comma); genColumn = encodeInteger(writer, segment[0], genColumn); if (segment.length === 1) continue; sourcesIndex = encodeInteger(writer, segment[1], sourcesIndex); sourceLine = encodeInteger(writer, segment[2], sourceLine); sourceColumn = encodeInteger(writer, segment[3], sourceColumn); if (segment.length === 4) continue; namesIndex = encodeInteger(writer, segment[4], namesIndex); } } return writer.flush(); } // ../../../node_modules/.pnpm/magic-string@0.30.17/node_modules/magic-string/dist/magic-string.es.mjs var BitSet = class _BitSet { constructor(arg) { this.bits = arg instanceof _BitSet ? arg.bits.slice() : []; } add(n2) { this.bits[n2 >> 5] |= 1 << (n2 & 31); } has(n2) { return !!(this.bits[n2 >> 5] & 1 << (n2 & 31)); } }; var Chunk = class _Chunk { constructor(start, end, content) { this.start = start; this.end = end; this.original = content; this.intro = ""; this.outro = ""; this.content = content; this.storeName = false; this.edited = false; { this.previous = null; this.next = null; } } appendLeft(content) { this.outro += content; } appendRight(content) { this.intro = this.intro + content; } clone() { const chunk = new _Chunk(this.start, this.end, this.original); chunk.intro = this.intro; chunk.outro = this.outro; chunk.content = this.content; chunk.storeName = this.storeName; chunk.edited = this.edited; return chunk; } contains(index) { return this.start < index && index < this.end; } eachNext(fn) { let chunk = this; while (chunk) { fn(chunk); chunk = chunk.next; } } eachPrevious(fn) { let chunk = this; while (chunk) { fn(chunk); chunk = chunk.previous; } } edit(content, storeName, contentOnly) { this.content = content; if (!contentOnly) { this.intro = ""; this.outro = ""; } this.storeName = storeName; this.edited = true; return this; } prependLeft(content) { this.outro = content + this.outro; } prependRight(content) { this.intro = content + this.intro; } reset() { this.intro = ""; this.outro = ""; if (this.edited) { this.content = this.original; this.storeName = false; this.edited = false; } } split(index) { const sliceIndex = index - this.start; const originalBefore = this.original.slice(0, sliceIndex); const originalAfter = this.original.slice(sliceIndex); this.original = originalBefore; const newChunk = new _Chunk(index, this.end, originalAfter); newChunk.outro = this.outro; this.outro = ""; this.end = index; if (this.edited) { newChunk.edit("", false); this.content = ""; } else { this.content = originalBefore; } newChunk.next = this.next; if (newChunk.next) newChunk.next.previous = newChunk; newChunk.previous = this; this.next = newChunk; return newChunk; } toString() { return this.intro + this.content + this.outro; } trimEnd(rx) { this.outro = this.outro.replace(rx, ""); if (this.outro.length) return true; const trimmed = this.content.replace(rx, ""); if (trimmed.length) { if (trimmed !== this.content) { this.split(this.start + trimmed.length).edit("", void 0, true); if (this.edited) { this.edit(trimmed, this.storeName, true); } } return true; } else { this.edit("", void 0, true); this.intro = this.intro.replace(rx, ""); if (this.intro.length) return true; } } trimStart(rx) { this.intro = this.intro.replace(rx, ""); if (this.intro.length) return true; const trimmed = this.content.replace(rx, ""); if (trimmed.length) { if (trimmed !== this.content) { const newChunk = this.split(this.end - trimmed.length); if (this.edited) { newChunk.edit(trimmed, this.storeName, true); } this.edit("", void 0, true); } return true; } else { this.edit("", void 0, true); this.outro = this.outro.replace(rx, ""); if (this.outro.length) return true; } } }; function getBtoa() { if (typeof globalThis !== "undefined" && typeof globalThis.btoa === "function") { return (str) => globalThis.btoa(unescape(encodeURIComponent(str))); } else if (typeof Buffer === "function") { return (str) => Buffer.from(str, "utf-8").toString("base64"); } else { return () => { throw new Error("Unsupported environment: `window.btoa` or `Buffer` should be supported."); }; } } var btoa = /* @__PURE__ */ getBtoa(); var SourceMap = class { constructor(properties) { this.version = 3; this.file = properties.file; this.sources = properties.sources; this.sourcesContent = properties.sourcesContent; this.names = properties.names; this.mappings = encode(properties.mappings); if (typeof properties.x_google_ignoreList !== "undefined") { this.x_google_ignoreList = properties.x_google_ignoreList; } if (typeof properties.debugId !== "undefined") { this.debugId = properties.debugId; } } toString() { return JSON.stringify(this); } toUrl() { return "data:application/json;charset=utf-8;base64," + btoa(this.toString()); } }; function guessIndent(code) { const lines = code.split("\n"); const tabbed = lines.filter((line) => /^\t+/.test(line)); const spaced = lines.filter((line) => /^ {2,}/.test(line)); if (tabbed.length === 0 && spaced.length === 0) { return null; } if (tabbed.length >= spaced.length) { return " "; } const min = spaced.reduce((previous, current) => { const numSpaces = /^ +/.exec(current)[0].length; return Math.min(numSpaces, previous); }, Infinity); return new Array(min + 1).join(" "); } function getRelativePath(from, to) { const fromParts = from.split(/[/\\]/); const toParts = to.split(/[/\\]/); fromParts.pop(); while (fromParts[0] === toParts[0]) { fromParts.shift(); toParts.shift(); } if (fromParts.length) { let i = fromParts.length; while (i--) fromParts[i] = ".."; } return fromParts.concat(toParts).join("/"); } var toString = Object.prototype.toString; function isObject(thing) { return toString.call(thing) === "[object Object]"; } function getLocator(source) { const originalLines = source.split("\n"); const lineOffsets = []; for (let i = 0, pos = 0; i < originalLines.length; i++) { lineOffsets.push(pos); pos += originalLines[i].length + 1; } return function locate(index) { let i = 0; let j = lineOffsets.length; while (i < j) { const m = i + j >> 1; if (index < lineOffsets[m]) { j = m; } else { i = m + 1; } } const line = i - 1; const column = index - lineOffsets[line]; return { line, column }; }; } var wordRegex = /\w/; var Mappings = class { constructor(hires) { this.hires = hires; this.generatedCodeLine = 0; this.generatedCodeColumn = 0; this.raw = []; this.rawSegments = this.raw[this.generatedCodeLine] = []; this.pending = null; } addEdit(sourceIndex, content, loc, nameIndex) { if (content.length) { const contentLengthMinusOne = content.length - 1; let contentLineEnd = content.indexOf("\n", 0); let previousContentLineEnd = -1; while (contentLineEnd >= 0 && contentLengthMinusOne > contentLineEnd) { const segment2 = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column]; if (nameIndex >= 0) { segment2.push(nameIndex); } this.rawSegments.push(segment2); this.generatedCodeLine += 1; this.raw[this.generatedCodeLine] = this.rawSegments = []; this.generatedCodeColumn = 0; previousContentLineEnd = contentLineEnd; contentLineEnd = content.indexOf("\n", contentLineEnd + 1); } const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column]; if (nameIndex >= 0) { segment.push(nameIndex); } this.rawSegments.push(segment); this.advance(content.slice(previousContentLineEnd + 1)); } else if (this.pending) { this.rawSegments.push(this.pending); this.advance(content); } this.pending = null; } addUneditedChunk(sourceIndex, chunk, original, loc, sourcemapLocations) { let originalCharIndex = chunk.start; let first = true; let charInHiresBoundary = false; while (originalCharIndex < chunk.end) { if (original[originalCharIndex] === "\n") { loc.line += 1; loc.column = 0; this.generatedCodeLine += 1; this.raw[this.generatedCodeLine] = this.rawSegments = []; this.generatedCodeColumn = 0; first = true; charInHiresBoundary = false; } else { if (this.hires || first || sourcemapLocations.has(originalCharIndex)) { const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column]; if (this.hires === "boundary") { if (wordRegex.test(original[originalCharIndex])) { if (!charInHiresBoundary) { this.rawSegments.push(segment); charInHiresBoundary = true; } } else { this.rawSegments.push(segment); charInHiresBoundary = false; } } else { this.rawSegments.push(segment); } } loc.column += 1; this.generatedCodeColumn += 1; first = false; } originalCharIndex += 1; } this.pending = null; } advance(str) { if (!str) return; const lines = str.split("\n"); if (lines.length > 1) { for (let i = 0; i < lines.length - 1; i++) { this.generatedCodeLine++; this.raw[this.generatedCodeLine] = this.rawSegments = []; } this.generatedCodeColumn = 0; } this.generatedCodeColumn += lines[lines.length - 1].length; } }; var n = "\n"; var warned = { insertLeft: false, insertRight: false, storeName: false }; var MagicString = class _MagicString { constructor(string, options = {}) { const chunk = new Chunk(0, string.length, string); Object.defineProperties(this, { original: { writable: true, value: string }, outro: { writable: true, value: "" }, intro: { writable: true, value: "" }, firstChunk: { writable: true, value: chunk }, lastChunk: { writable: true, value: chunk }, lastSearchedChunk: { writable: true, value: chunk }, byStart: { writable: true, value: {} }, byEnd: { writable: true, value: {} }, filename: { writable: true, value: options.filename }, indentExclusionRanges: { writable: true, value: options.indentExclusionRanges }, sourcemapLocations: { writable: true, value: new BitSet() }, storedNames: { writable: true, value: {} }, indentStr: { writable: true, value: void 0 }, ignoreList: { writable: true, value: options.ignoreList }, offset: { writable: true, value: options.offset || 0 } }); this.byStart[0] = chunk; this.byEnd[string.length] = chunk; } addSourcemapLocation(char) { this.sourcemapLocations.add(char); } append(content) { if (typeof content !== "string") throw new TypeError("outro content must be a string"); this.outro += content; return this; } appendLeft(index, content) { index = index + this.offset; if (typeof content !== "string") throw new TypeError("inserted content must be a string"); this._split(index); const chunk = this.byEnd[index]; if (chunk) { chunk.appendLeft(content); } else { this.intro += content; } return this; } appendRight(index, content) { index = index + this.offset; if (typeof content !== "string") throw new TypeError("inserted content must be a string"); this._split(index); const chunk = this.byStart[index]; if (chunk) { chunk.appendRight(content); } else { this.outro += content; } return this; } clone() { const cloned = new _MagicString(this.original, { filename: this.filename, offset: this.offset }); let originalChunk = this.firstChunk; let clonedChunk = cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone(); while (originalChunk) { cloned.byStart[clonedChunk.start] = clonedChunk; cloned.byEnd[clonedChunk.end] = clonedChunk; const nextOriginalChunk = originalChunk.next; const nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone(); if (nextClonedChunk) { clonedChunk.next = nextClonedChunk; nextClonedChunk.previous = clonedChunk; clonedChunk = nextClonedChunk; } originalChunk = nextOriginalChunk; } cloned.lastChunk = clonedChunk; if (this.indentExclusionRanges) { cloned.indentExclusionRanges = this.indentExclusionRanges.slice(); } cloned.sourcemapLocations = new BitSet(this.sourcemapLocations); cloned.intro = this.intro; cloned.outro = this.outro; return cloned; } generateDecodedMap(options) { options = options || {}; const sourceIndex = 0; const names = Object.keys(this.storedNames); const mappings = new Mappings(options.hires); const locate = getLocator(this.original); if (this.intro) { mappings.advance(this.intro); } this.firstChunk.eachNext((chunk) => { const loc = locate(chunk.start); if (chunk.intro.length) mappings.advance(chunk.intro); if (chunk.edited) { mappings.addEdit( sourceIndex, chunk.content, loc, chunk.storeName ? names.indexOf(chunk.original) : -1 ); } else { mappings.addUneditedChunk(sourceIndex, chunk, this.original, loc, this.sourcemapLocations); } if (chunk.outro.length) mappings.advance(chunk.outro); }); return { file: options.file ? options.file.split(/[/\\]/).pop() : void 0, sources: [ options.source ? getRelativePath(options.file || "", options.source) : options.file || "" ], sourcesContent: options.includeContent ? [this.original] : void 0, names, mappings: mappings.raw, x_google_ignoreList: this.ignoreList ? [sourceIndex] : void 0 }; } generateMap(options) { return new SourceMap(this.generateDecodedMap(options)); } _ensureindentStr() { if (this.indentStr === void 0) { this.indentStr = guessIndent(this.original); } } _getRawIndentString() { this._ensureindentStr(); return this.indentStr; } getIndentString() { this._ensureindentStr(); return this.indentStr === null ? " " : this.indentStr; } indent(indentStr, options) { const pattern = /^[^\r\n]/gm; if (isObject(indentStr)) { options = indentStr; indentStr = void 0; } if (indentStr === void 0) { this._ensureindentStr(); indentStr = this.indentStr || " "; } if (indentStr === "") return this; options = options || {}; const isExcluded = {}; if (options.exclude) { const exclusions = typeof options.exclude[0] === "number" ? [options.exclude] : options.exclude; exclusions.forEach((exclusion) => { for (let i = exclusion[0]; i < exclusion[1]; i += 1) { isExcluded[i] = true; } }); } let shouldIndentNextCharacter = options.indentStart !== false; const replacer = (match) => { if (shouldIndentNextCharacter) return `${indentStr}${match}`; shouldIndentNextCharacter = true; return match; }; this.intro = this.intro.replace(pattern, replacer); let charIndex = 0; let chunk = this.firstChunk; while (chunk) { const end = chunk.end; if (chunk.edited) { if (!isExcluded[charIndex]) { chunk.content = chunk.content.replace(pattern, replacer); if (chunk.content.length) { shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === "\n"; } } } else { charIndex = chunk.start; while (charIndex < end) { if (!isExcluded[charIndex]) { const char = this.original[charIndex]; if (char === "\n") { shouldIndentNextCharacter = true; } else if (char !== "\r" && shouldIndentNextCharacter) { shouldIndentNextCharacter = false; if (charIndex === chunk.start) { chunk.prependRight(indentStr); } else { this._splitChunk(chunk, charIndex); chunk = chunk.next; chunk.prependRight(indentStr); } } } charIndex += 1; } } charIndex = chunk.end; chunk = chunk.next; } this.outro = this.outro.replace(pattern, replacer); return this; } insert() { throw new Error( "magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)" ); } insertLeft(index, content) { if (!warned.insertLeft) { console.warn( "magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead" ); warned.insertLeft = true; } return this.appendLeft(index, content); } insertRight(index, content) { if (!warned.insertRight) { console.warn( "magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead" ); warned.insertRight = true; } return this.prependRight(index, content); } move(start, end, index) { start = start + this.offset; end = end + this.offset; index = index + this.offset; if (index >= start && index <= end) throw new Error("Cannot move a selection inside itself"); this._split(start); this._split(end); this._split(index); const first = this.byStart[start]; const last = this.byEnd[end]; const oldLeft = first.previous; const oldRight = last.next; const newRight = this.byStart[index]; if (!newRight && last === this.lastChunk) return this; const newLeft = newRight ? newRight.previous : this.lastChunk; if (oldLeft) oldLeft.next = oldRight; if (oldRight) oldRight.previous = oldLeft; if (newLeft) newLeft.next = first; if (newRight) newRight.previous = last; if (!first.previous) this.firstChunk = last.next; if (!last.next) { this.lastChunk = first.previous; this.lastChunk.next = null; } first.previous = newLeft; last.next = newRight || null; if (!newLeft) this.firstChunk = first; if (!newRight) this.lastChunk = last; return this; } overwrite(start, end, content, options) { options = options || {}; return this.update(start, end, content, { ...options, overwrite: !options.contentOnly }); } update(start, end, content, options) { start = start + this.offset; end = end + this.offset; if (typeof content !== "string") throw new TypeError("replacement content must be a string"); if (this.original.length !== 0) { while (start < 0) start += this.original.length; while (end < 0) end += this.original.length; } if (end > this.original.length) throw new Error("end is out of bounds"); if (start === end) throw new Error( "Cannot overwrite a zero-length range \u2013 use appendLeft or prependRight instead" ); this._split(start); this._split(end); if (options === true) { if (!warned.storeName) { console.warn( "The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string" ); warned.storeName = true; } options = { storeName: true }; } const storeName = options !== void 0 ? options.storeName : false; const overwrite = options !== void 0 ? options.overwrite : false; if (storeName) { const original = this.original.slice(start, end); Object.defineProperty(this.storedNames, original, { writable: true, value: true, enumerable: true }); } const first = this.byStart[start]; const last = this.byEnd[end]; if (first) { let chunk = first; while (chunk !== last) { if (chunk.next !== this.byStart[chunk.end]) { throw new Error("Cannot overwrite across a split point"); } chunk = chunk.next; chunk.edit("", false); } first.edit(content, storeName, !overwrite); } else { const newChunk = new Chunk(start, end, "").edit(content, storeName); last.next = newChunk; newChunk.previous = last; } return this; } prepend(content) { if (typeof content !== "string") throw new TypeError("outro content must be a string"); this.intro = content + this.intro; return this; } prependLeft(index, content) { index = index + this.offset; if (typeof content !== "string") throw new TypeError("inserted content must be a string"); this._split(index); const chunk = this.byEnd[index]; if (chunk) { chunk.prependLeft(content); } else { this.intro = content + this.intro; } return this; } prependRight(index, content) { index = index + this.offset; if (typeof content !== "string") throw new TypeError("inserted content must be a string"); this._split(index); const chunk = this.byStart[index]; if (chunk) { chunk.prependRight(content); } else { this.outro = content + this.outro; } return this; } remove(start, end) { start = start + this.offset; end = end + this.offset; if (this.original.length !== 0) { while (start < 0) start += this.original.length; while (end < 0) end += this.original.length; } if (start === end) return this; if (start < 0 || end > this.original.length) throw new Error("Character is out of bounds"); if (start > end) throw new Error("end must be greater than start"); this._split(start); this._split(end); let chunk = this.byStart[start]; while (chunk) { chunk.intro = ""; chunk.outro = ""; chunk.edit(""); chunk = end > chunk.end ? this.byStart[chunk.end] : null; } return this; } reset(start, end) { start = start + this.offset; end = end + this.offset; if (this.original.length !== 0) { while (start < 0) start += this.original.length; while (end < 0) end += this.original.length; } if (start === end) return this; if (start < 0 || end > this.original.length) throw new Error("Character is out of bounds"); if (start > end) throw new Error("end must be greater than start"); this._split(start); this._split(end); let chunk = this.byStart[start]; while (chunk) { chunk.reset(); chunk = end > chunk.end ? this.byStart[chunk.end] : null; } return this; } lastChar() { if (this.outro.length) return this.outro[this.outro.length - 1]; let chunk = this.lastChunk; do { if (chunk.outro.length) return chunk.outro[chunk.outro.length - 1]; if (chunk.content.length) return chunk.content[chunk.content.length - 1]; if (chunk.intro.length) return chunk.intro[chunk.intro.length - 1]; } while (chunk = chunk.previous); if (this.intro.length) return this.intro[this.intro.length - 1]; return ""; } lastLine() { let lineIndex = this.outro.lastIndexOf(n); if (lineIndex !== -1) return this.outro.substr(lineIndex + 1); let lineStr = this.outro; let chunk = this.lastChunk; do { if (chunk.outro.length > 0) { lineIndex = chunk.outro.lastIndexOf(n); if (lineIndex !== -1) return chunk.outro.substr(lineIndex + 1) + lineStr; lineStr = chunk.outro + lineStr; } if (chunk.content.length > 0) { lineIndex = chunk.content.lastIndexOf(n); if (lineIndex !== -1) return chunk.content.substr(lineIndex + 1) + lineStr; lineStr = chunk.content + lineStr; } if (chunk.intro.length > 0) { lineIndex = chunk.intro.lastIndexOf(n); if (lineIndex !== -1) return chunk.intro.substr(lineIndex + 1) + lineStr; lineStr = chunk.intro + lineStr; } } while (chunk = chunk.previous); lineIndex = this.intro.lastIndexOf(n); if (lineIndex !== -1) return this.intro.substr(lineIndex + 1) + lineStr; return this.intro + lineStr; } slice(start = 0, end = this.original.length - this.offset) { start = start + this.offset; end = end + this.offset; if (this.original.length !== 0) { while (start < 0) start += this.original.length; while (end < 0) end += this.original.length; } let result = ""; let chunk = this.firstChunk; while (chunk && (chunk.start > start || chunk.end <= start)) { if (chunk.start < end && chunk.end >= end) { return result; } chunk = chunk.next; } if (chunk && chunk.edited && chunk.start !== start) throw new Error(`Cannot use replaced character ${start} as slice start anchor.`); const startChunk = chunk; while (chunk) { if (chunk.intro && (startChunk !== chunk || chunk.start === start)) { result += chunk.intro; } const containsEnd = chunk.start < end && chunk.end >= end; if (containsEnd && chunk.edited && chunk.end !== end) throw new Error(`Cannot use replaced character ${end} as slice end anchor.`); const sliceStart = startChunk === chunk ? start - chunk.start : 0; const sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length; result += chunk.content.slice(sliceStart, sliceEnd); if (chunk.outro && (!containsEnd || chunk.end === end)) { result += chunk.outro; } if (containsEnd) { break; } chunk = chunk.next; } return result; } // TODO deprecate this? not really very useful snip(start, end) { const clone = this.clone(); clone.remove(0, start); clone.remove(end, clone.original.length); return clone; } _split(index) { if (this.byStart[index] || this.byEnd[index]) return; let chunk = this.lastSearchedChunk; const searchForward = index > chunk.end; while (chunk) { if (chunk.contains(index)) return this._splitChunk(chunk, index); chunk = searchForward ? this.byStart[chunk.end] : this.byEnd[chunk.start]; } } _splitChunk(chunk, index) { if (chunk.edited && chunk.content.length) { const loc = getLocator(this.original)(index); throw new Error( `Cannot split a chunk that has already been edited (${loc.line}:${loc.column} \u2013 "${chunk.original}")` ); } const newChunk = chunk.split(index); this.byEnd[index] = chunk; this.byStart[index] = newChunk; this.byEnd[newChunk.end] = newChunk; if (chunk === this.lastChunk) this.lastChunk = newChunk; this.lastSearchedChunk = chunk; return true; } toString() { let str = this.intro; let chunk = this.firstChunk; while (chunk) { str += chunk.toString(); chunk = chunk.next; } return str + this.outro; } isEmpty() { let chunk = this.firstChunk; do { if (chunk.intro.length && chunk.intro.trim() || chunk.content.length && chunk.content.trim() || chunk.outro.length && chunk.outro.trim()) return false; } while (chunk = chunk.next); return true; } length() { let chunk = this.firstChunk; let length = 0; do { length += chunk.intro.length + chunk.content.length + chunk.outro.length; } while (chunk = chunk.next); return length; } trimLines() { return this.trim("[\\r\\n]"); } trim(charType) { return this.trimStart(charType).trimEnd(charType); } trimEndAborted(charType) { const rx = new RegExp((charType || "\\s") + "+$"); this.outro = this.outro.replace(rx, ""); if (this.outro.length) return true; let chunk = this.lastChunk; do { const end = chunk.end; const aborted = chunk.trimEnd(rx); if (chunk.end !== end) { if (this.lastChunk === chunk) { this.lastChunk = chunk.next; } this.byEnd[chunk.end] = chunk; this.byStart[chunk.next.start] = chunk.next; this.byEnd[chunk.next.end] = chunk.next; } if (aborted) return true; chunk = chunk.previous; } while (chunk); return false; } trimEnd(charType) { this.trimEndAborted(charType); return this; } trimStartAborted(charType) { const rx = new RegExp("^" + (charType || "\\s") + "+"); this.intro = this.intro.replace(rx, ""); if (this.intro.length) return true; let chunk = this.firstChunk; do { const end = chunk.end; const aborted = chunk.trimStart(rx); if (chunk.end !== end) { if (chunk === this.lastChunk) this.lastChunk = chunk.next; this.byEnd[chunk.end] = chunk; this.byStart[chunk.next.start] = chunk.next; this.byEnd[chunk.next.end] = chunk.next; } if (aborted) return true; chunk = chunk.next; } while (chunk); return false; } trimStart(charType) { this.trimStartAborted(charType); return this; } hasChanged() { return this.original !== this.toString(); } _replaceRegexp(searchValue, replacement) { function getReplacement(match, str) { if (typeof replacement === "string") { return replacement.replace(/\$(\$|&|\d+)/g, (_, i) => { if (i === "$") return "$"; if (i === "&") return match[0]; const num = +i; if (num < match.length) return match[+i]; return `$${i}`; }); } else { return replacement(...match, match.index, str, match.groups); } } function matchAll(re, str) { let match; const matches = []; while (match = re.exec(str)) { matches.push(match); } return matches; } if (searchValue.global) { const matches = matchAll(searchValue, this.original); matches.forEach((match) => { if (match.index != null) { const replacement2 = getReplacement(match, this.original); if (replacement2 !== match[0]) { this.overwrite(match.index, match.index + match[0].length, replacement2); } } }); } else { const match = this.original.match(searchValue); if (match && match.index != null) { const replacement2 = getReplacement(match, this.original); if (replacement2 !== match[0]) { this.overwrite(match.index, match.index + match[0].length, replacement2); } } } return this; } _replaceString(string, replacement) { const { original } = this; const index = original.indexOf(string); if (index !== -1) { this.overwrite(index, index + string.length, replacement); } return this; } replace(searchValue, replacement) { if (typeof searchValue === "string") { return this._replaceString(searchValue, replacement); } return this._replaceRegexp(searchValue, replacement); } _replaceAllString(string, replacement) { const { original } = this; const stringLength = string.length; for (let index = original.indexOf(string); index !== -1; index = original.indexOf(string, index + stringLength)) { const previous = original.slice(index, index + stringLength); if (previous !== replacement) this.overwrite(index, index + stringLength, replacement); } return this; } replaceAll(searchValue, replacement) { if (typeof searchValue === "string") { return this._replaceAllString(searchValue, replacement); } if (!searchValue.global) { throw new TypeError( "MagicString.prototype.replaceAll called with a non-global RegExp argument" ); } return this._replaceRegexp(searchValue, replacement); } }; // src/transform.ts var import_ast_matcher = __toESM(require_ast_matcher()); function escapeStringRegexp(string) { if (typeof string !== "string") throw new TypeError("Expected a string"); return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d"); } function markEdited(node, edits) { for (const [start, end] of edits) { if (start <= node.start && node.start < end || start < node.end && node.end <= end) { return false; } } return edits.push([node.start, node.end]); } var SUPPORTED_FILES = ["js", "ts", "mjs", "mts", "cjs", "cts", "jsx", "tsx", "vue", "svelte"]; function createReplacerTransformFn(opts) { const keys = Object.keys(opts.replacements); let matchers; const extraMatchersForFileType = {}; const findAnyReplacementRegex = new RegExp(`(?:${keys.map(escapeStringRegexp).join("|")})`, "g"); return function transform(rollupPluginCtx, code, id) { if (keys.length === 0) return null; const fileExt = id.split(".").pop() || ""; if (!SUPPORTED_FILES.includes(fileExt)) return null; if (code.search(findAnyReplacementRegex) === -1) return null; const parse = (codeToParse, source = code) => { try { return rollupPluginCtx.parse(codeToParse, void 0); } catch (error) { error.message += ` in ${source}`; throw error; } }; const ast = parse(code, id); matchers ||= keys.map((key) => ({ matcher: (0, import_ast_matcher.default)(parse(key)), replacement: opts.replacements[key] })); if (fileExt === "vue") { extraMatchersForFileType.vue ||= keys.map((key) => ({ matcher: (0, import_ast_matcher.default)(parse(`$setup.${key}`)), replacement: opts.replacements[key] })); } const magicString = new MagicString(code); const edits = []; Object.values([...matchers, ...extraMatchersForFileType[fileExt] || []]).forEach(({ matcher, replacement }) => { for (const { node } of matcher(ast) || []) { if (markEdited(node, edits)) { magicString.overwrite( node.start, node.end, replacement ); } } }); if (edits.length === 0) return null; return magicString; }; } // src/index.ts globalThis.__varlockThrowOnMissingKeys = true; var originalProcessEnv = { ...process.env }; var debug = Debug("varlock:vite-integration"); var isFirstLoad = !process.__VARLOCK_ENV; debug("varlock vite plugin loaded. first load = ", isFirstLoad); var isDevCommand; var configIsValid = true; var varlockLoadedEnv; var staticReplacements = {}; var replacerFn; var DETECT_PRESETS_USING_PLUGINS = { "vite-plugin-cloudflare": "cloudflare-workers" }; var detectedPreset = null; function resetStaticReplacements() { staticReplacements = {}; for (const itemKey in varlockLoadedEnv?.config) { const itemInfo = varlockLoadedEnv.config[itemKey]; if (!itemInfo.isSensitive) { const val = itemInfo.value === void 0 ? "undefined" : JSON.stringify(itemInfo.value); staticReplacements[`ENV.${itemKey}`] = val; } } debug("static replacements", staticReplacements); replacerFn = createReplacerTransformFn({ replacements: staticReplacements }); } var loadCount = 0; function reloadConfig() { debug("loading config - count =", ++loadCount); try { const execResult = execSyncVarlock("load --format json-full", { env: originalProcessEnv, showLogsOnError: true }); process.env.__VARLOCK_ENV = execResult; varlockLoadedEnv = JSON.parse(process.env.__VARLOCK_ENV); configIsValid = true; } catch (err) { configIsValid = false; } initVarlockEnv(); patchGlobalConsole(); patchGlobalServerResponse(); patchGlobalResponse(); resetStaticReplacements(); } reloadConfig(); function varlockVitePlugin(vitePluginOptions) { return { name: "inject-varlock-config", enforce: "post", // hook to modify config before it is resolved async config(config, env) { debug("vite plugin - config fn called"); isDevCommand = env.command === "serve"; if (isFirstLoad) { isFirstLoad = false; } else if (isDevCommand) { reloadConfig(); } const allPlugins = config.plugins?.flatMap((p) => p); allPlugins?.forEach((p) => { if (p && "name" in p && p.name in DETECT_PRESETS_USING_PLUGINS) { detectedPreset = DETECT_PRESETS_USING_PLUGINS[p.name]; } }); if (!configIsValid) { if (isDevCommand) { config.clearScreen = false; } else { console.log("\u{1F4A5} Varlock config validation failed \u{1F4A5}"); process.exit(1); } } }, // hook to observe/modify config after it is resolved configResolved(config) { debug("vite plugin - configResolved fn called"); for (const varlockSource of varlockLoadedEnv.sources) { if (!varlockSource.enabled) continue; if (varlockLoadedEnv.basePath && varlockSource.path) { config.configFileDependencies.push(path.resolve(varlockLoadedEnv.basePath, varlockSource.path)); } } }, // hook to configure vite dev server async configureServer(server) { debug("vite plugin - configureServer fn called"); if (!configIsValid) { server.middlewares.use((req, res, next) => { server.hot.send({ type: "error", err: { plugin: "varlock", message: "Your config is currently invalid - check your terminal for more details", stack: "" } }); return next(); }); } }, transform(code, id, options) { let magicString = replacerFn(this, code, id); let isEntry = false; const moduleIds = Array.from(this.getModuleIds()); if (moduleIds[0] === id) isEntry = true; if (isEntry) { let isDevEnv = false; if (this.environment) { isDevEnv = this.environment.mode === "dev"; } else { isDevEnv = isDevCommand; } const injectCode = [ "// INJECTED BY @varlock/vite-integration ----", "globalThis.__varlockThrowOnMissingKeys = true;" ]; if (options?.ssr) { let ssrInjectMode = vitePluginOptions?.ssrInjectMode; if (detectedPreset === "cloudflare-workers") { ssrInjectMode ??= "resolved-env"; } ssrInjectMode ??= "init-only"; if (isDevEnv) ssrInjectMode = "i