-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
write first kysely query to get compiled data private
- Loading branch information
Showing
7 changed files
with
236 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
import { Kysely } from "kysely"; | ||
import { CompiledData } from "../../../ports/CompileData"; | ||
import { SoftwareExternalData } from "../../../ports/GetSoftwareExternalData"; | ||
import { ServiceProvider } from "../../../usecases/readWriteSillData"; | ||
import { Database } from "./kysely.database"; | ||
import { createPgDialect } from "./kysely.dialect"; | ||
import { emptyArrayIfNull, jsonAggOrEmptyArray, jsonBuildObject, jsonStripNulls } from "./kysely.utils"; | ||
|
||
export const createKyselyPgDbApi = (dbUrl: string) => { | ||
const db = new Kysely<Database>({ dialect: createPgDialect(dbUrl) }); | ||
|
||
return { | ||
// getSoftwareById: async (id: number): Promise<Db.SoftwareRow | undefined> => { | ||
// const result = await db.selectFrom("softwares").selectAll().where("id", "=", id).executeTakeFirst(); | ||
// if (!result) return; | ||
// | ||
// return { | ||
// ...result, | ||
// parentSoftwareWikidataId: result?.parentSoftwareWikidataId ?? undefined, | ||
// dereferencing: result?.dereferencing ?? undefined, | ||
// externalId: result?.externalId ?? undefined, | ||
// externalDataOrigin: result?.externalDataOrigin ?? "wikidata", | ||
// comptoirDuLibreId: result?.comptoirDuLibreId ?? undefined, | ||
// catalogNumeriqueGouvFrId: result?.catalogNumeriqueGouvFrId ?? undefined, | ||
// generalInfoMd: result?.generalInfoMd ?? undefined, | ||
// logoUrl: result?.logoUrl ?? undefined | ||
// }; | ||
// }, | ||
getCompiledDataPrivate: (): Promise<CompiledData<"private">> => { | ||
return db | ||
.selectFrom("softwares as s") | ||
.leftJoin("compiled_softwares as csft", "csft.softwareId", "s.id") | ||
.leftJoin("software_referents as referents", "s.id", "referents.softwareId") | ||
.leftJoin("software_users as users", "s.id", "users.softwareId") | ||
.leftJoin("agents as ar", "referents.agentId", "ar.id") | ||
.leftJoin("agents as au", "referents.agentId", "au.id") | ||
.leftJoin("instances", "s.id", "instances.mainSoftwareSillId") | ||
.select(({ ref, fn }) => | ||
// jsonStripNulls( | ||
jsonStripNulls( | ||
jsonBuildObject({ | ||
addedByAgentEmail: ref("s.addedByAgentEmail"), | ||
annuaireCnllServiceProviders: ref("annuaireCnllServiceProviders"), | ||
catalogNumeriqueGouvFrId: ref("s.catalogNumeriqueGouvFrId"), | ||
categories: ref("s.categories"), | ||
comptoirDuLibreSoftware: ref("csft.comptoirDuLibreSoftware"), | ||
dereferencing: ref("s.dereferencing"), | ||
description: ref("s.description"), | ||
doRespectRgaa: ref("s.doRespectRgaa"), | ||
externalDataOrigin: ref("s.externalDataOrigin"), | ||
externalId: ref("s.externalId"), | ||
generalInfoMd: ref("s.generalInfoMd"), | ||
id: ref("s.id"), | ||
isFromFrenchPublicService: ref("s.isFromFrenchPublicService"), | ||
isPresentInSupportContract: ref("s.isPresentInSupportContract"), | ||
isStillInObservation: ref("s.isStillInObservation"), | ||
keywords: ref("s.keywords"), | ||
latestVersion: ref("csft.latestVersion"), | ||
license: ref("s.license"), | ||
logoUrl: ref("s.logoUrl"), | ||
name: ref("s.name"), | ||
parentWikidataSoftware: ref("csft.parentWikidataSoftware"), | ||
referencedSinceTime: ref("s.referencedSinceTime"), | ||
serviceProviders: emptyArrayIfNull(fn, ref("csft.serviceProviders")).$castTo< | ||
ServiceProvider[] | ||
>(), | ||
similarExternalSoftwares: emptyArrayIfNull( | ||
fn, | ||
ref("csft.similarExternalSoftwares") | ||
).$castTo<CompiledData.SimilarSoftware[]>(), | ||
softwareExternalData: ref("csft.softwareExternalData"), | ||
softwareType: ref("s.softwareType"), | ||
testUrls: ref("s.testUrls"), | ||
updateTime: ref("s.updateTime"), | ||
versionMin: ref("s.versionMin"), | ||
workshopUrls: ref("s.workshopUrls"), | ||
referents: jsonAggOrEmptyArray( | ||
fn, | ||
jsonStripNulls( | ||
jsonBuildObject({ | ||
email: ref("ar.email").$castTo<string>(), | ||
organization: ref("ar.organization").$castTo<string>(), | ||
isExpert: ref("referents.isExpert").$castTo<boolean>(), | ||
serviceUrl: ref("referents.serviceUrl"), | ||
useCaseDescription: ref("referents.useCaseDescription").$castTo<string>() | ||
}) | ||
) | ||
), | ||
users: jsonAggOrEmptyArray( | ||
fn, | ||
jsonStripNulls( | ||
jsonBuildObject({ | ||
os: ref("users.os"), | ||
serviceUrl: ref("users.serviceUrl"), | ||
useCaseDescription: ref("users.useCaseDescription").$castTo<string>(), | ||
version: ref("users.version").$castTo<string>(), | ||
organization: ref("au.organization").$castTo<string>() | ||
}) | ||
) | ||
), | ||
instances: jsonAggOrEmptyArray( | ||
fn, | ||
jsonStripNulls( | ||
jsonBuildObject({ | ||
id: ref("instances.id").$castTo<number>(), | ||
organization: ref("instances.organization").$castTo<string>(), | ||
targetAudience: ref("instances.targetAudience").$castTo<string>(), | ||
publicUrl: ref("instances.publicUrl"), | ||
otherWikidataSoftwares: ref("instances.otherSoftwareWikidataIds").$castTo< | ||
SoftwareExternalData[] | ||
>(), // todo fetch the corresponding softwares, | ||
addedByAgentEmail: ref("instances.addedByAgentEmail").$castTo<string>() | ||
}) | ||
) | ||
) | ||
}) | ||
).as("compliedSoftware") | ||
) | ||
.execute() | ||
.then(results => | ||
results.map( | ||
({ compliedSoftware }): CompiledData.Software<"private"> => ({ | ||
...compliedSoftware, | ||
doRespectRgaa: compliedSoftware.doRespectRgaa ?? null | ||
}) | ||
) | ||
); | ||
} | ||
}; | ||
}; | ||
|
||
// ----------- common ----------- | ||
// annuaireCnllServiceProviders | ||
// catalogNumeriqueGouvFrId | ||
// categories | ||
// comptoirDuLibreSoftware | ||
// dereferencing | ||
// description | ||
// doRespectRgaa | ||
// externalDataOrigin | ||
// externalId | ||
// generalInfoMd | ||
// id | ||
// isFromFrenchPublicService | ||
// isPresentInSupportContract | ||
// isStillInObservation | ||
// keywords | ||
// latestVersion | ||
// license | ||
// logoUrl | ||
// name | ||
// parentWikidataSoftware | ||
// referencedSinceTime | ||
// serviceProviders | ||
// similarExternalSoftwares | ||
// softwareExternalData | ||
// softwareType | ||
// testUrls | ||
// updateTime | ||
// versionMin | ||
// workshopUrls | ||
// | ||
// ----------- private ----------- | ||
// addedByAgentEmail | ||
// users | ||
// referents | ||
// instances | ||
// | ||
// ----------- public ----------- | ||
// userAndReferentCountByOrganization | ||
// hasExpertReferent | ||
// instances |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { Expression, FunctionModule, RawBuilder, Simplify, sql } from "kysely"; | ||
|
||
export const jsonBuildObject = <O extends Record<string, Expression<unknown>>>( | ||
obj: O | ||
): RawBuilder< | ||
Simplify<{ | ||
[K in keyof O]: O[K] extends Expression<infer V> ? V : never; | ||
}> | ||
> => sql`json_build_object(${sql.join(Object.keys(obj).flatMap(k => [sql.lit(k), obj[k]]))})`; | ||
|
||
type NullableToUndefined<A> = A extends null ? Exclude<A, null> | undefined : A; | ||
type StripNullRecursive<T> = { | ||
[K in keyof T]: T[K] extends Record<any, unknown> ? StripNullRecursive<T[K]> : NullableToUndefined<T[K]>; | ||
}; | ||
export const jsonStripNulls = <T>(obj: RawBuilder<T>): RawBuilder<StripNullRecursive<T>> => | ||
sql`json_strip_nulls(${obj})`; | ||
|
||
export const jsonAggOrEmptyArray = <Db, E extends Expression<unknown>>(fn: FunctionModule<Db, keyof Db>, value: E) => | ||
emptyArrayIfNull(fn, fn.jsonAgg(value)); | ||
|
||
export const emptyArrayIfNull = <Db, E extends Expression<unknown>>(fn: FunctionModule<Db, keyof Db>, value: E) => | ||
fn.coalesce(value, sql`'[]'`); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters