made tiny updates
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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'>;
|
||||
|
||||
Reference in New Issue
Block a user