Skip to content
2 changes: 1 addition & 1 deletion .github/workflows/staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Staging
on:
push:
branches:
- release/2.35.0
- release/2.36.0

jobs:
build:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "project-sparrow-api",
"version": "2.35.0",
"version": "2.36.0",
"description": "Backend APIs for Project Sparrow.",
"author": "techdome",
"license": "",
Expand Down
3 changes: 3 additions & 0 deletions src/modules/common/instructions/generate-pre-script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,9 @@ export const generatePreScriptInstructions = `
- if user prompt is not valid then return
- If the user's prompt is not clearly about API pre-script generation or contains irrelevant content
(general coding questions, or non-API testing topics) then return
- If the user's prompt contains only special characters OR contains sequences of continuous special characters
(for example: "&&&&", "****", "*&#*&#&*#&", "@@@@") OR ends with such sequences
(for example: "generate a testcase *&&&&") then return
- Example format: '
sp.test("userId is a number", function () {
sp.expect(jsonBody.userId).to.be.a("number");
Expand Down
3 changes: 3 additions & 0 deletions src/modules/common/instructions/generate-test-cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ export const generateTestCasesInstructions = `
- if user prompt is not valid then return
- If the user's prompt is not clearly about API post-script generation or contains irrelevant content
(general coding questions, or non-API testing topics) then return
- If the user's prompt contains only special characters OR contains sequences of continuous special characters
(for example: "&&&&", "****", "*&#*&#&*#&", "@@@@") OR ends with such sequences
(for example: "generate a testcase *&&&&") then return
- Example format: '
sp.test("userId is a number", function () {
sp.expect(jsonBody.userId).to.be.a("number");
Expand Down
120 changes: 80 additions & 40 deletions src/modules/identity/repositories/team.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ export class TeamRepository {
name: team.name,
hubUrl: team.hubUrl,
logo: team.logo,
workspaces:[],
workspaces: [],
isRestricted: true,
users:team.users,
owner:team.owner
users: team.users,
owner: team.owner,
} as unknown as WithId<Team>;
}
// Case 2: Plan active → filter workspaces
Expand Down Expand Up @@ -141,10 +141,10 @@ export class TeamRepository {
name: team.name,
hubUrl: team.hubUrl,
logo: team.logo,
workspaces:[],
workspaces: [],
isRestricted: true,
users:team.users,
owner:team.owner
users: team.users,
owner: team.owner,
} as Partial<WithId<Team>>;
}
// Filter out restricted workspaces
Expand Down Expand Up @@ -239,7 +239,6 @@ export class TeamRepository {
return responseData.value;
}


async updateTeamWorkspaceCountById(
id: ObjectId,
planData: PlanDto,
Expand All @@ -249,9 +248,22 @@ export class TeamRepository {
.collection<Team>(Collections.TEAM)
.findOneAndUpdate(
{
_id: id, $expr: {
$lt: [{ $size: "$workspaces" }, planData.limits.workspacesPerHub.value],
} ,
_id: id,
$expr: {
$lt: [
{
$size: {
$filter: {
input: "$workspaces",
as: "workspace",
// keep only those where isRestricted is not true
cond: { $ne: ["$$workspace.isRestricted", true] },
},
},
},
planData.limits.workspacesPerHub.value,
],
},
},
{
$push: { workspaces: ws },
Expand Down Expand Up @@ -313,11 +325,16 @@ export class TeamRepository {
.updateOne({ _id }, { $set: { isHubTrialExhausted, plan } });
}

async hubCollaboratorLimitCheck(teamId: string, users: Invite[]): Promise<WithId<Team>> {
async hubCollaboratorLimitCheck(
teamId: string,
users: Invite[],
): Promise<WithId<Team>> {
const teamObjectId = new ObjectId(teamId);
const incomingEmails = users.map(u => u.email);
const incomingEmails = users.map((u) => u.email);

const result = await this.db.collection<Team>(Collections.TEAM).findOneAndUpdate(
const result = await this.db
.collection<Team>(Collections.TEAM)
.findOneAndUpdate(
{
_id: teamObjectId,
// Ensure limit not exceeded
Expand All @@ -333,18 +350,30 @@ export class TeamRepository {
incomingEmails,
{
$concatArrays: [
{ $map: { input: { $ifNull: ["$users", []] }, as: "u", in: "$$u.email" } },
{ $map: { input: { $ifNull: ["$invites", []] }, as: "i", in: "$$i.email" } }
]
}
]
}
}
]
{
$map: {
input: { $ifNull: ["$users", []] },
as: "u",
in: "$$u.email",
},
},
{
$map: {
input: { $ifNull: ["$invites", []] },
as: "i",
in: "$$i.email",
},
},
],
},
],
},
},
],
},
{ $add: ["$plan.limits.usersPerHub.value", 1] }
]
}
{ $add: ["$plan.limits.usersPerHub.value", 1] },
],
},
},
[
{
Expand All @@ -362,24 +391,35 @@ export class TeamRepository {
"$$newInvite.email",
{
$concatArrays: [
{ $map: { input: { $ifNull: ["$users", []] }, as: "u", in: "$$u.email" } },
{ $map: { input: { $ifNull: ["$invites", []] }, as: "i", in: "$$i.email" } }
]
}
]
}
}
}
}
]
}
}
}
] ,
{ returnDocument: "after" }
{
$map: {
input: { $ifNull: ["$users", []] },
as: "u",
in: "$$u.email",
},
},
{
$map: {
input: { $ifNull: ["$invites", []] },
as: "i",
in: "$$i.email",
},
},
],
},
],
},
},
},
},
],
},
},
},
],
{ returnDocument: "after" },
);

return result.value;
}

}
Loading