diff --git a/apps/api/package.json b/apps/api/package.json index b5425ed..a7ff31e 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -35,7 +35,7 @@ "bcryptjs": "^3.0.3", "better-sqlite3": "^12.10.0", "fastify": "^5.8.5", - "gitsheets": "^1.4.1", + "gitsheets": "^2.2.0", "jose": "^6.2.3", "resend": "^6.12.4", "samlify": "^2.13.0", diff --git a/apps/api/scripts/import-laddr/importer.ts b/apps/api/scripts/import-laddr/importer.ts index 80b4386..d4f7553 100644 --- a/apps/api/scripts/import-laddr/importer.ts +++ b/apps/api/scripts/import-laddr/importer.ts @@ -92,7 +92,7 @@ import { type TranslateCtx, type Warnings, } from './translators.js'; -import { BlobObject } from 'hologit'; +import type { BlobHandle } from 'gitsheets'; // --------------------------------------------------------------------------- // Public types @@ -187,7 +187,7 @@ export async function importLaddrFromJson(opts: ImportOptions): Promise>['repo'] | null = null; let existingIds: ExistingIds; @@ -500,7 +500,6 @@ export async function importLaddrFromJson(opts: ImportOptions): Promise 0) { - const blobs: Record = {}; + const blobs: Record = {}; for (const a of artifacts) { - // BlobObject.write hashes the buffer into the git object DB. - // Same `as unknown as string` cast as the avatar route — the - // declared signature is too narrow; the underlying - // git-client `$putBlob` accepts Buffer at runtime. - blobs[a.filename] = await BlobObject.write( - hologit, - a.bytes as unknown as string, - ); + // repo.writeBlob hashes the Buffer into the git object DB. + blobs[a.filename] = await publicRepo.writeBlob(a.bytes); } await tx['blog-posts'].setAttachments(record, blobs); } diff --git a/apps/api/src/routes/people.ts b/apps/api/src/routes/people.ts index 7bff95a..ccd4dae 100644 --- a/apps/api/src/routes/people.ts +++ b/apps/api/src/routes/people.ts @@ -16,7 +16,6 @@ import { computePersonPermissions, getCallerSession } from '../services/permissi import { buildTransactionOptions } from '../store/commit-meta.js'; import type { UpdatePersonInput } from '../services/person.write.js'; import { AVATAR_ALLOWED_MIME, processAvatar } from '../lib/avatar.js'; -import { BlobObject } from 'hologit'; import type { Person } from '@cfp/shared/schemas'; import { PersonSchema } from '@cfp/shared/schemas'; import { StateApply } from '../store/state-apply.js'; @@ -404,7 +403,6 @@ export async function peopleRoutes(fastify: FastifyInstance): Promise { const newAvatarKey = `people/${person.slug}/avatar.jpg`; const stateApply = new StateApply(); - const hologit = fastify.publicRepo.hologitRepo; let updatedPerson: Person = person; await fastify.store.transact( @@ -418,17 +416,11 @@ export async function peopleRoutes(fastify: FastifyInstance): Promise { }), async (tx) => { // Write the two attachment blobs into the gitsheets transaction - // tree. BlobObject.write hashes the buffer into the git object DB - // via `git hash-object -w`; the tx-level setAttachments then wires - // the blob refs into the post-commit tree at the conventional path. - // - // BlobObject.write's TypeScript signature declares `content: string` - // but the underlying `git-client` `$putBlob` spawns `git hash-object - // --stdin -w` and pipes `content` to stdin, which accepts both - // strings and Buffers at runtime. Cast to match the declared shape; - // hologit's type would tighten upstream eventually. - const originalBlob = await BlobObject.write(hologit, processed.original as unknown as string); - const thumbnailBlob = await BlobObject.write(hologit, processed.thumbnail as unknown as string); + // tree. repo.writeBlob hashes the buffer into the git object DB; + // the tx-level setAttachments then wires the blob refs into the + // post-commit tree at the conventional path. + const originalBlob = await fastify.publicRepo.writeBlob(processed.original); + const thumbnailBlob = await fastify.publicRepo.writeBlob(processed.thumbnail); await tx.public.people.setAttachments(person, { 'avatar.jpg': originalBlob, 'avatar-128.jpg': thumbnailBlob, diff --git a/apps/api/src/store/public.ts b/apps/api/src/store/public.ts index 348caac..3d752a7 100644 --- a/apps/api/src/store/public.ts +++ b/apps/api/src/store/public.ts @@ -33,7 +33,49 @@ import type { import type { Project } from '@cfp/shared/schemas'; /** - * Cast a Zod v4 schema to gitsheets' StandardSchemaV1. + * Recursively drop `null` / `undefined`-valued keys from a record. + * + * gitsheets 2.x (Rust core) refuses to marshal `null` or `undefined` field + * values — `serializeRecords`/`upsert` throw `cannot marshal JS value of type + * Null/Undefined to a TOML value`. gitsheets 1.4.1 (`@iarna/toml`) silently + * dropped such keys instead, so they were never written to disk: an absent + * optional field is simply an absent TOML key (verified against the on-disk + * `published` snapshot — no record carries a `null`-valued key). + * + * Our Zod schemas mark optional fields `.nullable().optional()` and the write + * services normalize "cleared" fields to `?? null`. To keep the on-disk form + * byte-identical to 1.4.1 (and to keep those `?? null` write paths working), + * we strip null/undefined keys here, at the single write boundary, before the + * record reaches the core marshaller. Nested tables (objects) are cleaned + * recursively; arrays are passed through untouched (TOML has no null in + * arrays, and our schemas never emit sparse arrays). + * + * `null` as an explicit "delete this field" signal only exists for + * `Sheet.patch` (RFC 7396 merge-patch); we don't use `patch`, so stripping on + * the full-record `upsert` path is unambiguous. + */ +function stripNullish(value: unknown): unknown { + if (value === null || value === undefined) return undefined; + if (Array.isArray(value)) return value; + if (typeof value === 'object' && !(value instanceof Date)) { + const out: Record = {}; + for (const [k, v] of Object.entries(value as Record)) { + const cleaned = stripNullish(v); + if (cleaned !== undefined) out[k] = cleaned; + } + return out; + } + return value; +} + +/** + * Cast a Zod v4 schema to gitsheets' StandardSchemaV1, wrapping its validator + * so the validated record has null/undefined-valued keys stripped before it + * reaches gitsheets' core marshaller. + * + * gitsheets runs the Standard Schema validator host-side and marshals the + * validator's *output* — so stripping here (rather than at every upsert call + * site) is the single, authoritative write boundary. See `stripNullish`. * * Zod v4 implements the Standard Schema interface at runtime, but TypeScript * cannot prove that Zod's Result type is assignable to gitsheets' narrow @@ -41,7 +83,24 @@ import type { Project } from '@cfp/shared/schemas'; * shape. Both are correct at runtime; the cast is safe. */ function asValidator>(schema: unknown): StandardSchemaV1 { - return schema as StandardSchemaV1; + const inner = schema as StandardSchemaV1; + const innerValidate = inner['~standard'].validate; + return { + ...inner, + '~standard': { + ...inner['~standard'], + validate: (value: unknown) => { + const result = innerValidate(value); + const strip = ( + r: Awaited>, + ): Awaited> => + r.issues === undefined + ? { value: stripNullish(r.value) as T } + : r; + return result instanceof Promise ? result.then(strip) : strip(result); + }, + }, + }; } /** Typed validator map for openStore. */ diff --git a/apps/api/tests/store.test.ts b/apps/api/tests/store.test.ts index 83b884e..49423a8 100644 --- a/apps/api/tests/store.test.ts +++ b/apps/api/tests/store.test.ts @@ -11,10 +11,17 @@ import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { openStore } from 'gitsheets'; +import { execFile } from 'node:child_process'; +import { promisify } from 'node:util'; + import { PersonSchema, ProjectSchema } from '@cfp/shared/schemas'; import { FilesystemPrivateStore } from '../src/store/private/filesystem.js'; import { Store } from '../src/store/store.js'; +import { openPublicStore } from '../src/store/public.js'; import { createTestRepo } from './helpers/test-repo.js'; +import { createFullDataRepo } from './helpers/test-full-repo.js'; + +const exec = promisify(execFile); const now = '2026-05-16T00:00:00Z'; const uuid = (n: number) => `01951a3c-0000-7000-8000-${String(n).padStart(12, '0')}`; @@ -99,6 +106,61 @@ describe('public store (gitsheets)', () => { await cleanup(); } }); + + it('drops null/undefined-valued keys before writing (gitsheets 2.x marshal contract)', async () => { + // gitsheets 2.x (Rust core) throws when asked to marshal a null- or + // undefined-valued field to TOML; 1.4.1 silently dropped such keys. Our + // Zod schemas use `.nullable().optional()` and write services normalize + // cleared fields to `?? null`, so openPublicStore's validator wrapper must + // strip those keys — keeping the on-disk form byte-identical to 1.4.1 + // (an absent optional field is simply an absent TOML key). See + // apps/api/src/store/public.ts → stripNullish / asValidator. + const repo = await createFullDataRepo(); + try { + const { store } = await openPublicStore(repo.path); + + await store.transact( + { message: 'test: person with nullish fields', author: { name: 'test', email: 'test@cfp.test' } }, + async (tx) => { + await tx.people.upsert( + PersonSchema.parse({ + id: uuid(70), + slug: 'nullish-person', + fullName: 'Nullish Person', + accountLevel: 'user', + legacyId: 31618, // integer w/o underscore (2.x re-baseline) + bio: null, // explicit null — must be dropped, not written + avatarKey: null, + deletedAt: null, + createdAt: now, + updatedAt: now, + }), + ); + }, + ); + + const { stdout: toml } = await exec( + 'git', + ['show', 'HEAD:people/nullish-person.toml'], + { cwd: repo.path }, + ); + + // Present fields survive. + expect(toml).toContain('slug = "nullish-person"'); + expect(toml).toContain('fullName = "Nullish Person"'); + // Integer re-baseline: no underscore separator under the Rust core. + expect(toml).toContain('legacyId = 31618'); + // Null-valued keys are absent from disk (never serialized as `null`). + expect(toml).not.toMatch(/^bio\s*=/m); + expect(toml).not.toMatch(/^avatarKey\s*=/m); + expect(toml).not.toMatch(/^deletedAt\s*=/m); + // No field is assigned a bare `null` value. (Substring 'null' on its own + // would false-match the fixture's "Nullish Person" / "nullish-person".) + expect(toml).not.toMatch(/=\s*null\b/); + } finally { + await repo.cleanup(); + } + }); }); // ------------------------------------------------------------------------- diff --git a/package-lock.json b/package-lock.json index 1dbe57d..aa3e9f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,7 +43,7 @@ "bcryptjs": "^3.0.3", "better-sqlite3": "^12.10.0", "fastify": "^5.8.5", - "gitsheets": "^1.4.1", + "gitsheets": "^2.2.0", "jose": "^6.2.3", "resend": "^6.12.4", "samlify": "^2.13.0", @@ -1145,15 +1145,6 @@ "resolved": "apps/web", "link": true }, - "node_modules/@colors/colors": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", - "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/@csstools/color-helpers": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", @@ -1294,17 +1285,6 @@ "node": ">=20.19.0" } }, - "node_modules/@dabh/diagnostics": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.8.tgz", - "integrity": "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==", - "license": "MIT", - "dependencies": { - "@so-ric/colorspace": "^1.1.6", - "enabled": "2.0.x", - "kuler": "^2.0.0" - } - }, "node_modules/@dotenvx/dotenvx": { "version": "1.66.0", "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.66.0.tgz", @@ -2534,6 +2514,119 @@ "url": "https://github.com/sponsors/ayuhito" } }, + "node_modules/@gitsheets/core-napi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@gitsheets/core-napi/-/core-napi-0.1.1.tgz", + "integrity": "sha512-ZoJGzwUo8K0ok/XiQpGJ5k4lEuss21ZcDP8+pIGHMsdMkXmLlXNZhPij1Z0MtvFJIu3nu3mCqWVFR8cJf5jNsA==", + "license": "Apache-2.0", + "engines": { + "node": ">=20" + }, + "optionalDependencies": { + "@gitsheets/core-napi-darwin-arm64": "0.1.1", + "@gitsheets/core-napi-darwin-x64": "0.1.1", + "@gitsheets/core-napi-linux-arm64-gnu": "0.1.1", + "@gitsheets/core-napi-linux-x64-gnu": "0.1.1", + "@gitsheets/core-napi-linux-x64-musl": "0.1.1", + "@gitsheets/core-napi-win32-x64-msvc": "0.1.1" + } + }, + "node_modules/@gitsheets/core-napi-darwin-arm64": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@gitsheets/core-napi-darwin-arm64/-/core-napi-darwin-arm64-0.1.1.tgz", + "integrity": "sha512-1rHQT78zFwOIeD2Gf9LWNmIzm17wibxYXz5U8F0SOY51W+BIfklnYanfSywWHmE1FclqIVOE3ngFKZEiH/XgpQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20" + } + }, + "node_modules/@gitsheets/core-napi-darwin-x64": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@gitsheets/core-napi-darwin-x64/-/core-napi-darwin-x64-0.1.1.tgz", + "integrity": "sha512-YDcId/vr8kw5hem3S78XVlxmdv/Nc7d8HaTSA2PSRVoMUHpjo3apx7g4agjthrKW5mUms14kKGOzG8s2Hn/G5w==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20" + } + }, + "node_modules/@gitsheets/core-napi-linux-arm64-gnu": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@gitsheets/core-napi-linux-arm64-gnu/-/core-napi-linux-arm64-gnu-0.1.1.tgz", + "integrity": "sha512-qfGKIccxWnFPiyJ/GCuU1H+YVejdcfBGKcjKlHn/c9A8CUglCfXhruIYhOa0Q/AKbdVcIumG1UQ+QcdJkHBPCw==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20" + } + }, + "node_modules/@gitsheets/core-napi-linux-x64-gnu": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@gitsheets/core-napi-linux-x64-gnu/-/core-napi-linux-x64-gnu-0.1.1.tgz", + "integrity": "sha512-G+7j08FLBIGzbjZK3BRZQ0sI8/i4r4CuPrESt2HZtBclsVWGEzx2X6avnLUlAOFZZVphPZgq6kqMxDLSUMl4og==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20" + } + }, + "node_modules/@gitsheets/core-napi-linux-x64-musl": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@gitsheets/core-napi-linux-x64-musl/-/core-napi-linux-x64-musl-0.1.1.tgz", + "integrity": "sha512-6cdOSsSGmpXq9raKQRv8Npro393H0FfvSbPEvt1V39ebEGOuhYSDr+H0UYH6rxv4IcYeCOPjdgZMOYTuhD94oA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20" + } + }, + "node_modules/@gitsheets/core-napi-win32-x64-msvc": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@gitsheets/core-napi-win32-x64-msvc/-/core-napi-win32-x64-msvc-0.1.1.tgz", + "integrity": "sha512-+dDxvrXbtkP6D1Ghpnk5F+N/MGkgTClng0SxuoUmy7Bfi1RYu5Syj8kE1Dz91dGLvVU4U/+SK44hJMv/OOvONw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20" + } + }, "node_modules/@hono/node-server": { "version": "1.19.14", "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", @@ -2624,12 +2717,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@iarna/toml": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", - "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", - "license": "ISC" - }, "node_modules/@img/colour": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", @@ -5328,16 +5415,6 @@ "node": ">=14.0.0" } }, - "node_modules/@so-ric/colorspace": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@so-ric/colorspace/-/colorspace-1.1.6.tgz", - "integrity": "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==", - "license": "MIT", - "dependencies": { - "color": "^5.0.2", - "text-hex": "1.0.x" - } - }, "node_modules/@stablelib/base64": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-1.0.1.tgz", @@ -5833,12 +5910,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/katex": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz", - "integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==", - "license": "MIT" - }, "node_modules/@types/mdast": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", @@ -5898,12 +5969,6 @@ "integrity": "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==", "license": "MIT" }, - "node_modules/@types/triple-beam": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", - "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", - "license": "MIT" - }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -6376,18 +6441,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/ajv": { "version": "8.20.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", @@ -6445,12 +6498,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "license": "MIT" - }, "node_modules/argon2": { "version": "0.44.0", "resolved": "https://registry.npmjs.org/argon2/-/argon2-0.44.0.tgz", @@ -6526,25 +6573,11 @@ "node": ">=4" } }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "license": "MIT" - }, - "node_modules/async-exit-hook": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", - "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, "license": "MIT" }, "node_modules/atomic-sleep": { @@ -6576,18 +6609,6 @@ "fastq": "^1.17.1" } }, - "node_modules/axios": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.1.tgz", - "integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.16.0", - "form-data": "^4.0.5", - "https-proxy-agent": "^5.0.1", - "proxy-from-env": "^2.1.0" - } - }, "node_modules/bail": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", @@ -6779,15 +6800,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "license": "Apache-2.0", - "dependencies": { - "node-int64": "^0.4.0" - } - }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -6974,31 +6986,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/character-reference-invalid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", - "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", - "license": "MIT", - "dependencies": { - "readdirp": "^5.0.0" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", @@ -7082,19 +7069,6 @@ "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==", "license": "MIT" }, - "node_modules/color": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz", - "integrity": "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==", - "license": "MIT", - "dependencies": { - "color-convert": "^3.1.3", - "color-string": "^2.1.3" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -7113,48 +7087,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, - "node_modules/color-string": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", - "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", - "license": "MIT", - "dependencies": { - "color-name": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/color-string/node_modules/color-name": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", - "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", - "license": "MIT", - "engines": { - "node": ">=12.20" - } - }, - "node_modules/color/node_modules/color-convert": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.3.tgz", - "integrity": "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==", - "license": "MIT", - "dependencies": { - "color-name": "^2.0.0" - }, - "engines": { - "node": ">=14.6" - } - }, - "node_modules/color/node_modules/color-name": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", - "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", - "license": "MIT", - "engines": { - "node": ">=12.20" - } - }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -7166,6 +7098,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -7193,12 +7126,6 @@ "node": ">=20" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "license": "MIT" - }, "node_modules/concurrently": { "version": "9.2.1", "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz", @@ -7433,18 +7360,6 @@ "node": "*" } }, - "node_modules/debounce": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-3.0.0.tgz", - "integrity": "sha512-64byRbF0/AirwbuHqB3/ZpMG9/nckDa6ZA0yd6UnaQNwbbemCOwvz2sL5sjXLHhZHADyiwLm0M5qMhltUUx+TA==", - "license": "MIT", - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -7580,6 +7495,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -7709,12 +7625,6 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, - "node_modules/enabled": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", - "license": "MIT" - }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -7837,6 +7747,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -8567,15 +8478,6 @@ "reusify": "^1.0.4" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "license": "Apache-2.0", - "dependencies": { - "bser": "2.1.1" - } - }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -8593,12 +8495,6 @@ } } }, - "node_modules/fecha": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", - "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", - "license": "MIT" - }, "node_modules/fetch-blob": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", @@ -8741,36 +8637,11 @@ "dev": true, "license": "ISC" }, - "node_modules/fn.name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", - "license": "MIT" - }, - "node_modules/follow-redirects": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", - "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/form-data": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -8833,12 +8704,6 @@ "node": ">=14.14" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "license": "ISC" - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -8984,18 +8849,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/git-client": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/git-client/-/git-client-1.12.1.tgz", - "integrity": "sha512-Px7HE2ug+IKiOhNE/vezkwpDE7IUYHnoRHQfds2BlRf6CZglNq7lmlxVoRtprJ4ZHTq0ZWrQLZtrcMxFw18zvw==", - "license": "MIT", - "dependencies": { - "async-exit-hook": "^2.0.1", - "mz": "^2.7.0", - "rusha": "^0.8.14", - "semver": "^7.6.3" - } - }, "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", @@ -9003,20 +8856,15 @@ "license": "MIT" }, "node_modules/gitsheets": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/gitsheets/-/gitsheets-1.4.1.tgz", - "integrity": "sha512-/GIsDgsjweXcNk8ThYjAsWYctGr/xn0iVFE2J4u7yvJgmQdLSsOdLgqAwlny8MinhStniqpPm1XE+tvjt615JQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/gitsheets/-/gitsheets-2.2.0.tgz", + "integrity": "sha512-Ul04Ap8uA5GjljA6fM3VBBYCb6lYDaXSxpLdmNHDoac3JmV11q7j6F89sZqdla0/P8yQGjVGvyptcu0PTBdCgg==", "license": "Apache-2.0", "dependencies": { - "@iarna/toml": "^2.2.5", - "ajv": "^8.20.0", - "ajv-formats": "^3.0.1", + "@gitsheets/core-napi": "^0.1.0", "csv-parse": "^6.2.1", "csv-stringify": "^6.7.0", - "hologit": "^0.50.2", - "markdownlint": "^0.40.0", "rfc6902": "^5.2.0", - "smol-toml": "^1.7.0", "sort-keys": "^6.0.0", "yargs": "^18.0.0" }, @@ -9147,27 +8995,6 @@ "node": "^20.19.0 || ^22.12.0 || >=23" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -9181,34 +9008,6 @@ "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/globals": { "version": "17.6.0", "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz", @@ -9249,38 +9048,6 @@ "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } }, - "node_modules/hab-client": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hab-client/-/hab-client-1.1.3.tgz", - "integrity": "sha512-CZzvibCCQqwk3XZeNh2DWotOcnGViOjTny7NQAkSZid014OGZu+gfhLmTAj2qnUxDKr/ZImRauFLorFR38IwGQ==", - "license": "MIT", - "dependencies": { - "axios": "^1.3.4", - "semver": "^7.3.8", - "underscore": "^1.13.6" - } - }, - "node_modules/handlebars": { - "version": "4.7.9", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", - "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -9307,6 +9074,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -9421,162 +9189,6 @@ "hermes-estree": "0.25.1" } }, - "node_modules/hologit": { - "version": "0.50.2", - "resolved": "https://registry.npmjs.org/hologit/-/hologit-0.50.2.tgz", - "integrity": "sha512-9StuAaE8TkdnJE/cA5vdq+pwt/hZH1JGa9qsGfAz7rvwsXrVlQT/lBJd+pedpJHOJgPdA4NXC0lqljFzOWV+7A==", - "license": "MIT", - "os": [ - "darwin", - "linux" - ], - "dependencies": { - "@iarna/toml": "^2.2.5", - "async-exit-hook": "^2.0.1", - "axios": "^1.14.0", - "chokidar": "^5.0.0", - "debounce": "^3.0.0", - "fb-watchman": "^2.0.2", - "git-client": "^1.12.0", - "hab-client": "^1.1.3", - "handlebars": "^4.7.9", - "minimatch": "^10.2.4", - "mz": "^2.7.0", - "mz-modules": "^2.1.0", - "object-squish": "^1.1.0", - "parse-url": "^11.1.0", - "shell-quote-word": "^1.0.1", - "sort-keys": "^6.0.0", - "toposort": "^2.0.2", - "winston": "^3.19.0", - "yargs": "^18.0.0" - }, - "bin": { - "git-holo": "bin/cli.js" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/hologit/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/hologit/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/hologit/node_modules/cliui": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", - "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", - "license": "ISC", - "dependencies": { - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/hologit/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, - "node_modules/hologit/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hologit/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/hologit/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/hologit/node_modules/yargs": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", - "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", - "license": "MIT", - "dependencies": { - "cliui": "^9.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "string-width": "^7.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^22.0.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/hologit/node_modules/yargs-parser": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", - "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", - "license": "ISC", - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, "node_modules/hono": { "version": "4.12.19", "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.19.tgz", @@ -9629,19 +9241,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/human-signals": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", @@ -9732,17 +9331,6 @@ "node": ">=8" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -9773,46 +9361,12 @@ "node": ">= 10" } }, - "node_modules/is-alphabetical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", - "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", - "license": "MIT", - "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "license": "MIT" }, - "node_modules/is-decimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", - "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/is-docker": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", @@ -9858,16 +9412,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-hexadecimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", - "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/is-in-ssh": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz", @@ -10220,31 +9764,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/katex": { - "version": "0.16.47", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz", - "integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==", - "funding": [ - "https://opencollective.com/katex", - "https://github.com/sponsors/katex" - ], - "license": "MIT", - "dependencies": { - "commander": "^8.3.0" - }, - "bin": { - "katex": "cli.js" - } - }, - "node_modules/katex/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -10264,21 +9783,6 @@ "node": ">=6" } }, - "node_modules/ko-sleep": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/ko-sleep/-/ko-sleep-1.1.4.tgz", - "integrity": "sha512-s05WGpvvzyTuRlRE8fM7ru2Z3O+InbJuBcckTWKg2W+2c1k6SnFa3IfiSSt0/peFrlYAXgNoxuJWWVNmWh+K/A==", - "license": "MIT", - "dependencies": { - "ms": "*" - } - }, - "node_modules/kuler": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", - "license": "MIT" - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -10641,23 +10145,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/logform": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", - "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", - "license": "MIT", - "dependencies": { - "@colors/colors": "1.6.0", - "@types/triple-beam": "^1.3.2", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "safe-stable-stringify": "^2.3.1", - "triple-beam": "^1.3.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, "node_modules/longest-streak": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", @@ -10716,72 +10203,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/markdownlint": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.40.0.tgz", - "integrity": "sha512-UKybllYNheWac61Ia7T6fzuQNDZimFIpCg2w6hHjgV1Qu0w1TV0LlSgryUGzM0bkKQCBhy2FDhEELB73Kb0kAg==", - "license": "MIT", - "dependencies": { - "micromark": "4.0.2", - "micromark-core-commonmark": "2.0.3", - "micromark-extension-directive": "4.0.0", - "micromark-extension-gfm-autolink-literal": "2.1.0", - "micromark-extension-gfm-footnote": "2.1.0", - "micromark-extension-gfm-table": "2.1.1", - "micromark-extension-math": "3.1.0", - "micromark-util-types": "2.0.2", - "string-width": "8.1.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/DavidAnson" - } - }, - "node_modules/markdownlint/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/markdownlint/node_modules/string-width": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz", - "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==", - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.3.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/markdownlint/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/marked": { "version": "18.0.4", "resolved": "https://registry.npmjs.org/marked/-/marked-18.0.4.tgz", @@ -11151,25 +10572,6 @@ "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-extension-directive": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-4.0.0.tgz", - "integrity": "sha512-/C2nqVmXXmiseSSuCdItCMho7ybwwop6RrrRPk0KbOHW21JKoCldC+8rFOaundDoRBUWBnJJcxeA/Kvi34WQXg==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "parse-entities": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/micromark-extension-gfm": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", @@ -11291,25 +10693,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/micromark-extension-math": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", - "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", - "license": "MIT", - "dependencies": { - "@types/katex": "^0.16.0", - "devlop": "^1.0.0", - "katex": "^0.16.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/micromark-factory-destination": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", @@ -11724,6 +11107,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -11733,6 +11117,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -11817,18 +11202,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -11894,33 +11267,6 @@ "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/mz-modules": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mz-modules/-/mz-modules-2.1.0.tgz", - "integrity": "sha512-sjk8lcRW3vrVYnZ+W+67L/2rL+jbO5K/N6PFGIcLWTiYytNr22Ah9FDXFs+AQntTM1boZcoHi5qS+CV1seuPog==", - "license": "MIT", - "dependencies": { - "glob": "^7.1.2", - "ko-sleep": "^1.0.3", - "mkdirp": "^0.5.1", - "pump": "^3.0.0", - "rimraf": "^2.6.1" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/nanoid": { "version": "3.3.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", @@ -11961,12 +11307,6 @@ "node": ">= 0.6" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "license": "MIT" - }, "node_modules/node-abi": { "version": "3.92.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", @@ -12037,12 +11377,6 @@ "node-gyp-build-test": "build-test.js" } }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "license": "MIT" - }, "node_modules/node-releases": { "version": "2.0.44", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz", @@ -12107,12 +11441,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-squish": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object-squish/-/object-squish-1.1.0.tgz", - "integrity": "sha512-u+gd7R29OnIETm+tv546B0wq9SQFWWSnzdN8AunFrrOI4QV2q9+blpQnL9QWZbCXh3oV7LGCkWe5P3BpzVTfDA==", - "license": "BSD-2-Clause" - }, "node_modules/object-treeify": { "version": "1.1.33", "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-1.1.33.tgz", @@ -12163,15 +11491,6 @@ "wrappy": "1" } }, - "node_modules/one-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", - "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", - "license": "MIT", - "dependencies": { - "fn.name": "1.x.x" - } - }, "node_modules/onetime": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", @@ -12366,31 +11685,6 @@ "node": ">=6" } }, - "node_modules/parse-entities": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", - "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/parse-entities/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "license": "MIT" - }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -12421,27 +11715,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-path": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.1.0.tgz", - "integrity": "sha512-EuCycjZtfPcjWk7KTksnJ5xPMvWGA/6i4zrLYhRG0hGvC3GPU/jGUj3Cy+ZR0v30duV3e23R95T1lE2+lsndSw==", - "license": "MIT", - "dependencies": { - "protocols": "^2.0.0" - } - }, - "node_modules/parse-url": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-11.1.0.tgz", - "integrity": "sha512-UYn/lNb1bmkYiM6UaqEbHl9T/VIYreM2Vm79MGZ2soUOXOoOq7qxoTwx8C8p9V4Ko2DLcsVnEhRJzhxsF2kssg==", - "license": "MIT", - "dependencies": { - "parse-path": "^7.1.0" - }, - "engines": { - "node": ">=14.13.0" - } - }, "node_modules/parse5": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz", @@ -12495,15 +11768,6 @@ "node": ">=14.0.0" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -12829,12 +12093,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/protocols": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.2.tgz", - "integrity": "sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==", - "license": "MIT" - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -12857,15 +12115,6 @@ "node": ">= 0.10" } }, - "node_modules/proxy-from-env": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", - "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/pump": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", @@ -13202,19 +12451,6 @@ "node": ">= 6" } }, - "node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/real-require": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", @@ -13465,19 +12701,6 @@ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "license": "MIT" }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/rolldown": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.1.tgz", @@ -13572,12 +12795,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/rusha": { - "version": "0.8.14", - "resolved": "https://registry.npmjs.org/rusha/-/rusha-0.8.14.tgz", - "integrity": "sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==", - "license": "MIT" - }, "node_modules/rxjs": { "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", @@ -13943,12 +13160,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/shell-quote-word": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/shell-quote-word/-/shell-quote-word-1.0.1.tgz", - "integrity": "sha512-lT297f1WLAdq0A4O+AknIFRP6kkiI3s8C913eJ0XqBxJbZPGWUNkRQk2u8zk4bEAjUJ5i+fSLwB6z1HzeT+DEg==", - "license": "MIT" - }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -14091,18 +13302,6 @@ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "license": "MIT" }, - "node_modules/smol-toml": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.7.0.tgz", - "integrity": "sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 18" - }, - "funding": { - "url": "https://github.com/sponsors/cyyynthia" - } - }, "node_modules/sonic-boom": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz", @@ -14123,9 +13322,9 @@ } }, "node_modules/sort-keys": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-6.0.0.tgz", - "integrity": "sha512-ueSlHJMwpIw42CJ4B11Uxzh/S0p0AlOyiNktlv2KOu5e1JpUE6DlC4AAUjXqesHdBRv/g0wC9Q4vwq0NP2pA9w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-6.0.1.tgz", + "integrity": "sha512-w7xWRu8U9MneKNna8ptG194jp9PLtbd/Rl6gwrmbK4yUeKbE66a64rHgl0iKTBBDr/hpanx7zMGP1Qo8MRkc/w==", "license": "MIT", "dependencies": { "is-plain-obj": "^4.1.0" @@ -14174,15 +13373,6 @@ "node": ">= 10.x" } }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -14464,33 +13654,6 @@ "node": ">=6" } }, - "node_modules/text-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", - "license": "MIT" - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/thread-stream": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.2.0.tgz", @@ -14606,12 +13769,6 @@ "node": ">=0.6" } }, - "node_modules/toposort": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", - "license": "MIT" - }, "node_modules/tough-cookie": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz", @@ -14657,15 +13814,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/triple-beam": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", - "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", - "license": "MIT", - "engines": { - "node": ">= 14.0.0" - } - }, "node_modules/trough": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", @@ -14881,25 +14029,6 @@ "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/underscore": { - "version": "1.13.8", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", - "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", - "license": "MIT" - }, "node_modules/undici": { "version": "7.25.0", "resolved": "https://registry.npmjs.org/undici/-/undici-7.25.0.tgz", @@ -15451,42 +14580,6 @@ "node": ">=8" } }, - "node_modules/winston": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz", - "integrity": "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==", - "license": "MIT", - "dependencies": { - "@colors/colors": "^1.6.0", - "@dabh/diagnostics": "^2.0.8", - "async": "^3.2.3", - "is-stream": "^2.0.0", - "logform": "^2.7.0", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "safe-stable-stringify": "^2.3.1", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.9.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/winston-transport": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", - "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", - "license": "MIT", - "dependencies": { - "logform": "^2.7.0", - "readable-stream": "^3.6.2", - "triple-beam": "^1.3.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -15497,12 +14590,6 @@ "node": ">=0.10.0" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "license": "MIT" - }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/plans/gitsheets-2x-bump.md b/plans/gitsheets-2x-bump.md new file mode 100644 index 0000000..73f1585 --- /dev/null +++ b/plans/gitsheets-2x-bump.md @@ -0,0 +1,128 @@ +--- +status: in-progress +depends: [] +specs: + - specs/behaviors/storage.md +issues: + - 150 +pr: +--- + +# Plan: upgrade gitsheets 1.4.1 → 2.x (Rust core) + +## Scope + +Bump `gitsheets` from `^1.4.1` to `^2.2.0` (the Rust-core line). This plan is +the **version bump only** — the "retire the three cache workarounds" half of +issue #150 is **out of scope and blocked** on upstream `gitsheets#184` +(per-sheet refresh API), which is OPEN, unassigned, and **not shipped in 2.x** +(verified: 2.x `Sheet` still carries the pre-commit `dataTree` snapshot). The +workarounds are therefore **ported/verified, not deleted**. + +## What actually changes in 2.x (verified against the gitsheets source) + +- **The Node public API is deliberately unchanged** — 2.x is an engine rewrite + behind the same `openRepo`/`openStore`/`Sheet`/`Transaction` surface + (`specs/rust-core.md` → "No consumer-visible public-API change"). So most of + our code compiles as-is. +- **`hologit` is dropped as a gitsheets dependency** (2.x deps are + `@gitsheets/core-napi` + csv/rfc6902/sort-keys/yargs — no hologit). This is + **one real breaking change for us**: our avatar-blob-write path imports + `BlobObject` from `hologit` and uses `publicRepo.hologitRepo`. +- **Null/undefined marshal contract changed (undocumented — found during this + bump).** The Rust core *throws* when asked to marshal a `null`- or + `undefined`-valued field to TOML (`cannot marshal JS value of type + Null/Undefined to a TOML value`). 1.4.1 (`@iarna/toml`) silently dropped such + keys. Our Zod schemas use `.nullable().optional()` and write services + normalize cleared fields to `?? null`, so every write of a record with a + cleared optional field threw a 500 under 2.x (16 test failures across + write-api / people-lifecycle / import-laddr). **Fix:** `openPublicStore` now + wraps each Standard Schema validator to strip null/undefined keys before the + record reaches the core marshaller (`apps/api/src/store/public.ts` → + `stripNullish` / `asValidator`). This is byte-identical to 1.4.1's on-disk + form (an absent optional field = an absent TOML key; verified against the + `published` snapshot). This is NOT one of the two documented re-baselines + below. +- **Two deliberate one-time byte re-baselines** (data-level, lossless — values + unchanged, only formatting): + 1. **Canonical TOML**: Rust `toml`/`toml_edit` drops integer underscores + (`legacyId = 31_618` → `31618`) across all sheets (matches gitsheets#196). + 2. **Markdown body**: content-typed sheets (our **blog-posts**) normalize the + body via native `dprint` instead of `markdownlint`. + +## Work + +### 1. Dependency bump + +- `npm install gitsheets@^2.2.0 -w apps/api`. Commit the generated + package.json + lock change first (drops hologit transitively). + +### 2. Migrate the blob-write path off `hologit` (the real code change) + +Replace the `hologit` `BlobObject.write(publicRepo.hologitRepo, buf)` pattern +with the 2.x `Repository.writeBlob(buf): Promise` + `setAttachment` +API. Sites: + +- `apps/api/src/routes/people.ts:19,407,430-431` (avatar upload) +- `apps/api/scripts/import-laddr/importer.ts:95,503,516-517,583-590` (legacy + avatar + media import) +- Drop the `as unknown as string` casts — 2.x `writeBlob` takes a `Buffer`. +- Confirm the exact 2.x `setAttachment(s)` signature in the gitsheets `Sheet` + API (`AttachmentBlobHandle` / `BlobHandle`) and wire accordingly. +- Grep for any other `hologit` / `hologitRepo` / `BlobObject` / `TreeObject` + references and migrate; ensure `hologit` is NOT needed as a direct dep. + +### 3. Verify (do NOT delete) the #184 workarounds still compile + work + +- `apps/api/src/store/store.ts` `swapPublic()` — re-opens the store via + `openPublicStore`; API unchanged, should be fine. Confirm it doesn't touch + `hologitRepo`. +- `apps/api/src/routes/attachments.ts` — raw `git cat-file` (git-level, not + gitsheets) — unaffected; confirm. +- `apps/api/src/lib/data-repo-lock.ts` — our own mutex — unaffected; confirm. + +### 4. Incidental cast checks (issue #150) + +- `apps/api/src/store/public.ts` `asValidator()` (Zod v4 ↔ `StandardSchemaV1`). + 2.x still exports `StandardSchemaV1`/`ValidatorMap`; keep the cast if still + needed, simplify if 2.x makes it clean. Don't force it. + +### 5. Validation + +- `npm run -w packages/shared build` (exports map points at dist), then + `npm run type-check` + `npm run lint` clean. +- **Full api test suite green.** The byte re-baseline will break any test that + asserts exact TOML bytes containing integer underscores, or exact blog-post + body bytes — fix those to the new canonical form (they're re-baseline + updates, not behavior changes; note each in the commit). +- **Byte-parity check on real data**: load the `published` import under 2.x and + confirm the change is **lossless** — parsed values identical to 1.4.1, only + the documented re-baselines (integer underscores, markdown bodies) differ. + (Mirror the approach used for the 1.4.1 swap.) +- Sanity-check the migrated blob path end to end: an avatar upload writes both + `avatar.jpg` + `avatar-128.jpg` attachments with the right `avatarKey`. + +## Out of scope / follow-ups + +- **Retiring `swapPublic` / attachments `git cat-file` / `data-repo-lock`** — + blocked on `gitsheets#184`; separate effort once that lands upstream. Keep + #150's second half open (or split it out). +- **Data-repo re-normalization commit** — under 2.x, records re-serialize + without integer underscores as they're written, so the repo drifts to mixed + format until fully rewritten. A deliberate one-time re-normalize (rewrite all + records) is cleaner but is a **data-ops task on `codeforphilly-data`**, not + part of this code bump. Flag it; do it deliberately (likely bundled with the + cutover data prep). +- **Timing note:** 2.x is days old (Rust rewrite) and we're near production + cutover (#54). This bump is validated but should merge on a deliberate + decision, not reflexively before cutover. + +## Validation checklist + +- [x] deps bumped; hologit gone from lock +- [x] blob-write path migrated off hologit; casts removed +- [x] workarounds verified (compile + covered by tests) +- [x] null/undefined marshal contract handled (`stripNullish` at write boundary) +- [x] type-check + lint clean +- [x] full api suite green (no re-baseline test updates were needed — see below) +- [x] byte-parity on `published` = lossless (only documented re-baselines)