@rubytech/create-maxy 1.0.651 → 1.0.652
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +115 -6
- package/dist/pinned-binaries.js +43 -0
- package/package.json +1 -1
- package/payload/platform/lib/graph-trash/dist/index.d.ts +91 -0
- package/payload/platform/lib/graph-trash/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/graph-trash/dist/index.js +238 -0
- package/payload/platform/lib/graph-trash/dist/index.js.map +1 -0
- package/payload/platform/lib/graph-trash/src/index.ts +360 -0
- package/payload/platform/lib/graph-trash/tsconfig.json +8 -0
- package/payload/platform/neo4j/schema.cypher +19 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/contacts/mcp/dist/index.js +9 -4
- package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.d.ts +16 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.js +23 -10
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.js +2 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js +8 -4
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js.map +1 -1
- package/payload/platform/plugins/docs/references/deployment.md +1 -1
- package/payload/platform/plugins/docs/references/troubleshooting.md +27 -0
- package/payload/platform/plugins/memory/PLUGIN.md +4 -2
- package/payload/platform/plugins/memory/mcp/dist/index.js +92 -28
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts +30 -15
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js +46 -84
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.d.ts +22 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js +36 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +16 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-list-attachments.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-list-attachments.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-list-attachments.js +42 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-list-attachments.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.d.ts +24 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.js +40 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js +35 -10
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js.map +1 -1
- package/payload/platform/plugins/memory/references/graph-primitives.md +49 -3
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +4 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/scripts/lib/resolve-account-dir.sh +166 -0
- package/payload/platform/scripts/seed-neo4j.sh +7 -11
- package/payload/platform/templates/systemd/maxy-ttyd.service +6 -1
- package/payload/server/public/assets/{admin-S2KHPNe4.js → admin-DQxieG3v.js} +1 -1
- package/payload/server/public/assets/data-CAKMrPTQ.js +1 -0
- package/payload/server/public/assets/{file-CRrDfnO1.js → file-dBmvpAuH.js} +1 -1
- package/payload/server/public/assets/{graph-CSBMZGGe.js → graph-3snSy3WW.js} +2 -2
- package/payload/server/public/assets/{house-D1CBraxB.js → house-IMEjNkQf.js} +1 -1
- package/payload/server/public/assets/{jsx-runtime-CZtLX8NN.css → jsx-runtime-BJhXEiL3.css} +1 -1
- package/payload/server/public/assets/{public-ukz9-gSe.js → public-b43rEAhq.js} +1 -1
- package/payload/server/public/assets/{share-2-DkF8neDM.js → share-2-ARoCxH5K.js} +1 -1
- package/payload/server/public/assets/{trash-2-Dde58AAR.js → trash-2-D_Rm8z21.js} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-Hz9X6luB.js → useVoiceRecorder-Cw8gxj1L.js} +1 -1
- package/payload/server/public/assets/x-CFPIrGuL.js +1 -0
- package/payload/server/public/data.html +7 -7
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +8 -8
- package/payload/server/public/public.html +5 -5
- package/payload/server/server.js +19 -0
- package/payload/server/public/assets/data-BajF3t1i.js +0 -1
- package/payload/server/public/assets/x-D52qhSya.js +0 -1
- /package/payload/server/public/assets/{jsx-runtime-Cb-WunFZ.js → jsx-runtime-CXoJCO3U.js} +0 -0
package/dist/index.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
|
3
3
|
import { existsSync, mkdirSync, writeFileSync, cpSync, readFileSync, rmSync, readdirSync, appendFileSync, openSync, closeSync, chmodSync, symlinkSync, unlinkSync, lstatSync, readlinkSync, accessSync, constants as fsConstants } from "node:fs";
|
|
4
4
|
import { resolve, join, dirname } from "node:path";
|
|
5
|
-
import { randomBytes } from "node:crypto";
|
|
5
|
+
import { randomBytes, createHash } from "node:crypto";
|
|
6
|
+
import { TTYD_VERSION, TTYD_SHA256_BY_ARCH, mapUnameToTtydArch, ttydDownloadUrl, } from "./pinned-binaries.js";
|
|
6
7
|
const PAYLOAD_DIR = resolve(import.meta.dirname, "../payload");
|
|
7
8
|
// Brand manifest — read from payload to derive all brand-specific installation values.
|
|
8
9
|
// The bundler stamps brand.json into the payload at build time.
|
|
@@ -220,11 +221,10 @@ function installSystemDeps() {
|
|
|
220
221
|
shell("apt-get", ["install", "-y", "curl", "git", "unzip", "jq", "avahi-daemon", "avahi-utils", "poppler-utils", "ffmpeg"], { sudo: true });
|
|
221
222
|
shell("apt-get", ["install", "-y", "tigervnc-standalone-server", "python3-websockify", "novnc", "xdg-utils", "chromium"], { sudo: true });
|
|
222
223
|
shell("apt-get", ["install", "-y", "hostapd", "dnsmasq"], { sudo: true });
|
|
223
|
-
//
|
|
224
|
-
//
|
|
225
|
-
//
|
|
226
|
-
|
|
227
|
-
shell("apt-get", ["install", "-y", "ttyd", "tmux"], { sudo: true });
|
|
224
|
+
// tmux backs the admin terminal's persistent named session (Task 591).
|
|
225
|
+
// ttyd is NOT in Debian Bookworm's apt repo (Task 602) — it ships as a
|
|
226
|
+
// pinned upstream binary installed by provisionTtydBinary() in step 11.
|
|
227
|
+
shell("apt-get", ["install", "-y", "tmux"], { sudo: true });
|
|
228
228
|
}
|
|
229
229
|
else {
|
|
230
230
|
console.log(" Skipping apt-get (sudo unavailable non-interactively — deps assumed present from prior install)");
|
|
@@ -1504,6 +1504,103 @@ function installCrons() {
|
|
|
1504
1504
|
logFile(` crontab write failed: ${write.stderr}`);
|
|
1505
1505
|
}
|
|
1506
1506
|
}
|
|
1507
|
+
const TTYD_INSTALL_PATH = "/usr/local/bin/ttyd";
|
|
1508
|
+
function sha256File(path) {
|
|
1509
|
+
const hash = createHash("sha256");
|
|
1510
|
+
hash.update(readFileSync(path));
|
|
1511
|
+
return hash.digest("hex");
|
|
1512
|
+
}
|
|
1513
|
+
// Provision the upstream ttyd binary into /usr/local/bin/ttyd. Degrades with
|
|
1514
|
+
// a loud warning and a copy-pasteable remediation command on any failure —
|
|
1515
|
+
// never throws. Contract: the caller (installTerminalService) uses the
|
|
1516
|
+
// presence of TTYD_INSTALL_PATH after return to decide whether to enable the
|
|
1517
|
+
// maxy-ttyd.service systemd unit. ttyd is NOT in Debian Bookworm apt, so we
|
|
1518
|
+
// own the full download / verify / install flow here.
|
|
1519
|
+
function provisionTtydBinary() {
|
|
1520
|
+
const unameRaw = spawnSync("uname", ["-m"], { encoding: "utf-8", stdio: "pipe", timeout: 5_000 });
|
|
1521
|
+
const uname = (unameRaw.stdout || "").trim();
|
|
1522
|
+
const arch = mapUnameToTtydArch(uname);
|
|
1523
|
+
if (arch === null) {
|
|
1524
|
+
console.error(` WARNING: ttyd — unsupported architecture 'uname -m'='${uname}'. Admin terminal will be unavailable.`);
|
|
1525
|
+
console.error(` Remediate: install ttyd ${TTYD_VERSION} manually for your platform and place it at ${TTYD_INSTALL_PATH}, then 'sudo chmod +x ${TTYD_INSTALL_PATH}'.`);
|
|
1526
|
+
return false;
|
|
1527
|
+
}
|
|
1528
|
+
const pinnedDigest = TTYD_SHA256_BY_ARCH[arch];
|
|
1529
|
+
const url = ttydDownloadUrl(arch);
|
|
1530
|
+
const remediation = `curl -L -o /tmp/ttyd.${arch} '${url}' && sudo mv /tmp/ttyd.${arch} ${TTYD_INSTALL_PATH} && sudo chmod +x ${TTYD_INSTALL_PATH}`;
|
|
1531
|
+
// Idempotency: existing binary with matching pinned digest → skip download.
|
|
1532
|
+
if (existsSync(TTYD_INSTALL_PATH)) {
|
|
1533
|
+
try {
|
|
1534
|
+
const existingDigest = sha256File(TTYD_INSTALL_PATH);
|
|
1535
|
+
if (existingDigest === pinnedDigest) {
|
|
1536
|
+
console.log(` ttyd ${TTYD_VERSION} already installed at ${TTYD_INSTALL_PATH} (SHA256 match — skipping download)`);
|
|
1537
|
+
return true;
|
|
1538
|
+
}
|
|
1539
|
+
console.log(` ttyd at ${TTYD_INSTALL_PATH} has different digest — replacing with pinned ${TTYD_VERSION}`);
|
|
1540
|
+
}
|
|
1541
|
+
catch (err) {
|
|
1542
|
+
console.error(` WARNING: could not read existing ${TTYD_INSTALL_PATH}: ${err instanceof Error ? err.message : String(err)} — will overwrite`);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
if (!canSudo()) {
|
|
1546
|
+
console.error(` WARNING: ttyd — sudo unavailable non-interactively, cannot write ${TTYD_INSTALL_PATH}. Admin terminal will be unavailable.`);
|
|
1547
|
+
console.error(` Remediate: ${remediation}`);
|
|
1548
|
+
return false;
|
|
1549
|
+
}
|
|
1550
|
+
const tmpPath = `/tmp/ttyd.${arch}`;
|
|
1551
|
+
try {
|
|
1552
|
+
console.log(` Downloading ttyd ${TTYD_VERSION} for ${arch} from ${url}`);
|
|
1553
|
+
shellRetry("curl", ["-fL", "--retry", "3", "--retry-delay", "5", "-o", tmpPath, url], { timeout: 60_000 });
|
|
1554
|
+
}
|
|
1555
|
+
catch (err) {
|
|
1556
|
+
console.error(` WARNING: ttyd download failed: ${err instanceof Error ? err.message : String(err)}. Admin terminal will be unavailable.`);
|
|
1557
|
+
console.error(` Remediate: ${remediation}`);
|
|
1558
|
+
try {
|
|
1559
|
+
unlinkSync(tmpPath);
|
|
1560
|
+
}
|
|
1561
|
+
catch { /* nothing to clean */ }
|
|
1562
|
+
return false;
|
|
1563
|
+
}
|
|
1564
|
+
let actualDigest;
|
|
1565
|
+
try {
|
|
1566
|
+
actualDigest = sha256File(tmpPath);
|
|
1567
|
+
}
|
|
1568
|
+
catch (err) {
|
|
1569
|
+
console.error(` WARNING: ttyd — could not read downloaded file ${tmpPath}: ${err instanceof Error ? err.message : String(err)}. Admin terminal will be unavailable.`);
|
|
1570
|
+
try {
|
|
1571
|
+
unlinkSync(tmpPath);
|
|
1572
|
+
}
|
|
1573
|
+
catch { /* nothing to clean */ }
|
|
1574
|
+
return false;
|
|
1575
|
+
}
|
|
1576
|
+
if (actualDigest !== pinnedDigest) {
|
|
1577
|
+
console.error(` WARNING: ttyd SHA256 mismatch — refusing to install unverified binary.`);
|
|
1578
|
+
console.error(` expected: ${pinnedDigest}`);
|
|
1579
|
+
console.error(` actual: ${actualDigest}`);
|
|
1580
|
+
console.error(` Admin terminal will be unavailable. A later installer version may pin a newer digest.`);
|
|
1581
|
+
try {
|
|
1582
|
+
unlinkSync(tmpPath);
|
|
1583
|
+
}
|
|
1584
|
+
catch { /* nothing to clean */ }
|
|
1585
|
+
return false;
|
|
1586
|
+
}
|
|
1587
|
+
console.log(` ttyd ${TTYD_VERSION} SHA256 verified (${actualDigest.slice(0, 12)}…)`);
|
|
1588
|
+
try {
|
|
1589
|
+
shell("mv", [tmpPath, TTYD_INSTALL_PATH], { sudo: true });
|
|
1590
|
+
shell("chmod", ["+x", TTYD_INSTALL_PATH], { sudo: true });
|
|
1591
|
+
}
|
|
1592
|
+
catch (err) {
|
|
1593
|
+
console.error(` WARNING: ttyd — could not install to ${TTYD_INSTALL_PATH}: ${err instanceof Error ? err.message : String(err)}. Admin terminal will be unavailable.`);
|
|
1594
|
+
console.error(` Remediate: ${remediation}`);
|
|
1595
|
+
try {
|
|
1596
|
+
unlinkSync(tmpPath);
|
|
1597
|
+
}
|
|
1598
|
+
catch { /* already moved or cleaned */ }
|
|
1599
|
+
return false;
|
|
1600
|
+
}
|
|
1601
|
+
console.log(` ttyd ${TTYD_VERSION} installed at ${TTYD_INSTALL_PATH}`);
|
|
1602
|
+
return true;
|
|
1603
|
+
}
|
|
1507
1604
|
function installTerminalService() {
|
|
1508
1605
|
log("11", TOTAL, "Installing admin terminal service (ttyd + tmux)...");
|
|
1509
1606
|
if (!isLinux()) {
|
|
@@ -1511,6 +1608,11 @@ function installTerminalService() {
|
|
|
1511
1608
|
console.log(" brew install ttyd tmux && ttyd -p 7681 -i 127.0.0.1 -W tmux new-session -A -s maxy-pty");
|
|
1512
1609
|
return;
|
|
1513
1610
|
}
|
|
1611
|
+
// ttyd is provisioned from upstream GitHub releases (pinned + SHA256-verified)
|
|
1612
|
+
// because Debian Bookworm's apt does NOT carry a ttyd package (Task 602).
|
|
1613
|
+
// A failure here is loud but non-fatal — the rest of the install completes
|
|
1614
|
+
// and the admin UI degrades to "terminal unavailable" per Task 603.
|
|
1615
|
+
const ttydReady = provisionTtydBinary();
|
|
1514
1616
|
// Default ~/.tmux.conf — only written if the operator doesn't already have
|
|
1515
1617
|
// one. `history-limit 50000` is load-bearing: a closed-tab + reopen during
|
|
1516
1618
|
// an upgrade must show every line the operator missed in scrollback.
|
|
@@ -1541,6 +1643,13 @@ function installTerminalService() {
|
|
|
1541
1643
|
// unit and every subsequent install is a no-op (idempotent overwrite).
|
|
1542
1644
|
const systemdUserDir = resolve(homeDir, ".config/systemd/user");
|
|
1543
1645
|
mkdirSync(systemdUserDir, { recursive: true });
|
|
1646
|
+
// Skip systemd-unit install if the ttyd binary is not in place — enabling
|
|
1647
|
+
// a unit whose ExecStart points at a missing file just churns systemd with
|
|
1648
|
+
// restart failures.
|
|
1649
|
+
if (!ttydReady) {
|
|
1650
|
+
console.error(" Skipping maxy-ttyd.service install — ttyd binary not present. Admin terminal will be unavailable until remediated.");
|
|
1651
|
+
return;
|
|
1652
|
+
}
|
|
1544
1653
|
const ttydUnitTemplate = resolve(INSTALL_DIR, "platform/templates/systemd/maxy-ttyd.service");
|
|
1545
1654
|
const ttydUnitDest = join(systemdUserDir, "maxy-ttyd.service");
|
|
1546
1655
|
try {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Pinned upstream binaries installed by the Linux provisioner.
|
|
2
|
+
//
|
|
3
|
+
// Some binaries we depend on are not available in Debian Bookworm's apt repo
|
|
4
|
+
// (e.g. ttyd — entered Debian trixie and Ubuntu 22.04+ but NOT Bookworm, which
|
|
5
|
+
// is the base of current Raspberry Pi OS). For those, we download the upstream
|
|
6
|
+
// prebuilt static binary from GitHub releases, SHA256-verified, and place it
|
|
7
|
+
// under /usr/local/bin. This module is the single source of truth for every
|
|
8
|
+
// such dependency — version bumps are a one-file change.
|
|
9
|
+
//
|
|
10
|
+
// Verification rule: on SHA256 mismatch the installer aborts the download
|
|
11
|
+
// step with a loud error and never writes the binary. No silent-install of
|
|
12
|
+
// unverified bytes. See packages/create-maxy/src/index.ts → provisionTtydBinary.
|
|
13
|
+
export const TTYD_VERSION = '1.7.7';
|
|
14
|
+
// Asset file name as published on github.com/tsl0922/ttyd/releases.
|
|
15
|
+
export const TTYD_ASSET_BY_ARCH = {
|
|
16
|
+
aarch64: 'ttyd.aarch64',
|
|
17
|
+
arm: 'ttyd.arm',
|
|
18
|
+
x86_64: 'ttyd.x86_64',
|
|
19
|
+
};
|
|
20
|
+
// SHA256 digest of each asset for TTYD_VERSION. Computed by downloading the
|
|
21
|
+
// release asset directly from GitHub and running `sha256sum`. Bump together
|
|
22
|
+
// with TTYD_VERSION — never update one without the other.
|
|
23
|
+
export const TTYD_SHA256_BY_ARCH = {
|
|
24
|
+
aarch64: 'b38acadd89d1d396a0f5649aa52c539edbad07f4bc7348b27b4f4b7219dd4165',
|
|
25
|
+
arm: '05eac1223914f18c65898d72c8d14e76bbb5435f7762c6dc7f16f041994a8109',
|
|
26
|
+
x86_64: '8a217c968aba172e0dbf3f34447218dc015bc4d5e59bf51db2f2cd12b7be4f55',
|
|
27
|
+
};
|
|
28
|
+
// Map Linux kernel `uname -m` output to a TtydArch key. Returns null for
|
|
29
|
+
// architectures we have not pinned a binary for — the caller must treat this
|
|
30
|
+
// as a hard error (no silent fallback, no "try latest").
|
|
31
|
+
export function mapUnameToTtydArch(uname) {
|
|
32
|
+
const trimmed = uname.trim();
|
|
33
|
+
if (trimmed === 'aarch64' || trimmed === 'arm64')
|
|
34
|
+
return 'aarch64';
|
|
35
|
+
if (trimmed === 'armv7l' || trimmed === 'armv6l' || trimmed === 'arm')
|
|
36
|
+
return 'arm';
|
|
37
|
+
if (trimmed === 'x86_64' || trimmed === 'amd64')
|
|
38
|
+
return 'x86_64';
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
export function ttydDownloadUrl(arch) {
|
|
42
|
+
return `https://github.com/tsl0922/ttyd/releases/download/${TTYD_VERSION}/${TTYD_ASSET_BY_ARCH[arch]}`;
|
|
43
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Soft-delete primitive for the knowledge graph.
|
|
3
|
+
*
|
|
4
|
+
* MCP-tool callers must NEVER `DETACH DELETE` user-domain nodes. Use
|
|
5
|
+
* `trashNode` to mark a node `:Trashed`; `restoreNode` removes the label;
|
|
6
|
+
* `emptyTrash` hard-deletes nodes whose `trashedAt < now - graceDays`. The
|
|
7
|
+
* 2026-04-20 incident wiped 19 nodes via a single autonomous `DETACH DELETE`
|
|
8
|
+
* — Neo4j Community has no PITR, so properties were unrecoverable. This
|
|
9
|
+
* primitive contains the blast radius for every caller.
|
|
10
|
+
*
|
|
11
|
+
* Unique-constraint handling: when the trashed node's labels carry single-
|
|
12
|
+
* key UNIQUE constraints (e.g. `OnboardingState.accountId`), the live values
|
|
13
|
+
* are snapshotted into `_trashedKeys` (JSON) and nulled on the node, so
|
|
14
|
+
* MERGE against the same key won't collide. `restoreNode` writes them back
|
|
15
|
+
* and fails loudly when an active node already occupies the slot.
|
|
16
|
+
*/
|
|
17
|
+
import type { Session } from "neo4j-driver";
|
|
18
|
+
export interface TrashParams {
|
|
19
|
+
session: Session;
|
|
20
|
+
accountId: string;
|
|
21
|
+
elementId: string;
|
|
22
|
+
/** Provenance marker — appears verbatim in `trashedBy` and `[trash:marked] by=`. */
|
|
23
|
+
by: string;
|
|
24
|
+
reason?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface TrashResult {
|
|
27
|
+
trashed: boolean;
|
|
28
|
+
alreadyTrashed: boolean;
|
|
29
|
+
nodeId: string;
|
|
30
|
+
/** Labels excluding `:Trashed`. */
|
|
31
|
+
labels: string[];
|
|
32
|
+
trashedAt: string;
|
|
33
|
+
originalKeys: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
export declare function trashNode(params: TrashParams): Promise<TrashResult>;
|
|
36
|
+
export interface RestoreParams {
|
|
37
|
+
session: Session;
|
|
38
|
+
accountId: string;
|
|
39
|
+
elementId: string;
|
|
40
|
+
}
|
|
41
|
+
export interface RestoreResult {
|
|
42
|
+
restored: boolean;
|
|
43
|
+
nodeId: string;
|
|
44
|
+
labels: string[];
|
|
45
|
+
restoredKeys: Record<string, unknown>;
|
|
46
|
+
}
|
|
47
|
+
export declare function restoreNode(params: RestoreParams): Promise<RestoreResult>;
|
|
48
|
+
export interface EmptyTrashParams {
|
|
49
|
+
session: Session;
|
|
50
|
+
accountId: string;
|
|
51
|
+
/** Default 30. */
|
|
52
|
+
graceDays?: number;
|
|
53
|
+
dryRun?: boolean;
|
|
54
|
+
/** Optional label whitelist — only nodes carrying any of these labels are eligible. */
|
|
55
|
+
labels?: string[];
|
|
56
|
+
/** Side-effect callback invoked per emptied node, e.g. to clean disk attachments. */
|
|
57
|
+
onEmpty?: (node: TrashCandidate) => Promise<void>;
|
|
58
|
+
}
|
|
59
|
+
export interface TrashCandidate {
|
|
60
|
+
elementId: string;
|
|
61
|
+
labels: string[];
|
|
62
|
+
trashedAt: string;
|
|
63
|
+
trashedBy: string | null;
|
|
64
|
+
/** Original unique-key snapshot — useful for KnowledgeDocument disk cleanup. */
|
|
65
|
+
trashedKeys: Record<string, unknown>;
|
|
66
|
+
}
|
|
67
|
+
export interface EmptyTrashResult {
|
|
68
|
+
graceDays: number;
|
|
69
|
+
dryRun: boolean;
|
|
70
|
+
candidates: TrashCandidate[];
|
|
71
|
+
emptied: number;
|
|
72
|
+
}
|
|
73
|
+
export declare function emptyTrash(params: EmptyTrashParams): Promise<EmptyTrashResult>;
|
|
74
|
+
/**
|
|
75
|
+
* Read-filter clause excluding trashed nodes for the given Cypher alias.
|
|
76
|
+
*
|
|
77
|
+
* Filters both the `:Trashed` label (Task 576 primitive) and the legacy
|
|
78
|
+
* `deletedAt` property (KnowledgeDocument soft-delete pre-Task 576). The
|
|
79
|
+
* `deletedAt` arm is a transitional belt-and-braces — production graphs may
|
|
80
|
+
* still hold pre-migration soft-deletes — and stays until those are confirmed
|
|
81
|
+
* empty, then is dropped.
|
|
82
|
+
*
|
|
83
|
+
* notTrashed("node") → "(NOT node:Trashed AND node.deletedAt IS NULL)"
|
|
84
|
+
* notTrashed("related") → "(NOT related:Trashed AND related.deletedAt IS NULL)"
|
|
85
|
+
*/
|
|
86
|
+
export declare function notTrashed(alias: string): string;
|
|
87
|
+
/** Runtime accessor for the static unique-keys map (for tests + sibling tooling). */
|
|
88
|
+
export declare function uniqueKeysForLabels(labels: string[]): string[];
|
|
89
|
+
/** Property names trashNode writes — exposed so callers can re-MERGE without colliding. */
|
|
90
|
+
export declare const TRASH_METADATA_PROPS: readonly string[];
|
|
91
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAuC5C,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAyEzE;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAkE/E;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uFAAuF;IACvF,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,qFAAqF;IACrF,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gFAAgF;IAChF,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA0EpF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,qFAAqF;AACrF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAI9D;AAED,2FAA2F;AAC3F,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAAqB,CAAC"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Soft-delete primitive for the knowledge graph.
|
|
4
|
+
*
|
|
5
|
+
* MCP-tool callers must NEVER `DETACH DELETE` user-domain nodes. Use
|
|
6
|
+
* `trashNode` to mark a node `:Trashed`; `restoreNode` removes the label;
|
|
7
|
+
* `emptyTrash` hard-deletes nodes whose `trashedAt < now - graceDays`. The
|
|
8
|
+
* 2026-04-20 incident wiped 19 nodes via a single autonomous `DETACH DELETE`
|
|
9
|
+
* — Neo4j Community has no PITR, so properties were unrecoverable. This
|
|
10
|
+
* primitive contains the blast radius for every caller.
|
|
11
|
+
*
|
|
12
|
+
* Unique-constraint handling: when the trashed node's labels carry single-
|
|
13
|
+
* key UNIQUE constraints (e.g. `OnboardingState.accountId`), the live values
|
|
14
|
+
* are snapshotted into `_trashedKeys` (JSON) and nulled on the node, so
|
|
15
|
+
* MERGE against the same key won't collide. `restoreNode` writes them back
|
|
16
|
+
* and fails loudly when an active node already occupies the slot.
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.TRASH_METADATA_PROPS = void 0;
|
|
20
|
+
exports.trashNode = trashNode;
|
|
21
|
+
exports.restoreNode = restoreNode;
|
|
22
|
+
exports.emptyTrash = emptyTrash;
|
|
23
|
+
exports.notTrashed = notTrashed;
|
|
24
|
+
exports.uniqueKeysForLabels = uniqueKeysForLabels;
|
|
25
|
+
/**
|
|
26
|
+
* Single-key UNIQUE properties per label, mirroring `platform/neo4j/schema.cypher`.
|
|
27
|
+
*
|
|
28
|
+
* Composite UNIQUEs (UserProfile, Email composite, AccessGrant) are
|
|
29
|
+
* represented by a single nullable component — Neo4j enforces a composite
|
|
30
|
+
* constraint only when every component is non-null, so nulling one frees it.
|
|
31
|
+
*/
|
|
32
|
+
const UNIQUE_KEYS_BY_LABEL = {
|
|
33
|
+
Person: ["email", "telephone"],
|
|
34
|
+
Service: ["serviceId"],
|
|
35
|
+
LocalBusiness: ["accountId"],
|
|
36
|
+
Task: ["taskId"],
|
|
37
|
+
Event: ["eventId"],
|
|
38
|
+
KnowledgeDocument: ["attachmentId"],
|
|
39
|
+
DigitalDocument: ["attachmentId"],
|
|
40
|
+
Conversation: ["conversationId", "sessionKey"],
|
|
41
|
+
Message: ["messageId"],
|
|
42
|
+
OnboardingState: ["accountId"],
|
|
43
|
+
Workflow: ["workflowId"],
|
|
44
|
+
WorkflowStep: ["stepId"],
|
|
45
|
+
WorkflowRun: ["runId"],
|
|
46
|
+
Preference: ["preferenceId"],
|
|
47
|
+
Email: ["emailId", "messageId"],
|
|
48
|
+
AdminUser: ["userId"],
|
|
49
|
+
ToolCall: ["callId"],
|
|
50
|
+
// Composite component nulls — frees the composite constraint:
|
|
51
|
+
AccessGrant: ["contactValue"], // composite (contactValue, agentSlug, accountId)
|
|
52
|
+
UserProfile: ["userId"], // composite (accountId, userId)
|
|
53
|
+
};
|
|
54
|
+
const TRASH_PROP_NAMES = [
|
|
55
|
+
"trashedAt",
|
|
56
|
+
"trashedBy",
|
|
57
|
+
"trashReason",
|
|
58
|
+
"_trashedKeys",
|
|
59
|
+
];
|
|
60
|
+
async function trashNode(params) {
|
|
61
|
+
const { session, accountId, elementId, by, reason } = params;
|
|
62
|
+
const lookup = await session.run(`MATCH (n) WHERE elementId(n) = $eid AND n.accountId = $accountId
|
|
63
|
+
RETURN labels(n) AS labels, properties(n) AS props`, { eid: elementId, accountId });
|
|
64
|
+
if (lookup.records.length === 0) {
|
|
65
|
+
throw new Error(`trashNode: node not found (elementId=${elementId} accountId=${accountId.slice(0, 8)}…)`);
|
|
66
|
+
}
|
|
67
|
+
const allLabels = lookup.records[0].get("labels");
|
|
68
|
+
const props = lookup.records[0].get("props");
|
|
69
|
+
const baseLabels = allLabels.filter((l) => l !== "Trashed");
|
|
70
|
+
if (allLabels.includes("Trashed")) {
|
|
71
|
+
return {
|
|
72
|
+
trashed: false,
|
|
73
|
+
alreadyTrashed: true,
|
|
74
|
+
nodeId: elementId,
|
|
75
|
+
labels: baseLabels,
|
|
76
|
+
trashedAt: String(props.trashedAt ?? ""),
|
|
77
|
+
originalKeys: {},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const uniqueKeys = new Set();
|
|
81
|
+
for (const label of baseLabels) {
|
|
82
|
+
for (const key of UNIQUE_KEYS_BY_LABEL[label] ?? [])
|
|
83
|
+
uniqueKeys.add(key);
|
|
84
|
+
}
|
|
85
|
+
const originalKeys = {};
|
|
86
|
+
for (const k of uniqueKeys) {
|
|
87
|
+
if (props[k] !== undefined && props[k] !== null)
|
|
88
|
+
originalKeys[k] = props[k];
|
|
89
|
+
}
|
|
90
|
+
const setNullClauses = Object.keys(originalKeys)
|
|
91
|
+
.map((k) => `n.\`${k}\` = null`)
|
|
92
|
+
.join(", ");
|
|
93
|
+
const setNullSuffix = setNullClauses ? `, ${setNullClauses}` : "";
|
|
94
|
+
const trashedAt = new Date().toISOString();
|
|
95
|
+
await session.run(`MATCH (n) WHERE elementId(n) = $eid
|
|
96
|
+
SET n:Trashed,
|
|
97
|
+
n.trashedAt = datetime($trashedAt),
|
|
98
|
+
n.trashedBy = $by,
|
|
99
|
+
n.trashReason = $reason,
|
|
100
|
+
n._trashedKeys = $trashedKeysJson${setNullSuffix}`, {
|
|
101
|
+
eid: elementId,
|
|
102
|
+
trashedAt,
|
|
103
|
+
by,
|
|
104
|
+
reason: reason ?? null,
|
|
105
|
+
trashedKeysJson: JSON.stringify(originalKeys),
|
|
106
|
+
});
|
|
107
|
+
process.stderr.write(`[trash:marked] accountId=${accountId} elementId=${elementId} labels=${baseLabels.join(",")} by=${by} reason=${reason ?? "null"}\n`);
|
|
108
|
+
return {
|
|
109
|
+
trashed: true,
|
|
110
|
+
alreadyTrashed: false,
|
|
111
|
+
nodeId: elementId,
|
|
112
|
+
labels: baseLabels,
|
|
113
|
+
trashedAt,
|
|
114
|
+
originalKeys,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
async function restoreNode(params) {
|
|
118
|
+
const { session, accountId, elementId } = params;
|
|
119
|
+
const lookup = await session.run(`MATCH (n:Trashed) WHERE elementId(n) = $eid
|
|
120
|
+
RETURN labels(n) AS labels, n._trashedKeys AS keysJson`, { eid: elementId });
|
|
121
|
+
if (lookup.records.length === 0) {
|
|
122
|
+
throw new Error(`restoreNode: trashed node not found (elementId=${elementId})`);
|
|
123
|
+
}
|
|
124
|
+
const allLabels = lookup.records[0].get("labels");
|
|
125
|
+
const baseLabels = allLabels.filter((l) => l !== "Trashed");
|
|
126
|
+
const keysJson = lookup.records[0].get("keysJson");
|
|
127
|
+
const originalKeys = keysJson ? JSON.parse(keysJson) : {};
|
|
128
|
+
// Conflict check: an active node already holds the unique slot we want back?
|
|
129
|
+
for (const label of baseLabels) {
|
|
130
|
+
const uniqueKeys = UNIQUE_KEYS_BY_LABEL[label] ?? [];
|
|
131
|
+
for (const k of uniqueKeys) {
|
|
132
|
+
const v = originalKeys[k];
|
|
133
|
+
if (v === undefined || v === null)
|
|
134
|
+
continue;
|
|
135
|
+
const conflict = await session.run(`MATCH (other:\`${label}\`)
|
|
136
|
+
WHERE elementId(other) <> $eid
|
|
137
|
+
AND NOT other:Trashed
|
|
138
|
+
AND other.\`${k}\` = $val
|
|
139
|
+
RETURN elementId(other) AS otherId LIMIT 1`, { eid: elementId, val: v });
|
|
140
|
+
if (conflict.records.length > 0) {
|
|
141
|
+
const otherId = conflict.records[0].get("otherId");
|
|
142
|
+
throw new Error(`restoreNode: cannot restore ${label} elementId=${elementId} — active node elementId=${otherId} already holds ${k}=${JSON.stringify(v)}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const setClauses = Object.keys(originalKeys)
|
|
147
|
+
.map((k) => `n.\`${k}\` = $val_${k}`)
|
|
148
|
+
.join(", ");
|
|
149
|
+
const setSuffix = setClauses ? `, ${setClauses}` : "";
|
|
150
|
+
const setParams = { eid: elementId };
|
|
151
|
+
for (const [k, v] of Object.entries(originalKeys))
|
|
152
|
+
setParams[`val_${k}`] = v;
|
|
153
|
+
await session.run(`MATCH (n:Trashed) WHERE elementId(n) = $eid
|
|
154
|
+
REMOVE n:Trashed, n.trashedAt, n.trashedBy, n.trashReason, n._trashedKeys
|
|
155
|
+
SET n.restoredAt = datetime()${setSuffix}`, setParams);
|
|
156
|
+
process.stderr.write(`[trash:restored] accountId=${accountId} elementId=${elementId} labels=${baseLabels.join(",")}\n`);
|
|
157
|
+
return {
|
|
158
|
+
restored: true,
|
|
159
|
+
nodeId: elementId,
|
|
160
|
+
labels: baseLabels,
|
|
161
|
+
restoredKeys: originalKeys,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
async function emptyTrash(params) {
|
|
165
|
+
const t0 = Date.now();
|
|
166
|
+
const { session, accountId, graceDays = 30, dryRun = false, labels: labelFilter, onEmpty } = params;
|
|
167
|
+
const cutoff = new Date(Date.now() - graceDays * 24 * 60 * 60 * 1000).toISOString();
|
|
168
|
+
const labelClause = labelFilter && labelFilter.length > 0
|
|
169
|
+
? `AND ANY(l IN labels(n) WHERE l IN $labelFilter)`
|
|
170
|
+
: "";
|
|
171
|
+
const candidatesResult = await session.run(`MATCH (n:Trashed)
|
|
172
|
+
WHERE n.trashedAt < datetime($cutoff)
|
|
173
|
+
${labelClause}
|
|
174
|
+
RETURN elementId(n) AS eid,
|
|
175
|
+
labels(n) AS labels,
|
|
176
|
+
toString(n.trashedAt) AS trashedAt,
|
|
177
|
+
n.trashedBy AS trashedBy,
|
|
178
|
+
n._trashedKeys AS keysJson
|
|
179
|
+
ORDER BY n.trashedAt ASC`, { cutoff, ...(labelFilter ? { labelFilter } : {}) });
|
|
180
|
+
const candidates = candidatesResult.records.map((r) => {
|
|
181
|
+
const keysJson = r.get("keysJson");
|
|
182
|
+
return {
|
|
183
|
+
elementId: r.get("eid"),
|
|
184
|
+
labels: r.get("labels").filter((l) => l !== "Trashed"),
|
|
185
|
+
trashedAt: String(r.get("trashedAt")),
|
|
186
|
+
trashedBy: r.get("trashedBy") ?? null,
|
|
187
|
+
trashedKeys: keysJson ? JSON.parse(keysJson) : {},
|
|
188
|
+
};
|
|
189
|
+
});
|
|
190
|
+
process.stderr.write(`[trash:empty-run] accountId=${accountId} graceDays=${graceDays} dryRun=${dryRun} candidates=${candidates.length}\n`);
|
|
191
|
+
if (dryRun || candidates.length === 0) {
|
|
192
|
+
process.stderr.write(`[graph:trash:summary] accountId=${accountId} trashedNow=0 emptiedThisRun=0 graceDays=${graceDays} dryRun=${dryRun} elapsedMs=${Date.now() - t0}\n`);
|
|
193
|
+
return { graceDays, dryRun, candidates, emptied: 0 };
|
|
194
|
+
}
|
|
195
|
+
let emptied = 0;
|
|
196
|
+
for (const c of candidates) {
|
|
197
|
+
if (onEmpty) {
|
|
198
|
+
try {
|
|
199
|
+
await onEmpty(c);
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
process.stderr.write(`[trash:empty-run] onEmpty side-effect failed for elementId=${c.elementId}: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
await session.run(`MATCH (n) WHERE elementId(n) = $eid DETACH DELETE n`, { eid: c.elementId });
|
|
206
|
+
const ageDays = Math.floor((Date.now() - new Date(c.trashedAt).getTime()) / (24 * 60 * 60 * 1000));
|
|
207
|
+
process.stderr.write(`[trash:emptied] accountId=${accountId} elementId=${c.elementId} labels=${c.labels.join(",")} trashedAt=${c.trashedAt} ageDays=${ageDays}\n`);
|
|
208
|
+
emptied++;
|
|
209
|
+
}
|
|
210
|
+
process.stderr.write(`[graph:trash:summary] accountId=${accountId} trashedNow=0 emptiedThisRun=${emptied} graceDays=${graceDays} dryRun=${dryRun} elapsedMs=${Date.now() - t0}\n`);
|
|
211
|
+
return { graceDays, dryRun, candidates, emptied };
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Read-filter clause excluding trashed nodes for the given Cypher alias.
|
|
215
|
+
*
|
|
216
|
+
* Filters both the `:Trashed` label (Task 576 primitive) and the legacy
|
|
217
|
+
* `deletedAt` property (KnowledgeDocument soft-delete pre-Task 576). The
|
|
218
|
+
* `deletedAt` arm is a transitional belt-and-braces — production graphs may
|
|
219
|
+
* still hold pre-migration soft-deletes — and stays until those are confirmed
|
|
220
|
+
* empty, then is dropped.
|
|
221
|
+
*
|
|
222
|
+
* notTrashed("node") → "(NOT node:Trashed AND node.deletedAt IS NULL)"
|
|
223
|
+
* notTrashed("related") → "(NOT related:Trashed AND related.deletedAt IS NULL)"
|
|
224
|
+
*/
|
|
225
|
+
function notTrashed(alias) {
|
|
226
|
+
return `(NOT \`${alias}\`:Trashed AND \`${alias}\`.deletedAt IS NULL)`;
|
|
227
|
+
}
|
|
228
|
+
/** Runtime accessor for the static unique-keys map (for tests + sibling tooling). */
|
|
229
|
+
function uniqueKeysForLabels(labels) {
|
|
230
|
+
const out = new Set();
|
|
231
|
+
for (const l of labels)
|
|
232
|
+
for (const k of UNIQUE_KEYS_BY_LABEL[l] ?? [])
|
|
233
|
+
out.add(k);
|
|
234
|
+
return [...out];
|
|
235
|
+
}
|
|
236
|
+
/** Property names trashNode writes — exposed so callers can re-MERGE without colliding. */
|
|
237
|
+
exports.TRASH_METADATA_PROPS = TRASH_PROP_NAMES;
|
|
238
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|