@fivepixels-js/lite-api 0.2.1
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/LICENSE +93 -0
- package/README.md +537 -0
- package/dist/app.d.ts +10 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +70 -0
- package/dist/app.js.map +1 -0
- package/dist/auth/identity.repository.d.ts +62 -0
- package/dist/auth/identity.repository.d.ts.map +1 -0
- package/dist/auth/identity.repository.js +202 -0
- package/dist/auth/identity.repository.js.map +1 -0
- package/dist/auth/identity.routes.d.ts +5 -0
- package/dist/auth/identity.routes.d.ts.map +1 -0
- package/dist/auth/identity.routes.js +56 -0
- package/dist/auth/identity.routes.js.map +1 -0
- package/dist/auth/identity.schemas.d.ts +2711 -0
- package/dist/auth/identity.schemas.d.ts.map +1 -0
- package/dist/auth/identity.schemas.js +117 -0
- package/dist/auth/identity.schemas.js.map +1 -0
- package/dist/auth/identity.service.d.ts +37 -0
- package/dist/auth/identity.service.d.ts.map +1 -0
- package/dist/auth/identity.service.js +131 -0
- package/dist/auth/identity.service.js.map +1 -0
- package/dist/auth/password.service.d.ts +15 -0
- package/dist/auth/password.service.d.ts.map +1 -0
- package/dist/auth/password.service.js +116 -0
- package/dist/auth/password.service.js.map +1 -0
- package/dist/auth/token.service.d.ts +38 -0
- package/dist/auth/token.service.d.ts.map +1 -0
- package/dist/auth/token.service.js +54 -0
- package/dist/auth/token.service.js.map +1 -0
- package/dist/cli/cli.d.ts +3 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +132 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/commands/backup.d.ts +4 -0
- package/dist/cli/commands/backup.d.ts.map +1 -0
- package/dist/cli/commands/backup.js +24 -0
- package/dist/cli/commands/backup.js.map +1 -0
- package/dist/cli/commands/init.d.ts +4 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +23 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/migrate.d.ts +4 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -0
- package/dist/cli/commands/migrate.js +20 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/commands/start.d.ts +4 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +13 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/status.d.ts +4 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +48 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/io.d.ts +6 -0
- package/dist/cli/io.d.ts.map +1 -0
- package/dist/cli/io.js +9 -0
- package/dist/cli/io.js.map +1 -0
- package/dist/community/contracts.d.ts +29 -0
- package/dist/community/contracts.d.ts.map +1 -0
- package/dist/community/contracts.js +41 -0
- package/dist/community/contracts.js.map +1 -0
- package/dist/community/error-handler.d.ts +3 -0
- package/dist/community/error-handler.d.ts.map +1 -0
- package/dist/community/error-handler.js +66 -0
- package/dist/community/error-handler.js.map +1 -0
- package/dist/community/errors.d.ts +10 -0
- package/dist/community/errors.d.ts.map +1 -0
- package/dist/community/errors.js +39 -0
- package/dist/community/errors.js.map +1 -0
- package/dist/community/etag.d.ts +5 -0
- package/dist/community/etag.d.ts.map +1 -0
- package/dist/community/etag.js +31 -0
- package/dist/community/etag.js.map +1 -0
- package/dist/community/input.d.ts +10 -0
- package/dist/community/input.d.ts.map +1 -0
- package/dist/community/input.js +48 -0
- package/dist/community/input.js.map +1 -0
- package/dist/community/mutation-route.d.ts +7 -0
- package/dist/community/mutation-route.d.ts.map +1 -0
- package/dist/community/mutation-route.js +47 -0
- package/dist/community/mutation-route.js.map +1 -0
- package/dist/community/schemas.d.ts +807 -0
- package/dist/community/schemas.d.ts.map +1 -0
- package/dist/community/schemas.js +100 -0
- package/dist/community/schemas.js.map +1 -0
- package/dist/community/system.schemas.d.ts +40 -0
- package/dist/community/system.schemas.d.ts.map +1 -0
- package/dist/community/system.schemas.js +30 -0
- package/dist/community/system.schemas.js.map +1 -0
- package/dist/config/config.d.ts +43 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +208 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/data-path.d.ts +2 -0
- package/dist/config/data-path.d.ts.map +1 -0
- package/dist/config/data-path.js +16 -0
- package/dist/config/data-path.js.map +1 -0
- package/dist/config/jwt-secret.d.ts +3 -0
- package/dist/config/jwt-secret.d.ts.map +1 -0
- package/dist/config/jwt-secret.js +67 -0
- package/dist/config/jwt-secret.js.map +1 -0
- package/dist/db/backup.d.ts +10 -0
- package/dist/db/backup.d.ts.map +1 -0
- package/dist/db/backup.js +51 -0
- package/dist/db/backup.js.map +1 -0
- package/dist/db/connection.d.ts +15 -0
- package/dist/db/connection.d.ts.map +1 -0
- package/dist/db/connection.js +82 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/guid-order.d.ts +2 -0
- package/dist/db/guid-order.d.ts.map +1 -0
- package/dist/db/guid-order.js +9 -0
- package/dist/db/guid-order.js.map +1 -0
- package/dist/db/migrate.d.ts +37 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +145 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/migrations/001_schema_migrations.sql +6 -0
- package/dist/db/migrations/002_identity.sql +95 -0
- package/dist/db/migrations/003_projects.sql +62 -0
- package/dist/db/migrations/004_feedback_core.sql +236 -0
- package/dist/db/migrations/005_project_member_management.sql +55 -0
- package/dist/db/migrations/006_align_credentials.sql +33 -0
- package/dist/db/migrations/007_align_storage_values.sql +78 -0
- package/dist/db/storage-migration.d.ts +9 -0
- package/dist/db/storage-migration.d.ts.map +1 -0
- package/dist/db/storage-migration.js +79 -0
- package/dist/db/storage-migration.js.map +1 -0
- package/dist/db/transaction.d.ts +9 -0
- package/dist/db/transaction.d.ts.map +1 -0
- package/dist/db/transaction.js +14 -0
- package/dist/db/transaction.js.map +1 -0
- package/dist/errors/error-handler.d.ts +3 -0
- package/dist/errors/error-handler.d.ts.map +1 -0
- package/dist/errors/error-handler.js +50 -0
- package/dist/errors/error-handler.js.map +1 -0
- package/dist/feedbacks/feedback-workflow.service.d.ts +59 -0
- package/dist/feedbacks/feedback-workflow.service.d.ts.map +1 -0
- package/dist/feedbacks/feedback-workflow.service.js +89 -0
- package/dist/feedbacks/feedback-workflow.service.js.map +1 -0
- package/dist/feedbacks/feedback.input.d.ts +4 -0
- package/dist/feedbacks/feedback.input.d.ts.map +1 -0
- package/dist/feedbacks/feedback.input.js +25 -0
- package/dist/feedbacks/feedback.input.js.map +1 -0
- package/dist/feedbacks/feedback.repository.d.ts +48 -0
- package/dist/feedbacks/feedback.repository.d.ts.map +1 -0
- package/dist/feedbacks/feedback.repository.js +238 -0
- package/dist/feedbacks/feedback.repository.js.map +1 -0
- package/dist/feedbacks/feedback.routes.d.ts +4 -0
- package/dist/feedbacks/feedback.routes.d.ts.map +1 -0
- package/dist/feedbacks/feedback.routes.js +78 -0
- package/dist/feedbacks/feedback.routes.js.map +1 -0
- package/dist/feedbacks/feedback.schemas.d.ts +642 -0
- package/dist/feedbacks/feedback.schemas.d.ts.map +1 -0
- package/dist/feedbacks/feedback.schemas.js +131 -0
- package/dist/feedbacks/feedback.schemas.js.map +1 -0
- package/dist/feedbacks/feedback.service.d.ts +23 -0
- package/dist/feedbacks/feedback.service.d.ts.map +1 -0
- package/dist/feedbacks/feedback.service.js +74 -0
- package/dist/feedbacks/feedback.service.js.map +1 -0
- package/dist/feedbacks/feedback.types.d.ts +64 -0
- package/dist/feedbacks/feedback.types.d.ts.map +1 -0
- package/dist/feedbacks/feedback.types.js +2 -0
- package/dist/feedbacks/feedback.types.js.map +1 -0
- package/dist/page-elements/page-element.input.d.ts +7 -0
- package/dist/page-elements/page-element.input.d.ts.map +1 -0
- package/dist/page-elements/page-element.input.js +59 -0
- package/dist/page-elements/page-element.input.js.map +1 -0
- package/dist/page-elements/page-element.repository.d.ts +21 -0
- package/dist/page-elements/page-element.repository.d.ts.map +1 -0
- package/dist/page-elements/page-element.repository.js +123 -0
- package/dist/page-elements/page-element.repository.js.map +1 -0
- package/dist/page-elements/page-element.schemas.d.ts +97 -0
- package/dist/page-elements/page-element.schemas.d.ts.map +1 -0
- package/dist/page-elements/page-element.schemas.js +40 -0
- package/dist/page-elements/page-element.schemas.js.map +1 -0
- package/dist/page-elements/page-element.types.d.ts +24 -0
- package/dist/page-elements/page-element.types.d.ts.map +1 -0
- package/dist/page-elements/page-element.types.js +2 -0
- package/dist/page-elements/page-element.types.js.map +1 -0
- package/dist/plugins/auth.plugin.d.ts +3 -0
- package/dist/plugins/auth.plugin.d.ts.map +1 -0
- package/dist/plugins/auth.plugin.js +28 -0
- package/dist/plugins/auth.plugin.js.map +1 -0
- package/dist/plugins/community-api.plugin.d.ts +5 -0
- package/dist/plugins/community-api.plugin.d.ts.map +1 -0
- package/dist/plugins/community-api.plugin.js +25 -0
- package/dist/plugins/community-api.plugin.js.map +1 -0
- package/dist/plugins/cors.plugin.d.ts +3 -0
- package/dist/plugins/cors.plugin.d.ts.map +1 -0
- package/dist/plugins/cors.plugin.js +19 -0
- package/dist/plugins/cors.plugin.js.map +1 -0
- package/dist/plugins/swagger.plugin.d.ts +3 -0
- package/dist/plugins/swagger.plugin.d.ts.map +1 -0
- package/dist/plugins/swagger.plugin.js +59 -0
- package/dist/plugins/swagger.plugin.js.map +1 -0
- package/dist/plugins/user-auth.plugin.d.ts +33 -0
- package/dist/plugins/user-auth.plugin.d.ts.map +1 -0
- package/dist/plugins/user-auth.plugin.js +62 -0
- package/dist/plugins/user-auth.plugin.js.map +1 -0
- package/dist/projects/members/project-member.repository.d.ts +49 -0
- package/dist/projects/members/project-member.repository.d.ts.map +1 -0
- package/dist/projects/members/project-member.repository.js +215 -0
- package/dist/projects/members/project-member.repository.js.map +1 -0
- package/dist/projects/members/project-member.routes.d.ts +4 -0
- package/dist/projects/members/project-member.routes.d.ts.map +1 -0
- package/dist/projects/members/project-member.routes.js +82 -0
- package/dist/projects/members/project-member.routes.js.map +1 -0
- package/dist/projects/members/project-member.schemas.d.ts +2735 -0
- package/dist/projects/members/project-member.schemas.d.ts.map +1 -0
- package/dist/projects/members/project-member.schemas.js +138 -0
- package/dist/projects/members/project-member.schemas.js.map +1 -0
- package/dist/projects/members/project-member.service.d.ts +29 -0
- package/dist/projects/members/project-member.service.d.ts.map +1 -0
- package/dist/projects/members/project-member.service.js +92 -0
- package/dist/projects/members/project-member.service.js.map +1 -0
- package/dist/projects/project-access.policy.d.ts +11 -0
- package/dist/projects/project-access.policy.d.ts.map +1 -0
- package/dist/projects/project-access.policy.js +30 -0
- package/dist/projects/project-access.policy.js.map +1 -0
- package/dist/projects/project-access.repository.d.ts +12 -0
- package/dist/projects/project-access.repository.d.ts.map +1 -0
- package/dist/projects/project-access.repository.js +45 -0
- package/dist/projects/project-access.repository.js.map +1 -0
- package/dist/projects/project-access.types.d.ts +9 -0
- package/dist/projects/project-access.types.d.ts.map +1 -0
- package/dist/projects/project-access.types.js +2 -0
- package/dist/projects/project-access.types.js.map +1 -0
- package/dist/projects/project-mutation.service.d.ts +15 -0
- package/dist/projects/project-mutation.service.d.ts.map +1 -0
- package/dist/projects/project-mutation.service.js +39 -0
- package/dist/projects/project-mutation.service.js.map +1 -0
- package/dist/projects/project.repository.d.ts +49 -0
- package/dist/projects/project.repository.d.ts.map +1 -0
- package/dist/projects/project.repository.js +155 -0
- package/dist/projects/project.repository.js.map +1 -0
- package/dist/projects/project.routes.d.ts +4 -0
- package/dist/projects/project.routes.d.ts.map +1 -0
- package/dist/projects/project.routes.js +45 -0
- package/dist/projects/project.routes.js.map +1 -0
- package/dist/projects/project.schemas.d.ts +2044 -0
- package/dist/projects/project.schemas.d.ts.map +1 -0
- package/dist/projects/project.schemas.js +90 -0
- package/dist/projects/project.schemas.js.map +1 -0
- package/dist/projects/project.service.d.ts +40 -0
- package/dist/projects/project.service.d.ts.map +1 -0
- package/dist/projects/project.service.js +128 -0
- package/dist/projects/project.service.js.map +1 -0
- package/dist/replies/reply-mutation.service.d.ts +19 -0
- package/dist/replies/reply-mutation.service.d.ts.map +1 -0
- package/dist/replies/reply-mutation.service.js +51 -0
- package/dist/replies/reply-mutation.service.js.map +1 -0
- package/dist/replies/reply.input.d.ts +4 -0
- package/dist/replies/reply.input.d.ts.map +1 -0
- package/dist/replies/reply.input.js +33 -0
- package/dist/replies/reply.input.js.map +1 -0
- package/dist/replies/reply.repository.d.ts +40 -0
- package/dist/replies/reply.repository.d.ts.map +1 -0
- package/dist/replies/reply.repository.js +173 -0
- package/dist/replies/reply.repository.js.map +1 -0
- package/dist/replies/reply.routes.d.ts +4 -0
- package/dist/replies/reply.routes.d.ts.map +1 -0
- package/dist/replies/reply.routes.js +64 -0
- package/dist/replies/reply.routes.js.map +1 -0
- package/dist/replies/reply.schemas.d.ts +251 -0
- package/dist/replies/reply.schemas.d.ts.map +1 -0
- package/dist/replies/reply.schemas.js +51 -0
- package/dist/replies/reply.schemas.js.map +1 -0
- package/dist/replies/reply.service.d.ts +19 -0
- package/dist/replies/reply.service.d.ts.map +1 -0
- package/dist/replies/reply.service.js +50 -0
- package/dist/replies/reply.service.js.map +1 -0
- package/dist/replies/reply.types.d.ts +31 -0
- package/dist/replies/reply.types.d.ts.map +1 -0
- package/dist/replies/reply.types.js +2 -0
- package/dist/replies/reply.types.js.map +1 -0
- package/dist/report-cases/report-case-workflow.service.d.ts +39 -0
- package/dist/report-cases/report-case-workflow.service.d.ts.map +1 -0
- package/dist/report-cases/report-case-workflow.service.js +103 -0
- package/dist/report-cases/report-case-workflow.service.js.map +1 -0
- package/dist/report-cases/report-case.input.d.ts +4 -0
- package/dist/report-cases/report-case.input.d.ts.map +1 -0
- package/dist/report-cases/report-case.input.js +29 -0
- package/dist/report-cases/report-case.input.js.map +1 -0
- package/dist/report-cases/report-case.repository.d.ts +45 -0
- package/dist/report-cases/report-case.repository.d.ts.map +1 -0
- package/dist/report-cases/report-case.repository.js +185 -0
- package/dist/report-cases/report-case.repository.js.map +1 -0
- package/dist/report-cases/report-case.routes.d.ts +4 -0
- package/dist/report-cases/report-case.routes.d.ts.map +1 -0
- package/dist/report-cases/report-case.routes.js +94 -0
- package/dist/report-cases/report-case.routes.js.map +1 -0
- package/dist/report-cases/report-case.schemas.d.ts +294 -0
- package/dist/report-cases/report-case.schemas.d.ts.map +1 -0
- package/dist/report-cases/report-case.schemas.js +77 -0
- package/dist/report-cases/report-case.schemas.js.map +1 -0
- package/dist/report-cases/report-case.service.d.ts +21 -0
- package/dist/report-cases/report-case.service.d.ts.map +1 -0
- package/dist/report-cases/report-case.service.js +60 -0
- package/dist/report-cases/report-case.service.js.map +1 -0
- package/dist/report-cases/report-case.types.d.ts +39 -0
- package/dist/report-cases/report-case.types.d.ts.map +1 -0
- package/dist/report-cases/report-case.types.js +2 -0
- package/dist/report-cases/report-case.types.js.map +1 -0
- package/dist/routes/health.route.d.ts +4 -0
- package/dist/routes/health.route.d.ts.map +1 -0
- package/dist/routes/health.route.js +39 -0
- package/dist/routes/health.route.js.map +1 -0
- package/dist/routes/version.route.d.ts +3 -0
- package/dist/routes/version.route.d.ts.map +1 -0
- package/dist/routes/version.route.js +22 -0
- package/dist/routes/version.route.js.map +1 -0
- package/dist/runtime/index.d.ts +8 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +11 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +66 -0
- package/dist/server.js.map +1 -0
- package/dist/storage/values.d.ts +3 -0
- package/dist/storage/values.d.ts.map +1 -0
- package/dist/storage/values.js +30 -0
- package/dist/storage/values.js.map +1 -0
- package/dist/users/current-user.routes.d.ts +3 -0
- package/dist/users/current-user.routes.d.ts.map +1 -0
- package/dist/users/current-user.routes.js +9 -0
- package/dist/users/current-user.routes.js.map +1 -0
- package/dist/users/current-user.schemas.d.ts +641 -0
- package/dist/users/current-user.schemas.d.ts.map +1 -0
- package/dist/users/current-user.schemas.js +21 -0
- package/dist/users/current-user.schemas.js.map +1 -0
- package/dist/users/user-search.repository.d.ts +19 -0
- package/dist/users/user-search.repository.d.ts.map +1 -0
- package/dist/users/user-search.repository.js +55 -0
- package/dist/users/user-search.repository.js.map +1 -0
- package/dist/users/user-search.routes.d.ts +4 -0
- package/dist/users/user-search.routes.d.ts.map +1 -0
- package/dist/users/user-search.routes.js +19 -0
- package/dist/users/user-search.routes.js.map +1 -0
- package/dist/users/user-search.schemas.d.ts +693 -0
- package/dist/users/user-search.schemas.d.ts.map +1 -0
- package/dist/users/user-search.schemas.js +41 -0
- package/dist/users/user-search.schemas.js.map +1 -0
- package/dist/users/user-search.service.d.ts +20 -0
- package/dist/users/user-search.service.d.ts.map +1 -0
- package/dist/users/user-search.service.js +41 -0
- package/dist/users/user-search.service.js.map +1 -0
- package/dist/users/user.schemas.d.ts +47 -0
- package/dist/users/user.schemas.d.ts.map +1 -0
- package/dist/users/user.schemas.js +13 -0
- package/dist/users/user.schemas.js.map +1 -0
- package/dist/users/user.types.d.ts +6 -0
- package/dist/users/user.types.d.ts.map +1 -0
- package/dist/users/user.types.js +2 -0
- package/dist/users/user.types.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/docs/guides/community-api-quickstart.md +171 -0
- package/docs/guides/feature-structure.md +138 -0
- package/docs/guides/independent-cli.md +73 -0
- package/docs/guides/non-attachment-api-contract.md +138 -0
- package/docs/plans/selfdev-schema-alignment.md +61 -0
- package/package.json +76 -0
- package/sql/fivepixels-lite-init.sql +518 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup.js","sourceRoot":"","sources":["../../src/db/backup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import BetterSqlite3 from 'better-sqlite3';
|
|
2
|
+
export type SqliteDatabase = BetterSqlite3.Database;
|
|
3
|
+
export declare class DatabaseConfigurationError extends Error {
|
|
4
|
+
constructor(message: string);
|
|
5
|
+
}
|
|
6
|
+
export interface OpenDatabaseOptions {
|
|
7
|
+
fileMustExist?: boolean;
|
|
8
|
+
readonly?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function openDatabase(dbPath: string, options?: OpenDatabaseOptions): SqliteDatabase;
|
|
11
|
+
export declare function applyAndVerifyPragmas(database: SqliteDatabase): void;
|
|
12
|
+
export declare function getSqliteVersion(database: SqliteDatabase): string;
|
|
13
|
+
export declare function isWalResetSafeVersion(version: string): boolean;
|
|
14
|
+
export declare function assertSafeSqliteVersion(version: string): void;
|
|
15
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/db/connection.ts"],"names":[],"mappings":"AAGA,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAE3C,MAAM,MAAM,cAAc,GAAG,aAAa,CAAC,QAAQ,CAAC;AAEpD,qBAAa,0BAA2B,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAInC;AAED,MAAM,WAAW,mBAAmB;IAClC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,mBAAwB,GAChC,cAAc,CAsBhB;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAsBpE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAGjE;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAa9D;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAM7D"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { chmodSync, existsSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import BetterSqlite3 from 'better-sqlite3';
|
|
4
|
+
export class DatabaseConfigurationError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'DatabaseConfigurationError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function openDatabase(dbPath, options = {}) {
|
|
11
|
+
const existed = existsSync(dbPath);
|
|
12
|
+
if (!options.readonly) {
|
|
13
|
+
mkdirSync(dirname(dbPath), { mode: 0o700, recursive: true });
|
|
14
|
+
}
|
|
15
|
+
const database = new BetterSqlite3(dbPath, {
|
|
16
|
+
fileMustExist: options.fileMustExist ?? false,
|
|
17
|
+
readonly: options.readonly ?? false,
|
|
18
|
+
});
|
|
19
|
+
try {
|
|
20
|
+
if (!options.readonly) {
|
|
21
|
+
applyAndVerifyPragmas(database);
|
|
22
|
+
if (!existed)
|
|
23
|
+
chmodSync(dbPath, 0o600);
|
|
24
|
+
}
|
|
25
|
+
assertSafeSqliteVersion(getSqliteVersion(database));
|
|
26
|
+
return database;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
database.close();
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function applyAndVerifyPragmas(database) {
|
|
34
|
+
const journalMode = String(database.pragma('journal_mode = WAL', { simple: true })).toLowerCase();
|
|
35
|
+
database.pragma('foreign_keys = ON');
|
|
36
|
+
database.pragma('busy_timeout = 5000');
|
|
37
|
+
database.pragma('synchronous = NORMAL');
|
|
38
|
+
const foreignKeys = Number(database.pragma('foreign_keys', { simple: true }));
|
|
39
|
+
const busyTimeout = Number(database.pragma('busy_timeout', { simple: true }));
|
|
40
|
+
const synchronous = Number(database.pragma('synchronous', { simple: true }));
|
|
41
|
+
if (journalMode !== 'wal') {
|
|
42
|
+
throw new DatabaseConfigurationError('SQLite WAL mode could not be enabled.');
|
|
43
|
+
}
|
|
44
|
+
if (foreignKeys !== 1) {
|
|
45
|
+
throw new DatabaseConfigurationError('SQLite foreign key enforcement could not be enabled.');
|
|
46
|
+
}
|
|
47
|
+
if (busyTimeout !== 5000) {
|
|
48
|
+
throw new DatabaseConfigurationError('SQLite busy timeout could not be configured.');
|
|
49
|
+
}
|
|
50
|
+
if (synchronous !== 1) {
|
|
51
|
+
throw new DatabaseConfigurationError('SQLite synchronous mode could not be set to NORMAL.');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export function getSqliteVersion(database) {
|
|
55
|
+
const row = database.prepare('SELECT sqlite_version() AS version').get();
|
|
56
|
+
return row.version;
|
|
57
|
+
}
|
|
58
|
+
export function isWalResetSafeVersion(version) {
|
|
59
|
+
const parts = version.split('.').map((value) => Number(value));
|
|
60
|
+
const major = parts[0] ?? 0;
|
|
61
|
+
const minor = parts[1] ?? 0;
|
|
62
|
+
const patch = parts[2] ?? 0;
|
|
63
|
+
if (major > 3)
|
|
64
|
+
return true;
|
|
65
|
+
if (major !== 3)
|
|
66
|
+
return false;
|
|
67
|
+
if (minor > 51)
|
|
68
|
+
return true;
|
|
69
|
+
if (minor === 51)
|
|
70
|
+
return patch >= 3;
|
|
71
|
+
if (minor === 50)
|
|
72
|
+
return patch >= 7;
|
|
73
|
+
if (minor === 44)
|
|
74
|
+
return patch >= 6;
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
export function assertSafeSqliteVersion(version) {
|
|
78
|
+
if (!isWalResetSafeVersion(version)) {
|
|
79
|
+
throw new DatabaseConfigurationError(`SQLite ${version} does not contain the required WAL-reset safety fix.`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/db/connection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guid-order.d.ts","sourceRoot":"","sources":["../../src/db/guid-order.ts"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAInD"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// SqlGuid compares Guid.ToByteArray() in order 10..15, 8,9, 6,7, 4,5, 0..3.
|
|
2
|
+
// SQL expressions use only repository-owned identifiers, never request values.
|
|
3
|
+
export function sqlGuidOrder(column) {
|
|
4
|
+
if (!/^(?:[a-z_]+\.)?[a-z_]+$/.test(column))
|
|
5
|
+
throw new Error('invalid-guid-column');
|
|
6
|
+
return '(' + [[25, 12], [20, 4], [17, 2], [15, 2], [12, 2], [10, 2], [7, 2], [5, 2], [3, 2], [1, 2]]
|
|
7
|
+
.map(([start, length]) => `substr(${column}, ${start}, ${length})`).join(' || ') + ')';
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=guid-order.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guid-order.js","sourceRoot":"","sources":["../../src/db/guid-order.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACpF,OAAO,GAAG,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SACjG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,UAAU,MAAM,KAAK,KAAK,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC;AAC3F,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { SqliteDatabase } from './connection.js';
|
|
2
|
+
export interface MigrationFile {
|
|
3
|
+
checksum: string;
|
|
4
|
+
name: string;
|
|
5
|
+
path: string;
|
|
6
|
+
sql: string;
|
|
7
|
+
version: number;
|
|
8
|
+
}
|
|
9
|
+
export interface AppliedMigration {
|
|
10
|
+
appliedAt: string;
|
|
11
|
+
checksum: string;
|
|
12
|
+
name: string;
|
|
13
|
+
version: number;
|
|
14
|
+
}
|
|
15
|
+
export interface MigrationStatus {
|
|
16
|
+
applied: AppliedMigration[];
|
|
17
|
+
currentVersion: number;
|
|
18
|
+
pending: MigrationFile[];
|
|
19
|
+
}
|
|
20
|
+
export interface MigrationResult {
|
|
21
|
+
appliedVersions: number[];
|
|
22
|
+
backupPath?: string;
|
|
23
|
+
currentVersion: number;
|
|
24
|
+
removedBackups: string[];
|
|
25
|
+
}
|
|
26
|
+
export interface MigrationOptions {
|
|
27
|
+
automaticBackupRetention?: number;
|
|
28
|
+
dbPath: string;
|
|
29
|
+
migrationsDirectory?: string;
|
|
30
|
+
}
|
|
31
|
+
export declare class MigrationError extends Error {
|
|
32
|
+
constructor(message: string, options?: ErrorOptions);
|
|
33
|
+
}
|
|
34
|
+
export declare function loadMigrations(directory?: string): MigrationFile[];
|
|
35
|
+
export declare function getMigrationStatus(database: SqliteDatabase, migrationsDirectory?: string): MigrationStatus;
|
|
36
|
+
export declare function migrateDatabase(database: SqliteDatabase, options: MigrationOptions): Promise<MigrationResult>;
|
|
37
|
+
//# sourceMappingURL=migrate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/db/migrate.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAMtD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,qBAAa,cAAe,SAAQ,KAAK;gBACpB,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAI3D;AAMD,wBAAgB,cAAc,CAAC,SAAS,SAA+B,GAAG,aAAa,EAAE,CAgCxF;AA4BD,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,cAAc,EACxB,mBAAmB,SAA+B,GACjD,eAAe,CAyBjB;AAOD,wBAAsB,eAAe,CACnC,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,CAyD1B"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
3
|
+
import { basename, dirname, join } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { createBackup, pruneAutomaticBackups } from './backup.js';
|
|
6
|
+
import { prepareStorageMigration } from './storage-migration.js';
|
|
7
|
+
const DEFAULT_MIGRATIONS_DIRECTORY = fileURLToPath(new URL('./migrations/', import.meta.url));
|
|
8
|
+
const MIGRATION_FILE_PATTERN = /^(\d+)_([a-z0-9_]+)\.sql$/;
|
|
9
|
+
export class MigrationError extends Error {
|
|
10
|
+
constructor(message, options) {
|
|
11
|
+
super(message, options);
|
|
12
|
+
this.name = 'MigrationError';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function checksum(sql) {
|
|
16
|
+
return createHash('sha256').update(sql).digest('hex');
|
|
17
|
+
}
|
|
18
|
+
export function loadMigrations(directory = DEFAULT_MIGRATIONS_DIRECTORY) {
|
|
19
|
+
const migrations = readdirSync(directory)
|
|
20
|
+
.filter((fileName) => fileName.endsWith('.sql'))
|
|
21
|
+
.map((fileName) => {
|
|
22
|
+
const match = MIGRATION_FILE_PATTERN.exec(fileName);
|
|
23
|
+
if (match === null) {
|
|
24
|
+
throw new MigrationError(`Invalid migration file name: ${fileName}`);
|
|
25
|
+
}
|
|
26
|
+
const version = Number(match[1]);
|
|
27
|
+
const name = match[2];
|
|
28
|
+
if (!Number.isSafeInteger(version) || version < 1 || name === undefined) {
|
|
29
|
+
throw new MigrationError(`Invalid migration file name: ${fileName}`);
|
|
30
|
+
}
|
|
31
|
+
const path = join(directory, fileName);
|
|
32
|
+
const sql = readFileSync(path, 'utf8');
|
|
33
|
+
return { checksum: checksum(sql), name, path, sql, version };
|
|
34
|
+
})
|
|
35
|
+
.sort((left, right) => left.version - right.version);
|
|
36
|
+
migrations.forEach((migration, index) => {
|
|
37
|
+
if (index > 0 && migrations[index - 1]?.version === migration.version) {
|
|
38
|
+
throw new MigrationError(`Duplicate migration version: ${migration.version}`);
|
|
39
|
+
}
|
|
40
|
+
const expectedVersion = index + 1;
|
|
41
|
+
if (migration.version !== expectedVersion) {
|
|
42
|
+
throw new MigrationError(`Migration sequence must be contiguous. Expected ${expectedVersion}, found ${migration.version}.`);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return migrations;
|
|
46
|
+
}
|
|
47
|
+
function migrationTableExists(database) {
|
|
48
|
+
const row = database.prepare("SELECT 1 AS found FROM sqlite_master WHERE type = 'table' AND name = ?").get('schema_migrations');
|
|
49
|
+
return row?.found === 1;
|
|
50
|
+
}
|
|
51
|
+
function databaseHasUserSchema(database) {
|
|
52
|
+
const row = database.prepare(`
|
|
53
|
+
SELECT 1 AS found
|
|
54
|
+
FROM sqlite_master
|
|
55
|
+
WHERE type = 'table'
|
|
56
|
+
AND name NOT LIKE 'sqlite_%'
|
|
57
|
+
LIMIT 1
|
|
58
|
+
`).get();
|
|
59
|
+
return row?.found === 1;
|
|
60
|
+
}
|
|
61
|
+
function readAppliedMigrations(database) {
|
|
62
|
+
if (!migrationTableExists(database))
|
|
63
|
+
return [];
|
|
64
|
+
const rows = database.prepare('SELECT version, name, checksum, applied_at AS appliedAt FROM schema_migrations ORDER BY version').all();
|
|
65
|
+
return rows;
|
|
66
|
+
}
|
|
67
|
+
export function getMigrationStatus(database, migrationsDirectory = DEFAULT_MIGRATIONS_DIRECTORY) {
|
|
68
|
+
const available = loadMigrations(migrationsDirectory);
|
|
69
|
+
const applied = readAppliedMigrations(database);
|
|
70
|
+
const availableByVersion = new Map(available.map((migration) => [migration.version, migration]));
|
|
71
|
+
for (const [index, appliedMigration] of applied.entries()) {
|
|
72
|
+
if (appliedMigration.version !== index + 1) {
|
|
73
|
+
throw new MigrationError('Applied migration history is not contiguous.');
|
|
74
|
+
}
|
|
75
|
+
const migration = availableByVersion.get(appliedMigration.version);
|
|
76
|
+
if (migration === undefined) {
|
|
77
|
+
throw new MigrationError(`Applied migration ${appliedMigration.version} is missing from the package.`);
|
|
78
|
+
}
|
|
79
|
+
if (migration.name !== appliedMigration.name || migration.checksum !== appliedMigration.checksum) {
|
|
80
|
+
throw new MigrationError(`Applied migration ${appliedMigration.version} has been modified.`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const appliedVersions = new Set(applied.map((migration) => migration.version));
|
|
84
|
+
const pending = available.filter((migration) => !appliedVersions.has(migration.version));
|
|
85
|
+
return {
|
|
86
|
+
applied,
|
|
87
|
+
currentVersion: applied.at(-1)?.version ?? 0,
|
|
88
|
+
pending,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function automaticBackupPath(dbPath, fromVersion, toVersion) {
|
|
92
|
+
const now = new Date().toISOString().replace(/[:.]/g, '-');
|
|
93
|
+
return join(dirname(dbPath), 'backups', `auto-v${fromVersion}-to-v${toVersion}-${now}.db`);
|
|
94
|
+
}
|
|
95
|
+
export async function migrateDatabase(database, options) {
|
|
96
|
+
const status = getMigrationStatus(database, options.migrationsDirectory);
|
|
97
|
+
if (status.pending.length === 0) {
|
|
98
|
+
return {
|
|
99
|
+
appliedVersions: [],
|
|
100
|
+
currentVersion: status.currentVersion,
|
|
101
|
+
removedBackups: [],
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
let backupPath;
|
|
105
|
+
if (existsSync(options.dbPath) && databaseHasUserSchema(database)) {
|
|
106
|
+
const targetVersion = status.pending.at(-1)?.version ?? status.currentVersion;
|
|
107
|
+
const backup = await createBackup(database, automaticBackupPath(options.dbPath, status.currentVersion, targetVersion));
|
|
108
|
+
backupPath = backup.path;
|
|
109
|
+
}
|
|
110
|
+
const appliedVersions = [];
|
|
111
|
+
const available = loadMigrations(options.migrationsDirectory);
|
|
112
|
+
for (const migration of status.pending) {
|
|
113
|
+
try {
|
|
114
|
+
database.transaction(() => {
|
|
115
|
+
const isStorageAlignment = (migration.version === 6 && migration.name === 'align_credentials')
|
|
116
|
+
|| (migration.version === 7 && migration.name === 'align_storage_values');
|
|
117
|
+
const verify = isStorageAlignment
|
|
118
|
+
? prepareStorageMigration(database, available, migration.version) : undefined;
|
|
119
|
+
database.exec(migration.sql);
|
|
120
|
+
verify?.();
|
|
121
|
+
database.prepare('INSERT INTO schema_migrations (version, name, checksum, applied_at) VALUES (?, ?, ?, ?)').run(migration.version, migration.name, migration.checksum, new Date().toISOString());
|
|
122
|
+
}).immediate();
|
|
123
|
+
appliedVersions.push(migration.version);
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
const safeReasons = new Set([
|
|
127
|
+
'unsupported-custom-schema', 'inconsistent-credential-keys', 'invalid-storage-timestamp',
|
|
128
|
+
'invalid-storage-pathname', 'foreign-keys-required', 'foreign-key-check-failed',
|
|
129
|
+
'integrity-check-failed', 'migration-row-count-mismatch',
|
|
130
|
+
]);
|
|
131
|
+
const reason = error instanceof Error && safeReasons.has(error.message) ? ` (${error.message})` : '';
|
|
132
|
+
throw new MigrationError(`Migration ${basename(migration.path)} failed${reason}.`, { cause: error });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const removedBackups = backupPath === undefined
|
|
136
|
+
? []
|
|
137
|
+
: pruneAutomaticBackups(options.dbPath, options.automaticBackupRetention ?? 3);
|
|
138
|
+
return {
|
|
139
|
+
...(backupPath === undefined ? {} : { backupPath }),
|
|
140
|
+
appliedVersions,
|
|
141
|
+
currentVersion: appliedVersions.at(-1) ?? status.currentVersion,
|
|
142
|
+
removedBackups,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/db/migrate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
CREATE TABLE users (
|
|
2
|
+
user_id TEXT PRIMARY KEY
|
|
3
|
+
, status_code INTEGER NOT NULL DEFAULT 1
|
|
4
|
+
, user_name TEXT NOT NULL
|
|
5
|
+
, profile_image_url TEXT
|
|
6
|
+
, created_at TEXT NOT NULL
|
|
7
|
+
, updated_at TEXT NOT NULL
|
|
8
|
+
, CHECK (
|
|
9
|
+
length(user_id) = 36
|
|
10
|
+
AND user_id = lower(user_id)
|
|
11
|
+
AND substr(user_id, 9, 1) = '-'
|
|
12
|
+
AND substr(user_id, 14, 1) = '-'
|
|
13
|
+
AND substr(user_id, 19, 1) = '-'
|
|
14
|
+
AND substr(user_id, 24, 1) = '-'
|
|
15
|
+
AND length(replace(user_id, '-', '')) = 32
|
|
16
|
+
AND replace(user_id, '-', '') NOT GLOB '*[^0-9a-f]*'
|
|
17
|
+
)
|
|
18
|
+
, CHECK (status_code IN (1, 2, 3))
|
|
19
|
+
, CHECK (user_name = trim(user_name) AND length(user_name) BETWEEN 1 AND 100)
|
|
20
|
+
, CHECK (
|
|
21
|
+
profile_image_url IS NULL
|
|
22
|
+
OR (profile_image_url = trim(profile_image_url) AND length(profile_image_url) BETWEEN 1 AND 2048)
|
|
23
|
+
)
|
|
24
|
+
) STRICT;
|
|
25
|
+
|
|
26
|
+
CREATE TABLE local_credentials (
|
|
27
|
+
user_id TEXT PRIMARY KEY
|
|
28
|
+
, login_id TEXT NOT NULL
|
|
29
|
+
, normalized_login_id TEXT NOT NULL
|
|
30
|
+
, email TEXT NOT NULL
|
|
31
|
+
, normalized_email TEXT NOT NULL
|
|
32
|
+
, password_hash TEXT NOT NULL
|
|
33
|
+
, failed_login_count INTEGER NOT NULL DEFAULT 0
|
|
34
|
+
, locked_until TEXT
|
|
35
|
+
, email_verified_at TEXT
|
|
36
|
+
, password_changed_at TEXT NOT NULL
|
|
37
|
+
, last_login_at TEXT
|
|
38
|
+
, lock_version INTEGER NOT NULL DEFAULT 0
|
|
39
|
+
, created_at TEXT NOT NULL
|
|
40
|
+
, updated_at TEXT NOT NULL
|
|
41
|
+
, CONSTRAINT fk_local_credentials_user FOREIGN KEY (user_id)
|
|
42
|
+
REFERENCES users (user_id) ON DELETE RESTRICT
|
|
43
|
+
, CHECK (login_id = trim(login_id) AND length(login_id) BETWEEN 4 AND 50)
|
|
44
|
+
, CHECK (substr(login_id, 1, 1) GLOB '[A-Za-z0-9]')
|
|
45
|
+
, CHECK (login_id NOT GLOB '*[^A-Za-z0-9._-]*')
|
|
46
|
+
, CHECK (normalized_login_id = lower(login_id))
|
|
47
|
+
, CHECK (email = trim(email) AND length(email) BETWEEN 3 AND 320)
|
|
48
|
+
, CHECK (normalized_email = trim(normalized_email) AND length(normalized_email) BETWEEN 3 AND 320)
|
|
49
|
+
, CHECK (password_hash = trim(password_hash) AND length(password_hash) BETWEEN 20 AND 512)
|
|
50
|
+
, CHECK (failed_login_count >= 0)
|
|
51
|
+
, CHECK (lock_version >= 0)
|
|
52
|
+
) STRICT;
|
|
53
|
+
|
|
54
|
+
CREATE UNIQUE INDEX uq_local_credentials_normalized_login_id
|
|
55
|
+
ON local_credentials (normalized_login_id);
|
|
56
|
+
|
|
57
|
+
CREATE UNIQUE INDEX uq_local_credentials_normalized_email
|
|
58
|
+
ON local_credentials (normalized_email);
|
|
59
|
+
|
|
60
|
+
CREATE TABLE auth_refresh_tokens (
|
|
61
|
+
refresh_token_id TEXT PRIMARY KEY
|
|
62
|
+
, user_id TEXT NOT NULL
|
|
63
|
+
, token_hash BLOB NOT NULL UNIQUE
|
|
64
|
+
, expires_at TEXT NOT NULL
|
|
65
|
+
, last_used_at TEXT
|
|
66
|
+
, revoked_at TEXT
|
|
67
|
+
, replaced_by_token_id TEXT
|
|
68
|
+
, lock_version INTEGER NOT NULL DEFAULT 0
|
|
69
|
+
, created_at TEXT NOT NULL
|
|
70
|
+
, CONSTRAINT fk_auth_refresh_tokens_user FOREIGN KEY (user_id)
|
|
71
|
+
REFERENCES users (user_id) ON DELETE RESTRICT
|
|
72
|
+
, CONSTRAINT fk_auth_refresh_tokens_replacement FOREIGN KEY (replaced_by_token_id)
|
|
73
|
+
REFERENCES auth_refresh_tokens (refresh_token_id) ON DELETE RESTRICT
|
|
74
|
+
, CHECK (
|
|
75
|
+
length(refresh_token_id) = 36
|
|
76
|
+
AND refresh_token_id = lower(refresh_token_id)
|
|
77
|
+
AND substr(refresh_token_id, 9, 1) = '-'
|
|
78
|
+
AND substr(refresh_token_id, 14, 1) = '-'
|
|
79
|
+
AND substr(refresh_token_id, 19, 1) = '-'
|
|
80
|
+
AND substr(refresh_token_id, 24, 1) = '-'
|
|
81
|
+
AND length(replace(refresh_token_id, '-', '')) = 32
|
|
82
|
+
AND replace(refresh_token_id, '-', '') NOT GLOB '*[^0-9a-f]*'
|
|
83
|
+
)
|
|
84
|
+
, CHECK (length(token_hash) = 32)
|
|
85
|
+
, CHECK (expires_at > created_at)
|
|
86
|
+
, CHECK (
|
|
87
|
+
replaced_by_token_id IS NULL
|
|
88
|
+
OR (replaced_by_token_id <> refresh_token_id AND revoked_at IS NOT NULL)
|
|
89
|
+
)
|
|
90
|
+
, CHECK (lock_version >= 0)
|
|
91
|
+
) STRICT;
|
|
92
|
+
|
|
93
|
+
CREATE INDEX ix_auth_refresh_tokens_user_active
|
|
94
|
+
ON auth_refresh_tokens (user_id, expires_at, refresh_token_id)
|
|
95
|
+
WHERE revoked_at IS NULL;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
CREATE TABLE projects (
|
|
2
|
+
project_id TEXT PRIMARY KEY
|
|
3
|
+
CHECK (
|
|
4
|
+
length(project_id) = 36
|
|
5
|
+
AND substr(project_id, 9, 1) = '-'
|
|
6
|
+
AND substr(project_id, 14, 1) = '-'
|
|
7
|
+
AND substr(project_id, 19, 1) = '-'
|
|
8
|
+
AND substr(project_id, 24, 1) = '-'
|
|
9
|
+
AND project_id = lower(project_id)
|
|
10
|
+
AND length(replace(project_id, '-', '')) = 32
|
|
11
|
+
AND replace(project_id, '-', '') NOT GLOB '*[^0-9a-f]*'
|
|
12
|
+
),
|
|
13
|
+
creator_id TEXT NOT NULL,
|
|
14
|
+
status_code INTEGER NOT NULL DEFAULT 1
|
|
15
|
+
CHECK (status_code IN (1, 2)),
|
|
16
|
+
project_name TEXT NOT NULL
|
|
17
|
+
CHECK (
|
|
18
|
+
length(project_name) BETWEEN 1 AND 100
|
|
19
|
+
AND project_name = trim(project_name)
|
|
20
|
+
),
|
|
21
|
+
lock_version INTEGER NOT NULL DEFAULT 0
|
|
22
|
+
CHECK (lock_version >= 0),
|
|
23
|
+
created_at TEXT NOT NULL,
|
|
24
|
+
updated_at TEXT NOT NULL,
|
|
25
|
+
CONSTRAINT fk_projects_creator
|
|
26
|
+
FOREIGN KEY (creator_id) REFERENCES users(user_id)
|
|
27
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT
|
|
28
|
+
) STRICT;
|
|
29
|
+
|
|
30
|
+
CREATE INDEX ix_projects_status_created_at
|
|
31
|
+
ON projects (status_code, created_at DESC, project_id DESC);
|
|
32
|
+
|
|
33
|
+
CREATE INDEX ix_projects_creator_created_at
|
|
34
|
+
ON projects (creator_id, created_at DESC, project_id DESC);
|
|
35
|
+
|
|
36
|
+
CREATE TABLE project_members (
|
|
37
|
+
project_id TEXT NOT NULL,
|
|
38
|
+
user_id TEXT NOT NULL,
|
|
39
|
+
role_code INTEGER NOT NULL
|
|
40
|
+
CHECK (role_code IN (1, 2)),
|
|
41
|
+
added_by TEXT NOT NULL,
|
|
42
|
+
lock_version INTEGER NOT NULL DEFAULT 0
|
|
43
|
+
CHECK (lock_version >= 0),
|
|
44
|
+
joined_at TEXT NOT NULL,
|
|
45
|
+
updated_at TEXT NOT NULL,
|
|
46
|
+
CONSTRAINT pk_project_members PRIMARY KEY (project_id, user_id),
|
|
47
|
+
CONSTRAINT fk_project_members_project
|
|
48
|
+
FOREIGN KEY (project_id) REFERENCES projects(project_id)
|
|
49
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
50
|
+
CONSTRAINT fk_project_members_user
|
|
51
|
+
FOREIGN KEY (user_id) REFERENCES users(user_id)
|
|
52
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
53
|
+
CONSTRAINT fk_project_members_added_by
|
|
54
|
+
FOREIGN KEY (added_by) REFERENCES users(user_id)
|
|
55
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT
|
|
56
|
+
) STRICT;
|
|
57
|
+
|
|
58
|
+
CREATE INDEX ix_project_members_user_joined_at
|
|
59
|
+
ON project_members (user_id, joined_at DESC, project_id DESC);
|
|
60
|
+
|
|
61
|
+
CREATE INDEX ix_project_members_project_role
|
|
62
|
+
ON project_members (project_id, role_code, user_id);
|