Initial commit - Event Planner application

This commit is contained in:
mberlin
2026-03-18 14:55:56 -03:00
commit 86d779eb4d
7548 changed files with 1006324 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
import type { QueryResult } from '../../driver/database-connection.js';
import type { RootOperationNode } from '../../query-compiler/query-compiler.js';
import type { KyselyPlugin, PluginTransformQueryArgs, PluginTransformResultArgs } from '../kysely-plugin.js';
import type { UnknownRow } from '../../util/type-utils.js';
export declare class WithSchemaPlugin implements KyselyPlugin {
#private;
constructor(schema: string);
/**
* This is called for each query before it is executed. You can modify the query by
* transforming its {@link OperationNode} tree provided in {@link PluginTransformQueryArgs.node | args.node}
* and returning the transformed tree. You'd usually want to use an {@link OperationNodeTransformer}
* for this.
*
* If you need to pass some query-related data between this method and `transformResult` you
* can use a `WeakMap` with {@link PluginTransformQueryArgs.queryId | args.queryId} as the key:
*
* ```ts
* import type {
* KyselyPlugin,
* QueryResult,
* RootOperationNode,
* UnknownRow
* } from 'kysely'
*
* interface MyData {
* // ...
* }
* const data = new WeakMap<any, MyData>()
*
* const plugin = {
* transformQuery(args: PluginTransformQueryArgs): RootOperationNode {
* const something: MyData = {}
*
* // ...
*
* data.set(args.queryId, something)
*
* // ...
*
* return args.node
* },
*
* async transformResult(args: PluginTransformResultArgs): Promise<QueryResult<UnknownRow>> {
* // ...
*
* const something = data.get(args.queryId)
*
* // ...
*
* return args.result
* }
* } satisfies KyselyPlugin
* ```
*
* You should use a `WeakMap` instead of a `Map` or some other strong references because `transformQuery`
* is not always matched by a call to `transformResult` which would leave orphaned items in the map
* and cause a memory leak.
*/
transformQuery(args: PluginTransformQueryArgs): RootOperationNode;
/**
* This method is called for each query after it has been executed. The result
* of the query can be accessed through {@link PluginTransformResultArgs.result | args.result}.
* You can modify the result and return the modifier result.
*/
transformResult(args: PluginTransformResultArgs): Promise<QueryResult<UnknownRow>>;
}

View File

@@ -0,0 +1,14 @@
/// <reference types="./with-schema-plugin.d.ts" />
import { WithSchemaTransformer } from './with-schema-transformer.js';
export class WithSchemaPlugin {
#transformer;
constructor(schema) {
this.#transformer = new WithSchemaTransformer(schema);
}
transformQuery(args) {
return this.#transformer.transformNode(args.node, args.queryId);
}
async transformResult(args) {
return args.result;
}
}

View File

@@ -0,0 +1,18 @@
import type { AggregateFunctionNode } from '../../operation-node/aggregate-function-node.js';
import type { FunctionNode } from '../../operation-node/function-node.js';
import { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js';
import type { OperationNode } from '../../operation-node/operation-node.js';
import type { ReferencesNode } from '../../operation-node/references-node.js';
import { SchemableIdentifierNode } from '../../operation-node/schemable-identifier-node.js';
import type { SelectModifierNode } from '../../operation-node/select-modifier-node.js';
import type { QueryId } from '../../util/query-id.js';
export declare class WithSchemaTransformer extends OperationNodeTransformer {
#private;
constructor(schema: string);
protected transformNodeImpl<T extends OperationNode>(node: T, queryId: QueryId): T;
protected transformSchemableIdentifier(node: SchemableIdentifierNode, queryId: QueryId): SchemableIdentifierNode;
protected transformReferences(node: ReferencesNode, queryId: QueryId): ReferencesNode;
protected transformAggregateFunction(node: AggregateFunctionNode, queryId: QueryId): AggregateFunctionNode;
protected transformFunction(node: FunctionNode, queryId: QueryId): FunctionNode;
protected transformSelectModifier(node: SelectModifierNode, queryId: QueryId): SelectModifierNode;
}

View File

@@ -0,0 +1,197 @@
/// <reference types="./with-schema-transformer.d.ts" />
import { AliasNode } from '../../operation-node/alias-node.js';
import { IdentifierNode } from '../../operation-node/identifier-node.js';
import { JoinNode } from '../../operation-node/join-node.js';
import { ListNode } from '../../operation-node/list-node.js';
import { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js';
import { SchemableIdentifierNode } from '../../operation-node/schemable-identifier-node.js';
import { TableNode } from '../../operation-node/table-node.js';
import { UsingNode } from '../../operation-node/using-node.js';
import { freeze } from '../../util/object-utils.js';
// This object exist only so that we get a type error when a new RootOperationNode
// is added. If you get a type error here, make sure to add the new root node and
// handle it correctly in the transformer.
//
// DO NOT REFACTOR THIS EVEN IF IT SEEMS USELESS TO YOU!
const ROOT_OPERATION_NODES = freeze({
AlterTableNode: true,
CreateIndexNode: true,
CreateSchemaNode: true,
CreateTableNode: true,
CreateTypeNode: true,
CreateViewNode: true,
RefreshMaterializedViewNode: true,
DeleteQueryNode: true,
DropIndexNode: true,
DropSchemaNode: true,
DropTableNode: true,
DropTypeNode: true,
DropViewNode: true,
InsertQueryNode: true,
RawNode: true,
SelectQueryNode: true,
UpdateQueryNode: true,
MergeQueryNode: true,
});
const SCHEMALESS_FUNCTIONS = {
json_agg: true,
to_json: true,
};
export class WithSchemaTransformer extends OperationNodeTransformer {
#schema;
#schemableIds = new Set();
#ctes = new Set();
constructor(schema) {
super();
this.#schema = schema;
}
transformNodeImpl(node, queryId) {
if (!this.#isRootOperationNode(node)) {
return super.transformNodeImpl(node, queryId);
}
const ctes = this.#collectCTEs(node);
for (const cte of ctes) {
this.#ctes.add(cte);
}
const tables = this.#collectSchemableIds(node);
for (const table of tables) {
this.#schemableIds.add(table);
}
const transformed = super.transformNodeImpl(node, queryId);
for (const table of tables) {
this.#schemableIds.delete(table);
}
for (const cte of ctes) {
this.#ctes.delete(cte);
}
return transformed;
}
transformSchemableIdentifier(node, queryId) {
const transformed = super.transformSchemableIdentifier(node, queryId);
if (transformed.schema || !this.#schemableIds.has(node.identifier.name)) {
return transformed;
}
return {
...transformed,
schema: IdentifierNode.create(this.#schema),
};
}
transformReferences(node, queryId) {
const transformed = super.transformReferences(node, queryId);
if (transformed.table.table.schema) {
return transformed;
}
return {
...transformed,
table: TableNode.createWithSchema(this.#schema, transformed.table.table.identifier.name),
};
}
transformAggregateFunction(node, queryId) {
return {
...super.transformAggregateFunction({ ...node, aggregated: [] }, queryId),
aggregated: this.#transformTableArgsWithoutSchemas(node, queryId, 'aggregated'),
};
}
transformFunction(node, queryId) {
return {
...super.transformFunction({ ...node, arguments: [] }, queryId),
arguments: this.#transformTableArgsWithoutSchemas(node, queryId, 'arguments'),
};
}
transformSelectModifier(node, queryId) {
return {
...super.transformSelectModifier({ ...node, of: undefined }, queryId),
of: node.of?.map((item) => TableNode.is(item) && !item.table.schema
? {
...item,
table: this.transformIdentifier(item.table.identifier, queryId),
}
: this.transformNode(item, queryId)),
};
}
#transformTableArgsWithoutSchemas(node, queryId, argsKey) {
return SCHEMALESS_FUNCTIONS[node.func]
? node[argsKey].map((arg) => !TableNode.is(arg) || arg.table.schema
? this.transformNode(arg, queryId)
: {
...arg,
table: this.transformIdentifier(arg.table.identifier, queryId),
})
: this.transformNodeList(node[argsKey], queryId);
}
#isRootOperationNode(node) {
return node.kind in ROOT_OPERATION_NODES;
}
#collectSchemableIds(node) {
const schemableIds = new Set();
if ('name' in node && node.name && SchemableIdentifierNode.is(node.name)) {
this.#collectSchemableId(node.name, schemableIds);
}
if ('from' in node && node.from) {
for (const from of node.from.froms) {
this.#collectSchemableIdsFromTableExpr(from, schemableIds);
}
}
if ('into' in node && node.into) {
this.#collectSchemableIdsFromTableExpr(node.into, schemableIds);
}
if ('table' in node && node.table) {
this.#collectSchemableIdsFromTableExpr(node.table, schemableIds);
}
if ('joins' in node && node.joins) {
for (const join of node.joins) {
this.#collectSchemableIdsFromTableExpr(join.table, schemableIds);
}
}
if ('using' in node && node.using) {
if (JoinNode.is(node.using)) {
this.#collectSchemableIdsFromTableExpr(node.using.table, schemableIds);
}
else {
this.#collectSchemableIdsFromTableExpr(node.using, schemableIds);
}
}
return schemableIds;
}
#collectCTEs(node) {
const ctes = new Set();
if ('with' in node && node.with) {
this.#collectCTEIds(node.with, ctes);
}
return ctes;
}
#collectSchemableIdsFromTableExpr(node, schemableIds) {
if (TableNode.is(node)) {
return this.#collectSchemableId(node.table, schemableIds);
}
if (AliasNode.is(node) && TableNode.is(node.node)) {
return this.#collectSchemableId(node.node.table, schemableIds);
}
if (ListNode.is(node)) {
for (const table of node.items) {
this.#collectSchemableIdsFromTableExpr(table, schemableIds);
}
return;
}
if (UsingNode.is(node)) {
for (const table of node.tables) {
this.#collectSchemableIdsFromTableExpr(table, schemableIds);
}
return;
}
}
#collectSchemableId(node, schemableIds) {
const id = node.identifier.name;
if (!this.#schemableIds.has(id) && !this.#ctes.has(id)) {
schemableIds.add(id);
}
}
#collectCTEIds(node, ctes) {
for (const expr of node.expressions) {
const cteId = expr.name.table.table.identifier.name;
if (!this.#ctes.has(cteId)) {
ctes.add(cteId);
}
}
}
}