@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
150 lines • 4.87 kB
JavaScript
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
import { BsonTypeTag, PRIMARY_KEY } from "./types.js";
import { isPlainObject } from "../../utils/records.js";
import { compareCodePoints } from "../../utils/sort.js";
function bump(counts, path, tag) {
let inner = counts.get(path);
if (inner === undefined) {
inner = new Map();
counts.set(path, inner);
}
inner.set(tag, (inner.get(tag) ?? 0) + 1);
}
function isObjectIdLike(v) {
if (typeof v !== 'object' || v === null)
return false;
const proto = v._bsontype;
return proto === 'ObjectId' || proto === 'ObjectID';
}
function isDecimalLike(v) {
if (typeof v !== 'object' || v === null)
return false;
return v._bsontype === 'Decimal128';
}
function isBinaryLike(v) {
if (typeof v !== 'object' || v === null)
return false;
return v._bsontype === 'Binary';
}
function isLongLike(v) {
if (typeof v !== 'object' || v === null)
return false;
return v._bsontype === 'Long';
}
function isTimestampLike(v) {
if (typeof v !== 'object' || v === null)
return false;
return v._bsontype === 'Timestamp';
}
function isRegexLike(v) {
if (v instanceof RegExp)
return true;
if (typeof v !== 'object' || v === null)
return false;
return v._bsontype === 'BSONRegExp';
}
function isDBRefLike(v) {
if (typeof v !== 'object' || v === null)
return false;
return v._bsontype === 'DBRef';
}
function scalarTag(v) {
if (typeof v === 'boolean')
return BsonTypeTag.BOOL;
if (isLongLike(v))
return BsonTypeTag.LONG;
if (typeof v === 'number')
return Number.isInteger(v) ? BsonTypeTag.INT : BsonTypeTag.DOUBLE;
if (typeof v === 'string')
return BsonTypeTag.STRING;
if (isObjectIdLike(v))
return BsonTypeTag.OBJECT_ID;
if (isDecimalLike(v))
return BsonTypeTag.DECIMAL;
if (v instanceof Date)
return BsonTypeTag.DATE;
if (isTimestampLike(v))
return BsonTypeTag.TIMESTAMP;
if (isBinaryLike(v))
return BsonTypeTag.BINARY;
if (isRegexLike(v))
return BsonTypeTag.REGEX;
if (isDBRefLike(v))
return BsonTypeTag.OBJECT;
if (v === null)
return BsonTypeTag.NULL;
return BsonTypeTag.UNKNOWN;
}
function arrayTag(items) {
if (items.length === 0)
return BsonTypeTag.ARRAY;
if (items.every((x) => typeof x === 'number' && Number.isFinite(x))) {
return `array<${BsonTypeTag.DOUBLE}>(${String(items.length)})`;
}
if (items.every((x) => typeof x === 'string')) {
return `array<${BsonTypeTag.STRING}>`;
}
return BsonTypeTag.ARRAY;
}
function walk(value, prefix, counts) {
if (isPlainObject(value)) {
if (prefix !== '')
bump(counts, prefix, BsonTypeTag.OBJECT);
for (const [k, v] of Object.entries(value)) {
const next = prefix === '' ? k : `${prefix}.${k}`;
walk(v, next, counts);
}
return;
}
if (Array.isArray(value)) {
if (prefix !== '')
bump(counts, prefix, arrayTag(value));
return;
}
if (prefix !== '')
bump(counts, prefix, scalarTag(value));
}
export async function sampleFieldTypes(accessor, database, collection, sampleSize = 100) {
const counts = new Map();
let total = 0;
for await (const doc of accessor.driver.iterDocuments(database, collection, {
batchSize: sampleSize,
sort: { _id: 1 },
})) {
total++;
walk(doc, '', counts);
if (total >= sampleSize)
break;
}
if (total === 0)
return [];
const fields = [];
for (const path of [...counts.keys()].sort(compareCodePoints)) {
if (path === PRIMARY_KEY)
continue;
const inner = counts.get(path) ?? new Map();
const presenceCount = [...inner.values()].reduce((a, b) => a + b, 0);
const types = {};
for (const [t, c] of inner)
types[t] = c / total;
fields.push({
path,
presence: presenceCount / total,
types,
});
}
return fields;
}
//# sourceMappingURL=_sampler.js.map