MCPcopy
hub / github.com/nowork-studio/NotFair / changeProjectSlug

Function changeProjectSlug

notfair-cmo/src/server/db/projects.ts:161–234  ·  view source on GitHub ↗
(
  old_slug: string,
  new_slug: string,
  new_display_name?: string,
)

Source from the content-addressed store, hash-verified

159 * Returns the renamed project, or null when the old slug doesn't exist.
160 */
161export function changeProjectSlug(
162 old_slug: string,
163 new_slug: string,
164 new_display_name?: string,
165): Project | null {
166 const db = getDb();
167 if (old_slug === new_slug) {
168 if (new_display_name) {
169 db.prepare("UPDATE projects SET display_name = ? WHERE slug = ?").run(
170 new_display_name.trim(),
171 old_slug,
172 );
173 }
174 return getProject(old_slug);
175 }
176 // Bail if the source doesn't exist or the destination already exists.
177 if (!db.prepare("SELECT 1 FROM projects WHERE slug = ?").get(old_slug)) {
178 return null;
179 }
180 if (db.prepare("SELECT 1 FROM projects WHERE slug = ?").get(new_slug)) {
181 throw new Error(`Project slug '${new_slug}' already exists`);
182 }
183
184 const childTables = [
185 "tasks",
186 "approvals",
187 "approval_policies",
188 "questions",
189 "cost_events",
190 "oauth_tokens",
191 "mcp_tokens",
192 "scheduled_jobs",
193 "sessions",
194 "agent_actions",
195 "sequence_runs",
196 ];
197
198 // Disable FK enforcement for the duration of the rename. Our FKs reference
199 // `projects(slug)` without ON UPDATE CASCADE, so updating the PK while
200 // child rows still point at the old value would violate. `defer_foreign_keys`
201 // inside a wrapped transaction doesn't take effect reliably across SQLite
202 // releases; toggling `foreign_keys` is universally supported and works the
203 // same way every popular SQLite migration tool uses.
204 const fkWasOn = db.pragma("foreign_keys = OFF", { simple: true });
205 try {
206 const tx = db.transaction(() => {
207 for (const table of childTables) {
208 try {
209 db.prepare(`UPDATE ${table} SET project_slug = ? WHERE project_slug = ?`).run(
210 new_slug,
211 old_slug,
212 );
213 } catch {
214 // table missing on this install; skip.
215 }
216 }
217 if (new_display_name) {
218 db.prepare("UPDATE projects SET slug = ?, display_name = ? WHERE slug = ?").run(

Callers 2

renameProjectFullActionFunction · 0.90
projects.test.tsFile · 0.90

Calls 2

getDbFunction · 0.90
getProjectFunction · 0.85

Tested by

no test coverage detected