Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new tooling/scripts/isomer-admin TypeScript-based admin script suite to centralize common Isomer operational tasks (DB maintenance, content export/import, schema validation, asset prep) behind an interactive CLI menu.
Changes:
- Introduces an interactive script runner (
npm run isomer-admin) and multiple admin scripts (collaborators, assets, export/import JSONs, schema validation). - Adds shared DB client lifecycle utility (
withDbClient) and script-local typing (types.ts). - Adds a dedicated TS config for
tooling/scriptsand updates the workspace package name/dependencies + lockfile.
Reviewed changes
Copilot reviewed 13 out of 15 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
| tooling/scripts/tsconfig.json | Adds TS config for scripts package (extends shared @isomer/tsconfig). |
| tooling/scripts/package.json | Renames package to @isomer/scripts, adds isomer-admin entrypoint + dependencies. |
| tooling/scripts/isomer-admin/utils/db.ts | Adds DB client helper with dotenv loading + connection lifecycle wrapper. |
| tooling/scripts/isomer-admin/types.ts | Adds shared row/script-type definitions for scripts. |
| tooling/scripts/isomer-admin/index.ts | Adds interactive script selector and dispatch. |
| tooling/scripts/isomer-admin/apps/add-isomer-collaborators.ts | Adds collaborator provisioning script (single-site or batch-from-ID). |
| tooling/scripts/isomer-admin/apps/bulk-upload-assets.ts | Adds asset copying/UUID-path mapping + CSV generation. |
| tooling/scripts/isomer-admin/apps/export-individual-jsons.ts | Adds DB export for specific resource IDs. |
| tooling/scripts/isomer-admin/apps/export-site-jsons.ts | Adds DB export for all resources in a site. |
| tooling/scripts/isomer-admin/apps/extract-folder-jsons.ts | Adds DB export for children under a parent resource. |
| tooling/scripts/isomer-admin/apps/find-invalid-schema.ts | Adds AJV-based schema validation for DB blobs or local JSON files. |
| tooling/scripts/isomer-admin/apps/import-folder-jsons.ts | Adds JSON import/update with optional publish behavior. |
| tooling/scripts/isomer-admin/README.md | Documents script suite usage and individual scripts. |
| tooling/scripts/isomer-admin/.env.example | Adds example env vars for scripts. |
| package-lock.json | Adds workspace link + dependency lock updates for new scripts package. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
adriangohjw
left a comment
There was a problem hiding this comment.
skimmed through and LGTM, left some non-blocking comments
| const csvContent = Object.entries(fileMapping) | ||
| .map( | ||
| ([originalFileName, newFilePath]) => | ||
| `"${originalFileName}","${newFilePath}"` | ||
| ) | ||
| .join("\n"); |
There was a problem hiding this comment.
nit: if filenames contain special characters like " or ,, then this will cause issue. But given that the list of files are provided by isoengs, non-blocker for me to assume that it should not contain them
| const allResources = await client.query<ResourceRow>( | ||
| `SELECT "Resource".id, "Resource".permalink, "Blob".content | ||
| FROM "Resource" | ||
| JOIN "Blob" ON "Resource"."draftBlobId" = "Blob".id | ||
| WHERE "Resource"."draftBlobId" IS NOT NULL | ||
| AND "Resource"."id" IN (${placeholders}) | ||
| AND "Resource".type NOT IN ('Folder', 'Collection', 'IndexPage') | ||
| UNION | ||
| SELECT "Resource".id, "Resource".permalink, "Blob".content | ||
| FROM "Resource" | ||
| JOIN "Version" ON "Resource"."publishedVersionId" = "Version".id | ||
| JOIN "Blob" ON "Version"."blobId" = "Blob".id | ||
| WHERE "Resource"."id" IN (${placeholders}) | ||
| AND "Resource"."draftBlobId" IS NULL | ||
| AND "Resource".type NOT IN ('Folder', 'Collection', 'IndexPage')`, | ||
| resourceIds | ||
| ); |
There was a problem hiding this comment.
nit: can use without union by joining both and coalesce the content e..g COALESCE(draftBlob.content, publishedBlob.content) to reduce logic duplication
same for the other files
non-blocker for me, just FYI!
There was a problem hiding this comment.
i think we can reuse apps/studio/prisma/scripts/addUsersToSite.ts
38f0dc2 to
1b0b0f3
Compare
Problem
Administrative operations (adding collaborators, exporting/importing page JSONs, uploading assets, validating schemas) were previously handled through scattered personal scripts outside the repository. This made it difficult for other team members to use them, and the scripts lacked proper typing, interactive prompts, and consistent patterns.
Solution
Adds a new
isomer-adminscript suite undertooling/scripts/isomer-admin/, following the patterns established in PR #1725 (ndf-collection) and PR #1805 (streamline). All scripts are converted from JavaScript to TypeScript with interactive prompts via@inquirer/prompts.Breaking Changes
Features:
schema.isomer.gov.sgImprovements:
withDbClientutility handles DB connection lifecycle and prompts fornpm run db:connectconfirmationnpm run isomer-adminwith script selection menuTests
Run from
tooling/scripts:Verify the interactive menu appears and each script prompts for the required inputs.
New scripts:
isomer-admin: Runsdotenv tsx isomer-admin/index.ts— interactive script selector for all admin operationsNew dependencies:
@inquirer/prompts: Interactive CLI prompts for script inputs@paralleldrive/cuid2: CUID2 ID generation (for add-isomer-collaborators)ajv: JSON Schema validation (for find-invalid-schema)dotenv: Environment variable loading from.envpapaparse: CSV parsing (currently unused after script removal, can be cleaned up)pg: PostgreSQL client for database operationsNew dev dependencies:
@isomer/tsconfig: Shared TypeScript configuration@types/papaparse: Type definitions for papaparse@types/pg: Type definitions for pg