Skip to content

Commit

Permalink
Fix populate
Browse files Browse the repository at this point in the history
  • Loading branch information
Francis Duvivier committed Nov 27, 2024
1 parent c6d3a79 commit 4dcd6d7
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 101 deletions.
62 changes: 42 additions & 20 deletions src/db/BadgeHubDataPostgresAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { getPool } from "@db/connectionPool";
import { DBProject as DBProject } from "@db/models/app/DBProject";
import sql, { join, raw } from "sql-template-tag";
import { DBInsertUser } from "@db/models/app/DBUser";
import { Entry, getEntriesWithDefinedValues } from "@util/objectEntries";
import { getEntriesWithDefinedValues } from "@util/objectEntries";
import { DBBadge } from "@db/models/DBBadge";
import {
getBaseSelectProjectQuery,
Expand All @@ -33,19 +33,19 @@ import {
DBInsertAppMetadataJSON,
} from "@db/models/app/DBAppMetadataJSON";
import { DBCategory } from "@db/models/app/DBCategory";
import { getInsertKeysAndValuesSql } from "@db/sqlHelpers/objectToSQL";
import {
assertValidColumKey,
getInsertKeysAndValuesSql,
} from "@db/sqlHelpers/objectToSQL";

function getUpdateAssigmentsSql(
definedEntries: Entry<Partial<Omit<ProjectCore, "slug">>>[]
) {
function getUpdateAssigmentsSql(changes: Object) {
const changeEntries = getEntriesWithDefinedValues(changes);
if (!changeEntries.length) {
return;
}
return join(
definedEntries.map(
([
key,
value,
]) => sql`${raw(key)} // raw is ok here because these keys are checked against our typescript definitions by tsoa
=
${value}`
changeEntries.map(
([key, value]) => sql`${raw(assertValidColumKey(key))} = ${value}`
)
);
}
Expand Down Expand Up @@ -91,13 +91,13 @@ export class BadgeHubDataPostgresAdapter implements BadgeHubDataPort {
projectSlug: ProjectSlug,
changes: Partial<Omit<ProjectCore, "slug">>
): Promise<void> {
const definedEntries = getEntriesWithDefinedValues(changes);
const setters = getUpdateAssigmentsSql(definedEntries);
if (definedEntries.length !== 0) {
await this.pool.query(sql`update projects
set ${setters}
where slug = ${projectSlug}`);
const setters = getUpdateAssigmentsSql(changes);
if (!setters) {
return;
}
await this.pool.query(sql`update projects
set ${setters}
where slug = ${projectSlug}`);
}

async deleteProject(projectSlug: ProjectSlug): Promise<void> {
Expand All @@ -106,12 +106,34 @@ export class BadgeHubDataPostgresAdapter implements BadgeHubDataPort {
where slug = ${projectSlug}`);
}

writeFile(
async writeFile(
projectSlug: ProjectSlug,
filePath: string,
contents: string | Uint8Array
): Promise<void> {
throw new Error("Method not implemented.");
if (filePath === "metadata.json") {
const appMetadata: DBAppMetadataJSON = JSON.parse(
typeof contents === "string"
? contents
: new TextDecoder().decode(contents)
);
const setters = getUpdateAssigmentsSql(appMetadata);
if (!setters) {
return;
}

const appMetadataUpdateQuery = sql`update app_metadata_jsons
set ${setters}
where id = (select app_metadata_json_id
from versions v
where v.id =
(select projects.version_id from projects where slug = ${projectSlug}))`;
await this.pool.query(appMetadataUpdateQuery);
} else {
throw new Error(
"Method not implemented for files other than the metadata.json file yet."
);
}
}

updateDraftMetadata(
Expand Down
12 changes: 8 additions & 4 deletions src/db/models/DBProjectStatusOnBadge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ import { BadgeSlugRelation } from "./DBBadge";
import { ProjectStatusName } from "@domain/readModels/app/Project";
import { ProjectSlugRelation } from "@db/models/app/DBProject";

export interface DBInsertProjectStatusOnBadge
extends BadgeSlugRelation,
ProjectSlugRelation {
status?: ProjectStatusName; // Status for this project for this particular badge
}

// table name: project_statuses_on_badges
export interface DBProjectStatusOnBadge
extends DBDatedData,
BadgeSlugRelation,
ProjectSlugRelation {
extends DBInsertProjectStatusOnBadge,
DBDatedData {
id: number;
status: ProjectStatusName; // Status for this project for this particular badge
}
1 change: 1 addition & 0 deletions src/db/models/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ In the db models, we try to stick to 2 principles
- DRY, no data duplication, unless it's accidental duplication
- No arrays. Arrays make querying and switching to another DB more difficult. So instead of arrays, we try to work with relation tables.
- There is currently an exception here for the MetaDataFileContents, there the mappings are records and arrays and records with arrays, this is because the data comes from the json file and we could also just store it as stringified JSON.
- Prefer slugs as primary keys where possible, because they are more human-readable which makes the api calls and db queries easier to read.
13 changes: 12 additions & 1 deletion src/db/sqlHelpers/objectToSQL.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import { getEntriesWithDefinedValues } from "@util/objectEntries";
import { join, raw } from "sql-template-tag";

const COLUMN_KEY_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]*$/;

export function assertValidColumKey(key: string): string {
if (!COLUMN_KEY_REGEX.test(key)) {
throw new Error("Invalid column key: " + key);
}
return key;
}

export function getInsertKeysAndValuesSql(user: Object) {
const definedEntries = getEntriesWithDefinedValues(user);
const keys = join(definedEntries.map(([key]) => raw(key))); // raw is ok here because these keys are checked against our typescript definitions by tsoa
const keys = join(
definedEntries.map(([key]) => raw(assertValidColumKey(key)))
);
const values = join(definedEntries.map(([, value]) => value));
return { keys, values };
}
4 changes: 2 additions & 2 deletions src/generated/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
/* eslint-disable */
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
import type { TsoaRoute } from "@tsoa/runtime";
import { fetchMiddlewares, ExpressTemplateService } from "@tsoa/runtime";
import { ExpressTemplateService, fetchMiddlewares } from "@tsoa/runtime";
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
import { PublicRestController } from "./../controllers/public-rest.js";
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
import { PrivateRestController } from "./../controllers/private-rest.js";
import type {
Request as ExRequest,
Response as ExResponse,
RequestHandler,
Response as ExResponse,
Router,
} from "express";

Expand Down
Loading

0 comments on commit 4dcd6d7

Please sign in to comment.