@stacksjs/database 0.74.37 → 0.74.38
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/dist/erd.d.ts +76 -0
- package/dist/erd.js +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/package.json +16 -16
package/dist/erd.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The column type a validation rule implies.
|
|
3
|
+
*
|
|
4
|
+
* The first rule names the base type - `schema.string().max(100)` is
|
|
5
|
+
* `[{ name: 'string' }, { name: 'max' }]` - so the head of the list is the
|
|
6
|
+
* answer and the rest are constraints a diagram does not show.
|
|
7
|
+
*/
|
|
8
|
+
export declare function columnType(attribute: unknown): string;
|
|
9
|
+
/** Every model name a `belongsTo` / `hasMany` / `hasOne` declaration names. */
|
|
10
|
+
export declare function relatedModelNames(raw: unknown): string[];
|
|
11
|
+
/**
|
|
12
|
+
* Reduce a model definition to the diagram's view of it.
|
|
13
|
+
*
|
|
14
|
+
* Trait columns are included because they are real columns: a diagram that
|
|
15
|
+
* omits `created_at` describes a table that does not exist. `belongsTo`
|
|
16
|
+
* foreign keys are added for the same reason - they are the columns the
|
|
17
|
+
* relationships are actually made of, and an ERD without them is a picture of
|
|
18
|
+
* arrows with nothing underneath.
|
|
19
|
+
*/
|
|
20
|
+
export declare function toDiagrammableModel(definition: {
|
|
21
|
+
name?: string
|
|
22
|
+
table?: string
|
|
23
|
+
primaryKey?: string
|
|
24
|
+
attributes?: Record<string, unknown>
|
|
25
|
+
belongsTo?: unknown
|
|
26
|
+
hasOne?: unknown
|
|
27
|
+
hasMany?: unknown
|
|
28
|
+
traits?: Record<string, unknown>
|
|
29
|
+
} | null | undefined, table: string): DiagrammableModel;
|
|
30
|
+
/**
|
|
31
|
+
* The relationship lines, deduplicated and ordered.
|
|
32
|
+
*
|
|
33
|
+
* One relationship is usually declared twice - `User hasMany Post` and
|
|
34
|
+
* `Post belongsTo User` are the same edge - and drawing both puts two arrows
|
|
35
|
+
* between the same pair of boxes. The parent-to-child direction wins, since
|
|
36
|
+
* that is how an ERD is read.
|
|
37
|
+
*
|
|
38
|
+
* A relation naming a model that is not in the set is dropped rather than
|
|
39
|
+
* drawn: an edge to a table that does not exist is worse than a missing edge,
|
|
40
|
+
* because it reads as schema rather than as a typo.
|
|
41
|
+
*/
|
|
42
|
+
export declare function relationEdges(models: DiagrammableModel[]): DiagramEdge[];
|
|
43
|
+
/**
|
|
44
|
+
* A Mermaid `erDiagram` for these models.
|
|
45
|
+
*
|
|
46
|
+
* Relationships first, then entities, which is the order Mermaid's own
|
|
47
|
+
* examples use and the order that reads well: the shape of the schema before
|
|
48
|
+
* the detail of each table.
|
|
49
|
+
*/
|
|
50
|
+
export declare function renderErd(models: DiagrammableModel[], options?: RenderErdOptions): string;
|
|
51
|
+
/** One model, reduced to what a diagram needs. */
|
|
52
|
+
export declare interface DiagrammableModel {
|
|
53
|
+
name: string
|
|
54
|
+
table: string
|
|
55
|
+
primaryKey: string
|
|
56
|
+
columns: DiagramColumn[]
|
|
57
|
+
belongsTo: string[]
|
|
58
|
+
hasOne: string[]
|
|
59
|
+
hasMany: string[]
|
|
60
|
+
}
|
|
61
|
+
export declare interface DiagramColumn {
|
|
62
|
+
name: string
|
|
63
|
+
type: string
|
|
64
|
+
key?: 'PK' | 'FK' | 'UK'
|
|
65
|
+
}
|
|
66
|
+
/** One line of the relationship section. */
|
|
67
|
+
export declare interface DiagramEdge {
|
|
68
|
+
from: string
|
|
69
|
+
to: string
|
|
70
|
+
cardinality: string
|
|
71
|
+
label: string
|
|
72
|
+
}
|
|
73
|
+
export declare interface RenderErdOptions {
|
|
74
|
+
columns?: boolean
|
|
75
|
+
only?: string[]
|
|
76
|
+
}
|
package/dist/erd.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{foreignKeyForModel}from"./vschema";const SAFE_TYPE=/^[a-z][a-z0-9_]*$/;export function columnType(attribute){const rules=attribute?.validation?.rule?.rules,head=Array.isArray(rules)?rules[0]?.name:void 0;if(typeof head==="string"&&SAFE_TYPE.test(head))return head;const fallback=attribute?.default;if(typeof fallback==="boolean")return"boolean";if(typeof fallback==="number")return"number";if(typeof fallback==="string")return"string";return"unknown"}export function relatedModelNames(raw){if(typeof raw==="string")return[raw];if(Array.isArray(raw))return raw.map((entry)=>typeof entry==="string"?entry:entry?.model).filter((entry)=>Boolean(entry));if(raw&&typeof raw==="object")return Object.keys(raw);return[]}export function toDiagrammableModel(definition,table){const primaryKey=definition?.primaryKey||"id",traits=definition?.traits??{},columns=[{name:primaryKey,type:"number",key:"PK"}];if(traits.useUuid)columns.push({name:"uuid",type:"string",key:"UK"});for(const[name,attribute]of Object.entries(definition?.attributes??{})){const unique=Boolean(attribute?.unique);columns.push({name,type:columnType(attribute),...unique?{key:"UK"}:{}})}const belongsTo=relatedModelNames(definition?.belongsTo);for(const parent of belongsTo){const column=foreignKeyForModel(parent);if(!columns.some((existing)=>existing.name===column))columns.push({name:column,type:"number",key:"FK"})}if(traits.useTimestamps){columns.push({name:"created_at",type:"datetime"});columns.push({name:"updated_at",type:"datetime"})}if(traits.useSoftDeletes)columns.push({name:"deleted_at",type:"datetime"});return{name:definition?.name??table,table,primaryKey,columns,belongsTo,hasOne:relatedModelNames(definition?.hasOne),hasMany:relatedModelNames(definition?.hasMany)}}export function relationEdges(models){const tableByModel=new Map(models.map((model)=>[model.name,model.table])),seen=new Set,edges=[],add=(from,to,cardinality,label)=>{const key=[from,to].sort().join("\x00");if(seen.has(key))return;seen.add(key);edges.push({from,to,cardinality,label})},sorted=[...models].sort((a,b)=>a.table.localeCompare(b.table));for(const model of sorted){for(const child of[...model.hasMany].sort()){const table=tableByModel.get(child);if(table)add(model.table,table,"||--o{","has many")}for(const child of[...model.hasOne].sort()){const table=tableByModel.get(child);if(table)add(model.table,table,"||--o|","has one")}}for(const model of sorted)for(const parent of[...model.belongsTo].sort()){const table=tableByModel.get(parent);if(table)add(table,model.table,"||--o{","has many")}return edges}export function renderErd(models,options={}){const sorted=[...options.only&&options.only.length>0?models.filter((model)=>options.only.includes(model.table)||options.only.includes(model.name)):models].sort((a,b)=>a.table.localeCompare(b.table)),lines=["erDiagram"];for(const edge of relationEdges(sorted))lines.push(` ${edge.from} ${edge.cardinality} ${edge.to} : "${edge.label}"`);if(options.columns===!1)return lines.join(`
|
|
2
|
+
`);for(const model of sorted){lines.push(` ${model.table} {`);for(const column of model.columns)lines.push(` ${column.type} ${column.name}${column.key?` ${column.key}`:""}`);lines.push(" }")}return lines.join(`
|
|
3
|
+
`)}
|
package/dist/index.d.ts
CHANGED
|
@@ -125,6 +125,7 @@ export * from './ddl-constraints';
|
|
|
125
125
|
// VSchema derivation — turns the model relationship graph into a Vitess
|
|
126
126
|
// keyspace topology, co-locating child tables with their parents so joins
|
|
127
127
|
// between them do not scatter across shards.
|
|
128
|
+
export * from './erd';
|
|
128
129
|
export * from './vschema';
|
|
129
130
|
// SQL dialect helpers & connection defaults
|
|
130
131
|
export * from './sql-helpers';
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{Database,createDatabase,createMysqlDatabase,createPostgresDatabase,createSqliteDatabase}from"./database";export{detectDriver,driverDefaults,getConfigFromEnv,getConnectionString,mergeWithDefaults,validateDriverConfig}from"./driver-config";export*from"./utils";export*from"./types";export*from"./migrations";export{setQueryTracker,logQuery}from"./query-logger";export{addColumnSafely,backfillInBatches,renameColumnSafely}from"./safe-migrations";export*from"./seeder";export*from"./drivers";export*from"./custom";export*from"./auth-tables";export*from"./utc-defaults";export*from"./uuid-columns";export*from"./managed-columns";export*from"./relation-columns";export{ensureNotificationForeignKeys,migrateNotificationTables}from"./notification-tables";export{migrateRbacTables}from"./rbac-tables";export*from"./trait-tables";export*from"./datetime-columns";export*from"./dialect";export*from"./replicas";export*from"./ddl-constraints";export*from"./vschema";export*from"./sql-helpers";export*from"./defaults";export*from"./migration-dialect";export*from"./migration-path";export*from"./migration-ledger";export*from"./model-sources";export*from"./package-migrations";export*from"./package-models";export*from"./shadowed-models";export*from"./ensure-database";export{auditForeignKeys,classifyDeclaredFKs,findFkOrphans,fkKey,getDeclaredFKs,getLiveFKs,getLiveTables}from"./fk-audit";export{auditSchemaDrift,formatSchemaDrift}from"./schema-drift";export{auditUniqueIndexes,getDeclaredUniques,getLiveUniqueIndexes}from"./unique-audit";export{__flushAfterCommitNow,__pendingAfterCommitCount,enqueueAfterCommit,isInTransaction,runInTransactionScope}from"./transaction-context";export{createQueryBuilder,setConfig}from"@stacksjs/query-builder";export{createDynamo,dynamo,EntityQueryBuilder,generateKeyPattern,parseKeyPattern,buildKey,marshall,unmarshall}from"./drivers/dynamodb";
|
|
1
|
+
export{Database,createDatabase,createMysqlDatabase,createPostgresDatabase,createSqliteDatabase}from"./database";export{detectDriver,driverDefaults,getConfigFromEnv,getConnectionString,mergeWithDefaults,validateDriverConfig}from"./driver-config";export*from"./utils";export*from"./types";export*from"./migrations";export{setQueryTracker,logQuery}from"./query-logger";export{addColumnSafely,backfillInBatches,renameColumnSafely}from"./safe-migrations";export*from"./seeder";export*from"./drivers";export*from"./custom";export*from"./auth-tables";export*from"./utc-defaults";export*from"./uuid-columns";export*from"./managed-columns";export*from"./relation-columns";export{ensureNotificationForeignKeys,migrateNotificationTables}from"./notification-tables";export{migrateRbacTables}from"./rbac-tables";export*from"./trait-tables";export*from"./datetime-columns";export*from"./dialect";export*from"./replicas";export*from"./ddl-constraints";export*from"./erd";export*from"./vschema";export*from"./sql-helpers";export*from"./defaults";export*from"./migration-dialect";export*from"./migration-path";export*from"./migration-ledger";export*from"./model-sources";export*from"./package-migrations";export*from"./package-models";export*from"./shadowed-models";export*from"./ensure-database";export{auditForeignKeys,classifyDeclaredFKs,findFkOrphans,fkKey,getDeclaredFKs,getLiveFKs,getLiveTables}from"./fk-audit";export{auditSchemaDrift,formatSchemaDrift}from"./schema-drift";export{auditUniqueIndexes,getDeclaredUniques,getLiveUniqueIndexes}from"./unique-audit";export{__flushAfterCommitNow,__pendingAfterCommitCount,enqueueAfterCommit,isInTransaction,runInTransactionScope}from"./transaction-context";export{createQueryBuilder,setConfig}from"@stacksjs/query-builder";export{createDynamo,dynamo,EntityQueryBuilder,generateKeyPattern,parseKeyPattern,buildKey,marshall,unmarshall}from"./drivers/dynamodb";
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/database",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.74.
|
|
5
|
+
"version": "0.74.38",
|
|
6
6
|
"description": "The Stacks database integration.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -60,26 +60,26 @@
|
|
|
60
60
|
"prepublishOnly": "bun run build"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@stacksjs/config": "0.74.
|
|
64
|
-
"@stacksjs/env": "0.74.
|
|
65
|
-
"@stacksjs/error-handling": "0.74.
|
|
66
|
-
"@stacksjs/faker": "^0.74.
|
|
67
|
-
"@stacksjs/features": "0.74.
|
|
68
|
-
"@stacksjs/logging": "0.74.
|
|
69
|
-
"@stacksjs/model-meta": "0.74.
|
|
70
|
-
"@stacksjs/path": "0.74.
|
|
71
|
-
"@stacksjs/query-builder": "^0.74.
|
|
72
|
-
"@stacksjs/security": "0.74.
|
|
73
|
-
"@stacksjs/storage": "0.74.
|
|
74
|
-
"@stacksjs/strings": "0.74.
|
|
63
|
+
"@stacksjs/config": "0.74.38",
|
|
64
|
+
"@stacksjs/env": "0.74.38",
|
|
65
|
+
"@stacksjs/error-handling": "0.74.38",
|
|
66
|
+
"@stacksjs/faker": "^0.74.38",
|
|
67
|
+
"@stacksjs/features": "0.74.38",
|
|
68
|
+
"@stacksjs/logging": "0.74.38",
|
|
69
|
+
"@stacksjs/model-meta": "0.74.38",
|
|
70
|
+
"@stacksjs/path": "0.74.38",
|
|
71
|
+
"@stacksjs/query-builder": "^0.74.38",
|
|
72
|
+
"@stacksjs/security": "0.74.38",
|
|
73
|
+
"@stacksjs/storage": "0.74.38",
|
|
74
|
+
"@stacksjs/strings": "0.74.38",
|
|
75
75
|
"@stacksjs/ts-validation": "^0.5.6",
|
|
76
76
|
"bun-query-builder": "^0.2.69",
|
|
77
77
|
"dynamodb-tooling": "^0.3.2"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
|
-
"@stacksjs/cli": "0.74.
|
|
81
|
-
"@stacksjs/router": "0.74.
|
|
82
|
-
"@stacksjs/utils": "0.74.
|
|
80
|
+
"@stacksjs/cli": "0.74.38",
|
|
81
|
+
"@stacksjs/router": "0.74.38",
|
|
82
|
+
"@stacksjs/utils": "0.74.38",
|
|
83
83
|
"better-dx": "^0.2.24"
|
|
84
84
|
}
|
|
85
85
|
}
|