@mathrunet/masamune
Version:
Manages packages for the server portion (NodeJS) of the Masamune framework.
297 lines • 11.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FirestoreModelTimestampConverter = exports.ModelTimestampConverter = void 0;
exports.createTimestampFromMicroseconds = createTimestampFromMicroseconds;
const model_field_value_converter_1 = require("../model_field_value_converter");
const utils_1 = require("../../utils");
const firestore_1 = require("firebase-admin/firestore");
const firestore_2 = require("@google-cloud/firestore");
const model_field_value_1 = require("../model_field_value");
/**
* ModelTimestamp ModelFieldValueConverter.
*
* ModelTimestamp用のModelFieldValueConverter。
*/
class ModelTimestampConverter extends model_field_value_converter_1.ModelFieldValueConverter {
/**
* ModelTimestamp ModelFieldValueConverter.
*
* ModelTimestamp用のModelFieldValueConverter。
*/
constructor() {
super();
}
type = "ModelTimestamp";
convertFrom(key, value, original) {
// Skip if already a ModelTimestamp instance (e.g., from FirestoreConverter)
if (value instanceof model_field_value_1.ModelTimestamp) {
return { [key]: value };
}
if (value !== null && typeof value === "object" && "@type" in value && value["@type"] === this.type) {
const time = value["@time"] ?? 0;
return {
[key]: new model_field_value_1.ModelTimestamp(new Date(time / 1000.0), "server"),
};
}
return null;
}
convertTo(key, value, original) {
if (value instanceof model_field_value_1.ModelTimestamp) {
// Pass through ModelTimestamp instance as-is; FirestoreConverter will handle it
return { [key]: value };
}
return null;
}
}
exports.ModelTimestampConverter = ModelTimestampConverter;
/**
* Create Timestamp from microseconds.
*
* マイクロ秒からTimestampを作成します。
*
* @param microseconds
* Microseconds.
*
* マイクロ秒。
*
* @returns {Timestamp}
* Timestamp.
*
* Timestamp。
*/
function createTimestampFromMicroseconds(microseconds) {
if (microseconds >= 0) {
return firestore_1.Timestamp.fromMillis(microseconds / 1000);
}
const seconds = Math.floor(microseconds / 1000000);
const remainingMicros = microseconds - (seconds * 1000000);
const nanoseconds = remainingMicros * 1000;
if (nanoseconds < 0) {
return new firestore_1.Timestamp(seconds - 1, nanoseconds + 1000000000);
}
return new firestore_1.Timestamp(seconds, nanoseconds);
}
/**
* FirestoreConverter for [ModelTimestamp].
*
* [ModelTimestamp]用のFirestoreConverter。
*/
class FirestoreModelTimestampConverter extends model_field_value_converter_1.FirestoreModelFieldValueConverter {
/**
* FirestoreConverter for [ModelTimestamp].
*
* [ModelTimestamp]用のFirestoreConverter。
*/
constructor() {
super();
}
type = "ModelTimestamp";
convertFrom(key, value, original, firestoreInstance) {
if (typeof value === "number") {
const targetKey = `#${key}`;
const targetMap = original[targetKey] ?? {};
const type = targetMap["@type"] ?? "";
if (type == this.type) {
return {
[key]: {
"@type": this.type,
"@time": value * 1000, // Convert milliseconds to microseconds
"@now": false,
"@source": "server"
},
[targetKey]: null,
};
}
}
else if (value instanceof firestore_1.Timestamp) {
const targetKey = `#${key}`;
const targetMap = original[targetKey] ?? {};
const type = targetMap["@type"] ?? "";
// Convert Timestamp to ModelTimestamp even without metadata (type === "")
if (type == this.type || type === "") {
// Return a proper ModelTimestamp instance so .value() works
const instance = new model_field_value_1.ModelTimestamp(undefined, "server");
instance["@time"] = value.toMillis() * 1000; // Store microseconds for .value() to work correctly
return {
[key]: instance,
[targetKey]: null,
};
}
}
else if (Array.isArray(value)) {
const targetKey = `#${key}`;
const targetList = original[targetKey] ?? [];
if (targetList != null && targetList.length > 0 && targetList.every((e) => e["@type"] === this.type)) {
const res = [];
for (const tmp of value) {
if (typeof tmp === "number") {
res.push({
"@type": this.type,
"@time": tmp * 1000, // Convert milliseconds to microseconds
"@now": false,
"@source": "server"
});
}
else if (tmp instanceof firestore_1.Timestamp) {
res.push({
"@type": this.type,
"@time": tmp.toMillis() * 1000, // Convert milliseconds to microseconds
"@now": false,
"@source": "server"
});
}
}
if (res.length > 0) {
return {
[key]: res,
[targetKey]: null,
};
}
}
}
else if ((0, utils_1.isDynamicMap)(value)) {
const targetKey = `#${key}`;
const targetMap = original[targetKey] ?? {};
targetMap;
if (targetMap != null) {
const res = {};
for (const key in value) {
const val = value[key];
const mapVal = targetMap[key] ?? {};
const type = mapVal["@type"] ?? "";
if (type != this.type) {
continue;
}
if (typeof val === "number") {
res[key] = {
"@type": this.type,
"@time": val * 1000, // Convert milliseconds to microseconds
"@now": false,
"@source": "server"
};
}
else if (val instanceof firestore_1.Timestamp) {
res[key] = {
"@type": this.type,
"@time": val.toMillis() * 1000, // Convert milliseconds to microseconds
"@now": false,
"@source": "server"
};
}
}
if (Object.keys(res).length > 0) {
return {
[key]: res,
[targetKey]: null,
};
}
}
}
return null;
}
convertTo(key, value, _original, firestoreInstance) {
if (value !== null && typeof value === "object" && "@type" in value) {
const type = value["@type"] ?? "";
if (type === this.type) {
const fromUser = (value["@source"] ?? "") === "user";
const val = value["@time"] ?? 0;
const useNow = value["@now"] ?? false;
const targetKey = `#${key}`;
const result = {
[targetKey]: {
"@type": this.type,
"@time": val,
"@target": key,
},
};
if (fromUser) {
if (useNow) {
result[key] = firestore_2.FieldValue.serverTimestamp();
}
else {
result[key] = createTimestampFromMicroseconds(val);
}
}
else {
result[key] = createTimestampFromMicroseconds(val);
}
return result;
}
}
else if (Array.isArray(value)) {
const list = value.filter((e) => e != null && typeof e === "object" && "@type" in e);
if (list.length > 0 && list.every((e) => e["@type"] === this.type)) {
const target = [];
const res = [];
const targetKey = `#${key}`;
for (const entry of list) {
const fromUser = (entry["@source"] ?? "") === "user";
const time = entry["@time"] ?? 0;
const useNow = entry["@now"] ?? false;
target.push({
"@type": this.type,
"@time": time,
"@target": key,
});
if (fromUser) {
if (useNow) {
res.push(firestore_2.FieldValue.serverTimestamp());
}
else {
res.push(createTimestampFromMicroseconds(time));
}
}
else {
res.push(createTimestampFromMicroseconds(time));
}
}
return {
[targetKey]: target,
[key]: res,
};
}
}
else if ((0, utils_1.isDynamicMap)(value)) {
const map = {};
for (const k in value) {
const v = value[k];
if (v != null && typeof v === "object" && "@type" in v) {
map[k] = v;
}
}
if (Object.keys(map).length > 0 && Object.values(map).every((e) => e["@type"] === this.type)) {
const target = {};
const res = {};
const targetKey = `#${key}`;
for (const [k, entry] of Object.entries(map)) {
const fromUser = (entry["@source"] ?? "") === "user";
const time = entry["@time"] ?? 0;
const useNow = entry["@now"] ?? false;
target[k] = {
"@type": this.type,
"@time": time,
"@target": key,
};
if (fromUser) {
if (useNow) {
res[k] = firestore_2.FieldValue.serverTimestamp();
}
else {
res[k] = createTimestampFromMicroseconds(time);
}
}
else {
res[k] = createTimestampFromMicroseconds(time);
}
}
return {
[targetKey]: target,
[key]: res,
};
}
}
return null;
}
}
exports.FirestoreModelTimestampConverter = FirestoreModelTimestampConverter;
//# sourceMappingURL=model_timestamp_converter.js.map