made tiny updates

This commit is contained in:
SinachPat
2026-05-06 22:11:40 +01:00
parent f21969f018
commit 1fc2702a4b
36 changed files with 2455 additions and 1558 deletions
+67 -2
View File
@@ -10,6 +10,9 @@ import type {
Origin,
IntentDiff,
DesignLanguageFile,
DesignLanguage,
DesignLanguageVersion,
InsertDesignLanguage,
AgentSession,
TeamMember,
Project,
@@ -31,6 +34,7 @@ export interface DbClient {
select(cols?: string): DbQuery;
insert(row: unknown): DbMutation;
update(row: unknown): DbMutation;
upsert(row: unknown, opts?: { onConflict?: string }): DbMutation;
delete(): DbMutation;
};
rpc(fn: string, args?: unknown): Promise<{ data: unknown; error: DbError | null }>;
@@ -236,6 +240,66 @@ export async function getActiveDesignLanguageFile(
return data;
}
// ── Phase 6: design_languages queries (migration 014) ────────────────────────
/**
* Return the single active design language row for a workspace, or null if none
* has been uploaded yet. Uses the UNIQUE(workspace_id) constraint — one row per
* workspace, no is_active flag needed.
*/
export async function getDesignLanguage(
db: DbClient,
workspaceId: string,
): Promise<DesignLanguage | null> {
const { data, error } = await (db
.from('design_languages')
.select('*')
.eq('workspace_id', workspaceId)
.limit(1)
.single() as Promise<{ data: DesignLanguage | null; error: DbError | null }>);
if (error?.code === 'PGRST116') return null; // No rows — no token file uploaded yet
if (error) throw new Error(error.message);
return data;
}
/**
* Upsert a design language row (INSERT … ON CONFLICT DO UPDATE).
* The DB enforces UNIQUE(workspace_id) so this is safe for concurrent callers.
* Also inserts a history row into design_language_versions (handled by trigger).
*/
export async function upsertDesignLanguage(
db: DbClient,
row: InsertDesignLanguage,
): Promise<DesignLanguage> {
const { data, error } = await (db
.from('design_languages')
.upsert(row, { onConflict: 'workspace_id' })
.select()
.single() as Promise<{ data: DesignLanguage; error: DbError | null }>);
if (error) throw new Error(error.message);
return data;
}
/**
* Return the version history for a design language, newest first.
* The prune trigger keeps at most 10 rows per design_language_id.
*/
export async function getDesignLanguageVersions(
db: DbClient,
designLanguageId: string,
): Promise<DesignLanguageVersion[]> {
const { data, error } = await (db
.from('design_language_versions')
.select('*')
.eq('design_language_id', designLanguageId)
.order('version', { ascending: false }) as unknown as Promise<{
data: DesignLanguageVersion[];
error: DbError | null;
}>);
if (error) throw new Error(error.message);
return data ?? [];
}
// ── Origin queries ────────────────────────────────────────────────────────────
export async function getOrigin(db: DbClient, id: string): Promise<Origin> {
@@ -342,13 +406,14 @@ export async function addTeamMember(db: DbClient, row: InsertTeamMember): Promis
export async function removeTeamMember(
db: DbClient,
workspaceId: string,
userId: string,
/** The email address of the member to remove. */
email: string,
): Promise<void> {
const { error } = await (db
.from('team_members')
.delete()
.eq('workspace_id', workspaceId)
.eq('user_id', userId) as unknown as Promise<{ data: unknown; error: DbError | null }>);
.eq('email', email) as unknown as Promise<{ data: unknown; error: DbError | null }>);
if (error) throw new Error(error.message);
}
+46 -3
View File
@@ -41,7 +41,7 @@ export type WorkspacePlan = z.infer<typeof WorkspacePlanSchema>;
export const WorkspaceSchema = z.object({
id: z.string().uuid(),
name: z.string(),
owner_id: z.string(),
owner_email: z.string().email(),
plan: WorkspacePlanSchema,
settings_jsonb: z.record(z.unknown()),
created_at: z.string().datetime(),
@@ -111,7 +111,7 @@ export type Origin = z.infer<typeof OriginSchema>;
export const IntentDiffSchema = z.object({
id: z.string().uuid(),
artboard_id: z.string().uuid(),
author_id: z.string(),
author_email: z.string().email(),
/** Spec column name: changes (renamed from changes_jsonb in migration 008) */
changes: z.record(z.unknown()),
/** Spec column name: aggregate_summary (renamed from summary in migration 008) */
@@ -157,7 +157,7 @@ export type DesignLanguageFile = z.infer<typeof DesignLanguageFileSchema>;
export const TeamMemberSchema = z.object({
id: z.string().uuid(),
workspace_id: z.string().uuid(),
user_id: z.string(),
email: z.string().email(),
role: TeamRoleSchema,
created_at: z.string().datetime(),
updated_at: z.string().datetime(),
@@ -199,3 +199,46 @@ export type InsertAgentSession = Omit<AgentSession, 'id' | 'created
export type InsertDesignLanguageFile = Omit<DesignLanguageFile, 'id' | 'created_at' | 'updated_at'>;
export type InsertTeamMember = Omit<TeamMember, 'id' | 'created_at' | 'updated_at'>;
export type InsertProject = Omit<Project, 'id' | 'created_at' | 'updated_at'>;
// ── Phase 6: design_languages (new token-file schema, migration 014) ──────────
/** Allowed source format discriminants (matches migration 014 CHECK constraint). */
export const SourceFormatSchema = z.enum(['dtcg', 'style-dictionary', 'flat-css-vars']);
export type SourceFormat = z.infer<typeof SourceFormatSchema>;
/**
* Mirrors the `design_languages` table (migration 014).
* One row per workspace — UPSERT on every token file upload.
*/
export const DesignLanguageSchema = z.object({
id: z.string().uuid(),
workspace_id: z.string().uuid(),
name: z.string(),
/** Raw token file JSON as uploaded (before normalisation). */
raw_json: z.record(z.unknown()),
/** Normalised DesignToken[] flat array (from Phase 6 parser). */
normalized: z.array(z.record(z.unknown())),
source_format: SourceFormatSchema,
token_count: z.number().int(),
version: z.number().int(),
created_at: z.string().datetime(),
updated_at: z.string().datetime(),
});
export type DesignLanguage = z.infer<typeof DesignLanguageSchema>;
/**
* Mirrors the `design_language_versions` table (migration 014).
* Append-only version history; pruned to last 10 per design_language.
*/
export const DesignLanguageVersionSchema = z.object({
id: z.string().uuid(),
design_language_id: z.string().uuid(),
version: z.number().int(),
raw_json: z.record(z.unknown()),
normalized: z.array(z.record(z.unknown())),
source_format: SourceFormatSchema,
created_at: z.string().datetime(),
});
export type DesignLanguageVersion = z.infer<typeof DesignLanguageVersionSchema>;
export type InsertDesignLanguage = Omit<DesignLanguage, 'id' | 'created_at' | 'updated_at'>;