headers-for-firebase
Version:
Converts _headers file to entries within a .firebase.json file
128 lines (127 loc) • 5.08 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { readFile, writeFile } from "node:fs/promises";
import { parse, stringify } from "comment-json";
import outdent from "outdent";
export class ParseFirebase {
static createFromPath(firebasePath) {
return __awaiter(this, void 0, void 0, function* () {
const parsed = new ParseFirebase();
yield parsed.readFile(firebasePath);
parsed.firebasePath = firebasePath;
return parsed;
});
}
readFile(firebasePath) {
return __awaiter(this, void 0, void 0, function* () {
this.content = yield readFile(firebasePath, "utf-8");
this.configuration = parse(this.content);
if (this.insertIndex === undefined || this.deleteCount === undefined) {
throw new Error(outdent `
Please make sure you include the following comments within "hosting.headers" at "${firebasePath}":
/* _headers */
/* end _headers */
the new headers will appear between the comments.
`);
}
});
}
get insertIndex() {
const { headers } = this.configuration.hosting;
const beforeComments = headers[Symbol.for("before")];
if (hasOpeningComment(beforeComments)) {
return 0;
}
for (let i = 0; i < headers.length; i++) {
const beforeComments = headers[Symbol.for("before:" + i)];
if (hasOpeningComment(beforeComments)) {
return i;
}
const afterComments = headers[Symbol.for("after:" + i)];
if (hasOpeningComment(afterComments)) {
return i + 1;
}
}
}
get deleteCount() {
const { headers } = this.configuration.hosting;
const beforeComments = headers[Symbol.for("before")];
if (hasClosingComment(beforeComments)) {
return 0;
}
for (let i = 0; i < headers.length; i++) {
const beforeComments = headers[Symbol.for("before:" + i)];
if (hasClosingComment(beforeComments)) {
return i - this.insertIndex;
}
const afterComments = headers[Symbol.for("after:" + i)];
if (hasClosingComment(afterComments)) {
return i + 1 - this.insertIndex;
}
}
;
}
insertHeaders(newHeaders) {
const { insertIndex, deleteCount } = this;
const { headers } = this.configuration.hosting;
removeComments(headers, insertIndex, deleteCount);
headers.splice(insertIndex, deleteCount, ...newHeaders);
addOpeningCommentAt(insertIndex, headers);
addClosingCommentAt(insertIndex + newHeaders.length - 1, headers);
}
writeFile() {
return __awaiter(this, void 0, void 0, function* () {
const updatedContent = stringify(this.configuration, undefined, this.space) + this.endOfFile;
yield writeFile(this.firebasePath, updatedContent, "utf-8");
});
}
get space() {
return this.content.match(/^\{\n?(?<space>\s*)"/).groups.space;
}
get endOfFile() {
return /\n$/.test(this.content) ? "\n" : "";
;
}
}
function hasOpeningComment(comments) {
return comments === null || comments === void 0 ? void 0 : comments.some(c => c.value === " _headers ");
}
function hasClosingComment(comments) {
return comments === null || comments === void 0 ? void 0 : comments.some(c => c.value === " end _headers ");
}
function removeComments(headers, insertIndex, deleteCount) {
delete headers[Symbol.for("before")];
delete headers[Symbol.for("before:" + insertIndex)];
delete headers[Symbol.for("after:" + (insertIndex + deleteCount - 1))];
}
function addOpeningCommentAt(i, headers) {
const key = Symbol.for("before:" + i);
if (!headers[key]) {
headers[key] = [];
}
const openingComment = {
type: "BlockComment",
value: " _headers ",
inline: false,
};
headers[key].push(openingComment);
}
function addClosingCommentAt(i, headers) {
const key = Symbol.for("after:" + i);
if (!headers[key]) {
headers[key] = [];
}
const closingComment = {
type: "BlockComment",
value: " end _headers ",
inline: false,
};
headers[key].push(closingComment);
}