streamby-core 0.43.0 → 0.43.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.43.1
4
+
5
+ ### Fixed
6
+
7
+ - **Inviting a member to a SQL project, or asking to join one, answered 500**: both write who
8
+ invited the member (`invitedBy`), a column `streamby.project_members` didn't have. It's added
9
+ at startup to existing tables, and is in the table made new.
10
+ - **Accepting or rejecting an invitation to a SQL project failed too**: they changed the project's
11
+ `members` as a MongoDB project has them, a field a SQL project doesn't have (its members are
12
+ rows of `project_members`); they change the member's row now. A SQL project's members are read
13
+ with `invitedBy`, so whoever invited them is told the answer.
14
+
3
15
  ## 0.43.0
4
16
 
5
17
  ### Added
@@ -123,6 +123,7 @@ const createTables = async (pool) => {
123
123
  archived BOOLEAN NOT NULL DEFAULT FALSE,
124
124
  "archivedBy" VARCHAR(255),
125
125
  "archivedAt" TIMESTAMP WITH TIME ZONE,
126
+ "invitedBy" VARCHAR(255),
126
127
  "createdAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
127
128
  "updatedAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
128
129
  UNIQUE ("projectId", "userId")
@@ -130,6 +131,8 @@ const createTables = async (pool) => {
130
131
  `);
131
132
  await pool.query(`
132
133
  ALTER TABLE streamby.project_members ADD COLUMN IF NOT EXISTS status VARCHAR(50) NOT NULL DEFAULT 'active';
134
+ -- Who invited a pending member (or the member, asking to join): told when it's answered.
135
+ ALTER TABLE streamby.project_members ADD COLUMN IF NOT EXISTS "invitedBy" VARCHAR(255);
133
136
  `);
134
137
  console.log('✅ "project_members" table ensured to exist.');
135
138
  // Migrate projectId FK column from UUID to TEXT if table predates this schema version
@@ -157,9 +157,19 @@ function memberRouter(config) {
157
157
  if (member.status !== 'pending') {
158
158
  return res.status(400).json({ message: 'Invitation is no longer pending' });
159
159
  }
160
- const updatedMembers = project.members.map((m) => m.userId?.toString() === targetUserId ? { ...m, status: 'active' } : m);
161
- await Project.update({ _id: projectId }, { members: updatedMembers });
162
- await (0, notification_1.createNotification)(member.invitedBy, 'member_accepted', `${member.username} aceptó la invitación al proyecto "${project.name}"`, { projectId, userId: targetUserId });
160
+ if (project.dbType === 'sql') {
161
+ // A SQL project's members are rows of project_members, not a field of the project.
162
+ const connection = getSqlConnection();
163
+ if (!connection) {
164
+ return res.status(503).json({ message: 'SQL connection not available' });
165
+ }
166
+ await sql_1.sqlAdapter.update(connection, 'project_members', { projectId, userId: targetUserId }, { status: 'active' }, 'streamby');
167
+ }
168
+ else {
169
+ const updatedMembers = project.members.map((m) => m.userId?.toString() === targetUserId ? { ...m, status: 'active' } : m);
170
+ await Project.update({ _id: projectId }, { members: updatedMembers });
171
+ }
172
+ await (0, notification_1.createNotification)(member.invitedBy, 'member_accepted', `${member.username ?? auth.username} aceptó la invitación al proyecto "${project.name}"`, { projectId, userId: targetUserId });
163
173
  res.status(200).json({ message: 'Invitation accepted' });
164
174
  }
165
175
  catch (err) {
@@ -184,8 +194,17 @@ function memberRouter(config) {
184
194
  if (member.status !== 'pending') {
185
195
  return res.status(400).json({ message: 'Invitation is no longer pending' });
186
196
  }
187
- await Project.update({ _id: projectId }, { $pull: { members: { userId: targetUserId } } });
188
- await (0, notification_1.createNotification)(member.invitedBy, 'member_rejected', `${member.username} rechazó la invitación al proyecto "${project.name}"`, { projectId, userId: targetUserId });
197
+ if (project.dbType === 'sql') {
198
+ const connection = getSqlConnection();
199
+ if (!connection) {
200
+ return res.status(503).json({ message: 'SQL connection not available' });
201
+ }
202
+ await sql_1.sqlAdapter.delete(connection, 'project_members', { projectId, userId: targetUserId }, 'streamby');
203
+ }
204
+ else {
205
+ await Project.update({ _id: projectId }, { $pull: { members: { userId: targetUserId } } });
206
+ }
207
+ await (0, notification_1.createNotification)(member.invitedBy, 'member_rejected', `${member.username ?? auth.username} rechazó la invitación al proyecto "${project.name}"`, { projectId, userId: targetUserId });
189
208
  res.status(200).json({ message: 'Invitation rejected' });
190
209
  }
191
210
  catch (err) {
@@ -48,27 +48,6 @@ class Model {
48
48
  const result = await connection.query(`SELECT * FROM "${schema}"."projects" WHERE "dbConnections" @> $1::jsonb OR "storageConnections" @> $1::jsonb OR "integrationConnections" @> $1::jsonb`, [has]);
49
49
  sqlResults = result.rows;
50
50
  }
51
- else if (this.tableName === 'projects' && processedFilter.members && processedFilter.members.$elemMatch) {
52
- // Handle members filter for SQL projects
53
- const userId = processedFilter.members.$elemMatch.userId;
54
- const schema = this.schema || 'streamby'; // Default to 'streamby' if schema not provided
55
- const query = `
56
- SELECT p.*, pm."userId" as memberUserId, pm.role as memberRole, pm.status as memberStatus, pm.archived as memberArchived
57
- FROM "${schema}"."projects" p
58
- JOIN "${schema}"."project_members" pm ON p.id = pm."projectId"
59
- WHERE pm."userId" = $1
60
- `;
61
- const result = await connection.query(query, [userId]);
62
- sqlResults = result.rows.map(row => ({
63
- ...row,
64
- members: [{
65
- userId: row.memberUserId,
66
- role: row.memberRole,
67
- status: row.memberStatus,
68
- archived: row.memberArchived,
69
- }]
70
- }));
71
- }
72
51
  else {
73
52
  // General SQL find
74
53
  sqlResults = await sql_1.sqlAdapter.find(connection, this.tableName, processedFilter, this.schema);
@@ -76,13 +55,14 @@ class Model {
76
55
  for (const item of sqlResults) {
77
56
  const transformedItem = this.transformResult(item);
78
57
  if (this.tableName === 'projects' && !transformedItem.members) {
79
- // For projects, if members not already populated by join, fetch from project_members table
58
+ // A SQL project's members are rows of project_members, read with it
80
59
  const projectMembers = await sql_1.sqlAdapter.find(connection, 'project_members', { projectId: transformedItem.id }, this.schema);
81
60
  transformedItem.members = projectMembers.map((member) => ({
82
61
  userId: member.userId,
83
62
  role: member.role,
84
63
  status: member.status,
85
64
  archived: member.archived,
65
+ ...(member.invitedBy ? { invitedBy: member.invitedBy } : {}),
86
66
  }));
87
67
  }
88
68
  allResults.push(transformedItem);
@@ -138,6 +118,7 @@ class Model {
138
118
  role: member.role,
139
119
  status: member.status,
140
120
  archived: member.archived,
121
+ ...(member.invitedBy ? { invitedBy: member.invitedBy } : {}),
141
122
  }));
142
123
  }
143
124
  // Track which connection found this record so update() routes correctly
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "streamby-core",
3
- "version": "0.43.0",
3
+ "version": "0.43.1",
4
4
  "description": "StreamBy middleware framework for media storage management",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",