@baseworks/organization 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-5UCSEIJS.js +64 -0
- package/dist/cli.d.ts +18 -0
- package/dist/cli.js +534 -0
- package/dist/index.d.ts +199 -0
- package/dist/index.js +335 -0
- package/dist/schema/pg/index.d.ts +562 -0
- package/dist/schema/pg/index.js +62 -0
- package/dist/schema/sqlite/index.d.ts +604 -0
- package/dist/schema/sqlite/index.js +12 -0
- package/package.json +37 -0
- package/src/__tests__/cli-env.test.ts +158 -0
- package/src/__tests__/cli-org.test.ts +154 -0
- package/src/__tests__/cli-proj.test.ts +157 -0
- package/src/__tests__/cli-ws.test.ts +156 -0
- package/src/__tests__/helpers.ts +29 -0
- package/src/cli.ts +682 -0
- package/src/index.ts +5 -0
- package/src/operations/bootstrap.ts +50 -0
- package/src/repo/environments.ts +82 -0
- package/src/repo/index.ts +9 -0
- package/src/repo/organizations.ts +96 -0
- package/src/repo/projects.ts +106 -0
- package/src/repo/workspaces.ts +87 -0
- package/src/schema/environments.ts +14 -0
- package/src/schema/index.ts +5 -0
- package/src/schema/organizations.ts +11 -0
- package/src/schema/pg/environments.ts +14 -0
- package/src/schema/pg/index.ts +4 -0
- package/src/schema/pg/organizations.ts +11 -0
- package/src/schema/pg/projects.ts +16 -0
- package/src/schema/pg/workspaces.ts +15 -0
- package/src/schema/projects.ts +16 -0
- package/src/schema/sqlite/environments.ts +14 -0
- package/src/schema/sqlite/index.ts +4 -0
- package/src/schema/sqlite/organizations.ts +11 -0
- package/src/schema/sqlite/projects.ts +16 -0
- package/src/schema/sqlite/workspaces.ts +15 -0
- package/src/schema/workspaces.ts +15 -0
- package/src/types.ts +88 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
export { environments, organizations, projects, workspaces } from './schema/sqlite/index.js';
|
|
2
|
+
export { generateId, generateShortId } from '@baseworks/core';
|
|
3
|
+
import 'drizzle-orm/sqlite-core';
|
|
4
|
+
|
|
5
|
+
interface Organization {
|
|
6
|
+
id: string;
|
|
7
|
+
shortId: string;
|
|
8
|
+
slug: string;
|
|
9
|
+
name: string;
|
|
10
|
+
metadata: string | null;
|
|
11
|
+
createdAt: number;
|
|
12
|
+
updatedAt: number;
|
|
13
|
+
}
|
|
14
|
+
interface NewOrganization {
|
|
15
|
+
id?: string;
|
|
16
|
+
shortId?: string;
|
|
17
|
+
slug?: string;
|
|
18
|
+
name: string;
|
|
19
|
+
metadata?: string | null;
|
|
20
|
+
createdAt?: number;
|
|
21
|
+
updatedAt?: number;
|
|
22
|
+
}
|
|
23
|
+
interface Workspace {
|
|
24
|
+
id: string;
|
|
25
|
+
organizationId: string;
|
|
26
|
+
shortId: string;
|
|
27
|
+
slug: string;
|
|
28
|
+
name: string;
|
|
29
|
+
isDefault: boolean;
|
|
30
|
+
createdAt: number;
|
|
31
|
+
updatedAt: number;
|
|
32
|
+
}
|
|
33
|
+
interface NewWorkspace {
|
|
34
|
+
id?: string;
|
|
35
|
+
organizationId: string;
|
|
36
|
+
shortId?: string;
|
|
37
|
+
slug?: string;
|
|
38
|
+
name: string;
|
|
39
|
+
isDefault?: boolean;
|
|
40
|
+
createdAt?: number;
|
|
41
|
+
updatedAt?: number;
|
|
42
|
+
}
|
|
43
|
+
interface Project {
|
|
44
|
+
id: string;
|
|
45
|
+
workspaceId: string;
|
|
46
|
+
shortId: string;
|
|
47
|
+
slug: string;
|
|
48
|
+
name: string;
|
|
49
|
+
isDefault: boolean;
|
|
50
|
+
metadata: string | null;
|
|
51
|
+
createdAt: number;
|
|
52
|
+
updatedAt: number;
|
|
53
|
+
}
|
|
54
|
+
interface NewProject {
|
|
55
|
+
id?: string;
|
|
56
|
+
workspaceId: string;
|
|
57
|
+
shortId?: string;
|
|
58
|
+
slug?: string;
|
|
59
|
+
name: string;
|
|
60
|
+
isDefault?: boolean;
|
|
61
|
+
metadata?: string | null;
|
|
62
|
+
createdAt?: number;
|
|
63
|
+
updatedAt?: number;
|
|
64
|
+
}
|
|
65
|
+
interface Environment {
|
|
66
|
+
id: string;
|
|
67
|
+
projectId: string;
|
|
68
|
+
shortId: string;
|
|
69
|
+
slug: string;
|
|
70
|
+
name: string;
|
|
71
|
+
createdAt: number;
|
|
72
|
+
updatedAt: number;
|
|
73
|
+
}
|
|
74
|
+
interface NewEnvironment {
|
|
75
|
+
id?: string;
|
|
76
|
+
projectId: string;
|
|
77
|
+
shortId?: string;
|
|
78
|
+
slug?: string;
|
|
79
|
+
name: string;
|
|
80
|
+
createdAt?: number;
|
|
81
|
+
updatedAt?: number;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
type AnyDB$4 = any;
|
|
85
|
+
declare function createOrganizationRepo(db: AnyDB$4, schema: {
|
|
86
|
+
organizations: any;
|
|
87
|
+
}): {
|
|
88
|
+
create(data: {
|
|
89
|
+
name: string;
|
|
90
|
+
slug?: string;
|
|
91
|
+
id?: string;
|
|
92
|
+
}): Promise<Organization>;
|
|
93
|
+
findById(id: string): Promise<Organization | undefined>;
|
|
94
|
+
findByShortId(shortId: string): Promise<Organization | undefined>;
|
|
95
|
+
findBySlug(slug: string): Promise<Organization | undefined>;
|
|
96
|
+
findByRef(ref: string): Promise<Organization | undefined>;
|
|
97
|
+
isSlugAvailable(slug: string): Promise<boolean>;
|
|
98
|
+
claimSlug(id: string, slug: string): Promise<void>;
|
|
99
|
+
update(id: string, data: {
|
|
100
|
+
name?: string;
|
|
101
|
+
slug?: string;
|
|
102
|
+
metadata?: string | null;
|
|
103
|
+
}): Promise<Organization | undefined>;
|
|
104
|
+
patchMetadata(id: string, patch: Record<string, unknown>): Promise<Organization | undefined>;
|
|
105
|
+
delete(id: string): Promise<void>;
|
|
106
|
+
listAll(): Promise<Organization[]>;
|
|
107
|
+
hardDelete(id: string): Promise<void>;
|
|
108
|
+
};
|
|
109
|
+
type OrganizationRepo = ReturnType<typeof createOrganizationRepo>;
|
|
110
|
+
|
|
111
|
+
type AnyDB$3 = any;
|
|
112
|
+
declare function createWorkspaceRepo(db: AnyDB$3, schema: {
|
|
113
|
+
workspaces: any;
|
|
114
|
+
}): {
|
|
115
|
+
create(data: {
|
|
116
|
+
organizationId: string;
|
|
117
|
+
name: string;
|
|
118
|
+
slug?: string;
|
|
119
|
+
isDefault?: boolean;
|
|
120
|
+
id?: string;
|
|
121
|
+
}): Promise<Workspace>;
|
|
122
|
+
findById(id: string): Promise<Workspace | undefined>;
|
|
123
|
+
findByShortId(shortId: string): Promise<Workspace | undefined>;
|
|
124
|
+
findBySlug(organizationId: string, slug: string): Promise<Workspace | undefined>;
|
|
125
|
+
findByRef(organizationId: string, ref: string): Promise<Workspace | undefined>;
|
|
126
|
+
listByOrg(organizationId: string): Promise<Workspace[]>;
|
|
127
|
+
findDefault(organizationId: string): Promise<Workspace | undefined>;
|
|
128
|
+
update(id: string, data: {
|
|
129
|
+
name?: string;
|
|
130
|
+
}): Promise<Workspace | undefined>;
|
|
131
|
+
delete(id: string): Promise<void>;
|
|
132
|
+
};
|
|
133
|
+
type WorkspaceRepo = ReturnType<typeof createWorkspaceRepo>;
|
|
134
|
+
|
|
135
|
+
type AnyDB$2 = any;
|
|
136
|
+
declare function createProjectRepo(db: AnyDB$2, schema: {
|
|
137
|
+
projects: any;
|
|
138
|
+
}): {
|
|
139
|
+
create(data: {
|
|
140
|
+
workspaceId: string;
|
|
141
|
+
name: string;
|
|
142
|
+
slug?: string;
|
|
143
|
+
isDefault?: boolean;
|
|
144
|
+
id?: string;
|
|
145
|
+
}): Promise<Project>;
|
|
146
|
+
findById(id: string): Promise<Project | undefined>;
|
|
147
|
+
findByShortId(shortId: string): Promise<Project | undefined>;
|
|
148
|
+
findBySlug(workspaceId: string, slug: string): Promise<Project | undefined>;
|
|
149
|
+
findByRef(workspaceId: string, ref: string): Promise<Project | undefined>;
|
|
150
|
+
listByWorkspace(workspaceId: string): Promise<Project[]>;
|
|
151
|
+
findDefault(workspaceId: string): Promise<Project | undefined>;
|
|
152
|
+
update(id: string, data: {
|
|
153
|
+
name?: string;
|
|
154
|
+
}): Promise<Project | undefined>;
|
|
155
|
+
delete(id: string): Promise<void>;
|
|
156
|
+
getMetadata(id: string): Promise<Record<string, unknown>>;
|
|
157
|
+
patchMetadata(id: string, patch: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
158
|
+
};
|
|
159
|
+
type ProjectRepo = ReturnType<typeof createProjectRepo>;
|
|
160
|
+
|
|
161
|
+
type AnyDB$1 = any;
|
|
162
|
+
declare function createEnvironmentRepo(db: AnyDB$1, schema: {
|
|
163
|
+
environments: any;
|
|
164
|
+
}): {
|
|
165
|
+
create(data: {
|
|
166
|
+
projectId: string;
|
|
167
|
+
name: string;
|
|
168
|
+
slug?: string;
|
|
169
|
+
id?: string;
|
|
170
|
+
}): Promise<Environment>;
|
|
171
|
+
findById(id: string): Promise<Environment | undefined>;
|
|
172
|
+
findByShortId(shortId: string): Promise<Environment | undefined>;
|
|
173
|
+
findByIdentifier(projectId: string, identifier: string): Promise<Environment | undefined>;
|
|
174
|
+
findByRef(projectId: string, ref: string): Promise<Environment | undefined>;
|
|
175
|
+
listByProject(projectId: string): Promise<Environment[]>;
|
|
176
|
+
update(id: string, data: {
|
|
177
|
+
name?: string;
|
|
178
|
+
slug?: string;
|
|
179
|
+
}): Promise<Environment | undefined>;
|
|
180
|
+
delete(id: string): Promise<void>;
|
|
181
|
+
};
|
|
182
|
+
type EnvironmentRepo = ReturnType<typeof createEnvironmentRepo>;
|
|
183
|
+
|
|
184
|
+
type AnyDB = any;
|
|
185
|
+
type AnySchema = any;
|
|
186
|
+
interface OrganizationBootstrapResult {
|
|
187
|
+
organization: Organization;
|
|
188
|
+
defaultWorkspace: Workspace;
|
|
189
|
+
defaultProject: Project;
|
|
190
|
+
}
|
|
191
|
+
interface OrganizationBootstrapInput {
|
|
192
|
+
name: string;
|
|
193
|
+
slug?: string;
|
|
194
|
+
workspaceName?: string;
|
|
195
|
+
projectName?: string;
|
|
196
|
+
}
|
|
197
|
+
declare function createOrganizationWithDefaults(db: AnyDB, schema: AnySchema, input: OrganizationBootstrapInput): Promise<OrganizationBootstrapResult>;
|
|
198
|
+
|
|
199
|
+
export { type Environment, type EnvironmentRepo, type NewEnvironment, type NewOrganization, type NewProject, type NewWorkspace, type Organization, type OrganizationBootstrapInput, type OrganizationBootstrapResult, type OrganizationRepo, type Project, type ProjectRepo, type Workspace, type WorkspaceRepo, createEnvironmentRepo, createOrganizationRepo, createOrganizationWithDefaults, createProjectRepo, createWorkspaceRepo };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import {
|
|
2
|
+
environments,
|
|
3
|
+
organizations,
|
|
4
|
+
projects,
|
|
5
|
+
workspaces
|
|
6
|
+
} from "./chunk-5UCSEIJS.js";
|
|
7
|
+
|
|
8
|
+
// src/repo/organizations.ts
|
|
9
|
+
import { eq, desc } from "drizzle-orm";
|
|
10
|
+
import { generateId, generateShortId, generateSlug } from "@baseworks/core";
|
|
11
|
+
function createOrganizationRepo(db, schema) {
|
|
12
|
+
const { organizations: organizations2 } = schema;
|
|
13
|
+
return {
|
|
14
|
+
async create(data) {
|
|
15
|
+
const now = Date.now();
|
|
16
|
+
const shortId = generateShortId();
|
|
17
|
+
const row = {
|
|
18
|
+
id: data.id ?? generateId(),
|
|
19
|
+
shortId,
|
|
20
|
+
slug: data.slug ?? generateSlug(data.name),
|
|
21
|
+
name: data.name,
|
|
22
|
+
metadata: null,
|
|
23
|
+
createdAt: now,
|
|
24
|
+
updatedAt: now
|
|
25
|
+
};
|
|
26
|
+
await db.insert(organizations2).values(row);
|
|
27
|
+
return row;
|
|
28
|
+
},
|
|
29
|
+
async findById(id) {
|
|
30
|
+
const rows = await db.select().from(organizations2).where(eq(organizations2.id, id)).limit(1);
|
|
31
|
+
return rows[0];
|
|
32
|
+
},
|
|
33
|
+
async findByShortId(shortId) {
|
|
34
|
+
const rows = await db.select().from(organizations2).where(eq(organizations2.shortId, shortId)).limit(1);
|
|
35
|
+
return rows[0];
|
|
36
|
+
},
|
|
37
|
+
async findBySlug(slug) {
|
|
38
|
+
const rows = await db.select().from(organizations2).where(eq(organizations2.slug, slug)).limit(1);
|
|
39
|
+
return rows[0];
|
|
40
|
+
},
|
|
41
|
+
async findByRef(ref) {
|
|
42
|
+
const bySlug = await db.select().from(organizations2).where(eq(organizations2.slug, ref)).limit(1);
|
|
43
|
+
if (bySlug[0]) return bySlug[0];
|
|
44
|
+
const byShortId = await db.select().from(organizations2).where(eq(organizations2.shortId, ref)).limit(1);
|
|
45
|
+
return byShortId[0];
|
|
46
|
+
},
|
|
47
|
+
async isSlugAvailable(slug) {
|
|
48
|
+
const rows = await db.select({ id: organizations2.id }).from(organizations2).where(eq(organizations2.slug, slug)).limit(1);
|
|
49
|
+
return rows.length === 0;
|
|
50
|
+
},
|
|
51
|
+
async claimSlug(id, slug) {
|
|
52
|
+
await db.update(organizations2).set({ slug, updatedAt: Date.now() }).where(eq(organizations2.id, id));
|
|
53
|
+
},
|
|
54
|
+
async update(id, data) {
|
|
55
|
+
await db.update(organizations2).set({ ...data, updatedAt: Date.now() }).where(eq(organizations2.id, id));
|
|
56
|
+
const rows = await db.select().from(organizations2).where(eq(organizations2.id, id)).limit(1);
|
|
57
|
+
return rows[0];
|
|
58
|
+
},
|
|
59
|
+
async patchMetadata(id, patch) {
|
|
60
|
+
const rows = await db.select().from(organizations2).where(eq(organizations2.id, id)).limit(1);
|
|
61
|
+
const org = rows[0];
|
|
62
|
+
if (!org) return void 0;
|
|
63
|
+
const current = org.metadata ? JSON.parse(org.metadata) : {};
|
|
64
|
+
const merged = { ...current };
|
|
65
|
+
for (const [k, v] of Object.entries(patch)) {
|
|
66
|
+
if (v === null) delete merged[k];
|
|
67
|
+
else merged[k] = v;
|
|
68
|
+
}
|
|
69
|
+
await db.update(organizations2).set({ metadata: JSON.stringify(merged), updatedAt: Date.now() }).where(eq(organizations2.id, id));
|
|
70
|
+
const updated = await db.select().from(organizations2).where(eq(organizations2.id, id)).limit(1);
|
|
71
|
+
return updated[0];
|
|
72
|
+
},
|
|
73
|
+
async delete(id) {
|
|
74
|
+
await db.delete(organizations2).where(eq(organizations2.id, id));
|
|
75
|
+
},
|
|
76
|
+
async listAll() {
|
|
77
|
+
return db.select().from(organizations2).orderBy(desc(organizations2.createdAt));
|
|
78
|
+
},
|
|
79
|
+
async hardDelete(id) {
|
|
80
|
+
await db.delete(organizations2).where(eq(organizations2.id, id));
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// src/repo/workspaces.ts
|
|
86
|
+
import { and, eq as eq2 } from "drizzle-orm";
|
|
87
|
+
import { generateId as generateId2, generateShortId as generateShortId2, generateSlug as generateSlug2 } from "@baseworks/core";
|
|
88
|
+
async function resolveSlug(db, workspacesTable, organizationId, base) {
|
|
89
|
+
let slug = base;
|
|
90
|
+
let i = 2;
|
|
91
|
+
while (true) {
|
|
92
|
+
const rows = await db.select({ id: workspacesTable.id }).from(workspacesTable).where(and(eq2(workspacesTable.organizationId, organizationId), eq2(workspacesTable.slug, slug))).limit(1);
|
|
93
|
+
if (rows.length === 0) return slug;
|
|
94
|
+
slug = `${base}-${i++}`;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function createWorkspaceRepo(db, schema) {
|
|
98
|
+
const { workspaces: workspaces2 } = schema;
|
|
99
|
+
return {
|
|
100
|
+
async create(data) {
|
|
101
|
+
const now = Date.now();
|
|
102
|
+
const base = data.slug ?? generateSlug2(data.name);
|
|
103
|
+
const slug = await resolveSlug(db, workspaces2, data.organizationId, base);
|
|
104
|
+
const row = {
|
|
105
|
+
id: data.id ?? generateId2(),
|
|
106
|
+
organizationId: data.organizationId,
|
|
107
|
+
shortId: generateShortId2(),
|
|
108
|
+
slug,
|
|
109
|
+
name: data.name,
|
|
110
|
+
isDefault: data.isDefault ?? false,
|
|
111
|
+
createdAt: now,
|
|
112
|
+
updatedAt: now
|
|
113
|
+
};
|
|
114
|
+
await db.insert(workspaces2).values(row);
|
|
115
|
+
return row;
|
|
116
|
+
},
|
|
117
|
+
async findById(id) {
|
|
118
|
+
const rows = await db.select().from(workspaces2).where(eq2(workspaces2.id, id)).limit(1);
|
|
119
|
+
return rows[0];
|
|
120
|
+
},
|
|
121
|
+
async findByShortId(shortId) {
|
|
122
|
+
const rows = await db.select().from(workspaces2).where(eq2(workspaces2.shortId, shortId)).limit(1);
|
|
123
|
+
return rows[0];
|
|
124
|
+
},
|
|
125
|
+
async findBySlug(organizationId, slug) {
|
|
126
|
+
const rows = await db.select().from(workspaces2).where(and(eq2(workspaces2.organizationId, organizationId), eq2(workspaces2.slug, slug))).limit(1);
|
|
127
|
+
return rows[0];
|
|
128
|
+
},
|
|
129
|
+
async findByRef(organizationId, ref) {
|
|
130
|
+
const bySlug = await db.select().from(workspaces2).where(and(eq2(workspaces2.organizationId, organizationId), eq2(workspaces2.slug, ref))).limit(1);
|
|
131
|
+
if (bySlug[0]) return bySlug[0];
|
|
132
|
+
const byShortId = await db.select().from(workspaces2).where(and(eq2(workspaces2.organizationId, organizationId), eq2(workspaces2.shortId, ref))).limit(1);
|
|
133
|
+
return byShortId[0];
|
|
134
|
+
},
|
|
135
|
+
async listByOrg(organizationId) {
|
|
136
|
+
return db.select().from(workspaces2).where(eq2(workspaces2.organizationId, organizationId));
|
|
137
|
+
},
|
|
138
|
+
async findDefault(organizationId) {
|
|
139
|
+
const rows = await db.select().from(workspaces2).where(and(eq2(workspaces2.organizationId, organizationId), eq2(workspaces2.isDefault, true))).limit(1);
|
|
140
|
+
return rows[0];
|
|
141
|
+
},
|
|
142
|
+
async update(id, data) {
|
|
143
|
+
await db.update(workspaces2).set({ ...data, updatedAt: Date.now() }).where(eq2(workspaces2.id, id));
|
|
144
|
+
const rows = await db.select().from(workspaces2).where(eq2(workspaces2.id, id)).limit(1);
|
|
145
|
+
return rows[0];
|
|
146
|
+
},
|
|
147
|
+
async delete(id) {
|
|
148
|
+
await db.delete(workspaces2).where(eq2(workspaces2.id, id));
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/repo/projects.ts
|
|
154
|
+
import { and as and2, eq as eq3 } from "drizzle-orm";
|
|
155
|
+
import { generateId as generateId3, generateShortId as generateShortId3, generateSlug as generateSlug3 } from "@baseworks/core";
|
|
156
|
+
async function resolveSlug2(db, projectsTable, workspaceId, base) {
|
|
157
|
+
let slug = base;
|
|
158
|
+
let i = 2;
|
|
159
|
+
while (true) {
|
|
160
|
+
const rows = await db.select({ id: projectsTable.id }).from(projectsTable).where(and2(eq3(projectsTable.workspaceId, workspaceId), eq3(projectsTable.slug, slug))).limit(1);
|
|
161
|
+
if (rows.length === 0) return slug;
|
|
162
|
+
slug = `${base}-${i++}`;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function createProjectRepo(db, schema) {
|
|
166
|
+
const { projects: projects2 } = schema;
|
|
167
|
+
return {
|
|
168
|
+
async create(data) {
|
|
169
|
+
const now = Date.now();
|
|
170
|
+
const base = data.slug ?? generateSlug3(data.name);
|
|
171
|
+
const slug = await resolveSlug2(db, projects2, data.workspaceId, base);
|
|
172
|
+
const row = {
|
|
173
|
+
id: data.id ?? generateId3(),
|
|
174
|
+
workspaceId: data.workspaceId,
|
|
175
|
+
shortId: generateShortId3(),
|
|
176
|
+
slug,
|
|
177
|
+
name: data.name,
|
|
178
|
+
isDefault: data.isDefault ?? false,
|
|
179
|
+
metadata: null,
|
|
180
|
+
createdAt: now,
|
|
181
|
+
updatedAt: now
|
|
182
|
+
};
|
|
183
|
+
await db.insert(projects2).values(row);
|
|
184
|
+
return row;
|
|
185
|
+
},
|
|
186
|
+
async findById(id) {
|
|
187
|
+
const rows = await db.select().from(projects2).where(eq3(projects2.id, id)).limit(1);
|
|
188
|
+
return rows[0];
|
|
189
|
+
},
|
|
190
|
+
async findByShortId(shortId) {
|
|
191
|
+
const rows = await db.select().from(projects2).where(eq3(projects2.shortId, shortId)).limit(1);
|
|
192
|
+
return rows[0];
|
|
193
|
+
},
|
|
194
|
+
async findBySlug(workspaceId, slug) {
|
|
195
|
+
const rows = await db.select().from(projects2).where(and2(eq3(projects2.workspaceId, workspaceId), eq3(projects2.slug, slug))).limit(1);
|
|
196
|
+
return rows[0];
|
|
197
|
+
},
|
|
198
|
+
async findByRef(workspaceId, ref) {
|
|
199
|
+
const bySlug = await db.select().from(projects2).where(and2(eq3(projects2.workspaceId, workspaceId), eq3(projects2.slug, ref))).limit(1);
|
|
200
|
+
if (bySlug[0]) return bySlug[0];
|
|
201
|
+
const byShortId = await db.select().from(projects2).where(and2(eq3(projects2.workspaceId, workspaceId), eq3(projects2.shortId, ref))).limit(1);
|
|
202
|
+
return byShortId[0];
|
|
203
|
+
},
|
|
204
|
+
async listByWorkspace(workspaceId) {
|
|
205
|
+
return db.select().from(projects2).where(eq3(projects2.workspaceId, workspaceId));
|
|
206
|
+
},
|
|
207
|
+
async findDefault(workspaceId) {
|
|
208
|
+
const rows = await db.select().from(projects2).where(and2(eq3(projects2.workspaceId, workspaceId), eq3(projects2.isDefault, true))).limit(1);
|
|
209
|
+
return rows[0];
|
|
210
|
+
},
|
|
211
|
+
async update(id, data) {
|
|
212
|
+
await db.update(projects2).set({ ...data, updatedAt: Date.now() }).where(eq3(projects2.id, id));
|
|
213
|
+
const rows = await db.select().from(projects2).where(eq3(projects2.id, id)).limit(1);
|
|
214
|
+
return rows[0];
|
|
215
|
+
},
|
|
216
|
+
async delete(id) {
|
|
217
|
+
await db.delete(projects2).where(eq3(projects2.id, id));
|
|
218
|
+
},
|
|
219
|
+
async getMetadata(id) {
|
|
220
|
+
const rows = await db.select({ metadata: projects2.metadata }).from(projects2).where(eq3(projects2.id, id)).limit(1);
|
|
221
|
+
const row = rows[0];
|
|
222
|
+
if (!row?.metadata) return {};
|
|
223
|
+
try {
|
|
224
|
+
return JSON.parse(row.metadata);
|
|
225
|
+
} catch {
|
|
226
|
+
return {};
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
async patchMetadata(id, patch) {
|
|
230
|
+
const existing = await this.getMetadata(id);
|
|
231
|
+
const next = { ...existing };
|
|
232
|
+
for (const [k, v] of Object.entries(patch)) {
|
|
233
|
+
if (v === null) delete next[k];
|
|
234
|
+
else next[k] = v;
|
|
235
|
+
}
|
|
236
|
+
await db.update(projects2).set({ metadata: JSON.stringify(next), updatedAt: Date.now() }).where(eq3(projects2.id, id));
|
|
237
|
+
return next;
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// src/repo/environments.ts
|
|
243
|
+
import { and as and3, eq as eq4, or } from "drizzle-orm";
|
|
244
|
+
import { generateId as generateId4, generateShortId as generateShortId4, generateSlug as generateSlug4 } from "@baseworks/core";
|
|
245
|
+
async function resolveSlug3(db, envsTable, projectId, base) {
|
|
246
|
+
let slug = base;
|
|
247
|
+
let i = 2;
|
|
248
|
+
while (true) {
|
|
249
|
+
const rows = await db.select({ id: envsTable.id }).from(envsTable).where(and3(eq4(envsTable.projectId, projectId), eq4(envsTable.slug, slug))).limit(1);
|
|
250
|
+
if (rows.length === 0) return slug;
|
|
251
|
+
slug = `${base}-${i++}`;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
function createEnvironmentRepo(db, schema) {
|
|
255
|
+
const { environments: environments2 } = schema;
|
|
256
|
+
return {
|
|
257
|
+
async create(data) {
|
|
258
|
+
const now = Date.now();
|
|
259
|
+
const base = data.slug ?? generateSlug4(data.name);
|
|
260
|
+
const slug = await resolveSlug3(db, environments2, data.projectId, base);
|
|
261
|
+
const row = {
|
|
262
|
+
id: data.id ?? generateId4(),
|
|
263
|
+
projectId: data.projectId,
|
|
264
|
+
shortId: generateShortId4(),
|
|
265
|
+
slug,
|
|
266
|
+
name: data.name,
|
|
267
|
+
createdAt: now,
|
|
268
|
+
updatedAt: now
|
|
269
|
+
};
|
|
270
|
+
await db.insert(environments2).values(row);
|
|
271
|
+
return row;
|
|
272
|
+
},
|
|
273
|
+
async findById(id) {
|
|
274
|
+
const rows = await db.select().from(environments2).where(eq4(environments2.id, id)).limit(1);
|
|
275
|
+
return rows[0];
|
|
276
|
+
},
|
|
277
|
+
async findByShortId(shortId) {
|
|
278
|
+
const rows = await db.select().from(environments2).where(eq4(environments2.shortId, shortId)).limit(1);
|
|
279
|
+
return rows[0];
|
|
280
|
+
},
|
|
281
|
+
async findByIdentifier(projectId, identifier) {
|
|
282
|
+
const rows = await db.select().from(environments2).where(and3(eq4(environments2.projectId, projectId), or(eq4(environments2.shortId, identifier), eq4(environments2.slug, identifier)))).limit(1);
|
|
283
|
+
return rows[0];
|
|
284
|
+
},
|
|
285
|
+
async findByRef(projectId, ref) {
|
|
286
|
+
return this.findByIdentifier(projectId, ref);
|
|
287
|
+
},
|
|
288
|
+
async listByProject(projectId) {
|
|
289
|
+
return db.select().from(environments2).where(eq4(environments2.projectId, projectId));
|
|
290
|
+
},
|
|
291
|
+
async update(id, data) {
|
|
292
|
+
await db.update(environments2).set({ ...data, updatedAt: Date.now() }).where(eq4(environments2.id, id));
|
|
293
|
+
const rows = await db.select().from(environments2).where(eq4(environments2.id, id)).limit(1);
|
|
294
|
+
return rows[0];
|
|
295
|
+
},
|
|
296
|
+
async delete(id) {
|
|
297
|
+
await db.delete(environments2).where(eq4(environments2.id, id));
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// src/operations/bootstrap.ts
|
|
303
|
+
async function createOrganizationWithDefaults(db, schema, input) {
|
|
304
|
+
const orgRepo = createOrganizationRepo(db, schema);
|
|
305
|
+
const workspaceRepo = createWorkspaceRepo(db, schema);
|
|
306
|
+
const projectRepo = createProjectRepo(db, schema);
|
|
307
|
+
const organization = await orgRepo.create({ name: input.name, slug: input.slug });
|
|
308
|
+
const defaultWorkspace = await workspaceRepo.create({
|
|
309
|
+
organizationId: organization.id,
|
|
310
|
+
name: input.workspaceName ?? "Default",
|
|
311
|
+
isDefault: true
|
|
312
|
+
});
|
|
313
|
+
const defaultProject = await projectRepo.create({
|
|
314
|
+
workspaceId: defaultWorkspace.id,
|
|
315
|
+
name: input.projectName ?? "Default",
|
|
316
|
+
isDefault: true
|
|
317
|
+
});
|
|
318
|
+
return { organization, defaultWorkspace, defaultProject };
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// src/index.ts
|
|
322
|
+
import { generateId as generateId5, generateShortId as generateShortId5 } from "@baseworks/core";
|
|
323
|
+
export {
|
|
324
|
+
createEnvironmentRepo,
|
|
325
|
+
createOrganizationRepo,
|
|
326
|
+
createOrganizationWithDefaults,
|
|
327
|
+
createProjectRepo,
|
|
328
|
+
createWorkspaceRepo,
|
|
329
|
+
environments,
|
|
330
|
+
generateId5 as generateId,
|
|
331
|
+
generateShortId5 as generateShortId,
|
|
332
|
+
organizations,
|
|
333
|
+
projects,
|
|
334
|
+
workspaces
|
|
335
|
+
};
|