@flatfile/records
Version:
Record management utilities for Flatfile
290 lines (289 loc) • 8.77 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.FlatfileRecord = void 0;
const node_crypto_1 = require("node:crypto");
const util = __importStar(require("util"));
const constants_1 = require("./constants");
const casting_1 = require("./utils/casting");
const is_nullish_1 = require("./utils/is.nullish");
class FlatfileRecord {
constructor(data, dirty = false) {
this.data = data;
this._changes = new Map();
this._errs = new Map();
this._deleted = false;
if (dirty) {
this.data = Object.freeze({});
Object.entries(data).forEach(([key, value]) => {
this.set(key, value);
});
}
else {
Object.freeze(this.data);
}
}
get id() {
return this.data.__k || this._tempId;
}
get slug() {
return this.data.__n;
}
get sheetId() {
return this.data.__s;
}
set(key, value) {
if (this.data[key] === value) {
this._changes.delete(key);
return;
}
this._changes.set(key, value);
return this;
}
flag(key) {
this.set(key, true);
}
unflag(key) {
this.set(key, false);
}
get(key) {
if (this._changes.has(key)) {
return this._changes.get(key);
}
return this.data[key];
}
has(key) {
return (0, is_nullish_1.isPresent)(this.get(key));
}
hasAny(...keys) {
return keys.some((k) => this.has(k));
}
hasAll(...keys) {
return keys.every((k) => this.has(k));
}
isEmpty(key) {
return !this.has(key);
}
keys(options) {
const set = new Set(Object.keys(this.data).filter((key) => !key.startsWith("__")));
for (const key of this._changes.keys()) {
if (!key.startsWith("__")) {
set.add(key);
}
}
const res = Array.from(set);
if (options?.omit?.length) {
return res.filter((key) => !options.omit.includes(key));
}
if (options?.pick?.length) {
return res.filter((key) => options.pick.includes(key));
}
return res;
}
keysWithData(props) {
const keys = this.keys().filter((k) => this.has(k));
if (props?.exclude) {
const f = props.exclude.flat();
return keys.filter((k) => !f.includes(k));
}
return keys;
}
intersects(item, keys) {
return keys.every((key) => {
const value1 = this.str(key);
const value2 = item.str(key);
return value1 === value2;
});
}
hash(...keys) {
return keys
.map((k) => [k, this.get(k)])
.map(([k, v]) => `${k}${constants_1.HASH_VALUE_DELIM}${(0, casting_1.asString)(v)}`)
.join(constants_1.HASH_PROP_DELIM);
}
isDirty(key) {
if (key) {
const errors = this._errs.get(key);
return this._changes.has(key) || (errors?.size ?? 0) > 0;
}
return this._changes.size > 0 || this._errs.size > 0 || this._deleted;
}
eachOfKeysPresent(keys, callback) {
for (const key of keys) {
if (this.has(key)) {
callback(key, this.get(key));
}
}
}
isDeleted() {
return this._deleted;
}
delete() {
this._deleted = true;
}
str(key) {
return (0, casting_1.asNullableString)(this.get(key));
}
defStr(key) {
return (0, casting_1.asString)(this.get(key));
}
bool(key) {
return (0, casting_1.asBool)(this.get(key));
}
date(key) {
return (0, casting_1.asDate)(this.get(key));
}
pick(...keys) {
const obj = {};
for (const key of keys) {
obj[key] = this.get(key);
}
return obj;
}
err(key, msg) {
if (!this._errs.has(key)) {
this._errs.set(key, new Set([msg]));
}
const errors = this._errs.get(key);
if (errors) {
errors.add(msg);
}
return this;
}
values() {
return Object.fromEntries(this.entries());
}
entries() {
return this.keys().map((key) => [key, this.get(key)]);
}
merge(item, props = {}) {
for (const key of item.keys()) {
if (props.overwrite) {
this.set(key, item.get(key));
}
else if (!this.has(key)) {
this.set(key, item.get(key));
}
}
return this;
}
hasConflict(b, keys) {
if (keys) {
return keys.some((key) => {
const aValue = this.get(key);
const bValue = b.get(key);
return aValue && bValue && aValue !== bValue;
});
}
return this.entries().some(([key, aValue]) => {
const bValue = b.get(key);
return aValue && bValue && aValue !== bValue;
});
}
toJSON() {
return { ...this.data, ...this.changeset() };
}
[util.inspect.custom]() {
return `${this._deleted ? "❌ " : ""}${this.slug || this.sheetId}(${this.id ?? "new"}) ${JSON.stringify(this.values(), null, " ")}`;
}
copy(props) {
const newObj = new FlatfileRecord({});
newObj._tempId = `TEMP_${(0, node_crypto_1.randomUUID)()}`;
if (props?.slug) {
newObj.set("__n", props.slug);
}
if (props?.sheetId) {
newObj.set("__s", props.sheetId);
}
if (props?.select) {
for (const key of props.select) {
newObj.set(key, props.mixin?.get(key) ?? this.get(key));
}
}
else {
for (const key in this.data) {
if (!key.startsWith("__")) {
newObj.set(key, this.get(key));
}
}
if (props?.mixin) {
for (const key in props.mixin.data) {
if (!key.startsWith("__")) {
newObj.set(key, props.mixin.get(key));
}
}
}
}
return newObj;
}
commit() {
const newObj = Object.assign({}, this.data);
for (const [key, value] of this._changes) {
newObj[key] = value;
}
this._changes.clear();
if (this._errs.size) {
newObj.__i = [];
for (const [key, errs] of this._errs) {
for (const err of errs) {
newObj.__i.push({ x: key, m: err });
}
}
}
this._errs.clear();
this.data = Object.freeze(newObj);
}
changeset() {
const val = Object.fromEntries(this._changes);
val.__k = this.get("__k");
val.__s = this.get("__s");
val.__n = this.get("__n");
if (this._deleted) {
val.__d = true;
}
if (this._errs.size) {
if (!val.__i) {
val.__i = [];
}
for (const [key, errs] of this._errs) {
for (const err of errs) {
val.__i.push({ x: key, m: err });
}
}
}
return val;
}
}
exports.FlatfileRecord = FlatfileRecord;