@decohere/data-typeorm 0.0.1-dev.116
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/commonjs/src/bootstrap-policy.js +69 -0
- package/commonjs/src/bootstrap.js +142 -0
- package/commonjs/src/data-source.factory.js +42 -0
- package/commonjs/src/database-options.js +4 -0
- package/commonjs/src/dialect-map.js +26 -0
- package/commonjs/src/index.js +24 -0
- package/commonjs/src/inject-data-source.js +33 -0
- package/commonjs/src/scripts/user.js +259 -0
- package/commonjs/src/server-manager.js +294 -0
- package/commonjs/src/sql-pretty.transport.js +35 -0
- package/commonjs/src/type-orm.module.js +115 -0
- package/commonjs/src/type-orm.provider.js +36 -0
- package/commonjs/src/type-orm.repository.js +30 -0
- package/commonjs/src/typeorm-scribe.logger.js +70 -0
- package/commonjs/src/typeorm.extensions.js +60 -0
- package/commonjs/src/unit-of-work.js +49 -0
- package/es6/src/bootstrap-policy.js +55 -0
- package/es6/src/bootstrap.js +139 -0
- package/es6/src/data-source.factory.js +27 -0
- package/es6/src/database-options.js +1 -0
- package/es6/src/dialect-map.js +8 -0
- package/es6/src/index.js +7 -0
- package/es6/src/inject-data-source.js +20 -0
- package/es6/src/scripts/user.js +209 -0
- package/es6/src/server-manager.js +284 -0
- package/es6/src/sql-pretty.transport.js +20 -0
- package/es6/src/type-orm.module.js +105 -0
- package/es6/src/type-orm.provider.js +26 -0
- package/es6/src/type-orm.repository.js +20 -0
- package/es6/src/typeorm-scribe.logger.js +60 -0
- package/es6/src/typeorm.extensions.js +50 -0
- package/es6/src/unit-of-work.js +39 -0
- package/package.json +30 -0
- package/types/src/bootstrap-policy.d.ts +19 -0
- package/types/src/bootstrap.d.ts +16 -0
- package/types/src/data-source.factory.d.ts +17 -0
- package/types/src/database-options.d.ts +9 -0
- package/types/src/dialect-map.d.ts +8 -0
- package/types/src/index.d.ts +7 -0
- package/types/src/inject-data-source.d.ts +14 -0
- package/types/src/scripts/user.d.ts +56 -0
- package/types/src/server-manager.d.ts +39 -0
- package/types/src/sql-pretty.transport.d.ts +2 -0
- package/types/src/type-orm.module.d.ts +17 -0
- package/types/src/type-orm.provider.d.ts +14 -0
- package/types/src/type-orm.repository.d.ts +12 -0
- package/types/src/typeorm-scribe.logger.d.ts +9 -0
- package/types/src/typeorm.extensions.d.ts +11 -0
- package/types/src/unit-of-work.d.ts +20 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ConnectionInfo } from "@decohere/data";
|
|
2
|
+
import type { Constructable } from "@decohere/core/reflection";
|
|
3
|
+
import { DataSource, type Logger } from "typeorm";
|
|
4
|
+
export type ConnectionOptions = ConnectionInfo & {
|
|
5
|
+
entities: Constructable[];
|
|
6
|
+
applicationName?: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* A DataSource the container can close: TypeORM's has `destroy()` but no `Symbol.asyncDispose`,
|
|
10
|
+
* so disposing the app's container used to leave its connections open (#541).
|
|
11
|
+
*/
|
|
12
|
+
export declare class ManagedDataSource extends DataSource {
|
|
13
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export declare class DataSourceFactory {
|
|
16
|
+
static create(options: ConnectionOptions, logger: Logger): DataSource;
|
|
17
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Constructable } from "@decohere/core/reflection";
|
|
2
|
+
import type { DataSource } from "typeorm";
|
|
3
|
+
export type ModuleConfig = {
|
|
4
|
+
/** The unique identifier for the data source. Required when multiple data sources are configured. */
|
|
5
|
+
name?: string | symbol;
|
|
6
|
+
repositories?: Constructable[];
|
|
7
|
+
entities: Constructable[];
|
|
8
|
+
seed?: (dataSource: DataSource) => Promise<void>;
|
|
9
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from "./bootstrap.js";
|
|
2
|
+
export * from "./inject-data-source.js";
|
|
3
|
+
export * from "./sql-pretty.transport.js";
|
|
4
|
+
export * from "./type-orm.provider.js";
|
|
5
|
+
export * from "./type-orm.repository.js";
|
|
6
|
+
export * from "./typeorm.extensions.js";
|
|
7
|
+
export * from "./unit-of-work.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Default TypeORM DataSource when `withTypeOrm` is used without `name`. */
|
|
2
|
+
export declare const TypeOrmDataSourceToken: unique symbol;
|
|
3
|
+
/**
|
|
4
|
+
* Container key for a TypeORM DataSource. Distinct from the unit-of-work key
|
|
5
|
+
* (datasource name / {@link DEFAULT_DATA_SOURCE}) so request-scoped UoW and
|
|
6
|
+
* process-lifetime DataSource can coexist.
|
|
7
|
+
*/
|
|
8
|
+
export declare function typeOrmDataSourceToken(name?: string | symbol): symbol;
|
|
9
|
+
/**
|
|
10
|
+
* Inject the TypeORM DataSource for process-lifetime (singleton) work.
|
|
11
|
+
* Pass the same `name` as `withTypeOrm({ name })`. Request-scoped persistence
|
|
12
|
+
* should keep using `injectUnitOfWork`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function injectDataSource(name?: string | symbol): (target: object, _propertyKey: string | symbol | undefined, idx: number) => void;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export declare function assertSafeSqlIdent(value: string, label: string): string;
|
|
2
|
+
/** Double-quote a validated identifier for use in DDL. */
|
|
3
|
+
export declare function quoteIdent(value: string, label?: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* Single-quote a string literal for DDL that cannot take bind parameters
|
|
6
|
+
* (e.g. CREATE USER … PASSWORD — Postgres rejects PASSWORD $1).
|
|
7
|
+
*/
|
|
8
|
+
export declare function quoteLiteral(value: string): string;
|
|
9
|
+
export type SqlQuery = {
|
|
10
|
+
text: string;
|
|
11
|
+
values: unknown[];
|
|
12
|
+
};
|
|
13
|
+
/** Existence check — username bound as $1 (never concatenated). */
|
|
14
|
+
export declare function roleExistsQuery(username: string): SqlQuery;
|
|
15
|
+
/**
|
|
16
|
+
* CREATE USER with password as an escaped SQL literal.
|
|
17
|
+
* Username is validated + quoted as an identifier (cannot be parameterized in DDL).
|
|
18
|
+
* Password cannot use bind params in CREATE USER … PASSWORD (Postgres syntax error).
|
|
19
|
+
*
|
|
20
|
+
* `password` omitted (undefined) creates a role with no password, for a local dev server that
|
|
21
|
+
* trusts every connection. An empty string is still an error: that is a typo, not a choice.
|
|
22
|
+
* Callers decide when no password is allowed (see PostgresServerManager).
|
|
23
|
+
*/
|
|
24
|
+
export declare function createUserQuery(username: string, password?: string): SqlQuery;
|
|
25
|
+
/** CONNECT only — production runtime app role. */
|
|
26
|
+
export declare function grantConnectQuery(username: string, database: string): SqlQuery;
|
|
27
|
+
export declare function grantSchemaUsageQuery(username: string, schema?: string): SqlQuery;
|
|
28
|
+
/** Needed for TypeORM synchronize (dev only). */
|
|
29
|
+
export declare function grantSchemaCreateQuery(username: string, schema?: string): SqlQuery;
|
|
30
|
+
/** The schema, owned by `owner`. Unchanged when it already exists. */
|
|
31
|
+
export declare function createSchemaQuery(schema: string, owner: string): SqlQuery;
|
|
32
|
+
/**
|
|
33
|
+
* Whether a role already holds a privilege. Postgres checks that the grantor may grant even when
|
|
34
|
+
* the grant would change nothing, so bootstrap asks first and grants only what is missing.
|
|
35
|
+
*/
|
|
36
|
+
export declare function hasDatabasePrivilegeQuery(username: string, database: string, privilege: string): SqlQuery;
|
|
37
|
+
export declare function hasSchemaPrivilegeQuery(username: string, schema: string, privilege: string): SqlQuery;
|
|
38
|
+
/** Whether `member` already has the privileges of `role` (inherited, or as a superuser). */
|
|
39
|
+
export declare function hasRolePrivilegesQuery(member: string, role: string): SqlQuery;
|
|
40
|
+
export declare function databaseOwnerQuery(database: string): SqlQuery;
|
|
41
|
+
export declare function grantSchemaPrivilegesQuery(username: string, schema?: string): SqlQuery;
|
|
42
|
+
export declare function alterDatabaseOwnerQuery(database: string, username: string): SqlQuery;
|
|
43
|
+
/**
|
|
44
|
+
* Postgres requires the session user to be a member of the target role to
|
|
45
|
+
* `ALTER DATABASE … OWNER TO` / `ALTER DEFAULT PRIVILEGES FOR ROLE`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function grantRoleMembershipQuery(member: string, role: string): SqlQuery;
|
|
48
|
+
export declare function revokeRoleMembershipQuery(member: string, role: string): SqlQuery;
|
|
49
|
+
/**
|
|
50
|
+
* Future tables/sequences created by the migration role are usable by the app role (DML only).
|
|
51
|
+
*/
|
|
52
|
+
export declare function defaultPrivilegesForAppQueries(migrateUsername: string, appUsername: string, schema?: string): SqlQuery[];
|
|
53
|
+
export declare const userScripts: {
|
|
54
|
+
createOwnerUser: (username: string, password: string, database: string) => SqlQuery;
|
|
55
|
+
userExists: (username: string) => SqlQuery;
|
|
56
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type ConnectionInfo } from "@decohere/data";
|
|
2
|
+
export type ProvisionRolesOptions = {
|
|
3
|
+
database: string;
|
|
4
|
+
appUsername: string;
|
|
5
|
+
/** Omit only when the server is declared `auth: trust`. */
|
|
6
|
+
appPassword?: string;
|
|
7
|
+
migrateUsername?: string;
|
|
8
|
+
migratePassword?: string;
|
|
9
|
+
/** When true (TypeORM synchronize), grant CREATE on the schema to the app role (dev only). */
|
|
10
|
+
allowAppDdl: boolean;
|
|
11
|
+
/** The schema the app role works in, created when missing. Default `public`. */
|
|
12
|
+
schema?: string;
|
|
13
|
+
};
|
|
14
|
+
export declare class PostgresServerManager {
|
|
15
|
+
private readonly applicationName;
|
|
16
|
+
private readonly config;
|
|
17
|
+
private pool;
|
|
18
|
+
private client;
|
|
19
|
+
constructor(applicationName: string, config: ConnectionInfo);
|
|
20
|
+
/** `auth: trust`: the server lets every connection in, so roles have no password. */
|
|
21
|
+
private get trusted();
|
|
22
|
+
connect(): Promise<void>;
|
|
23
|
+
initializeDatabase(database: string): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Create the runtime app role (+ optional migrate role) and its schema, with least-privilege
|
|
26
|
+
* grants. Running it again changes nothing: each grant is made only where the role lacks it,
|
|
27
|
+
* since Postgres checks the grantor's rights even for a grant that would change nothing.
|
|
28
|
+
*
|
|
29
|
+
* The admin acts with the database owner's rights while it runs (it is made a member of the
|
|
30
|
+
* owner, and of the migrate role, only for as long as it needs to be). That is how it creates a
|
|
31
|
+
* schema and grants on it once the migrate role owns the database.
|
|
32
|
+
*/
|
|
33
|
+
provisionRoles(options: ProvisionRolesOptions): Promise<void>;
|
|
34
|
+
/** @deprecated Use provisionRoles. */
|
|
35
|
+
createApiUser(username: string, password: string, database: string, _role?: string): Promise<void>;
|
|
36
|
+
private ensureRole;
|
|
37
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
38
|
+
closeConnection(): Promise<void>;
|
|
39
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type DatabaseConfig } from "@decohere/data";
|
|
2
|
+
import type { ContainerBuilder } from "@decohere/crucible";
|
|
3
|
+
import type { ModuleConfig } from "./database-options.js";
|
|
4
|
+
export type TypeOrmModuleOptions = {
|
|
5
|
+
applicationName: string;
|
|
6
|
+
databaseConfig: DatabaseConfig;
|
|
7
|
+
moduleConfigurations: ModuleConfig[];
|
|
8
|
+
containerBuilder: ContainerBuilder;
|
|
9
|
+
};
|
|
10
|
+
export declare class TypeOrmModule {
|
|
11
|
+
/** Registers and opens a DataSource per module. Returns the names it registered them under. */
|
|
12
|
+
configure(options: TypeOrmModuleOptions): Promise<(string | symbol)[]>;
|
|
13
|
+
private resolveDataSources;
|
|
14
|
+
private init;
|
|
15
|
+
private configureTypeOrmDataSource;
|
|
16
|
+
private getLoggerFor;
|
|
17
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Entity, IDataProvider } from "@decohere/data";
|
|
2
|
+
import type { Constructable } from "@decohere/core/reflection";
|
|
3
|
+
import type { FindManyOptions, FindOneOptions } from "typeorm";
|
|
4
|
+
import type { TypeOrmUnitOfWork } from "./unit-of-work.js";
|
|
5
|
+
export declare class TypeOrmQueryProvider implements IDataProvider {
|
|
6
|
+
private unitOfWork;
|
|
7
|
+
constructor(unitOfWork: TypeOrmUnitOfWork);
|
|
8
|
+
firstOrDefault<T extends Entity>(entity: Constructable<T>, options: FindOneOptions<T>): Promise<T>;
|
|
9
|
+
all<T>(entity: Constructable, options?: FindManyOptions<T>): Promise<T[]>;
|
|
10
|
+
findById<T extends Entity>(entity: Constructable<T>, key: number | string): Promise<T>;
|
|
11
|
+
save<T>(entity: T): Promise<T>;
|
|
12
|
+
query<T extends Entity>(entity: Constructable<T>, filter: FindManyOptions<T>): Promise<T[]>;
|
|
13
|
+
delete<T>(entity: T): Promise<T>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Entity, Repository } from "@decohere/data";
|
|
2
|
+
import type { Constructable } from "@decohere/core/reflection";
|
|
3
|
+
import type { FindOneOptions } from "typeorm";
|
|
4
|
+
import { TypeOrmQueryProvider } from "./type-orm.provider.js";
|
|
5
|
+
import type { TypeOrmUnitOfWork } from "./unit-of-work.js";
|
|
6
|
+
export declare abstract class TypeOrmRepository<T extends Entity> extends Repository<T> {
|
|
7
|
+
protected provider: TypeOrmQueryProvider;
|
|
8
|
+
protected type: Constructable<T>;
|
|
9
|
+
constructor(unitOfWork: TypeOrmUnitOfWork, type: Constructable<T>);
|
|
10
|
+
firstOrDefault(options: FindOneOptions<T>): Promise<T | null>;
|
|
11
|
+
firstOrDefault<U extends Entity>(type: Constructable<U>, options: FindOneOptions<U>): Promise<U | null>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Dialect, Provider } from "@decohere/data";
|
|
2
|
+
import { AbstractLogger, type LogLevel, type LogMessage, type QueryRunner } from "typeorm";
|
|
3
|
+
export declare class TypeOrmScribeLogger extends AbstractLogger {
|
|
4
|
+
private readonly logger;
|
|
5
|
+
private readonly dialect;
|
|
6
|
+
constructor(name: string, dialect: Dialect | Provider, enable?: boolean);
|
|
7
|
+
protected writeLog(level: LogLevel, logMessage: LogMessage | LogMessage[], _queryRunner?: QueryRunner): void;
|
|
8
|
+
private getLogLevel;
|
|
9
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Builder } from "@decohere/http";
|
|
2
|
+
import type { Logger } from "typeorm";
|
|
3
|
+
import type { ModuleConfig } from "./database-options.js";
|
|
4
|
+
declare module "@decohere/http" {
|
|
5
|
+
interface Builder {
|
|
6
|
+
withTypeOrm(options?: ModuleConfig[] | ModuleConfig, logger?: Logger): Builder;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export declare class BuilderExtensions {
|
|
10
|
+
static withTypeOrm(builder: Builder, config: ModuleConfig[] | ModuleConfig): Builder<import("@decohere/http").App>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { IUnitOfWork } from "@decohere/data";
|
|
2
|
+
import type { Constructable } from "@decohere/core/reflection";
|
|
3
|
+
import type { DataSource, QueryRunner, Repository } from "typeorm";
|
|
4
|
+
export declare class TypeOrmUnitOfWork implements IUnitOfWork {
|
|
5
|
+
private readonly dataSource;
|
|
6
|
+
readonly queryRunner: QueryRunner;
|
|
7
|
+
constructor(dataSource: DataSource);
|
|
8
|
+
get entityManager(): import("typeorm").EntityManager;
|
|
9
|
+
getRepository<T>(entity: Constructable): Repository<T>;
|
|
10
|
+
beginTransaction(): Promise<void>;
|
|
11
|
+
commit(): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Hand the connection back to the pool, rolling back first if a transaction is still open
|
|
14
|
+
* (e.g. the request failed before commit). Otherwise the next user of that pooled
|
|
15
|
+
* connection would inherit the half-finished transaction (#502).
|
|
16
|
+
*/
|
|
17
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
18
|
+
/** Prefer `await using` / async disposal; this starts the same cleanup without waiting. */
|
|
19
|
+
[Symbol.dispose](): void;
|
|
20
|
+
}
|