@sudobility/entity_service 1.0.1
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/CLAUDE.md +124 -0
- package/dist/helpers/EntityHelper.cjs +234 -0
- package/dist/helpers/EntityHelper.d.ts +60 -0
- package/dist/helpers/EntityHelper.d.ts.map +1 -0
- package/dist/helpers/EntityHelper.js +234 -0
- package/dist/helpers/EntityHelper.js.map +1 -0
- package/dist/helpers/EntityMemberHelper.cjs +215 -0
- package/dist/helpers/EntityMemberHelper.d.ts +45 -0
- package/dist/helpers/EntityMemberHelper.d.ts.map +1 -0
- package/dist/helpers/EntityMemberHelper.js +215 -0
- package/dist/helpers/EntityMemberHelper.js.map +1 -0
- package/dist/helpers/InvitationHelper.cjs +251 -0
- package/dist/helpers/InvitationHelper.d.ts +59 -0
- package/dist/helpers/InvitationHelper.d.ts.map +1 -0
- package/dist/helpers/InvitationHelper.js +251 -0
- package/dist/helpers/InvitationHelper.js.map +1 -0
- package/dist/helpers/PermissionHelper.cjs +197 -0
- package/dist/helpers/PermissionHelper.d.ts +86 -0
- package/dist/helpers/PermissionHelper.d.ts.map +1 -0
- package/dist/helpers/PermissionHelper.js +197 -0
- package/dist/helpers/PermissionHelper.js.map +1 -0
- package/dist/helpers/index.cjs +15 -0
- package/dist/helpers/index.d.ts +8 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +15 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/index.cjs +76 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/hono.cjs +148 -0
- package/dist/middleware/hono.d.ts +102 -0
- package/dist/middleware/hono.d.ts.map +1 -0
- package/dist/middleware/hono.js +148 -0
- package/dist/middleware/hono.js.map +1 -0
- package/dist/middleware/index.cjs +12 -0
- package/dist/middleware/index.d.ts +5 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +12 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/migrations/001_add_entities.cjs +269 -0
- package/dist/migrations/001_add_entities.d.ts +29 -0
- package/dist/migrations/001_add_entities.d.ts.map +1 -0
- package/dist/migrations/001_add_entities.js +269 -0
- package/dist/migrations/001_add_entities.js.map +1 -0
- package/dist/migrations/index.cjs +10 -0
- package/dist/migrations/index.d.ts +5 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +10 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/schema/entities.cjs +304 -0
- package/dist/schema/entities.d.ts +1047 -0
- package/dist/schema/entities.d.ts.map +1 -0
- package/dist/schema/entities.js +304 -0
- package/dist/schema/entities.js.map +1 -0
- package/dist/types/index.cjs +14 -0
- package/dist/types/index.d.ts +71 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +14 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.cjs +21 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +21 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/slug-generator.cjs +92 -0
- package/dist/utils/slug-generator.d.ts +41 -0
- package/dist/utils/slug-generator.d.ts.map +1 -0
- package/dist/utils/slug-generator.js +92 -0
- package/dist/utils/slug-generator.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Entity Tables Migration
|
|
4
|
+
* @description Creates entity tables and migrates existing data
|
|
5
|
+
*
|
|
6
|
+
* This migration:
|
|
7
|
+
* 1. Creates entities, entity_members, entity_invitations tables
|
|
8
|
+
* 2. Adds entity_id column to projects table (nullable for backward compatibility)
|
|
9
|
+
* 3. Creates personal entities for existing users
|
|
10
|
+
* 4. Populates entity_id for existing projects
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.runEntityMigration = runEntityMigration;
|
|
14
|
+
exports.rollbackEntityMigration = rollbackEntityMigration;
|
|
15
|
+
/**
|
|
16
|
+
* Run the full entity migration.
|
|
17
|
+
*/
|
|
18
|
+
async function runEntityMigration(config) {
|
|
19
|
+
const { client, schemaName, indexPrefix, migrateProjects = true } = config;
|
|
20
|
+
const prefix = `${schemaName}.`;
|
|
21
|
+
console.log(`Running entity migration for schema: ${schemaName}`);
|
|
22
|
+
// Step 1: Create entity tables
|
|
23
|
+
await createEntityTables(client, prefix, indexPrefix);
|
|
24
|
+
// Step 2: Add entity_id to projects if requested
|
|
25
|
+
if (migrateProjects) {
|
|
26
|
+
await addEntityIdToProjects(client, prefix, indexPrefix);
|
|
27
|
+
}
|
|
28
|
+
// Step 3: Migrate existing users to personal entities
|
|
29
|
+
await migrateUsersToPersonalEntities(client, prefix);
|
|
30
|
+
// Step 4: Populate entity_id for existing projects
|
|
31
|
+
if (migrateProjects) {
|
|
32
|
+
await populateProjectEntityIds(client, prefix);
|
|
33
|
+
}
|
|
34
|
+
console.log('Entity migration completed successfully');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Create the entity tables.
|
|
38
|
+
*/
|
|
39
|
+
async function createEntityTables(client, prefix, indexPrefix) {
|
|
40
|
+
console.log('Creating entity tables...');
|
|
41
|
+
// Create entities table
|
|
42
|
+
await client.unsafe(`
|
|
43
|
+
CREATE TABLE IF NOT EXISTS ${prefix}entities (
|
|
44
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
45
|
+
entity_slug VARCHAR(12) NOT NULL UNIQUE,
|
|
46
|
+
entity_type VARCHAR(20) NOT NULL CHECK (entity_type IN ('personal', 'organization')),
|
|
47
|
+
display_name VARCHAR(255) NOT NULL,
|
|
48
|
+
description TEXT,
|
|
49
|
+
avatar_url TEXT,
|
|
50
|
+
owner_user_id UUID NOT NULL,
|
|
51
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
52
|
+
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
53
|
+
)
|
|
54
|
+
`);
|
|
55
|
+
await client.unsafe(`
|
|
56
|
+
CREATE UNIQUE INDEX IF NOT EXISTS ${indexPrefix}_entities_slug_idx
|
|
57
|
+
ON ${prefix}entities (entity_slug)
|
|
58
|
+
`);
|
|
59
|
+
await client.unsafe(`
|
|
60
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_entities_owner_idx
|
|
61
|
+
ON ${prefix}entities (owner_user_id)
|
|
62
|
+
`);
|
|
63
|
+
await client.unsafe(`
|
|
64
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_entities_type_idx
|
|
65
|
+
ON ${prefix}entities (entity_type)
|
|
66
|
+
`);
|
|
67
|
+
// Create entity_members table
|
|
68
|
+
await client.unsafe(`
|
|
69
|
+
CREATE TABLE IF NOT EXISTS ${prefix}entity_members (
|
|
70
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
71
|
+
entity_id UUID NOT NULL REFERENCES ${prefix}entities(id) ON DELETE CASCADE,
|
|
72
|
+
user_id UUID NOT NULL,
|
|
73
|
+
role VARCHAR(20) NOT NULL CHECK (role IN ('admin', 'manager', 'viewer')),
|
|
74
|
+
joined_at TIMESTAMPTZ DEFAULT NOW(),
|
|
75
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
76
|
+
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
77
|
+
UNIQUE(entity_id, user_id)
|
|
78
|
+
)
|
|
79
|
+
`);
|
|
80
|
+
await client.unsafe(`
|
|
81
|
+
CREATE UNIQUE INDEX IF NOT EXISTS ${indexPrefix}_entity_members_entity_user_idx
|
|
82
|
+
ON ${prefix}entity_members (entity_id, user_id)
|
|
83
|
+
`);
|
|
84
|
+
await client.unsafe(`
|
|
85
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_entity_members_entity_idx
|
|
86
|
+
ON ${prefix}entity_members (entity_id)
|
|
87
|
+
`);
|
|
88
|
+
await client.unsafe(`
|
|
89
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_entity_members_user_idx
|
|
90
|
+
ON ${prefix}entity_members (user_id)
|
|
91
|
+
`);
|
|
92
|
+
// Create entity_invitations table
|
|
93
|
+
await client.unsafe(`
|
|
94
|
+
CREATE TABLE IF NOT EXISTS ${prefix}entity_invitations (
|
|
95
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
96
|
+
entity_id UUID NOT NULL REFERENCES ${prefix}entities(id) ON DELETE CASCADE,
|
|
97
|
+
email VARCHAR(255) NOT NULL,
|
|
98
|
+
role VARCHAR(20) NOT NULL CHECK (role IN ('admin', 'manager', 'viewer')),
|
|
99
|
+
status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'accepted', 'declined', 'expired')),
|
|
100
|
+
invited_by_user_id UUID NOT NULL,
|
|
101
|
+
token VARCHAR(64) NOT NULL UNIQUE,
|
|
102
|
+
expires_at TIMESTAMPTZ NOT NULL,
|
|
103
|
+
accepted_at TIMESTAMPTZ,
|
|
104
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
105
|
+
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
106
|
+
)
|
|
107
|
+
`);
|
|
108
|
+
await client.unsafe(`
|
|
109
|
+
CREATE UNIQUE INDEX IF NOT EXISTS ${indexPrefix}_entity_invitations_token_idx
|
|
110
|
+
ON ${prefix}entity_invitations (token)
|
|
111
|
+
`);
|
|
112
|
+
await client.unsafe(`
|
|
113
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_entity_invitations_entity_idx
|
|
114
|
+
ON ${prefix}entity_invitations (entity_id)
|
|
115
|
+
`);
|
|
116
|
+
await client.unsafe(`
|
|
117
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_entity_invitations_email_idx
|
|
118
|
+
ON ${prefix}entity_invitations (email)
|
|
119
|
+
`);
|
|
120
|
+
await client.unsafe(`
|
|
121
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_entity_invitations_status_idx
|
|
122
|
+
ON ${prefix}entity_invitations (status)
|
|
123
|
+
`);
|
|
124
|
+
console.log('Entity tables created');
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Add entity_id column to projects table.
|
|
128
|
+
*/
|
|
129
|
+
async function addEntityIdToProjects(client, prefix, indexPrefix) {
|
|
130
|
+
console.log('Adding entity_id to projects table...');
|
|
131
|
+
// Check if column already exists
|
|
132
|
+
const columnExists = await client.unsafe(`
|
|
133
|
+
SELECT EXISTS (
|
|
134
|
+
SELECT 1 FROM information_schema.columns
|
|
135
|
+
WHERE table_schema = '${prefix.replace('.', '')}'
|
|
136
|
+
AND table_name = 'projects'
|
|
137
|
+
AND column_name = 'entity_id'
|
|
138
|
+
)
|
|
139
|
+
`);
|
|
140
|
+
if (!columnExists[0]?.exists) {
|
|
141
|
+
// Add nullable entity_id column
|
|
142
|
+
await client.unsafe(`
|
|
143
|
+
ALTER TABLE ${prefix}projects
|
|
144
|
+
ADD COLUMN entity_id UUID REFERENCES ${prefix}entities(id) ON DELETE CASCADE
|
|
145
|
+
`);
|
|
146
|
+
// Create index on entity_id
|
|
147
|
+
await client.unsafe(`
|
|
148
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_projects_entity_idx
|
|
149
|
+
ON ${prefix}projects (entity_id)
|
|
150
|
+
`);
|
|
151
|
+
console.log('entity_id column added to projects');
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
console.log('entity_id column already exists in projects');
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Create personal entities for existing users.
|
|
159
|
+
*/
|
|
160
|
+
async function migrateUsersToPersonalEntities(client, prefix) {
|
|
161
|
+
console.log('Migrating users to personal entities...');
|
|
162
|
+
// Get users without personal entities
|
|
163
|
+
const usersWithoutEntities = await client.unsafe(`
|
|
164
|
+
SELECT u.id, u.email, u.display_name,
|
|
165
|
+
COALESCE(s.organization_path, SUBSTRING(MD5(RANDOM()::TEXT) FROM 1 FOR 8)) as slug_source
|
|
166
|
+
FROM ${prefix}users u
|
|
167
|
+
LEFT JOIN ${prefix}user_settings s ON u.id = s.user_id
|
|
168
|
+
WHERE NOT EXISTS (
|
|
169
|
+
SELECT 1 FROM ${prefix}entities e
|
|
170
|
+
WHERE e.owner_user_id = u.id AND e.entity_type = 'personal'
|
|
171
|
+
)
|
|
172
|
+
`);
|
|
173
|
+
let migratedCount = 0;
|
|
174
|
+
for (const user of usersWithoutEntities) {
|
|
175
|
+
// Generate a unique slug (8 chars, lowercase alphanumeric)
|
|
176
|
+
const slug = generateSlug(user.slug_source);
|
|
177
|
+
const displayName = user.display_name || user.email?.split('@')[0] || 'Personal';
|
|
178
|
+
try {
|
|
179
|
+
// Create personal entity
|
|
180
|
+
const [entity] = await client.unsafe(`
|
|
181
|
+
INSERT INTO ${prefix}entities (entity_slug, entity_type, display_name, owner_user_id)
|
|
182
|
+
VALUES ('${slug}', 'personal', '${displayName.replace(/'/g, "''")}', '${user.id}')
|
|
183
|
+
RETURNING id
|
|
184
|
+
`);
|
|
185
|
+
// Add user as admin member
|
|
186
|
+
await client.unsafe(`
|
|
187
|
+
INSERT INTO ${prefix}entity_members (entity_id, user_id, role)
|
|
188
|
+
VALUES ('${entity.id}', '${user.id}', 'admin')
|
|
189
|
+
`);
|
|
190
|
+
migratedCount++;
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
// If slug collision, generate a new one and retry
|
|
194
|
+
if (error.code === '23505') {
|
|
195
|
+
const newSlug = generateSlug();
|
|
196
|
+
const [entity] = await client.unsafe(`
|
|
197
|
+
INSERT INTO ${prefix}entities (entity_slug, entity_type, display_name, owner_user_id)
|
|
198
|
+
VALUES ('${newSlug}', 'personal', '${displayName.replace(/'/g, "''")}', '${user.id}')
|
|
199
|
+
RETURNING id
|
|
200
|
+
`);
|
|
201
|
+
await client.unsafe(`
|
|
202
|
+
INSERT INTO ${prefix}entity_members (entity_id, user_id, role)
|
|
203
|
+
VALUES ('${entity.id}', '${user.id}', 'admin')
|
|
204
|
+
`);
|
|
205
|
+
migratedCount++;
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
console.log(`Migrated ${migratedCount} users to personal entities`);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Populate entity_id for existing projects.
|
|
216
|
+
*/
|
|
217
|
+
async function populateProjectEntityIds(client, prefix) {
|
|
218
|
+
console.log('Populating entity_id for existing projects...');
|
|
219
|
+
// Update projects to use owner's personal entity
|
|
220
|
+
const result = await client.unsafe(`
|
|
221
|
+
UPDATE ${prefix}projects p
|
|
222
|
+
SET entity_id = e.id
|
|
223
|
+
FROM ${prefix}entities e
|
|
224
|
+
WHERE p.user_id = e.owner_user_id
|
|
225
|
+
AND e.entity_type = 'personal'
|
|
226
|
+
AND p.entity_id IS NULL
|
|
227
|
+
`);
|
|
228
|
+
console.log(`Updated entity_id for ${result.count || 0} projects`);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Generate a slug from a source string or random.
|
|
232
|
+
*/
|
|
233
|
+
function generateSlug(source) {
|
|
234
|
+
if (source) {
|
|
235
|
+
// Normalize: lowercase, remove non-alphanumeric, take first 8 chars
|
|
236
|
+
return source
|
|
237
|
+
.toLowerCase()
|
|
238
|
+
.replace(/[^a-z0-9]/g, '')
|
|
239
|
+
.substring(0, 8)
|
|
240
|
+
.padEnd(8, '0');
|
|
241
|
+
}
|
|
242
|
+
// Generate random slug
|
|
243
|
+
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
|
244
|
+
let slug = '';
|
|
245
|
+
for (let i = 0; i < 8; i++) {
|
|
246
|
+
slug += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
247
|
+
}
|
|
248
|
+
return slug;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Rollback the entity migration.
|
|
252
|
+
*/
|
|
253
|
+
async function rollbackEntityMigration(config) {
|
|
254
|
+
const { client, schemaName, migrateProjects = true } = config;
|
|
255
|
+
const prefix = `${schemaName}.`;
|
|
256
|
+
console.log(`Rolling back entity migration for schema: ${schemaName}`);
|
|
257
|
+
// Remove entity_id from projects first
|
|
258
|
+
if (migrateProjects) {
|
|
259
|
+
await client.unsafe(`
|
|
260
|
+
ALTER TABLE ${prefix}projects DROP COLUMN IF EXISTS entity_id
|
|
261
|
+
`);
|
|
262
|
+
}
|
|
263
|
+
// Drop tables in reverse order
|
|
264
|
+
await client.unsafe(`DROP TABLE IF EXISTS ${prefix}entity_invitations`);
|
|
265
|
+
await client.unsafe(`DROP TABLE IF EXISTS ${prefix}entity_members`);
|
|
266
|
+
await client.unsafe(`DROP TABLE IF EXISTS ${prefix}entities`);
|
|
267
|
+
console.log('Entity migration rolled back');
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=001_add_entities.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Entity Tables Migration
|
|
3
|
+
* @description Creates entity tables and migrates existing data
|
|
4
|
+
*
|
|
5
|
+
* This migration:
|
|
6
|
+
* 1. Creates entities, entity_members, entity_invitations tables
|
|
7
|
+
* 2. Adds entity_id column to projects table (nullable for backward compatibility)
|
|
8
|
+
* 3. Creates personal entities for existing users
|
|
9
|
+
* 4. Populates entity_id for existing projects
|
|
10
|
+
*/
|
|
11
|
+
export interface MigrationConfig {
|
|
12
|
+
/** postgres-js client instance */
|
|
13
|
+
client: ReturnType<typeof import('postgres')>;
|
|
14
|
+
/** PostgreSQL schema name (e.g., 'whisperly', 'shapeshyft') */
|
|
15
|
+
schemaName: string;
|
|
16
|
+
/** Index prefix for avoiding name conflicts */
|
|
17
|
+
indexPrefix: string;
|
|
18
|
+
/** Whether to also add entity_id to projects table */
|
|
19
|
+
migrateProjects?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Run the full entity migration.
|
|
23
|
+
*/
|
|
24
|
+
export declare function runEntityMigration(config: MigrationConfig): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Rollback the entity migration.
|
|
27
|
+
*/
|
|
28
|
+
export declare function rollbackEntityMigration(config: MigrationConfig): Promise<void>;
|
|
29
|
+
//# sourceMappingURL=001_add_entities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"001_add_entities.d.ts","sourceRoot":"","sources":["../../src/migrations/001_add_entities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,MAAM,EAAE,UAAU,CAAC,cAAc,UAAU,CAAC,CAAC,CAAC;IAC9C,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB/E;AAqQD;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBpF"}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Entity Tables Migration
|
|
4
|
+
* @description Creates entity tables and migrates existing data
|
|
5
|
+
*
|
|
6
|
+
* This migration:
|
|
7
|
+
* 1. Creates entities, entity_members, entity_invitations tables
|
|
8
|
+
* 2. Adds entity_id column to projects table (nullable for backward compatibility)
|
|
9
|
+
* 3. Creates personal entities for existing users
|
|
10
|
+
* 4. Populates entity_id for existing projects
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.runEntityMigration = runEntityMigration;
|
|
14
|
+
exports.rollbackEntityMigration = rollbackEntityMigration;
|
|
15
|
+
/**
|
|
16
|
+
* Run the full entity migration.
|
|
17
|
+
*/
|
|
18
|
+
async function runEntityMigration(config) {
|
|
19
|
+
const { client, schemaName, indexPrefix, migrateProjects = true } = config;
|
|
20
|
+
const prefix = `${schemaName}.`;
|
|
21
|
+
console.log(`Running entity migration for schema: ${schemaName}`);
|
|
22
|
+
// Step 1: Create entity tables
|
|
23
|
+
await createEntityTables(client, prefix, indexPrefix);
|
|
24
|
+
// Step 2: Add entity_id to projects if requested
|
|
25
|
+
if (migrateProjects) {
|
|
26
|
+
await addEntityIdToProjects(client, prefix, indexPrefix);
|
|
27
|
+
}
|
|
28
|
+
// Step 3: Migrate existing users to personal entities
|
|
29
|
+
await migrateUsersToPersonalEntities(client, prefix);
|
|
30
|
+
// Step 4: Populate entity_id for existing projects
|
|
31
|
+
if (migrateProjects) {
|
|
32
|
+
await populateProjectEntityIds(client, prefix);
|
|
33
|
+
}
|
|
34
|
+
console.log('Entity migration completed successfully');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Create the entity tables.
|
|
38
|
+
*/
|
|
39
|
+
async function createEntityTables(client, prefix, indexPrefix) {
|
|
40
|
+
console.log('Creating entity tables...');
|
|
41
|
+
// Create entities table
|
|
42
|
+
await client.unsafe(`
|
|
43
|
+
CREATE TABLE IF NOT EXISTS ${prefix}entities (
|
|
44
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
45
|
+
entity_slug VARCHAR(12) NOT NULL UNIQUE,
|
|
46
|
+
entity_type VARCHAR(20) NOT NULL CHECK (entity_type IN ('personal', 'organization')),
|
|
47
|
+
display_name VARCHAR(255) NOT NULL,
|
|
48
|
+
description TEXT,
|
|
49
|
+
avatar_url TEXT,
|
|
50
|
+
owner_user_id UUID NOT NULL,
|
|
51
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
52
|
+
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
53
|
+
)
|
|
54
|
+
`);
|
|
55
|
+
await client.unsafe(`
|
|
56
|
+
CREATE UNIQUE INDEX IF NOT EXISTS ${indexPrefix}_entities_slug_idx
|
|
57
|
+
ON ${prefix}entities (entity_slug)
|
|
58
|
+
`);
|
|
59
|
+
await client.unsafe(`
|
|
60
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_entities_owner_idx
|
|
61
|
+
ON ${prefix}entities (owner_user_id)
|
|
62
|
+
`);
|
|
63
|
+
await client.unsafe(`
|
|
64
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_entities_type_idx
|
|
65
|
+
ON ${prefix}entities (entity_type)
|
|
66
|
+
`);
|
|
67
|
+
// Create entity_members table
|
|
68
|
+
await client.unsafe(`
|
|
69
|
+
CREATE TABLE IF NOT EXISTS ${prefix}entity_members (
|
|
70
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
71
|
+
entity_id UUID NOT NULL REFERENCES ${prefix}entities(id) ON DELETE CASCADE,
|
|
72
|
+
user_id UUID NOT NULL,
|
|
73
|
+
role VARCHAR(20) NOT NULL CHECK (role IN ('admin', 'manager', 'viewer')),
|
|
74
|
+
joined_at TIMESTAMPTZ DEFAULT NOW(),
|
|
75
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
76
|
+
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
77
|
+
UNIQUE(entity_id, user_id)
|
|
78
|
+
)
|
|
79
|
+
`);
|
|
80
|
+
await client.unsafe(`
|
|
81
|
+
CREATE UNIQUE INDEX IF NOT EXISTS ${indexPrefix}_entity_members_entity_user_idx
|
|
82
|
+
ON ${prefix}entity_members (entity_id, user_id)
|
|
83
|
+
`);
|
|
84
|
+
await client.unsafe(`
|
|
85
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_entity_members_entity_idx
|
|
86
|
+
ON ${prefix}entity_members (entity_id)
|
|
87
|
+
`);
|
|
88
|
+
await client.unsafe(`
|
|
89
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_entity_members_user_idx
|
|
90
|
+
ON ${prefix}entity_members (user_id)
|
|
91
|
+
`);
|
|
92
|
+
// Create entity_invitations table
|
|
93
|
+
await client.unsafe(`
|
|
94
|
+
CREATE TABLE IF NOT EXISTS ${prefix}entity_invitations (
|
|
95
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
96
|
+
entity_id UUID NOT NULL REFERENCES ${prefix}entities(id) ON DELETE CASCADE,
|
|
97
|
+
email VARCHAR(255) NOT NULL,
|
|
98
|
+
role VARCHAR(20) NOT NULL CHECK (role IN ('admin', 'manager', 'viewer')),
|
|
99
|
+
status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'accepted', 'declined', 'expired')),
|
|
100
|
+
invited_by_user_id UUID NOT NULL,
|
|
101
|
+
token VARCHAR(64) NOT NULL UNIQUE,
|
|
102
|
+
expires_at TIMESTAMPTZ NOT NULL,
|
|
103
|
+
accepted_at TIMESTAMPTZ,
|
|
104
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
105
|
+
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
106
|
+
)
|
|
107
|
+
`);
|
|
108
|
+
await client.unsafe(`
|
|
109
|
+
CREATE UNIQUE INDEX IF NOT EXISTS ${indexPrefix}_entity_invitations_token_idx
|
|
110
|
+
ON ${prefix}entity_invitations (token)
|
|
111
|
+
`);
|
|
112
|
+
await client.unsafe(`
|
|
113
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_entity_invitations_entity_idx
|
|
114
|
+
ON ${prefix}entity_invitations (entity_id)
|
|
115
|
+
`);
|
|
116
|
+
await client.unsafe(`
|
|
117
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_entity_invitations_email_idx
|
|
118
|
+
ON ${prefix}entity_invitations (email)
|
|
119
|
+
`);
|
|
120
|
+
await client.unsafe(`
|
|
121
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_entity_invitations_status_idx
|
|
122
|
+
ON ${prefix}entity_invitations (status)
|
|
123
|
+
`);
|
|
124
|
+
console.log('Entity tables created');
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Add entity_id column to projects table.
|
|
128
|
+
*/
|
|
129
|
+
async function addEntityIdToProjects(client, prefix, indexPrefix) {
|
|
130
|
+
console.log('Adding entity_id to projects table...');
|
|
131
|
+
// Check if column already exists
|
|
132
|
+
const columnExists = await client.unsafe(`
|
|
133
|
+
SELECT EXISTS (
|
|
134
|
+
SELECT 1 FROM information_schema.columns
|
|
135
|
+
WHERE table_schema = '${prefix.replace('.', '')}'
|
|
136
|
+
AND table_name = 'projects'
|
|
137
|
+
AND column_name = 'entity_id'
|
|
138
|
+
)
|
|
139
|
+
`);
|
|
140
|
+
if (!columnExists[0]?.exists) {
|
|
141
|
+
// Add nullable entity_id column
|
|
142
|
+
await client.unsafe(`
|
|
143
|
+
ALTER TABLE ${prefix}projects
|
|
144
|
+
ADD COLUMN entity_id UUID REFERENCES ${prefix}entities(id) ON DELETE CASCADE
|
|
145
|
+
`);
|
|
146
|
+
// Create index on entity_id
|
|
147
|
+
await client.unsafe(`
|
|
148
|
+
CREATE INDEX IF NOT EXISTS ${indexPrefix}_projects_entity_idx
|
|
149
|
+
ON ${prefix}projects (entity_id)
|
|
150
|
+
`);
|
|
151
|
+
console.log('entity_id column added to projects');
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
console.log('entity_id column already exists in projects');
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Create personal entities for existing users.
|
|
159
|
+
*/
|
|
160
|
+
async function migrateUsersToPersonalEntities(client, prefix) {
|
|
161
|
+
console.log('Migrating users to personal entities...');
|
|
162
|
+
// Get users without personal entities
|
|
163
|
+
const usersWithoutEntities = await client.unsafe(`
|
|
164
|
+
SELECT u.id, u.email, u.display_name,
|
|
165
|
+
COALESCE(s.organization_path, SUBSTRING(MD5(RANDOM()::TEXT) FROM 1 FOR 8)) as slug_source
|
|
166
|
+
FROM ${prefix}users u
|
|
167
|
+
LEFT JOIN ${prefix}user_settings s ON u.id = s.user_id
|
|
168
|
+
WHERE NOT EXISTS (
|
|
169
|
+
SELECT 1 FROM ${prefix}entities e
|
|
170
|
+
WHERE e.owner_user_id = u.id AND e.entity_type = 'personal'
|
|
171
|
+
)
|
|
172
|
+
`);
|
|
173
|
+
let migratedCount = 0;
|
|
174
|
+
for (const user of usersWithoutEntities) {
|
|
175
|
+
// Generate a unique slug (8 chars, lowercase alphanumeric)
|
|
176
|
+
const slug = generateSlug(user.slug_source);
|
|
177
|
+
const displayName = user.display_name || user.email?.split('@')[0] || 'Personal';
|
|
178
|
+
try {
|
|
179
|
+
// Create personal entity
|
|
180
|
+
const [entity] = await client.unsafe(`
|
|
181
|
+
INSERT INTO ${prefix}entities (entity_slug, entity_type, display_name, owner_user_id)
|
|
182
|
+
VALUES ('${slug}', 'personal', '${displayName.replace(/'/g, "''")}', '${user.id}')
|
|
183
|
+
RETURNING id
|
|
184
|
+
`);
|
|
185
|
+
// Add user as admin member
|
|
186
|
+
await client.unsafe(`
|
|
187
|
+
INSERT INTO ${prefix}entity_members (entity_id, user_id, role)
|
|
188
|
+
VALUES ('${entity.id}', '${user.id}', 'admin')
|
|
189
|
+
`);
|
|
190
|
+
migratedCount++;
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
// If slug collision, generate a new one and retry
|
|
194
|
+
if (error.code === '23505') {
|
|
195
|
+
const newSlug = generateSlug();
|
|
196
|
+
const [entity] = await client.unsafe(`
|
|
197
|
+
INSERT INTO ${prefix}entities (entity_slug, entity_type, display_name, owner_user_id)
|
|
198
|
+
VALUES ('${newSlug}', 'personal', '${displayName.replace(/'/g, "''")}', '${user.id}')
|
|
199
|
+
RETURNING id
|
|
200
|
+
`);
|
|
201
|
+
await client.unsafe(`
|
|
202
|
+
INSERT INTO ${prefix}entity_members (entity_id, user_id, role)
|
|
203
|
+
VALUES ('${entity.id}', '${user.id}', 'admin')
|
|
204
|
+
`);
|
|
205
|
+
migratedCount++;
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
console.log(`Migrated ${migratedCount} users to personal entities`);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Populate entity_id for existing projects.
|
|
216
|
+
*/
|
|
217
|
+
async function populateProjectEntityIds(client, prefix) {
|
|
218
|
+
console.log('Populating entity_id for existing projects...');
|
|
219
|
+
// Update projects to use owner's personal entity
|
|
220
|
+
const result = await client.unsafe(`
|
|
221
|
+
UPDATE ${prefix}projects p
|
|
222
|
+
SET entity_id = e.id
|
|
223
|
+
FROM ${prefix}entities e
|
|
224
|
+
WHERE p.user_id = e.owner_user_id
|
|
225
|
+
AND e.entity_type = 'personal'
|
|
226
|
+
AND p.entity_id IS NULL
|
|
227
|
+
`);
|
|
228
|
+
console.log(`Updated entity_id for ${result.count || 0} projects`);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Generate a slug from a source string or random.
|
|
232
|
+
*/
|
|
233
|
+
function generateSlug(source) {
|
|
234
|
+
if (source) {
|
|
235
|
+
// Normalize: lowercase, remove non-alphanumeric, take first 8 chars
|
|
236
|
+
return source
|
|
237
|
+
.toLowerCase()
|
|
238
|
+
.replace(/[^a-z0-9]/g, '')
|
|
239
|
+
.substring(0, 8)
|
|
240
|
+
.padEnd(8, '0');
|
|
241
|
+
}
|
|
242
|
+
// Generate random slug
|
|
243
|
+
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
|
244
|
+
let slug = '';
|
|
245
|
+
for (let i = 0; i < 8; i++) {
|
|
246
|
+
slug += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
247
|
+
}
|
|
248
|
+
return slug;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Rollback the entity migration.
|
|
252
|
+
*/
|
|
253
|
+
async function rollbackEntityMigration(config) {
|
|
254
|
+
const { client, schemaName, migrateProjects = true } = config;
|
|
255
|
+
const prefix = `${schemaName}.`;
|
|
256
|
+
console.log(`Rolling back entity migration for schema: ${schemaName}`);
|
|
257
|
+
// Remove entity_id from projects first
|
|
258
|
+
if (migrateProjects) {
|
|
259
|
+
await client.unsafe(`
|
|
260
|
+
ALTER TABLE ${prefix}projects DROP COLUMN IF EXISTS entity_id
|
|
261
|
+
`);
|
|
262
|
+
}
|
|
263
|
+
// Drop tables in reverse order
|
|
264
|
+
await client.unsafe(`DROP TABLE IF EXISTS ${prefix}entity_invitations`);
|
|
265
|
+
await client.unsafe(`DROP TABLE IF EXISTS ${prefix}entity_members`);
|
|
266
|
+
await client.unsafe(`DROP TABLE IF EXISTS ${prefix}entities`);
|
|
267
|
+
console.log('Entity migration rolled back');
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=001_add_entities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"001_add_entities.js","sourceRoot":"","sources":["../../src/migrations/001_add_entities.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Migration Exports
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.rollbackEntityMigration = exports.runEntityMigration = void 0;
|
|
7
|
+
var _001_add_entities_1 = require("./001_add_entities");
|
|
8
|
+
Object.defineProperty(exports, "runEntityMigration", { enumerable: true, get: function () { return _001_add_entities_1.runEntityMigration; } });
|
|
9
|
+
Object.defineProperty(exports, "rollbackEntityMigration", { enumerable: true, get: function () { return _001_add_entities_1.rollbackEntityMigration; } });
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Migration Exports
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.rollbackEntityMigration = exports.runEntityMigration = void 0;
|
|
7
|
+
var _001_add_entities_1 = require("./001_add_entities");
|
|
8
|
+
Object.defineProperty(exports, "runEntityMigration", { enumerable: true, get: function () { return _001_add_entities_1.runEntityMigration; } });
|
|
9
|
+
Object.defineProperty(exports, "rollbackEntityMigration", { enumerable: true, get: function () { return _001_add_entities_1.rollbackEntityMigration; } });
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,wDAI4B;AAH1B,uHAAA,kBAAkB,OAAA;AAClB,4HAAA,uBAAuB,OAAA"}
|