@better-media/core 0.3.0 → 0.5.0

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/README.md CHANGED
@@ -36,4 +36,4 @@ export const myPlugin: PipelinePlugin = {
36
36
 
37
37
  ## Documentation
38
38
 
39
- For full documentation, visit [better-media-platform.vercel.app](https://better-media-platform.vercel.app/docs/core).
39
+ For full documentation, visit [better-media-platform.vercel.app](https://better-media.dev/docs/core).
package/dist/index.js CHANGED
@@ -74,22 +74,26 @@ var schema = {
74
74
  id: { type: "string", primaryKey: true, required: true },
75
75
  ownerId: { type: "string" },
76
76
  filename: { type: "string" },
77
+ extension: { type: "string" },
77
78
  mimeType: { type: "string" },
78
79
  size: { type: "number" },
79
80
  storageProvider: { type: "string" },
80
81
  storageKey: { type: "string" },
81
- checksum: { type: "string" },
82
+ checksumSha256: { type: "string" },
83
+ checksumMd5: { type: "string" },
82
84
  width: { type: "number" },
83
85
  height: { type: "number" },
84
86
  duration: { type: "number" },
85
- context: { type: "json" },
87
+ metadata: { type: "json" },
86
88
  status: { type: "string" },
89
+ // 'pending' | 'processing' | 'ready' | 'failed' | 'quarantined'
87
90
  visibility: { type: "string" },
91
+ // 'public' | 'private' | 'unlisted'
88
92
  createdAt: { type: "date" },
89
93
  updatedAt: { type: "date" },
90
94
  deletedAt: { type: "date" }
91
95
  },
92
- indexes: [{ fields: ["checksum", "storageKey"] }]
96
+ indexes: [{ fields: ["checksumSha256", "storageKey"] }]
93
97
  },
94
98
  // Different versions of the media (thumbnails, previews, etc.)
95
99
  media_versions: {
@@ -103,22 +107,25 @@ var schema = {
103
107
  onDelete: "cascade"
104
108
  }
105
109
  },
110
+ storageProvider: { type: "string" },
106
111
  storageKey: { type: "string" },
107
- checksum: { type: "string" },
112
+ checksumSha256: { type: "string" },
113
+ mimeType: { type: "string" },
114
+ size: { type: "number" },
115
+ width: { type: "number" },
116
+ height: { type: "number" },
108
117
  isOriginal: { type: "boolean" },
109
118
  type: { type: "string" },
110
- // e.g., 'thumbnail', 'preview', 'compressed'
119
+ // 'thumbnail' | 'preview' | 'compressed' | 'original'
111
120
  versionNumber: { type: "number" },
112
- createdAt: { type: "date" }
121
+ createdAt: { type: "date" },
122
+ deletedAt: { type: "date" }
113
123
  },
114
- indexes: [
115
- {
116
- fields: ["mediaId", "versionNumber"],
117
- unique: true
118
- }
119
- ]
124
+ indexes: [{ fields: ["mediaId"] }, { fields: ["mediaId", "versionNumber"], unique: true }]
120
125
  },
121
- // Background job state for media processing
126
+ // Business record for media processing jobs — not a BullMQ state mirror.
127
+ // Tracks idempotency, final outcome, and links jobs to media.
128
+ // Runtime state (queue position, locks, backoff) lives in BullMQ/Redis.
122
129
  media_jobs: {
123
130
  fields: {
124
131
  id: { type: "string", primaryKey: true, required: true },
@@ -131,18 +138,22 @@ var schema = {
131
138
  }
132
139
  },
133
140
  type: { type: "string" },
134
- // e.g., 'virus-scan', 'thumbnail'
141
+ // 'virus-scan' | 'thumbnail' | 'compress' | 'validate'
135
142
  status: { type: "string" },
136
- // e.g., 'pending', 'running', 'completed', 'failed'
143
+ // 'pending' | 'running' | 'completed' | 'failed'
137
144
  attempts: { type: "number" },
138
145
  maxAttempts: { type: "number" },
139
146
  idempotencyKey: { type: "string", unique: true },
140
147
  scheduledAt: { type: "date" },
141
148
  startedAt: { type: "date" },
142
149
  completedAt: { type: "date" },
143
- error: { type: "string" },
144
- createdAt: { type: "date" }
145
- }
150
+ error: { type: "json" },
151
+ // { message, code, stack, retryable }
152
+ result: { type: "json" },
153
+ createdAt: { type: "date" },
154
+ updatedAt: { type: "date" }
155
+ },
156
+ indexes: [{ fields: ["mediaId"] }]
146
157
  },
147
158
  media_validation_results: {
148
159
  fields: {
@@ -154,8 +165,10 @@ var schema = {
154
165
  valid: { type: "boolean" },
155
166
  pluginId: { type: "string" },
156
167
  errors: { type: "json" },
168
+ warnings: { type: "json" },
157
169
  createdAt: { type: "date" }
158
- }
170
+ },
171
+ indexes: [{ fields: ["mediaId"] }]
159
172
  },
160
173
  media_virus_scan_results: {
161
174
  fields: {
@@ -165,13 +178,13 @@ var schema = {
165
178
  references: { model: "media", field: "id", onDelete: "cascade" }
166
179
  },
167
180
  status: { type: "string" },
168
- // 'clean', 'infected', 'error'
181
+ // 'clean' | 'infected' | 'error'
169
182
  threats: { type: "json" },
170
- // List of detected threats
171
183
  scanner: { type: "string" },
172
- // clamd, etc.
184
+ metadata: { type: "json" },
173
185
  createdAt: { type: "date" }
174
- }
186
+ },
187
+ indexes: [{ fields: ["mediaId"] }]
175
188
  }
176
189
  };
177
190
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/plugin/verified-sources.ts","../src/plugin/interfaces/trusted-metadata.interface.ts","../src/plugin/interfaces/hook-name.interface.ts","../src/plugin/interfaces/hook-mode.interface.ts","../src/plugin/interfaces/media-runtime.interface.ts","../src/database/schema.ts","../src/database/naming.ts","../src/database/fields.ts","../src/database/plan.ts","../src/database/sql.ts","../src/database/migration.ts","../src/database/hooks.ts","../src/database/postgres-utils.ts","../src/adapter/get-adapter.ts","../src/constants/mime-types.ts","../src/index.ts"],"names":["z","schema"],"mappings":";;;;;AAaO,SAAS,wBAAwB,OAAA,EAAgC;AACtE,EAAA,MAAM,CAAA,GAAI,OAAA;AACV,EAAA,CAAA,CAAE,gBAAA,yBAAyB,GAAA,EAAI;AAC/B,EAAA,CAAA,CAAE,gBAAA,CAAiB,IAAI,cAAc,CAAA;AACvC;ACXO,IAAM,qBAAA,GAAwBA,MAClC,MAAA,CAAO;AAAA,EACN,IAAA,EAAMA,MACH,MAAA,CAAO;AAAA,IACN,QAAA,EAAUA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,IAC9B,IAAA,EAAMA,MAAE,MAAA,EAAO,CAAE,KAAI,CAAE,WAAA,GAAc,QAAA,EAAS;AAAA,IAC9C,YAAA,EAAcA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,IAClC,SAAA,EAAWA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AAAS,GAChC,CAAA,CACA,MAAA,EAAO,CACP,QAAA,EAAS;AAAA,EACZ,SAAA,EAAWA,MACR,MAAA,CAAO;AAAA,IACN,MAAA,EAAQA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,IAC5B,GAAA,EAAKA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AAAS,GAC1B,CAAA,CACA,MAAA,EAAO,CACP,QAAA,EAAS;AAAA,EACZ,KAAA,EAAOA,MACJ,MAAA,CAAO;AAAA,IACN,KAAA,EAAOA,MAAE,MAAA,EAAO,CAAE,KAAI,CAAE,WAAA,GAAc,QAAA,EAAS;AAAA,IAC/C,MAAA,EAAQA,MAAE,MAAA,EAAO,CAAE,KAAI,CAAE,WAAA,GAAc,QAAA,EAAS;AAAA,IAChD,UAAUA,KAAA,CAAE,MAAA,EAAO,CAAE,WAAA,GAAc,QAAA;AAAS,GAC7C,CAAA,CACA,MAAA,EAAO,CACP,QAAA;AACL,CAAC,EACA,MAAA;;;AChCI,IAAM,UAAA,GAAa;AAAA,EACxB,aAAA;AAAA,EACA,gBAAA;AAAA,EACA,UAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF;;;ACIO,IAAM,qBAAA,GAA8D;AAAA,EACzE,aAAA,EAAe,WAAA;AAAA,EACf,gBAAA,EAAkB,WAAA;AAAA,EAClB,UAAA,EAAY,WAAA;AAAA,EACZ,aAAA,EAAe,oBAAA;AAAA,EACf,iBAAA,EAAmB;AACrB;AAMO,SAAS,eAAA,CACd,UACA,SAAA,EAC2D;AAC3D,EAAA,MAAM,UAAA,GAAa,sBAAsB,QAAQ,CAAA;AAEjD,EAAA,IAAI,UAAA,KAAe,WAAA,IAAe,SAAA,KAAc,YAAA,EAAc;AAC5D,IAAA,OAAO,EAAE,SAAA,EAAW,MAAA,EAAQ,UAAA,EAAY,IAAA,EAAK;AAAA,EAC/C;AACA,EAAA,IAAI,UAAA,KAAe,iBAAA,IAAqB,SAAA,KAAc,MAAA,EAAQ;AAC5D,IAAA,OAAO,EAAE,SAAA,EAAW,YAAA,EAAc,UAAA,EAAY,IAAA,EAAK;AAAA,EACrD;AAEA,EAAA,OAAO,EAAE,SAAA,EAAW,SAAA,EAAW,UAAA,EAAY,KAAA,EAAM;AACnD;AC7BO,IAAM,sBAAA,GAAyBA,MACnC,MAAA,CAAO;AAAA,EACN,KAAA,EAAOA,MAAE,OAAA,EAAQ;AAAA,EACjB,QAAA,EAAUA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC9B,OAAA,EAASA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC7B,QAAQA,KAAAA,CAAE,KAAA,CAAMA,MAAE,MAAA,EAAQ,EAAE,QAAA;AAC9B,CAAC,EACA,MAAA;AAQI,IAAM,qBAAA,GAAwBA,MAClC,MAAA,CAAO;AAAA,EACN,QAAQA,KAAAA,CAAE,IAAA,CAAK,CAAC,OAAA,EAAS,UAAA,EAAY,OAAO,CAAC,CAAA;AAAA,EAC7C,SAASA,KAAAA,CAAE,KAAA,CAAMA,MAAE,MAAA,EAAQ,EAAE,QAAA,EAAS;AAAA,EACtC,OAAA,EAASA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC7B,WAAWA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,GAAW,QAAA;AACnC,CAAC,EACA,MAAA;;;ACxBI,IAAM,MAAA,GAAmB;AAAA;AAAA,EAE9B,KAAA,EAAO;AAAA,IACL,MAAA,EAAQ;AAAA,MACN,IAAI,EAAE,IAAA,EAAM,UAAU,UAAA,EAAY,IAAA,EAAM,UAAU,IAAA,EAAK;AAAA,MACvD,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC1B,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC3B,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC3B,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACvB,eAAA,EAAiB,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAClC,UAAA,EAAY,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC7B,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC3B,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACxB,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACzB,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC3B,OAAA,EAAS,EAAE,IAAA,EAAM,MAAA,EAAO;AAAA,MACxB,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACzB,UAAA,EAAY,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC7B,SAAA,EAAW,EAAE,IAAA,EAAM,MAAA,EAAO;AAAA,MAC1B,SAAA,EAAW,EAAE,IAAA,EAAM,MAAA,EAAO;AAAA,MAC1B,SAAA,EAAW,EAAE,IAAA,EAAM,MAAA;AAAO,KAC5B;AAAA,IACA,OAAA,EAAS,CAAC,EAAE,MAAA,EAAQ,CAAC,UAAA,EAAY,YAAY,GAAG;AAAA,GAClD;AAAA;AAAA,EAGA,cAAA,EAAgB;AAAA,IACd,MAAA,EAAQ;AAAA,MACN,IAAI,EAAE,IAAA,EAAM,UAAU,UAAA,EAAY,IAAA,EAAM,UAAU,IAAA,EAAK;AAAA,MACvD,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,QAAA;AAAA,QACN,UAAA,EAAY;AAAA,UACV,KAAA,EAAO,OAAA;AAAA,UACP,KAAA,EAAO,IAAA;AAAA,UACP,QAAA,EAAU;AAAA;AACZ,OACF;AAAA,MACA,UAAA,EAAY,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC7B,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC3B,UAAA,EAAY,EAAE,IAAA,EAAM,SAAA,EAAU;AAAA,MAC9B,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA;AAAA,MACvB,aAAA,EAAe,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAChC,SAAA,EAAW,EAAE,IAAA,EAAM,MAAA;AAAO,KAC5B;AAAA,IACA,OAAA,EAAS;AAAA,MACP;AAAA,QACE,MAAA,EAAQ,CAAC,SAAA,EAAW,eAAe,CAAA;AAAA,QACnC,MAAA,EAAQ;AAAA;AACV;AACF,GACF;AAAA;AAAA,EAGA,UAAA,EAAY;AAAA,IACV,MAAA,EAAQ;AAAA,MACN,IAAI,EAAE,IAAA,EAAM,UAAU,UAAA,EAAY,IAAA,EAAM,UAAU,IAAA,EAAK;AAAA,MACvD,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,QAAA;AAAA,QACN,UAAA,EAAY;AAAA,UACV,KAAA,EAAO,OAAA;AAAA,UACP,KAAA,EAAO,IAAA;AAAA,UACP,QAAA,EAAU;AAAA;AACZ,OACF;AAAA,MACA,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA;AAAA,MACvB,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA;AAAA,MACzB,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC3B,WAAA,EAAa,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC9B,cAAA,EAAgB,EAAE,IAAA,EAAM,QAAA,EAAU,QAAQ,IAAA,EAAK;AAAA,MAC/C,WAAA,EAAa,EAAE,IAAA,EAAM,MAAA,EAAO;AAAA,MAC5B,SAAA,EAAW,EAAE,IAAA,EAAM,MAAA,EAAO;AAAA,MAC1B,WAAA,EAAa,EAAE,IAAA,EAAM,MAAA,EAAO;AAAA,MAC5B,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACxB,SAAA,EAAW,EAAE,IAAA,EAAM,MAAA;AAAO;AAC5B,GACF;AAAA,EAEA,wBAAA,EAA0B;AAAA,IACxB,MAAA,EAAQ;AAAA,MACN,IAAI,EAAE,IAAA,EAAM,UAAU,UAAA,EAAY,IAAA,EAAM,UAAU,IAAA,EAAK;AAAA,MACvD,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,QAAA;AAAA,QACN,YAAY,EAAE,KAAA,EAAO,SAAS,KAAA,EAAO,IAAA,EAAM,UAAU,SAAA;AAAU,OACjE;AAAA,MACA,KAAA,EAAO,EAAE,IAAA,EAAM,SAAA,EAAU;AAAA,MACzB,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC3B,MAAA,EAAQ,EAAE,IAAA,EAAM,MAAA,EAAO;AAAA,MACvB,SAAA,EAAW,EAAE,IAAA,EAAM,MAAA;AAAO;AAC5B,GACF;AAAA,EAEA,wBAAA,EAA0B;AAAA,IACxB,MAAA,EAAQ;AAAA,MACN,IAAI,EAAE,IAAA,EAAM,UAAU,UAAA,EAAY,IAAA,EAAM,UAAU,IAAA,EAAK;AAAA,MACvD,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,QAAA;AAAA,QACN,YAAY,EAAE,KAAA,EAAO,SAAS,KAAA,EAAO,IAAA,EAAM,UAAU,SAAA;AAAU,OACjE;AAAA,MACA,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA;AAAA,MACzB,OAAA,EAAS,EAAE,IAAA,EAAM,MAAA,EAAO;AAAA;AAAA,MACxB,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA;AAAA,MAC1B,SAAA,EAAW,EAAE,IAAA,EAAM,MAAA;AAAO;AAC5B;AAEJ;;;AC9GO,SAAS,YAAY,KAAA,EAAuB;AACjD,EAAA,OAAO,KAAA,CACJ,QAAQ,oBAAA,EAAsB,OAAO,EACrC,OAAA,CAAQ,SAAA,EAAW,GAAG,CAAA,CACtB,WAAA,EAAY;AACjB;AAEO,SAAS,YAAY,KAAA,EAAuB;AACjD,EAAA,OAAO,KAAA,CAAM,QAAQ,WAAA,EAAa,CAAC,GAAG,CAAA,KAAc,CAAA,CAAE,aAAa,CAAA;AACrE;AAEO,SAAS,cAAc,KAAA,EAAuB;AACnD,EAAA,OAAO,YAAY,KAAK,CAAA;AAC1B;;;ACNO,IAAM,UAAA,GAAgD;AAAA,EAC3D,IAAA,EAAM;AAAA,IACJ,SAAA,EAAW,CAAC,KAAA,KAAW,KAAA,KAAU,SAAY,MAAA,GAAY,IAAA,CAAK,UAAU,KAAK,CAAA;AAAA,IAC7E,WAAA,EAAa,CAAC,KAAA,KAAW,OAAO,UAAU,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA,GAAI;AAAA,GAC3E;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,SAAA,EAAW,CAAC,KAAA,KACV,KAAA,YAAiB,IAAA,GAAO,KAAA,CAAM,WAAA,EAAY,GAAI,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,KAAA;AAAA,IACpF,WAAA,EAAa,CAAC,KAAA,KAAW,OAAO,UAAU,QAAA,GAAW,IAAI,IAAA,CAAK,KAAK,CAAA,GAAI;AAAA,GACzE;AAAA,EACA,OAAA,EAAS;AAAA,IACP,SAAA,EAAW,CAAC,KAAA,KAAW,OAAO,UAAU,SAAA,GAAa,KAAA,GAAQ,IAAI,CAAA,GAAK,KAAA;AAAA,IACtE,WAAA,EAAa,CAAC,KAAA,KAAW,OAAO,UAAU,QAAA,GAAW,KAAA,KAAU,CAAA,GAAI,OAAA,CAAQ,KAAK;AAAA,GAClF;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,SAAA,EAAW,CAAC,KAAA,KAAU,KAAA;AAAA,IACtB,WAAA,EAAa,CAAC,KAAA,KAAW,OAAO,UAAU,QAAA,GAAW,MAAA,CAAO,KAAK,CAAA,GAAI;AAAA,GACvE;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,SAAA,EAAW,CAAC,KAAA,KAAW,OAAO,UAAU,QAAA,GAAW,MAAA,CAAO,KAAK,CAAA,GAAI,KAAA;AAAA,IACnE,WAAA,EAAa,CAAC,KAAA,KAAU;AAAA;AAE5B;AAEO,SAAS,cAAA,CAAe,MAAiB,KAAA,EAAyB;AACvE,EAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,EAAW,OAAO,KAAA;AAClD,EAAA,OAAO,UAAA,CAAW,IAAI,CAAA,EAAG,SAAA,CAAU,KAAK,CAAA,IAAK,KAAA;AAC/C;AAEO,SAAS,gBAAA,CAAiB,MAAiB,KAAA,EAAyB;AACzE,EAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,EAAW,OAAO,KAAA;AAClD,EAAA,OAAO,UAAA,CAAW,IAAI,CAAA,EAAG,WAAA,CAAY,KAAK,CAAA,IAAK,KAAA;AACjD;AAEO,SAAS,aAAA,CACd,QACA,IAAA,EACyB;AACzB,EAAA,MAAM,SAAkC,EAAC;AACzC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC/C,IAAA,IAAI,MAAA,CAAO,GAAG,CAAA,EAAG;AACf,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,cAAA,CAAe,OAAO,GAAG,CAAA,CAAE,MAAM,KAAK,CAAA;AAAA,IACtD,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,IAChB;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,eAAA,CACd,QACA,IAAA,EACyB;AACzB,EAAA,MAAM,SAAkC,EAAC;AACzC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC/C,IAAA,IAAI,MAAA,CAAO,GAAG,CAAA,EAAG;AACf,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,gBAAA,CAAiB,OAAO,GAAG,CAAA,CAAE,MAAM,KAAK,CAAA;AAAA,IACxD,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,IAChB;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;;;AC5DA,IAAM,UAAA,GAA4D;AAAA,EAChE,MAAA,EAAQ;AAAA,IACN,QAAA,EAAU,MAAA;AAAA,IACV,KAAA,EAAO,cAAA;AAAA,IACP,MAAA,EAAQ,MAAA;AAAA,IACR,KAAA,EAAO;AAAA,GACT;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,QAAA,EAAU,SAAA;AAAA,IACV,KAAA,EAAO,SAAA;AAAA,IACP,MAAA,EAAQ,SAAA;AAAA,IACR,KAAA,EAAO;AAAA,GACT;AAAA,EACA,OAAA,EAAS;AAAA,IACP,QAAA,EAAU,SAAA;AAAA,IACV,KAAA,EAAO,SAAA;AAAA,IACP,MAAA,EAAQ,SAAA;AAAA,IACR,KAAA,EAAO;AAAA,GACT;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,QAAA,EAAU,WAAA;AAAA,IACV,KAAA,EAAO,UAAA;AAAA,IACP,MAAA,EAAQ,MAAA;AAAA,IACR,KAAA,EAAO;AAAA,GACT;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,QAAA,EAAU,OAAA;AAAA,IACV,KAAA,EAAO,MAAA;AAAA,IACP,MAAA,EAAQ,MAAA;AAAA,IACR,KAAA,EAAO;AAAA;AAEX,CAAA;AAEO,SAAS,aAAA,CAAc,OAAwB,OAAA,EAA6B;AAEjF,EAAA,IAAI,KAAA,CAAM,UAAA,IAAc,KAAA,CAAM,IAAA,KAAS,QAAA,EAAU;AAC/C,IAAA,IAAI,OAAA,KAAY,YAAY,OAAO,MAAA;AACnC,IAAA,OAAO,OAAA,KAAY,OAAA,IAAW,OAAA,KAAY,OAAA,GAAU,aAAA,GAAgB,MAAA;AAAA,EACtE;AACA,EAAA,IAAI,MAAM,UAAA,IAAc,KAAA,CAAM,IAAA,KAAS,QAAA,IAAY,YAAY,UAAA,EAAY;AACzE,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,KAAA,CAAM,IAAI,CAAA;AACnC,EAAA,IAAI,CAAC,OAAO,OAAO,MAAA;AAEnB,EAAA,MAAM,IAAA,GAAO,MAAM,OAAO,CAAA;AAC1B,EAAA,OAAO,IAAA,IAAQ,MAAA;AACjB;AAEO,SAAS,SAAA,CAAU,MAAA,EAAgB,YAAA,EAAyB,OAAA,EAA8B;AAC/F,EAAA,MAAM,YAAA,GAAA,CAAgB,MAAA,CAAO,WAAA,EAAY,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA,EAAI,IAAA,EAAK;AACrE,EAAA,MAAM,aAAA,GAAiE;AAAA,IACrE,QAAA,EAAU;AAAA,MACR,MAAA,EAAQ,CAAC,mBAAA,EAAqB,SAAA,EAAW,QAAQ,MAAM,CAAA;AAAA,MACvD,MAAA,EAAQ,CAAC,MAAA,EAAQ,SAAA,EAAW,UAAU,UAAA,EAAY,SAAA,EAAW,QAAQ,kBAAkB,CAAA;AAAA,MACvF,OAAA,EAAS,CAAC,MAAA,EAAQ,SAAS,CAAA;AAAA,MAC3B,IAAA,EAAM,CAAC,aAAA,EAAe,WAAA,EAAa,MAAM,CAAA;AAAA,MACzC,IAAA,EAAM,CAAC,MAAA,EAAQ,OAAO;AAAA,KACxB;AAAA,IACA,KAAA,EAAO;AAAA,MACL,MAAA,EAAQ,CAAC,SAAA,EAAW,MAAA,EAAQ,QAAQ,MAAM,CAAA;AAAA,MAC1C,MAAA,EAAQ,CAAC,SAAA,EAAW,KAAA,EAAO,UAAU,UAAA,EAAY,SAAA,EAAW,SAAS,QAAQ,CAAA;AAAA,MAC7E,OAAA,EAAS,CAAC,SAAA,EAAW,SAAA,EAAW,KAAK,CAAA;AAAA,MACrC,IAAA,EAAM,CAAC,WAAA,EAAa,UAAA,EAAY,MAAM,CAAA;AAAA,MACtC,IAAA,EAAM,CAAC,MAAA,EAAQ,MAAA,EAAQ,UAAU;AAAA,KACnC;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,MAAA,EAAQ,CAAC,MAAA,EAAQ,SAAS,CAAA;AAAA,MAC1B,MAAA,EAAQ,CAAC,SAAA,EAAW,MAAA,EAAQ,SAAS,CAAA;AAAA,MACrC,OAAA,EAAS,CAAC,SAAA,EAAW,SAAS,CAAA;AAAA,MAC9B,IAAA,EAAM,CAAC,MAAA,EAAQ,MAAA,EAAQ,SAAS,CAAA;AAAA,MAChC,IAAA,EAAM,CAAC,MAAM;AAAA,KACf;AAAA,IACA,KAAA,EAAO;AAAA,MACL,MAAA,EAAQ,CAAC,SAAA,EAAW,UAAA,EAAY,kBAAkB,CAAA;AAAA,MAClD,MAAA,EAAQ,CAAC,KAAA,EAAO,QAAA,EAAU,YAAY,SAAA,EAAW,OAAA,EAAS,UAAU,SAAS,CAAA;AAAA,MAC7E,OAAA,EAAS,CAAC,KAAA,EAAO,UAAU,CAAA;AAAA,MAC3B,IAAA,EAAM,CAAC,WAAA,EAAa,MAAA,EAAQ,YAAY,WAAW,CAAA;AAAA,MACnD,IAAA,EAAM,CAAC,SAAA,EAAW,UAAU;AAAA;AAC9B,GACF;AAEA,EAAA,OAAO,cAAc,OAAO,CAAA,CAAE,YAAY,CAAA,CAAE,SAAS,YAAY,CAAA;AACnE;AAKO,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAA6B,OAAA,EAAqB;AAArB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EAAsB;AAAA,EAEnD,IAAA,CAAKC,SAAkB,aAAA,EAAsD;AAC3E,IAAA,MAAM,aAAmC,EAAC;AAE1C,IAAA,KAAA,MAAW,CAAC,SAAA,EAAW,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQA,OAAM,CAAA,EAAG;AACvD,MAAA,MAAM,gBAAgB,aAAA,CAAc,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,SAAS,CAAA;AAEpE,MAAA,IAAI,CAAC,aAAA,EAAe;AAElB,QAAA,UAAA,CAAW,IAAA,CAAK,EAAE,IAAA,EAAM,aAAA,EAAe,OAAO,SAAA,EAAW,UAAA,EAAY,OAAO,CAAA;AAC5E,QAAA;AAAA,MACF;AAGA,MAAA,KAAA,MAAW,CAAC,WAAW,QAAQ,CAAA,IAAK,OAAO,OAAA,CAAQ,KAAA,CAAM,MAAM,CAAA,EAAG;AAChE,QAAA,MAAM,cAAA,GAAiB,cAAc,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,SAAS,CAAA;AAE7E,QAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,UAAA,UAAA,CAAW,IAAA,CAAK;AAAA,YACd,IAAA,EAAM,WAAA;AAAA,YACN,KAAA,EAAO,SAAA;AAAA,YACP,KAAA,EAAO,SAAA;AAAA,YACP,UAAA,EAAY;AAAA,WACb,CAAA;AAAA,QACH,CAAA,MAAO;AAEL,UAAA,IAAI,CAAC,UAAU,cAAA,CAAe,QAAA,EAAU,SAAS,IAAA,EAAM,IAAA,CAAK,OAAO,CAAA,EAAG;AACpE,YAAA,OAAA,CAAQ,IAAA;AAAA,cACN,CAAA,gCAAA,EAAmC,SAAS,CAAA,CAAA,EAAI,SAAS,cAC3C,QAAA,CAAS,IAAI,CAAA,WAAA,EAAc,cAAA,CAAe,QAAQ,CAAA,OAAA;AAAA,aAClE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IAGF;AAEA,IAAA,OAAO,UAAA;AAAA,EACT;AACF;AAMO,SAAS,yBAAA,CACd,eAAA,EACA,UAAA,EACA,OAAA,EACiB;AACjB,EAAA,MAAM,WAAW,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,SAAA,CAAU,eAAe,CAAC,CAAA;AAE3D,EAAA,KAAA,MAAW,MAAM,UAAA,EAAY;AAC3B,IAAA,IAAI,EAAA,CAAG,SAAS,aAAA,EAAe;AAC7B,MAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,EAAA,CAAG,UAAA,CAAW,MAAM,CAAA,CAAE,GAAA,CAAI,CAAC,CAAC,IAAA,EAAM,KAAK,CAAA,MAAO;AAAA,QAC3E,IAAA;AAAA,QACA,QAAA,EAAU,aAAA,CAAc,KAAA,EAAO,OAAO,CAAA;AAAA,QACtC,UAAA,EAAY,CAAC,KAAA,CAAM,QAAA,IAAY,CAAC,KAAA,CAAM,UAAA;AAAA,QACtC,QAAA,EAAU,KAAA,CAAM,MAAA,IAAU,KAAA,CAAM;AAAA,OAClC,CAAE,CAAA;AACF,MAAA,QAAA,CAAS,KAAK,EAAE,IAAA,EAAM,EAAA,CAAG,KAAA,EAAO,SAAS,CAAA;AAAA,IAC3C,CAAA,MAAA,IAAW,EAAA,CAAG,IAAA,KAAS,WAAA,EAAa;AAClC,MAAA,MAAM,KAAA,GAAQ,SAAS,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,IAAA,KAAS,GAAG,KAAK,CAAA;AACtD,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,KAAA,CAAM,QAAQ,IAAA,CAAK;AAAA,UACjB,MAAM,EAAA,CAAG,KAAA;AAAA,UACT,QAAA,EAAU,aAAA,CAAc,EAAA,CAAG,UAAA,EAAY,OAAO,CAAA;AAAA,UAC9C,UAAA,EAAY,CAAC,EAAA,CAAG,UAAA,CAAW,QAAA;AAAA,UAC3B,QAAA,EAAU,CAAC,CAAC,EAAA,CAAG,UAAA,CAAW;AAAA,SAC3B,CAAA;AAAA,MACH;AAAA,IACF;AAAA,EAEF;AAEA,EAAA,OAAO,QAAA;AACT;;;ACvKA,SAAS,UAAA,CAAW,OAAe,OAAA,EAA6B;AAE9D,EAAA,IAAI,OAAA,KAAY,OAAA,EAAS,OAAO,CAAA,EAAA,EAAK,KAAK,CAAA,EAAA,CAAA;AAC1C,EAAA,OAAO,IAAI,KAAK,CAAA,CAAA,CAAA;AAClB;AAEA,SAAS,YACP,QAAA,EAKQ;AACR,EAAA,IAAI,CAAC,UAAU,OAAO,EAAA;AACtB,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,QAAQ,CAAA,CAAE,WAAA,EAAY;AAChD,EAAA,IAAI,UAAA,KAAe,WAAW,OAAO,oBAAA;AACrC,EAAA,IAAI,UAAA,KAAe,YAAY,OAAO,qBAAA;AACtC,EAAA,IAAI,UAAA,KAAe,YAAY,OAAO,qBAAA;AACtC,EAAA,OAAO,EAAA;AACT;AAEA,SAAS,SAAA,CACP,KAAA,EACA,IAAA,EACA,KAAA,EACA,OAAA,EACQ;AACR,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,MAAM,MAAA,GAAS,cAAc,IAAI,CAAA;AACjC,EAAA,KAAA,CAAM,IAAA,CAAK,UAAA,CAAW,MAAA,EAAQ,OAAO,CAAC,CAAA;AACtC,EAAA,KAAA,CAAM,IAAA,CAAK,aAAA,CAAc,KAAA,EAAO,OAAO,CAAC,CAAA;AAExC,EAAA,IAAI,KAAA,CAAM,UAAA,EAAY,KAAA,CAAM,IAAA,CAAK,aAAa,CAAA;AAC9C,EAAA,IAAI,KAAA,CAAM,QAAA,EAAU,KAAA,CAAM,IAAA,CAAK,UAAU,CAAA;AACzC,EAAA,IAAI,KAAA,CAAM,MAAA,EAAQ,KAAA,CAAM,IAAA,CAAK,QAAQ,CAAA;AAErC,EAAA,IAAI,MAAM,UAAA,EAAY;AACpB,IAAA,MAAM,MAAM,KAAA,CAAM,UAAA;AAClB,IAAA,MAAM,QAAA,GAAW,UAAA,CAAW,GAAA,CAAI,KAAA,EAAO,OAAO,CAAA;AAC9C,IAAA,MAAM,WAAW,UAAA,CAAW,aAAA,CAAc,GAAA,CAAI,KAAK,GAAG,OAAO,CAAA;AAC7D,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,WAAA,EAAc,QAAQ,CAAA,CAAA,EAAI,QAAQ,IAAI,WAAA,CAAY,GAAA,CAAI,QAAQ,CAAC,CAAA,CAAE,CAAA;AAAA,EAC9E;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,GAAG,CAAA;AACvB;AAEA,SAAS,cAAA,CAAe,KAAA,EAAe,UAAA,EAA6B,OAAA,EAA6B;AAC/F,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,KAAA,EAAO,OAAO,CAAA;AAC3C,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,OAAA,CAAQ,UAAA,CAAW,MAAM,CAAA,CAAE,GAAA;AAAA,IAAI,CAAC,CAAC,IAAA,EAAM,KAAK,MAC9D,SAAA,CAAU,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,OAAO;AAAA,GACvC;AACA,EAAA,MAAM,WAAA,GAAc,OAAA,KAAY,OAAA,GAAU,EAAA,GAAK,gBAAA;AAC/C,EAAA,OAAO,CAAA,YAAA,EAAe,WAAW,CAAA,CAAA,EAAI,SAAS,CAAA;AAAA,EAAA,EAAS,IAAA,CAAK,IAAA,CAAK,OAAO,CAAC;AAAA,EAAA,CAAA;AAC3E;AAEA,SAAS,cAAA,CACP,KAAA,EACA,SAAA,EACA,MAAA,EACA,QACA,OAAA,EACQ;AACR,EAAA,MAAM,GAAA,GAAM,UAAA,CAAW,SAAA,EAAW,OAAO,CAAA;AACzC,EAAA,MAAM,GAAA,GAAM,UAAA,CAAW,KAAA,EAAO,OAAO,CAAA;AACrC,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,UAAA,CAAW,aAAA,CAAc,CAAC,CAAA,EAAG,OAAO,CAAC,CAAA,CAAE,KAAK,IAAI,CAAA;AAC/E,EAAA,MAAM,SAAA,GAAY,SAAS,SAAA,GAAY,EAAA;AACvC,EAAA,MAAM,WAAA,GAAc,OAAA,KAAY,OAAA,GAAU,EAAA,GAAK,gBAAA;AAC/C,EAAA,OAAO,CAAA,OAAA,EAAU,SAAS,CAAA,KAAA,EAAQ,WAAW,IAAI,GAAG,CAAA,IAAA,EAAO,GAAG,CAAA,EAAA,EAAK,IAAI,CAAA,EAAA,CAAA;AACzE;AAEA,SAAS,YAAA,CACP,KAAA,EACA,KAAA,EACA,UAAA,EACA,OAAA,EACQ;AACR,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,KAAA,EAAO,OAAO,CAAA;AAC3C,EAAA,MAAM,SAAA,GAAY,SAAA,CAAU,KAAA,EAAO,KAAA,EAAO,YAAY,OAAO,CAAA;AAC7D,EAAA,OAAO,CAAA,YAAA,EAAe,SAAS,CAAA,YAAA,EAAe,SAAS,CAAA,CAAA,CAAA;AACzD;AAEO,SAAS,8BAA8B,OAAA,EAGnC;AACT,EAAA,MAAM,EAAE,UAAA,EAAY,OAAA,EAAQ,GAAI,OAAA;AAChC,EAAA,MAAM,aAAuB,EAAC;AAC9B,EAAA,UAAA,CAAW,IAAA,CAAK,CAAA,oCAAA,EAAuC,OAAO,CAAA,CAAA,CAAG,CAAA;AAEjE,EAAA,IAAI,YAAY,QAAA,EAAU;AACxB,IAAA,UAAA,CAAW,KAAK,2BAA2B,CAAA;AAAA,EAC7C;AAEA,EAAA,KAAA,MAAW,MAAM,UAAA,EAAY;AAC3B,IAAA,IAAI,EAAA,CAAG,SAAS,aAAA,EAAe;AAC7B,MAAA,UAAA,CAAW,KAAK,cAAA,CAAe,EAAA,CAAG,OAAO,EAAA,CAAG,UAAA,EAAY,OAAO,CAAC,CAAA;AAChE,MAAA,IAAI,EAAA,CAAG,WAAW,OAAA,EAAS;AACzB,QAAA,KAAA,MAAW,KAAA,IAAS,EAAA,CAAG,UAAA,CAAW,OAAA,EAAS;AACzC,UAAA,MAAM,YAAY,CAAA,IAAA,EAAO,EAAA,CAAG,KAAK,CAAA,CAAA,EAAI,MAAM,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,cAAc,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AACxF,UAAA,UAAA,CAAW,IAAA,CAAK,cAAA,CAAe,EAAA,CAAG,KAAA,EAAO,SAAA,EAAW,MAAM,MAAA,EAAQ,KAAA,CAAM,MAAA,EAAQ,OAAO,CAAC,CAAA;AAAA,QAC1F;AAAA,MACF;AACA,MAAA;AAAA,IACF;AACA,IAAA,IAAI,EAAA,CAAG,SAAS,WAAA,EAAa;AAC3B,MAAA,UAAA,CAAW,IAAA,CAAK,aAAa,EAAA,CAAG,KAAA,EAAO,GAAG,KAAA,EAAO,EAAA,CAAG,UAAA,EAAY,OAAO,CAAC,CAAA;AACxE,MAAA;AAAA,IACF;AACA,IAAA,IAAI,EAAA,CAAG,SAAS,aAAA,EAAe;AAC7B,MAAA,UAAA,CAAW,IAAA,CAAK,cAAA,CAAe,EAAA,CAAG,KAAA,EAAO,EAAA,CAAG,IAAA,EAAM,EAAA,CAAG,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,OAAO,CAAC,CAAA;AAAA,IAClF;AAAA,EACF;AAEA,EAAA,OAAO,UAAA,CAAW,IAAA,CAAK,MAAM,CAAA,GAAI,IAAA;AACnC;AAEO,SAAS,wBAAwB,OAAA,EAG7B;AACT,EAAA,MAAM,EAAE,MAAA,EAAAA,OAAAA,EAAQ,OAAA,EAAQ,GAAI,OAAA;AAE5B,EAAA,MAAM,aAAuB,EAAC;AAC9B,EAAA,UAAA,CAAW,IAAA,CAAK,CAAA,wBAAA,EAA2B,OAAO,CAAA,CAAA,CAAG,CAAA;AAGrD,EAAA,IAAI,YAAY,QAAA,EAAU;AACxB,IAAA,UAAA,CAAW,KAAK,2BAA2B,CAAA;AAAA,EAC7C;AAGA,EAAA,KAAA,MAAW,CAAC,KAAA,EAAO,GAAG,KAAK,MAAA,CAAO,OAAA,CAAQA,OAAM,CAAA,EAAG;AACjD,IAAA,UAAA,CAAW,IAAA,CAAK,cAAA,CAAe,KAAA,EAAO,GAAA,EAAK,OAAO,CAAC,CAAA;AAAA,EACrD;AAGA,EAAA,KAAA,MAAW,CAAC,KAAA,EAAO,GAAG,KAAK,MAAA,CAAO,OAAA,CAAQA,OAAM,CAAA,EAAG;AACjD,IAAA,IAAI,CAAC,IAAI,OAAA,EAAS;AAClB,IAAA,KAAA,MAAW,KAAA,IAAS,IAAI,OAAA,EAAS;AAC/B,MAAA,MAAM,SAAA,GAAY,CAAA,IAAA,EAAO,KAAK,CAAA,CAAA,EAAI,MAAM,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,cAAc,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AACrF,MAAA,UAAA,CAAW,IAAA,CAAK,eAAe,KAAA,EAAO,SAAA,EAAW,MAAM,MAAA,EAAQ,KAAA,CAAM,MAAA,EAAQ,OAAO,CAAC,CAAA;AAAA,IACvF;AAAA,EACF;AAEA,EAAA,OAAO,UAAA,CAAW,IAAA,CAAK,MAAM,CAAA,GAAI,IAAA;AACnC;;;ACnGA,eAAsB,aAAA,CACpB,OAAA,EACA,OAAA,GAA4B,EAAC,EACD;AAC5B,EAAA,MAAM,UAAA,GAAa,OAAA;AAEnB,EAAA,IACE,OAAO,UAAA,CAAW,aAAA,KAAkB,cACpC,OAAO,UAAA,CAAW,uBAAuB,UAAA,EACzC;AACA,IAAA,OAAO;AAAA,MACL,aAAa,EAAC;AAAA,MACd,WAAW,EAAC;AAAA,MACZ,YAAY,EAAC;AAAA,MACb,mBAAmB,MAAM,EAAA;AAAA,MACzB,eAAe,YAAY;AACzB,QAAA,MAAM,IAAI,MAAM,4DAA4D,CAAA;AAAA,MAC9E;AAAA,KACF;AAAA,EACF;AAEA,EAAA,IAAI,UAAU,OAAA,CAAQ,OAAA;AACtB,EAAA,IAAI,CAAC,OAAA,IAAW,OAAO,UAAA,CAAW,iBAAiB,UAAA,EAAY;AAC7D,IAAA,OAAA,GAAU,WAAW,YAAA,EAAa;AAAA,EACpC;AACA,EAAA,MAAM,kBAAkB,OAAA,IAAW,UAAA;AACnC,EAAA,MAAM,QAAA,GAAW,MAAM,UAAA,CAAW,aAAA,EAAc;AAChD,EAAA,MAAM,OAAA,GAAU,IAAI,gBAAA,CAAiB,eAAe,CAAA;AACpD,EAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,IAAA,CAAK,MAAA,EAAQ,QAAQ,CAAA;AAEhD,EAAA,MAAM,cAAc,UAAA,CACjB,MAAA;AAAA,IACC,CAAC,EAAA,KAAmE,EAAA,CAAG,IAAA,KAAS;AAAA,GAClF,CACC,GAAA,CAAI,CAAC,EAAA,MAAQ,EAAE,KAAA,EAAO,EAAA,CAAG,KAAA,EAAO,MAAA,EAAQ,OAAO,IAAA,CAAK,EAAA,CAAG,UAAA,CAAW,MAAM,GAAE,CAAE,CAAA;AAE/E,EAAA,MAAM,YAAY,UAAA,CACf,MAAA;AAAA,IACC,CAAC,EAAA,KAAiE,EAAA,CAAG,IAAA,KAAS;AAAA,GAChF,CACC,MAAA,CAAgC,CAAC,GAAA,EAAK,EAAA,KAAO;AAC5C,IAAA,MAAM,QAAA,GAAW,IAAI,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,KAAA,KAAU,GAAG,KAAK,CAAA;AACrD,IAAA,IAAI,QAAA,EAAU,QAAA,CAAS,MAAA,CAAO,IAAA,CAAK,GAAG,KAAK,CAAA;AAAA,SACtC,GAAA,CAAI,IAAA,CAAK,EAAE,KAAA,EAAO,EAAA,CAAG,KAAA,EAAO,MAAA,EAAQ,CAAC,EAAA,CAAG,KAAK,CAAA,EAAG,CAAA;AACrD,IAAA,OAAO,GAAA;AAAA,EACT,CAAA,EAAG,EAAE,CAAA;AAEP,EAAA,OAAO;AAAA,IACL,WAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,IACA,mBAAmB,MACjB,6BAAA,CAA8B,EAAE,UAAA,EAAY,OAAA,EAAS,iBAAiB,CAAA;AAAA,IACxE,eAAe,YAAY;AACzB,MAAA,KAAA,MAAW,MAAM,UAAA,EAAY;AAC3B,QAAA,MAAM,UAAA,CAAW,mBAAoB,EAAE,CAAA;AAAA,MACzC;AAAA,IACF;AAAA,GACF;AACF;AAMA,eAAsB,aAAA,CACpB,OAAA,EACA,OAAA,GAA4B,EAAC,EACd;AACf,EAAA,MAAM,IAAA,GAAO,QAAQ,IAAA,IAAQ,MAAA;AAC7B,EAAA,MAAM,UAAA,GAAa,OAAA;AAGnB,EAAA,IACE,OAAO,UAAA,CAAW,aAAA,KAAkB,cACpC,OAAO,UAAA,CAAW,uBAAuB,UAAA,EACzC;AACA,IAAA,OAAA,CAAQ,IAAI,6CAA6C,CAAA;AAEzD,IAAA,MAAM,EAAE,UAAA,EAAY,aAAA,EAAe,oBAAA,KAAyB,MAAM,aAAA;AAAA,MAChE,OAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC3B,MAAA,OAAA,CAAQ,IAAI,uCAAuC,CAAA;AACnD,MAAA;AAAA,IACF;AAEA,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,oBAAA,EAAuB,UAAA,CAAW,MAAM,CAAA,yBAAA,CAA2B,CAAA;AAC/E,IAAA,MAAM,oBAAA,EAAqB;AAC3B,IAAA,OAAA,CAAQ,IAAI,iDAAiD,CAAA;AAC7D,IAAA;AAAA,EACF;AAGA,EAAA,IAAI,OAAO,UAAA,CAAW,aAAA,KAAkB,UAAA,EAAY;AAElD,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,UAAU,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACxD,MAAA,MAAM,WAAW,aAAA,CAAc,KAAA,EAAO,UAAA,EAAY,EAAE,MAAM,CAAA;AAAA,IAC5D;AAAA,EACF,CAAA,MAAA,IAAW,OAAO,UAAA,CAAW,gBAAA,KAAqB,UAAA,EAAY;AAE5D,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,UAAU,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACxD,MAAA,MAAM,WAAW,gBAAA,CAAiB,KAAA,EAAO,UAAA,EAAY,EAAE,MAAM,CAAA;AAAA,IAC/D;AAAA,EACF,CAAA,MAAO;AACL,IAAA,OAAA,CAAQ,KAAK,8DAA8D,CAAA;AAAA,EAC7E;AACF;;;AC/JO,IAAM,QAAA,GAAW;AAAA,EACtB,MAAM,YAAA,CACJ,KAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,IAAI,WAAA,GAAc,IAAA;AAClB,IAAA,MAAM,QAAA,GAAW,KAAA,EAAO,MAAA,EAAQ,MAAA,IAAU,EAAC;AAC3C,IAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,MAAA,WAAA,GAAc,MAAM,OAAA,CAAQ,WAAA,EAAa,OAAO,CAAA;AAAA,IAClD;AACA,IAAA,OAAO,WAAA;AAAA,EACT,CAAA;AAAA,EAEA,MAAM,YAAA,CACJ,KAAA,EACA,IAAA,EACA,OAAA,EACA;AACA,IAAA,IAAI,WAAA,GAAc,IAAA;AAClB,IAAA,MAAM,QAAA,GAAW,KAAA,EAAO,MAAA,EAAQ,MAAA,IAAU,EAAC;AAC3C,IAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,MAAA,WAAA,GAAc,MAAM,OAAA,CAAQ,WAAA,EAAa,OAAO,CAAA;AAAA,IAClD;AACA,IAAA,OAAO,WAAA;AAAA,EACT,CAAA;AAAA,EAEA,MAAM,YAAA,CAAa,KAAA,EAA4B,KAAA,EAAoB,OAAA,EAA8B;AAC/F,IAAA,MAAM,QAAA,GAAW,KAAA,EAAO,MAAA,EAAQ,MAAA,IAAU,EAAC;AAC3C,IAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,MAAA,MAAM,OAAA,CAAQ,OAAO,OAAO,CAAA;AAAA,IAC9B;AAAA,EACF,CAAA;AAAA,EAEA,MAAM,WAAA,CACJ,KAAA,EACA,MAAA,EACA,OAAA,EACA;AACA,IAAA,MAAM,QAAA,GAAW,KAAA,EAAO,KAAA,EAAO,MAAA,IAAU,EAAC;AAC1C,IAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,MAAA,MAAM,OAAA,CAAQ,QAAQ,OAAO,CAAA;AAAA,IAC/B;AAAA,EACF,CAAA;AAAA,EAEA,MAAM,WAAA,CACJ,KAAA,EACA,MAAA,EACA,OAAA,EACA;AACA,IAAA,MAAM,QAAA,GAAW,KAAA,EAAO,KAAA,EAAO,MAAA,IAAU,EAAC;AAC1C,IAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,MAAA,MAAM,OAAA,CAAQ,QAAQ,OAAO,CAAA;AAAA,IAC/B;AAAA,EACF,CAAA;AAAA,EAEA,MAAM,WAAA,CAAY,KAAA,EAA4B,KAAA,EAAoB,OAAA,EAA8B;AAC9F,IAAA,MAAM,QAAA,GAAW,KAAA,EAAO,KAAA,EAAO,MAAA,IAAU,EAAC;AAC1C,IAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,MAAA,MAAM,OAAA,CAAQ,OAAO,OAAO,CAAA;AAAA,IAC9B;AAAA,EACF;AACF;;;ACpDO,SAAS,aAAa,KAAA,EAAqC;AAChE,EAAA,OAAO,OAAA;AAAA,IACL,SAAS,OAAO,KAAA,KAAU,QAAA,IAAY,OAAQ,MAA8B,KAAA,KAAU;AAAA,GACxF;AACF;AAOO,SAAS,iBAAA,CACd,UACA,eAAA,EACiB;AACjB,EAAA,IAAI,aAAa,QAAQ,CAAA,IAAK,OAAQ,QAAA,CAAkC,WAAW,UAAA,EAAY;AAC7F,IAAA,IAAI,eAAA,EAAiB,OAAO,eAAA,CAAgB,QAAQ,CAAA;AACpD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AACA,EAAA,OAAO,QAAA;AACT;;;AC5BA,eAAsB,WAAW,OAAA,EAAsD;AACrF,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,QAAA,IAAa,MAAM,QAAQ,cAAA,IAAiB;AACrE,EAAA,MAAM,OAAA,GAAU,QAAA,GAAW,iBAAA,CAAkB,QAAQ,CAAA,GAAI,MAAA;AACzD,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,wFAAA;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,OAAA;AACT;;;AChBO,IAAM,qBAAA,GAAkD;AAAA,EAC7D,MAAA,EAAQ,CAAC,WAAW,CAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,uBAAuB,CAAA;AAAA,EAChC,OAAA,EAAS,CAAC,YAAY,CAAA;AAAA,EACtB,MAAA,EAAQ,CAAC,uBAAuB,CAAA;AAAA,EAChC,OAAA,EAAS,CAAC,YAAY,CAAA;AAAA,EACtB,MAAA,EAAQ,CAAC,iBAAiB,CAAA;AAAA,EAC1B,MAAA,EAAQ,CAAC,8BAA8B,CAAA;AAAA,EACvC,MAAA,EAAQ,CAAC,0BAA0B,CAAA;AAAA,EACnC,MAAA,EAAQ,CAAC,WAAW,CAAA;AAAA,EACpB,KAAA,EAAO,CAAC,oBAAoB,CAAA;AAAA,EAC5B,MAAA,EAAQ,CAAC,qBAAqB,CAAA;AAAA,EAC9B,MAAA,EAAQ,CAAC,mBAAmB,CAAA;AAAA,EAC5B,MAAA,EAAQ,CAAC,mBAAmB,CAAA;AAAA,EAC5B,MAAA,EAAQ,CAAC,UAAU,CAAA;AAAA,EACnB,MAAA,EAAQ,CAAC,UAAU,CAAA;AAAA,EACnB,MAAA,EAAQ,CAAC,oBAAoB,CAAA;AAAA,EAC7B,OAAA,EAAS,CAAC,yEAAyE,CAAA;AAAA,EACnF,MAAA,EAAQ,CAAC,+BAA+B,CAAA;AAAA,EACxC,OAAA,EAAS,CAAC,sBAAsB,CAAA;AAAA,EAChC,KAAA,EAAO,CAAC,kBAAA,EAAoB,oBAAoB,CAAA;AAAA,EAChD,MAAA,EAAQ,CAAC,WAAW,CAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,WAAW,CAAA;AAAA,EACpB,OAAA,EAAS,CAAC,WAAW,CAAA;AAAA,EACrB,MAAA,EAAQ,CAAC,0BAA0B,CAAA;AAAA,EACnC,MAAA,EAAQ,CAAC,eAAe,CAAA;AAAA,EACxB,MAAA,EAAQ,CAAC,0BAA0B,CAAA;AAAA,EACnC,OAAA,EAAS,CAAC,YAAY,CAAA;AAAA,EACtB,MAAA,EAAQ,CAAC,YAAY,CAAA;AAAA,EACrB,KAAA,EAAO,CAAC,iBAAiB,CAAA;AAAA,EACzB,MAAA,EAAQ,CAAC,iBAAiB,CAAA;AAAA,EAC1B,OAAA,EAAS,CAAC,kBAAkB,CAAA;AAAA,EAC5B,SAAA,EAAW,CAAC,qBAAqB,CAAA;AAAA,EACjC,KAAA,EAAO,CAAC,eAAe,CAAA;AAAA,EACvB,MAAA,EAAQ,CAAC,YAAA,EAAc,cAAc,CAAA;AAAA,EACrC,OAAA,EAAS,CAAC,YAAA,EAAc,cAAc,CAAA;AAAA,EACtC,MAAA,EAAQ,CAAC,YAAY,CAAA;AAAA,EACrB,MAAA,EAAQ,CAAC,WAAW,CAAA;AAAA,EACpB,OAAA,EAAS,CAAC,YAAY,CAAA;AAAA,EACtB,OAAA,EAAS,CAAC,qCAAqC,CAAA;AAAA,EAC/C,MAAA,EAAQ,CAAC,iDAAiD,CAAA;AAAA,EAC1D,MAAA,EAAQ,CAAC,gDAAgD,CAAA;AAAA,EACzD,MAAA,EAAQ,CAAC,yCAAyC,CAAA;AAAA,EAClD,MAAA,EAAQ,CAAC,WAAW,CAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,WAAW,CAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,iBAAiB,CAAA;AAAA,EAC1B,OAAA,EAAS,CAAC,WAAW,CAAA;AAAA,EACrB,MAAA,EAAQ,CAAC,UAAU,CAAA;AAAA,EACnB,MAAA,EAAQ,CAAC,WAAW,CAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,iBAAiB,CAAA;AAAA,EAC1B,MAAA,EAAQ,CAAC,yBAAyB,CAAA;AAAA,EAClC,MAAA,EAAQ,CAAC,+BAA+B,CAAA;AAAA,EACxC,OAAA,EAAS,CAAC,2EAA2E,CAAA;AAAA,EACrF,MAAA,EAAQ,CAAC,qBAAqB,CAAA;AAAA,EAC9B,MAAA,EAAQ,CAAC,iBAAiB,CAAA;AAAA,EAC1B,KAAA,EAAO,CAAC,kBAAkB,CAAA;AAAA,EAC1B,MAAA,EAAQ,CAAC,eAAe,CAAA;AAAA,EACxB,MAAA,EAAQ,CAAC,mBAAmB,CAAA;AAAA,EAC5B,MAAA,EAAQ,CAAC,YAAY,CAAA;AAAA,EACrB,OAAA,EAAS,CAAC,YAAY,CAAA;AAAA,EACtB,KAAA,EAAO,CAAC,YAAY,CAAA;AAAA,EACpB,MAAA,EAAQ,CAAC,UAAU,CAAA;AAAA,EACnB,MAAA,EAAQ,CAAC,YAAY,CAAA;AAAA,EACrB,MAAA,EAAQ,CAAC,uBAAuB,CAAA;AAAA,EAChC,MAAA,EAAQ,CAAC,WAAW,CAAA;AAAA,EACpB,OAAA,EAAS,CAAC,YAAY,CAAA;AAAA,EACtB,OAAA,EAAS,CAAC,YAAY,CAAA;AAAA,EACtB,cAAA,EAAgB,CAAC,2BAA2B,CAAA;AAAA,EAC5C,OAAA,EAAS,CAAC,YAAY,CAAA;AAAA,EACtB,OAAA,EAAS,CAAC,WAAW,CAAA;AAAA,EACrB,QAAA,EAAU,CAAC,YAAY,CAAA;AAAA,EACvB,QAAA,EAAU,CAAC,uBAAuB,CAAA;AAAA,EAClC,MAAA,EAAQ,CAAC,0BAA0B,CAAA;AAAA,EACnC,OAAA,EAAS,CAAC,mEAAmE,CAAA;AAAA,EAC7E,MAAA,EAAQ,CAAC,iBAAA,EAAmB,UAAA,EAAY,sBAAsB,CAAA;AAAA,EAC9D,MAAA,EAAQ,CAAC,iCAAiC,CAAA;AAAA,EAC1C,MAAA,EAAQ,CAAC,iBAAA,EAAmB,8BAA8B,CAAA;AAAA,EAC1D,MAAA,EAAQ,CAAC,YAAA,EAAc,YAAY,CAAA;AAAA,EACnC,MAAA,EAAQ,CAAC,aAAA,EAAe,aAAa,CAAA;AAAA,EACrC,KAAA,EAAO,CAAC,6BAA6B;AACvC;;;ACjFO,SAAS,MAAM,EAAA,EAAY;AAChC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACzD","file":"index.js","sourcesContent":["import type { PipelineContext } from \"./interfaces/context.interface\";\n\n/** Provenance tokens for trusted metadata (e.g. proposeTrusted). */\nexport type VerifiedSourceId = \"file:content\";\n\nexport interface PipelineContextWithVerified extends PipelineContext {\n _verifiedSources?: Set<VerifiedSourceId>;\n}\n\n/**\n * Mark that this pipeline run has read file bytes from storage (buffer or temp path).\n * Required before trusted plugins may call proposeTrusted with file/checksums/media patches.\n */\nexport function markFileContentVerified(context: PipelineContext): void {\n const c = context as PipelineContextWithVerified;\n c._verifiedSources ??= new Set();\n c._verifiedSources.add(\"file:content\");\n}\n","import { z } from \"zod\";\n\n/**\n * Zod Schema for Trusted Metadata.\n * Strictly enforced to prevent trust injection from the database.\n */\nexport const TrustedMetadataSchema = z\n .object({\n file: z\n .object({\n mimeType: z.string().optional(),\n size: z.number().int().nonnegative().optional(),\n originalName: z.string().optional(),\n extension: z.string().optional(),\n })\n .strict()\n .optional(),\n checksums: z\n .object({\n sha256: z.string().optional(),\n md5: z.string().optional(),\n })\n .strict()\n .optional(),\n media: z\n .object({\n width: z.number().int().nonnegative().optional(),\n height: z.number().int().nonnegative().optional(),\n duration: z.number().nonnegative().optional(),\n })\n .strict()\n .optional(),\n })\n .strict();\n\n/** Metadata from DB/Trusted Sources (Schema validated) */\nexport type TrustedMetadata = z.infer<typeof TrustedMetadataSchema>;\n","/** Lifecycle hook names (aligns with AWS/Cloudinary media pipeline stages). Single source of truth. */\nexport const HOOK_NAMES = [\n \"upload:init\",\n \"validation:run\",\n \"scan:run\",\n \"process:run\",\n \"upload:complete\",\n] as const;\n\nexport type HookName = (typeof HOOK_NAMES)[number];\n","import type { HookName } from \"./hook-name.interface\";\n\n/**\n * Hook-level execution mode constraint.\n * - sync-only: Handler always runs inline. Passing background is overridden with a warning.\n * - sync-or-background: Plugin may choose either; both are valid.\n * - background-only: Handler always runs enqueued. Passing sync is overridden with a warning.\n */\nexport type HookModeConstraint = \"sync-only\" | \"sync-or-background\" | \"background-only\";\n\n/** Per-hook mode constraints. Single source of truth for hook execution rules. */\nexport const HOOK_MODE_CONSTRAINTS: Record<HookName, HookModeConstraint> = {\n \"upload:init\": \"sync-only\",\n \"validation:run\": \"sync-only\",\n \"scan:run\": \"sync-only\",\n \"process:run\": \"sync-or-background\",\n \"upload:complete\": \"sync-or-background\",\n};\n\n/**\n * Resolve effective execution mode given hook constraint and requested mode.\n * Returns the mode to use and whether it was overridden (for logging).\n */\nexport function resolveHookMode(\n hookName: HookName,\n requested: \"sync\" | \"background\"\n): { effective: \"sync\" | \"background\"; overridden: boolean } {\n const constraint = HOOK_MODE_CONSTRAINTS[hookName];\n\n if (constraint === \"sync-only\" && requested === \"background\") {\n return { effective: \"sync\", overridden: true };\n }\n if (constraint === \"background-only\" && requested === \"sync\") {\n return { effective: \"background\", overridden: true };\n }\n\n return { effective: requested, overridden: false };\n}\n","import { z } from \"zod\";\nimport type { PipelineContext, PluginApi } from \"./context.interface\";\nimport type { HookName } from \"./hook-name.interface\";\n\n/**\n * Result from validation-phase handlers; can abort pipeline.\n * Persisted to 'validation_results' table.\n */\nexport const ValidationResultSchema = z\n .object({\n valid: z.boolean(),\n pluginId: z.string().optional(),\n message: z.string().optional(),\n errors: z.array(z.string()).optional(),\n })\n .strict();\n\nexport type ValidationResult = z.infer<typeof ValidationResultSchema>;\n\n/**\n * Result from virus-scan handlers.\n * Persisted to 'virus_scan_results' table.\n */\nexport const VirusScanResultSchema = z\n .object({\n status: z.enum([\"clean\", \"infected\", \"error\"]),\n threats: z.array(z.string()).optional(),\n scanner: z.string().optional(),\n scannedAt: z.string().datetime().optional(),\n })\n .strict();\n\nexport type VirusScanResult = z.infer<typeof VirusScanResultSchema>;\n\n/** Hook interface for plugin registration (Tapable-style) */\nexport interface MediaRuntimeHook {\n tap(\n name: string,\n fn: (ctx: PipelineContext, api: PluginApi) => Promise<void | ValidationResult>,\n options?: { mode?: \"sync\" | \"background\" }\n ): void;\n}\n\n/** Runtime host passed to plugins via apply(); exposes lifecycle hooks */\nexport interface MediaRuntime {\n readonly hooks: {\n [K in HookName]: MediaRuntimeHook;\n };\n}\n","import type { BmSchema } from \"./types\";\n\n/**\n * Central schema defining all Better Media tables and relationships.\n * This is the single source of truth for the database structure.\n */\nexport const schema: BmSchema = {\n // Core media records\n media: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n ownerId: { type: \"string\" },\n filename: { type: \"string\" },\n mimeType: { type: \"string\" },\n size: { type: \"number\" },\n storageProvider: { type: \"string\" },\n storageKey: { type: \"string\" },\n checksum: { type: \"string\" },\n width: { type: \"number\" },\n height: { type: \"number\" },\n duration: { type: \"number\" },\n context: { type: \"json\" },\n status: { type: \"string\" },\n visibility: { type: \"string\" },\n createdAt: { type: \"date\" },\n updatedAt: { type: \"date\" },\n deletedAt: { type: \"date\" },\n },\n indexes: [{ fields: [\"checksum\", \"storageKey\"] }],\n },\n\n // Different versions of the media (thumbnails, previews, etc.)\n media_versions: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: {\n model: \"media\",\n field: \"id\",\n onDelete: \"cascade\",\n },\n },\n storageKey: { type: \"string\" },\n checksum: { type: \"string\" },\n isOriginal: { type: \"boolean\" },\n type: { type: \"string\" }, // e.g., 'thumbnail', 'preview', 'compressed'\n versionNumber: { type: \"number\" },\n createdAt: { type: \"date\" },\n },\n indexes: [\n {\n fields: [\"mediaId\", \"versionNumber\"],\n unique: true,\n },\n ],\n },\n\n // Background job state for media processing\n media_jobs: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: {\n model: \"media\",\n field: \"id\",\n onDelete: \"cascade\",\n },\n },\n type: { type: \"string\" }, // e.g., 'virus-scan', 'thumbnail'\n status: { type: \"string\" }, // e.g., 'pending', 'running', 'completed', 'failed'\n attempts: { type: \"number\" },\n maxAttempts: { type: \"number\" },\n idempotencyKey: { type: \"string\", unique: true },\n scheduledAt: { type: \"date\" },\n startedAt: { type: \"date\" },\n completedAt: { type: \"date\" },\n error: { type: \"string\" },\n createdAt: { type: \"date\" },\n },\n },\n\n media_validation_results: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: { model: \"media\", field: \"id\", onDelete: \"cascade\" },\n },\n valid: { type: \"boolean\" },\n pluginId: { type: \"string\" },\n errors: { type: \"json\" },\n createdAt: { type: \"date\" },\n },\n },\n\n media_virus_scan_results: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: { model: \"media\", field: \"id\", onDelete: \"cascade\" },\n },\n status: { type: \"string\" }, // 'clean', 'infected', 'error'\n threats: { type: \"json\" }, // List of detected threats\n scanner: { type: \"string\" }, // clamd, etc.\n createdAt: { type: \"date\" },\n },\n },\n};\n","export function toSnakeCase(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/[\\s-]+/g, \"_\")\n .toLowerCase();\n}\n\nexport function toCamelCase(value: string): string {\n return value.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\nexport function toDbFieldName(field: string): string {\n return toSnakeCase(field);\n}\n","import type { FieldType } from \"./types\";\n\nexport interface FieldConverter {\n serialize(value: unknown): unknown;\n deserialize(value: unknown): unknown;\n}\n\nexport const converters: Record<FieldType, FieldConverter> = {\n json: {\n serialize: (value) => (value === undefined ? undefined : JSON.stringify(value)),\n deserialize: (value) => (typeof value === \"string\" ? JSON.parse(value) : value),\n },\n date: {\n serialize: (value) =>\n value instanceof Date ? value.toISOString() : typeof value === \"string\" ? value : value,\n deserialize: (value) => (typeof value === \"string\" ? new Date(value) : value),\n },\n boolean: {\n serialize: (value) => (typeof value === \"boolean\" ? (value ? 1 : 0) : value),\n deserialize: (value) => (typeof value === \"number\" ? value === 1 : Boolean(value)),\n },\n string: {\n serialize: (value) => value,\n deserialize: (value) => (typeof value === \"number\" ? String(value) : value),\n },\n number: {\n serialize: (value) => (typeof value === \"string\" ? Number(value) : value),\n deserialize: (value) => value,\n },\n};\n\nexport function serializeField(type: FieldType, value: unknown): unknown {\n if (value === null || value === undefined) return value;\n return converters[type]?.serialize(value) ?? value;\n}\n\nexport function deserializeField(type: FieldType, value: unknown): unknown {\n if (value === null || value === undefined) return value;\n return converters[type]?.deserialize(value) ?? value;\n}\n\nexport function serializeData(\n fields: Record<string, { type: FieldType }>,\n data: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (fields[key]) {\n result[key] = serializeField(fields[key].type, value);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\nexport function deserializeData(\n fields: Record<string, { type: FieldType }>,\n data: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (fields[key]) {\n result[key] = deserializeField(fields[key].type, value);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n","import type {\n BmSchema,\n FieldDefinition,\n FieldType,\n SqlDialect,\n TableMetadata,\n MigrationOperation,\n} from \"./types\";\n\nconst dialectMap: Record<FieldType, Record<SqlDialect, string>> = {\n string: {\n postgres: \"text\",\n mysql: \"varchar(255)\",\n sqlite: \"text\",\n mssql: \"varchar(255)\",\n },\n number: {\n postgres: \"integer\",\n mysql: \"integer\",\n sqlite: \"integer\",\n mssql: \"integer\",\n },\n boolean: {\n postgres: \"boolean\",\n mysql: \"boolean\",\n sqlite: \"integer\",\n mssql: \"bit\",\n },\n date: {\n postgres: \"timestamp\",\n mysql: \"datetime\",\n sqlite: \"text\",\n mssql: \"datetime2\",\n },\n json: {\n postgres: \"jsonb\",\n mysql: \"json\",\n sqlite: \"text\",\n mssql: \"nvarchar(max)\",\n },\n};\n\nexport function getColumnType(field: FieldDefinition, dialect: SqlDialect): string {\n // Overrides for specific cases\n if (field.primaryKey && field.type === \"string\") {\n if (dialect === \"postgres\") return \"uuid\";\n return dialect === \"mysql\" || dialect === \"mssql\" ? \"varchar(36)\" : \"text\";\n }\n if (field.references && field.type === \"string\" && dialect === \"postgres\") {\n return \"uuid\";\n }\n\n const types = dialectMap[field.type];\n if (!types) return \"text\";\n\n const type = types[dialect];\n return type || \"text\";\n}\n\nexport function matchType(dbType: string, expectedType: FieldType, dialect: SqlDialect): boolean {\n const normalizedDb = (dbType.toLowerCase().split(\"(\")[0] || \"\").trim();\n const normalizedMap: Record<SqlDialect, Record<FieldType, string[]>> = {\n postgres: {\n string: [\"character varying\", \"varchar\", \"text\", \"uuid\"],\n number: [\"int4\", \"integer\", \"bigint\", \"smallint\", \"numeric\", \"real\", \"double precision\"],\n boolean: [\"bool\", \"boolean\"],\n date: [\"timestamptz\", \"timestamp\", \"date\"],\n json: [\"json\", \"jsonb\"],\n },\n mysql: {\n string: [\"varchar\", \"text\", \"uuid\", \"char\"],\n number: [\"integer\", \"int\", \"bigint\", \"smallint\", \"decimal\", \"float\", \"double\"],\n boolean: [\"boolean\", \"tinyint\", \"bit\"],\n date: [\"timestamp\", \"datetime\", \"date\"],\n json: [\"json\", \"text\", \"longtext\"],\n },\n sqlite: {\n string: [\"text\", \"varchar\"],\n number: [\"integer\", \"real\", \"numeric\"],\n boolean: [\"integer\", \"boolean\"],\n date: [\"date\", \"text\", \"integer\"],\n json: [\"text\"],\n },\n mssql: {\n string: [\"varchar\", \"nvarchar\", \"uniqueidentifier\"],\n number: [\"int\", \"bigint\", \"smallint\", \"decimal\", \"float\", \"double\", \"numeric\"],\n boolean: [\"bit\", \"smallint\"],\n date: [\"datetime2\", \"date\", \"datetime\", \"timestamp\"],\n json: [\"varchar\", \"nvarchar\"],\n },\n };\n\n return normalizedMap[dialect][expectedType].includes(normalizedDb);\n}\n\n/**\n * MigrationPlanner calculates the delta between the desired schema and the actual DB state.\n */\nexport class MigrationPlanner {\n constructor(private readonly dialect: SqlDialect) {}\n\n plan(schema: BmSchema, currentTables: TableMetadata[]): MigrationOperation[] {\n const operations: MigrationOperation[] = [];\n\n for (const [tableName, model] of Object.entries(schema)) {\n const existingTable = currentTables.find((t) => t.name === tableName);\n\n if (!existingTable) {\n // Table doesn't exist\n operations.push({ type: \"createTable\", table: tableName, definition: model });\n continue;\n }\n\n // Table exists, check for missing columns\n for (const [fieldName, fieldDef] of Object.entries(model.fields)) {\n const existingColumn = existingTable.columns.find((c) => c.name === fieldName);\n\n if (!existingColumn) {\n operations.push({\n type: \"addColumn\",\n table: tableName,\n field: fieldName,\n definition: fieldDef,\n });\n } else {\n // Optional: Check for type mismatches (logging only for now to avoid destructive changes)\n if (!matchType(existingColumn.dataType, fieldDef.type, this.dialect)) {\n console.warn(\n `[BetterMedia] Type mismatch for ${tableName}.${fieldName}: ` +\n `Expected ${fieldDef.type} but found ${existingColumn.dataType} in DB.`\n );\n }\n }\n }\n\n // Missing indexes: not yet diffed against DB metadata (createIndex ops TBD).\n }\n\n return operations;\n }\n}\n\n/**\n * Applies a list of migration operations to an existing metadata state to project\n * what the database will look like after the migration.\n */\nexport function applyOperationsToMetadata(\n currentMetadata: TableMetadata[],\n operations: MigrationOperation[],\n dialect: SqlDialect\n): TableMetadata[] {\n const metadata = JSON.parse(JSON.stringify(currentMetadata)) as TableMetadata[];\n\n for (const op of operations) {\n if (op.type === \"createTable\") {\n const columns = Object.entries(op.definition.fields).map(([name, field]) => ({\n name,\n dataType: getColumnType(field, dialect),\n isNullable: !field.required && !field.primaryKey,\n isUnique: field.unique || field.primaryKey,\n }));\n metadata.push({ name: op.table, columns });\n } else if (op.type === \"addColumn\") {\n const table = metadata.find((t) => t.name === op.table);\n if (table) {\n table.columns.push({\n name: op.field,\n dataType: getColumnType(op.definition, dialect),\n isNullable: !op.definition.required,\n isUnique: !!op.definition.unique,\n });\n }\n }\n // Handle other operation types (like createIndex) if metadata starts tracking them\n }\n\n return metadata;\n}\n","import type {\n BmSchema,\n FieldDefinition,\n ModelDefinition,\n SqlDialect,\n MigrationOperation,\n} from \"./types\";\nimport { getColumnType } from \"./plan\";\nimport { toDbFieldName } from \"./naming\";\n\nfunction quoteIdent(ident: string, dialect: SqlDialect): string {\n // Keep it simple and safe; Better Media table/field names are controlled.\n if (dialect === \"mysql\") return `\\`${ident}\\``;\n return `\"${ident}\"`;\n}\n\nfunction onDeleteSql(\n onDelete?: FieldDefinition[\"references\"] extends infer R\n ? R extends { onDelete?: infer D }\n ? D | string\n : string\n : string\n): string {\n if (!onDelete) return \"\";\n const normalized = String(onDelete).toUpperCase();\n if (normalized === \"CASCADE\") return \" ON DELETE CASCADE\";\n if (normalized === \"SET NULL\") return \" ON DELETE SET NULL\";\n if (normalized === \"RESTRICT\") return \" ON DELETE RESTRICT\";\n return \"\";\n}\n\nfunction columnSql(\n table: string,\n name: string,\n field: FieldDefinition,\n dialect: SqlDialect\n): string {\n const parts: string[] = [];\n const dbName = toDbFieldName(name);\n parts.push(quoteIdent(dbName, dialect));\n parts.push(getColumnType(field, dialect));\n\n if (field.primaryKey) parts.push(\"PRIMARY KEY\");\n if (field.required) parts.push(\"NOT NULL\");\n if (field.unique) parts.push(\"UNIQUE\");\n\n if (field.references) {\n const ref = field.references;\n const refTable = quoteIdent(ref.model, dialect);\n const refField = quoteIdent(toDbFieldName(ref.field), dialect);\n parts.push(`REFERENCES ${refTable}(${refField})${onDeleteSql(ref.onDelete)}`);\n }\n\n return parts.join(\" \");\n}\n\nfunction createTableSql(table: string, definition: ModelDefinition, dialect: SqlDialect): string {\n const tableName = quoteIdent(table, dialect);\n const cols = Object.entries(definition.fields).map(([name, field]) =>\n columnSql(table, name, field, dialect)\n );\n const ifNotExists = dialect === \"mssql\" ? \"\" : \" IF NOT EXISTS\";\n return `CREATE TABLE${ifNotExists} ${tableName} (\\n ${cols.join(\",\\n \")}\\n);`;\n}\n\nfunction createIndexSql(\n table: string,\n indexName: string,\n fields: string[],\n unique: boolean | undefined,\n dialect: SqlDialect\n): string {\n const idx = quoteIdent(indexName, dialect);\n const tbl = quoteIdent(table, dialect);\n const cols = fields.map((f) => quoteIdent(toDbFieldName(f), dialect)).join(\", \");\n const uniqueSql = unique ? \"UNIQUE \" : \"\";\n const ifNotExists = dialect === \"mssql\" ? \"\" : \" IF NOT EXISTS\";\n return `CREATE ${uniqueSql}INDEX${ifNotExists} ${idx} ON ${tbl} (${cols});`;\n}\n\nfunction addColumnSql(\n table: string,\n field: string,\n definition: FieldDefinition,\n dialect: SqlDialect\n): string {\n const tableName = quoteIdent(table, dialect);\n const columnDef = columnSql(table, field, definition, dialect);\n return `ALTER TABLE ${tableName} ADD COLUMN ${columnDef};`;\n}\n\nexport function compileMigrationOperationsSql(options: {\n operations: MigrationOperation[];\n dialect: SqlDialect;\n}): string {\n const { operations, dialect } = options;\n const statements: string[] = [];\n statements.push(`-- Better Media planned migrations (${dialect})`);\n\n if (dialect === \"sqlite\") {\n statements.push(\"PRAGMA foreign_keys = ON;\");\n }\n\n for (const op of operations) {\n if (op.type === \"createTable\") {\n statements.push(createTableSql(op.table, op.definition, dialect));\n if (op.definition.indexes) {\n for (const index of op.definition.indexes) {\n const indexName = `idx_${op.table}_${index.fields.map((f) => toDbFieldName(f)).join(\"_\")}`;\n statements.push(createIndexSql(op.table, indexName, index.fields, index.unique, dialect));\n }\n }\n continue;\n }\n if (op.type === \"addColumn\") {\n statements.push(addColumnSql(op.table, op.field, op.definition, dialect));\n continue;\n }\n if (op.type === \"createIndex\") {\n statements.push(createIndexSql(op.table, op.name, op.fields, op.unique, dialect));\n }\n }\n\n return statements.join(\"\\n\\n\") + \"\\n\";\n}\n\nexport function generateCreateSchemaSql(options: {\n schema: BmSchema;\n dialect: SqlDialect;\n}): string {\n const { schema, dialect } = options;\n\n const statements: string[] = [];\n statements.push(`-- Better Media schema (${dialect})`);\n\n // SQLite requires foreign keys enabled explicitly per-connection; harmless elsewhere.\n if (dialect === \"sqlite\") {\n statements.push(\"PRAGMA foreign_keys = ON;\");\n }\n\n // Create tables first (FKs reference earlier tables in this schema, but SQL engines allow forward refs too).\n for (const [table, def] of Object.entries(schema)) {\n statements.push(createTableSql(table, def, dialect));\n }\n\n // Create indexes after.\n for (const [table, def] of Object.entries(schema)) {\n if (!def.indexes) continue;\n for (const index of def.indexes) {\n const indexName = `idx_${table}_${index.fields.map((f) => toDbFieldName(f)).join(\"_\")}`;\n statements.push(createIndexSql(table, indexName, index.fields, index.unique, dialect));\n }\n }\n\n return statements.join(\"\\n\\n\") + \"\\n\";\n}\n","import type { DatabaseAdapter } from \"./interfaces/adapter.interface\";\nimport { schema } from \"./schema\";\nimport type { ModelDefinition, TableMetadata, MigrationOperation, SqlDialect } from \"./types\";\nimport { MigrationPlanner } from \"./plan\";\nimport { compileMigrationOperationsSql } from \"./sql\";\n\n/**\n * Internal interface used only by runMigrations. Adapter authors do NOT need to\n * declare or implement this — the migration engine discovers these methods via\n * duck-typing at runtime. Prefix `__` signals framework-internal use.\n */\ninterface MigratableAdapter extends DatabaseAdapter {\n __getMetadata?(): Promise<TableMetadata[]>;\n __executeMigration?(operation: MigrationOperation): Promise<void>;\n __getDialect?(): SqlDialect;\n // Legacy fallback paths\n __createTable?(\n model: string,\n definition: ModelDefinition,\n options: { mode: \"safe\" | \"diff\" | \"force\" }\n ): Promise<void>;\n __initCollection?(\n model: string,\n definition: ModelDefinition,\n options: { mode: \"safe\" | \"diff\" | \"force\" }\n ): Promise<void>;\n}\n\nexport interface MigrationOptions {\n /**\n * Migration mode:\n * - 'safe': Only create missing tables/collections and add missing columns/indexes.\n * - 'diff': Full schema comparison and incremental updates (Recommended).\n * - 'force': Drop and recreate all tables/collections (destructive).\n */\n mode?: \"safe\" | \"diff\" | \"force\";\n /**\n * For SQL adapters, the dialect can be manually specified.\n * If omitted, the adapter will try to detect it.\n */\n dialect?: SqlDialect;\n}\n\nexport interface PlannedMigrationTable {\n table: string;\n fields: string[];\n}\n\nexport interface PlannedMigrations {\n toBeCreated: PlannedMigrationTable[];\n toBeAdded: PlannedMigrationTable[];\n operations: MigrationOperation[];\n compileMigrations: () => string;\n runMigrations: () => Promise<void>;\n}\n\nexport async function getMigrations(\n adapter: DatabaseAdapter,\n options: MigrationOptions = {}\n): Promise<PlannedMigrations> {\n const migratable = adapter as MigratableAdapter;\n\n if (\n typeof migratable.__getMetadata !== \"function\" ||\n typeof migratable.__executeMigration !== \"function\"\n ) {\n return {\n toBeCreated: [],\n toBeAdded: [],\n operations: [],\n compileMigrations: () => \"\",\n runMigrations: async () => {\n throw new Error(\"[BetterMedia] Adapter does not support planned migrations.\");\n },\n };\n }\n\n let dialect = options.dialect;\n if (!dialect && typeof migratable.__getDialect === \"function\") {\n dialect = migratable.__getDialect();\n }\n const resolvedDialect = dialect || \"postgres\";\n const metadata = await migratable.__getMetadata();\n const planner = new MigrationPlanner(resolvedDialect);\n const operations = planner.plan(schema, metadata);\n\n const toBeCreated = operations\n .filter(\n (op): op is Extract<MigrationOperation, { type: \"createTable\" }> => op.type === \"createTable\"\n )\n .map((op) => ({ table: op.table, fields: Object.keys(op.definition.fields) }));\n\n const toBeAdded = operations\n .filter(\n (op): op is Extract<MigrationOperation, { type: \"addColumn\" }> => op.type === \"addColumn\"\n )\n .reduce<PlannedMigrationTable[]>((acc, op) => {\n const existing = acc.find((t) => t.table === op.table);\n if (existing) existing.fields.push(op.field);\n else acc.push({ table: op.table, fields: [op.field] });\n return acc;\n }, []);\n\n return {\n toBeCreated,\n toBeAdded,\n operations,\n compileMigrations: () =>\n compileMigrationOperationsSql({ operations, dialect: resolvedDialect }),\n runMigrations: async () => {\n for (const op of operations) {\n await migratable.__executeMigration!(op);\n }\n },\n };\n}\n\n/**\n * Migration engine. It iterates through the central BmSchema and invokes\n * engine-specific setup commands on the adapter.\n */\nexport async function runMigrations(\n adapter: DatabaseAdapter,\n options: MigrationOptions = {}\n): Promise<void> {\n const mode = options.mode ?? \"safe\";\n const migratable = adapter as MigratableAdapter;\n\n // Preferred path: adapter exposes __getMetadata + __executeMigration\n if (\n typeof migratable.__getMetadata === \"function\" &&\n typeof migratable.__executeMigration === \"function\"\n ) {\n console.log(\"[BetterMedia] Starting planned migration...\");\n\n const { operations, runMigrations: runPlannedMigrations } = await getMigrations(\n adapter,\n options\n );\n\n if (operations.length === 0) {\n console.log(\"[BetterMedia] Database is up to date.\");\n return;\n }\n\n console.log(`[BetterMedia] Plan: ${operations.length} operation(s) to execute.`);\n await runPlannedMigrations();\n console.log(\"[BetterMedia] Migration completed successfully.\");\n return;\n }\n\n // Legacy fallback for MongoDB or unrefactored adapters\n if (typeof migratable.__createTable === \"function\") {\n // Kysely / SQL adapter (Legacy)\n for (const [model, definition] of Object.entries(schema)) {\n await migratable.__createTable(model, definition, { mode });\n }\n } else if (typeof migratable.__initCollection === \"function\") {\n // MongoDB adapter\n for (const [model, definition] of Object.entries(schema)) {\n await migratable.__initCollection(model, definition, { mode });\n }\n } else {\n console.warn(\"[BetterMedia] Adapter does not support automatic migrations.\");\n }\n}\n","import type { WhereClause, DbHooks, DatabaseHookContext } from \"./types\";\n\n/**\n * Utility to run hooks sequentially.\n * Supports multiple handlers and passes DatabaseHookContext.\n */\nexport const runHooks = {\n async beforeCreate(\n hooks: DbHooks | undefined,\n data: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n let currentData = data;\n const handlers = hooks?.before?.create || [];\n for (const handler of handlers) {\n currentData = await handler(currentData, context);\n }\n return currentData;\n },\n\n async beforeUpdate(\n hooks: DbHooks | undefined,\n data: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n let currentData = data;\n const handlers = hooks?.before?.update || [];\n for (const handler of handlers) {\n currentData = await handler(currentData, context);\n }\n return currentData;\n },\n\n async beforeDelete(hooks: DbHooks | undefined, where: WhereClause, context: DatabaseHookContext) {\n const handlers = hooks?.before?.delete || [];\n for (const handler of handlers) {\n await handler(where, context);\n }\n },\n\n async afterCreate(\n hooks: DbHooks | undefined,\n result: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n const handlers = hooks?.after?.create || [];\n for (const handler of handlers) {\n await handler(result, context);\n }\n },\n\n async afterUpdate(\n hooks: DbHooks | undefined,\n result: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n const handlers = hooks?.after?.update || [];\n for (const handler of handlers) {\n await handler(result, context);\n }\n },\n\n async afterDelete(hooks: DbHooks | undefined, where: WhereClause, context: DatabaseHookContext) {\n const handlers = hooks?.after?.delete || [];\n for (const handler of handlers) {\n await handler(where, context);\n }\n },\n};\n","import type { DatabaseAdapter } from \"./interfaces/adapter.interface\";\n\nexport type QueryResultLike<T = unknown> = { rows: T[]; rowCount?: number | null };\n\nexport type Queryable = {\n query: (text: string, values?: unknown[]) => Promise<QueryResultLike<Record<string, unknown>>>;\n};\n\nexport type PgPoolLike = Queryable & {\n connect?: () => Promise<PgClientLike>;\n};\n\nexport type PgClientLike = Queryable & {\n release?: () => void;\n};\n\nexport function isPgPoolLike(value: unknown): value is PgPoolLike {\n return Boolean(\n value && typeof value === \"object\" && typeof (value as { query?: unknown }).query === \"function\"\n );\n}\n\n/**\n * Normalizes a database pool or adapter into a standard DatabaseAdapter.\n * Note: If using the built-in Postgres pool, this requires the actual\n * implementation to be registered or known.\n */\nexport function toDatabaseAdapter(\n database: DatabaseAdapter | PgPoolLike,\n postgresFactory?: (pool: PgPoolLike) => DatabaseAdapter\n): DatabaseAdapter {\n if (isPgPoolLike(database) && typeof (database as { create?: unknown }).create !== \"function\") {\n if (postgresFactory) return postgresFactory(database);\n throw new Error(\n \"[BetterMedia] Postgres pool detected but no adapter factory provided. \" +\n \"This typically means you should use the main @better-media/framework package.\"\n );\n }\n return database as DatabaseAdapter;\n}\n","import type { DatabaseAdapter } from \"../database/interfaces/adapter.interface\";\nimport { toDatabaseAdapter, type PgPoolLike } from \"../database/postgres-utils\";\n\nexport type GetAdapterOptions = {\n database?: DatabaseAdapter | PgPoolLike;\n createDatabase?: () => Promise<DatabaseAdapter | PgPoolLike> | DatabaseAdapter | PgPoolLike;\n dialect?: string;\n schemaOutput?: string;\n migrationsDir?: string;\n};\n\nexport async function getAdapter(options: GetAdapterOptions): Promise<DatabaseAdapter> {\n const database = options.database ?? (await options.createDatabase?.());\n const adapter = database ? toDatabaseAdapter(database) : undefined;\n if (!adapter) {\n throw new Error(\n `[media] Failed to initialize database adapter. Provide \"database\" or \"createDatabase()\".`\n );\n }\n return adapter;\n}\n","/**\n * Mapping of common file extensions to their valid MIME types.\n * Based on MDN Common Media Types: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types\n */\nexport const EXTENSION_TO_MIME_MAP: Record<string, string[]> = {\n \".aac\": [\"audio/aac\"],\n \".abw\": [\"application/x-abiword\"],\n \".apng\": [\"image/apng\"],\n \".arc\": [\"application/x-freearc\"],\n \".avif\": [\"image/avif\"],\n \".avi\": [\"video/x-msvideo\"],\n \".azw\": [\"application/vnd.amazon.ebook\"],\n \".bin\": [\"application/octet-stream\"],\n \".bmp\": [\"image/bmp\"],\n \".bz\": [\"application/x-bzip\"],\n \".bz2\": [\"application/x-bzip2\"],\n \".cda\": [\"application/x-cdf\"],\n \".csh\": [\"application/x-csh\"],\n \".css\": [\"text/css\"],\n \".csv\": [\"text/csv\"],\n \".doc\": [\"application/msword\"],\n \".docx\": [\"application/vnd.openxmlformats-officedocument.wordprocessingml.document\"],\n \".eot\": [\"application/vnd.ms-fontobject\"],\n \".epub\": [\"application/epub+zip\"],\n \".gz\": [\"application/gzip\", \"application/x-gzip\"],\n \".gif\": [\"image/gif\"],\n \".htm\": [\"text/html\"],\n \".html\": [\"text/html\"],\n \".ico\": [\"image/vnd.microsoft.icon\"],\n \".ics\": [\"text/calendar\"],\n \".jar\": [\"application/java-archive\"],\n \".jpeg\": [\"image/jpeg\"],\n \".jpg\": [\"image/jpeg\"],\n \".js\": [\"text/javascript\"],\n \".mjs\": [\"text/javascript\"],\n \".json\": [\"application/json\"],\n \".jsonld\": [\"application/ld+json\"],\n \".md\": [\"text/markdown\"],\n \".mid\": [\"audio/midi\", \"audio/x-midi\"],\n \".midi\": [\"audio/midi\", \"audio/x-midi\"],\n \".mp3\": [\"audio/mpeg\"],\n \".mp4\": [\"video/mp4\"],\n \".mpeg\": [\"video/mpeg\"],\n \".mpkg\": [\"application/vnd.apple.installer+xml\"],\n \".odp\": [\"application/vnd.oasis.opendocument.presentation\"],\n \".ods\": [\"application/vnd.oasis.opendocument.spreadsheet\"],\n \".odt\": [\"application/vnd.oasis.opendocument.text\"],\n \".oga\": [\"audio/ogg\"],\n \".ogv\": [\"video/ogg\"],\n \".ogx\": [\"application/ogg\"],\n \".opus\": [\"audio/ogg\"],\n \".otf\": [\"font/otf\"],\n \".png\": [\"image/png\"],\n \".pdf\": [\"application/pdf\"],\n \".php\": [\"application/x-httpd-php\"],\n \".ppt\": [\"application/vnd.ms-powerpoint\"],\n \".pptx\": [\"application/vnd.openxmlformats-officedocument.presentationml.presentation\"],\n \".rar\": [\"application/vnd.rar\"],\n \".rtf\": [\"application/rtf\"],\n \".sh\": [\"application/x-sh\"],\n \".svg\": [\"image/svg+xml\"],\n \".tar\": [\"application/x-tar\"],\n \".tif\": [\"image/tiff\"],\n \".tiff\": [\"image/tiff\"],\n \".ts\": [\"video/mp2t\"],\n \".ttf\": [\"font/ttf\"],\n \".txt\": [\"text/plain\"],\n \".vsd\": [\"application/vnd.visio\"],\n \".wav\": [\"audio/wav\"],\n \".weba\": [\"audio/webm\"],\n \".webm\": [\"video/webm\"],\n \".webmanifest\": [\"application/manifest+json\"],\n \".webp\": [\"image/webp\"],\n \".woff\": [\"font/woff\"],\n \".woff2\": [\"font/woff2\"],\n \".xhtml\": [\"application/xhtml+xml\"],\n \".xls\": [\"application/vnd.ms-excel\"],\n \".xlsx\": [\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\"],\n \".xml\": [\"application/xml\", \"text/xml\", \"application/atom+xml\"],\n \".xul\": [\"application/vnd.mozilla.xul+xml\"],\n \".zip\": [\"application/zip\", \"application/x-zip-compressed\"],\n \".3gp\": [\"video/3gpp\", \"audio/3gpp\"],\n \".3g2\": [\"video/3gpp2\", \"audio/3gpp2\"],\n \".7z\": [\"application/x-7z-compressed\"],\n};\n","// Core types and utilities\nexport type MediaStatus = \"PENDING_VERIFICATION\" | \"VALID\" | \"INVALID\" | \"PROCESSING\" | \"COMPLETED\";\n\nexport function sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport { HOOK_NAMES, HOOK_MODE_CONSTRAINTS, resolveHookMode } from \"./plugin/index\";\nexport type {\n PipelinePlugin,\n PipelineContext,\n FileInfo,\n FileContent,\n StorageLocation,\n ProcessingResults,\n ThumbnailResult,\n VariantResult,\n MediaDimensions,\n PluginExecutionMode,\n PluginHooks,\n HookName,\n HookHandler,\n HookHandlerOptions,\n HookModeConstraint,\n MediaPlugin,\n HookContext,\n MediaRuntime,\n MediaRuntimeHook,\n ValidationResult,\n TrustedMetadata,\n PluginManifest,\n PluginApi,\n} from \"./plugin/index\";\nexport {\n ValidationResultSchema,\n VirusScanResultSchema,\n TrustedMetadataSchema,\n markFileContentVerified,\n} from \"./plugin/index\";\nexport type { VerifiedSourceId, PipelineContextWithVerified } from \"./plugin/index\";\nexport type {\n StorageAdapter,\n GetUrlOptions,\n PresignedUploadMethod,\n PresignedUploadOptions,\n PresignedUploadResult,\n StorageObject,\n ListResult,\n ListOptions,\n} from \"./storage/index\";\nexport type {\n DatabaseAdapter,\n DatabaseTransactionAdapter,\n WhereClause,\n CreateOptions,\n FindOptions,\n UpdateOptions,\n DeleteOptions,\n CountOptions,\n} from \"./database/index\";\nexport type { JobAdapter } from \"./job/index\";\nexport * from \"./database/index\";\nexport type { DatabaseHookContext } from \"./database/index\";\nexport { getAdapter, type GetAdapterOptions } from \"./adapter/get-adapter\";\nexport { EXTENSION_TO_MIME_MAP } from \"./constants/mime-types\";\n"]}
1
+ {"version":3,"sources":["../src/plugin/verified-sources.ts","../src/plugin/interfaces/trusted-metadata.interface.ts","../src/plugin/interfaces/hook-name.interface.ts","../src/plugin/interfaces/hook-mode.interface.ts","../src/plugin/interfaces/media-runtime.interface.ts","../src/database/schema.ts","../src/database/naming.ts","../src/database/fields.ts","../src/database/plan.ts","../src/database/sql.ts","../src/database/migration.ts","../src/database/hooks.ts","../src/database/postgres-utils.ts","../src/adapter/get-adapter.ts","../src/constants/mime-types.ts","../src/index.ts"],"names":["z","schema"],"mappings":"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","file":"index.js","sourcesContent":["import type { PipelineContext } from \"./interfaces/context.interface\";\n\n/** Provenance tokens for trusted metadata (e.g. proposeTrusted). */\nexport type VerifiedSourceId = \"file:content\";\n\nexport interface PipelineContextWithVerified extends PipelineContext {\n _verifiedSources?: Set<VerifiedSourceId>;\n}\n\n/**\n * Mark that this pipeline run has read file bytes from storage (buffer or temp path).\n * Required before trusted plugins may call proposeTrusted with file/checksums/media patches.\n */\nexport function markFileContentVerified(context: PipelineContext): void {\n const c = context as PipelineContextWithVerified;\n c._verifiedSources ??= new Set();\n c._verifiedSources.add(\"file:content\");\n}\n","import { z } from \"zod\";\n\n/**\n * Zod Schema for Trusted Metadata.\n * Strictly enforced to prevent trust injection from the database.\n */\nexport const TrustedMetadataSchema = z\n .object({\n file: z\n .object({\n mimeType: z.string().optional(),\n size: z.number().int().nonnegative().optional(),\n originalName: z.string().optional(),\n extension: z.string().optional(),\n })\n .strict()\n .optional(),\n checksums: z\n .object({\n sha256: z.string().optional(),\n md5: z.string().optional(),\n })\n .strict()\n .optional(),\n media: z\n .object({\n width: z.number().int().nonnegative().optional(),\n height: z.number().int().nonnegative().optional(),\n duration: z.number().nonnegative().optional(),\n })\n .strict()\n .optional(),\n })\n .strict();\n\n/** Metadata from DB/Trusted Sources (Schema validated) */\nexport type TrustedMetadata = z.infer<typeof TrustedMetadataSchema>;\n","/** Lifecycle hook names (aligns with AWS/Cloudinary media pipeline stages). Single source of truth. */\nexport const HOOK_NAMES = [\n \"upload:init\",\n \"validation:run\",\n \"scan:run\",\n \"process:run\",\n \"upload:complete\",\n] as const;\n\nexport type HookName = (typeof HOOK_NAMES)[number];\n","import type { HookName } from \"./hook-name.interface\";\n\n/**\n * Hook-level execution mode constraint.\n * - sync-only: Handler always runs inline. Passing background is overridden with a warning.\n * - sync-or-background: Plugin may choose either; both are valid.\n * - background-only: Handler always runs enqueued. Passing sync is overridden with a warning.\n */\nexport type HookModeConstraint = \"sync-only\" | \"sync-or-background\" | \"background-only\";\n\n/** Per-hook mode constraints. Single source of truth for hook execution rules. */\nexport const HOOK_MODE_CONSTRAINTS: Record<HookName, HookModeConstraint> = {\n \"upload:init\": \"sync-only\",\n \"validation:run\": \"sync-only\",\n \"scan:run\": \"sync-only\",\n \"process:run\": \"sync-or-background\",\n \"upload:complete\": \"sync-or-background\",\n};\n\n/**\n * Resolve effective execution mode given hook constraint and requested mode.\n * Returns the mode to use and whether it was overridden (for logging).\n */\nexport function resolveHookMode(\n hookName: HookName,\n requested: \"sync\" | \"background\"\n): { effective: \"sync\" | \"background\"; overridden: boolean } {\n const constraint = HOOK_MODE_CONSTRAINTS[hookName];\n\n if (constraint === \"sync-only\" && requested === \"background\") {\n return { effective: \"sync\", overridden: true };\n }\n if (constraint === \"background-only\" && requested === \"sync\") {\n return { effective: \"background\", overridden: true };\n }\n\n return { effective: requested, overridden: false };\n}\n","import { z } from \"zod\";\nimport type { PipelineContext, PluginApi } from \"./context.interface\";\nimport type { HookName } from \"./hook-name.interface\";\n\n/**\n * Result from validation-phase handlers; can abort pipeline.\n * Persisted to 'validation_results' table.\n */\nexport const ValidationResultSchema = z\n .object({\n valid: z.boolean(),\n pluginId: z.string().optional(),\n message: z.string().optional(),\n errors: z.array(z.string()).optional(),\n })\n .strict();\n\nexport type ValidationResult = z.infer<typeof ValidationResultSchema>;\n\n/**\n * Result from virus-scan handlers.\n * Persisted to 'virus_scan_results' table.\n */\nexport const VirusScanResultSchema = z\n .object({\n status: z.enum([\"clean\", \"infected\", \"error\"]),\n threats: z.array(z.string()).optional(),\n scanner: z.string().optional(),\n scannedAt: z.string().datetime().optional(),\n })\n .strict();\n\nexport type VirusScanResult = z.infer<typeof VirusScanResultSchema>;\n\n/** Hook interface for plugin registration (Tapable-style) */\nexport interface MediaRuntimeHook {\n tap(\n name: string,\n fn: (ctx: PipelineContext, api: PluginApi) => Promise<void | ValidationResult>,\n options?: { mode?: \"sync\" | \"background\" }\n ): void;\n}\n\n/** Runtime host passed to plugins via apply(); exposes lifecycle hooks */\nexport interface MediaRuntime {\n readonly hooks: {\n [K in HookName]: MediaRuntimeHook;\n };\n}\n","import type { BmSchema } from \"./types\";\n\n/**\n * Central schema defining all Better Media tables and relationships.\n * This is the single source of truth for the database structure.\n */\nexport const schema: BmSchema = {\n // Core media records\n media: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n ownerId: { type: \"string\" },\n filename: { type: \"string\" },\n extension: { type: \"string\" },\n mimeType: { type: \"string\" },\n size: { type: \"number\" },\n storageProvider: { type: \"string\" },\n storageKey: { type: \"string\" },\n checksumSha256: { type: \"string\" },\n checksumMd5: { type: \"string\" },\n width: { type: \"number\" },\n height: { type: \"number\" },\n duration: { type: \"number\" },\n metadata: { type: \"json\" },\n status: { type: \"string\" }, // 'pending' | 'processing' | 'ready' | 'failed' | 'quarantined'\n visibility: { type: \"string\" }, // 'public' | 'private' | 'unlisted'\n createdAt: { type: \"date\" },\n updatedAt: { type: \"date\" },\n deletedAt: { type: \"date\" },\n },\n indexes: [{ fields: [\"checksumSha256\", \"storageKey\"] }],\n },\n\n // Different versions of the media (thumbnails, previews, etc.)\n media_versions: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: {\n model: \"media\",\n field: \"id\",\n onDelete: \"cascade\",\n },\n },\n storageProvider: { type: \"string\" },\n storageKey: { type: \"string\" },\n checksumSha256: { type: \"string\" },\n mimeType: { type: \"string\" },\n size: { type: \"number\" },\n width: { type: \"number\" },\n height: { type: \"number\" },\n isOriginal: { type: \"boolean\" },\n type: { type: \"string\" }, // 'thumbnail' | 'preview' | 'compressed' | 'original'\n versionNumber: { type: \"number\" },\n createdAt: { type: \"date\" },\n deletedAt: { type: \"date\" },\n },\n indexes: [{ fields: [\"mediaId\"] }, { fields: [\"mediaId\", \"versionNumber\"], unique: true }],\n },\n\n // Business record for media processing jobs — not a BullMQ state mirror.\n // Tracks idempotency, final outcome, and links jobs to media.\n // Runtime state (queue position, locks, backoff) lives in BullMQ/Redis.\n media_jobs: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: {\n model: \"media\",\n field: \"id\",\n onDelete: \"cascade\",\n },\n },\n type: { type: \"string\" }, // 'virus-scan' | 'thumbnail' | 'compress' | 'validate'\n status: { type: \"string\" }, // 'pending' | 'running' | 'completed' | 'failed'\n attempts: { type: \"number\" },\n maxAttempts: { type: \"number\" },\n idempotencyKey: { type: \"string\", unique: true },\n scheduledAt: { type: \"date\" },\n startedAt: { type: \"date\" },\n completedAt: { type: \"date\" },\n error: { type: \"json\" }, // { message, code, stack, retryable }\n result: { type: \"json\" },\n createdAt: { type: \"date\" },\n updatedAt: { type: \"date\" },\n },\n indexes: [{ fields: [\"mediaId\"] }],\n },\n\n media_validation_results: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: { model: \"media\", field: \"id\", onDelete: \"cascade\" },\n },\n valid: { type: \"boolean\" },\n pluginId: { type: \"string\" },\n errors: { type: \"json\" },\n warnings: { type: \"json\" },\n createdAt: { type: \"date\" },\n },\n indexes: [{ fields: [\"mediaId\"] }],\n },\n\n media_virus_scan_results: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: { model: \"media\", field: \"id\", onDelete: \"cascade\" },\n },\n status: { type: \"string\" }, // 'clean' | 'infected' | 'error'\n threats: { type: \"json\" },\n scanner: { type: \"string\" },\n metadata: { type: \"json\" },\n createdAt: { type: \"date\" },\n },\n indexes: [{ fields: [\"mediaId\"] }],\n },\n};\n","export function toSnakeCase(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/[\\s-]+/g, \"_\")\n .toLowerCase();\n}\n\nexport function toCamelCase(value: string): string {\n return value.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\nexport function toDbFieldName(field: string): string {\n return toSnakeCase(field);\n}\n","import type { FieldType } from \"./types\";\n\nexport interface FieldConverter {\n serialize(value: unknown): unknown;\n deserialize(value: unknown): unknown;\n}\n\nexport const converters: Record<FieldType, FieldConverter> = {\n json: {\n serialize: (value) => (value === undefined ? undefined : JSON.stringify(value)),\n deserialize: (value) => (typeof value === \"string\" ? JSON.parse(value) : value),\n },\n date: {\n serialize: (value) =>\n value instanceof Date ? value.toISOString() : typeof value === \"string\" ? value : value,\n deserialize: (value) => (typeof value === \"string\" ? new Date(value) : value),\n },\n boolean: {\n serialize: (value) => (typeof value === \"boolean\" ? (value ? 1 : 0) : value),\n deserialize: (value) => (typeof value === \"number\" ? value === 1 : Boolean(value)),\n },\n string: {\n serialize: (value) => value,\n deserialize: (value) => (typeof value === \"number\" ? String(value) : value),\n },\n number: {\n serialize: (value) => (typeof value === \"string\" ? Number(value) : value),\n deserialize: (value) => value,\n },\n};\n\nexport function serializeField(type: FieldType, value: unknown): unknown {\n if (value === null || value === undefined) return value;\n return converters[type]?.serialize(value) ?? value;\n}\n\nexport function deserializeField(type: FieldType, value: unknown): unknown {\n if (value === null || value === undefined) return value;\n return converters[type]?.deserialize(value) ?? value;\n}\n\nexport function serializeData(\n fields: Record<string, { type: FieldType }>,\n data: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (fields[key]) {\n result[key] = serializeField(fields[key].type, value);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\nexport function deserializeData(\n fields: Record<string, { type: FieldType }>,\n data: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (fields[key]) {\n result[key] = deserializeField(fields[key].type, value);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n","import type {\n BmSchema,\n FieldDefinition,\n FieldType,\n SqlDialect,\n TableMetadata,\n MigrationOperation,\n} from \"./types\";\n\nconst dialectMap: Record<FieldType, Record<SqlDialect, string>> = {\n string: {\n postgres: \"text\",\n mysql: \"varchar(255)\",\n sqlite: \"text\",\n mssql: \"varchar(255)\",\n },\n number: {\n postgres: \"integer\",\n mysql: \"integer\",\n sqlite: \"integer\",\n mssql: \"integer\",\n },\n boolean: {\n postgres: \"boolean\",\n mysql: \"boolean\",\n sqlite: \"integer\",\n mssql: \"bit\",\n },\n date: {\n postgres: \"timestamp\",\n mysql: \"datetime\",\n sqlite: \"text\",\n mssql: \"datetime2\",\n },\n json: {\n postgres: \"jsonb\",\n mysql: \"json\",\n sqlite: \"text\",\n mssql: \"nvarchar(max)\",\n },\n};\n\nexport function getColumnType(field: FieldDefinition, dialect: SqlDialect): string {\n // Overrides for specific cases\n if (field.primaryKey && field.type === \"string\") {\n if (dialect === \"postgres\") return \"uuid\";\n return dialect === \"mysql\" || dialect === \"mssql\" ? \"varchar(36)\" : \"text\";\n }\n if (field.references && field.type === \"string\" && dialect === \"postgres\") {\n return \"uuid\";\n }\n\n const types = dialectMap[field.type];\n if (!types) return \"text\";\n\n const type = types[dialect];\n return type || \"text\";\n}\n\nexport function matchType(dbType: string, expectedType: FieldType, dialect: SqlDialect): boolean {\n const normalizedDb = (dbType.toLowerCase().split(\"(\")[0] || \"\").trim();\n const normalizedMap: Record<SqlDialect, Record<FieldType, string[]>> = {\n postgres: {\n string: [\"character varying\", \"varchar\", \"text\", \"uuid\"],\n number: [\"int4\", \"integer\", \"bigint\", \"smallint\", \"numeric\", \"real\", \"double precision\"],\n boolean: [\"bool\", \"boolean\"],\n date: [\"timestamptz\", \"timestamp\", \"date\"],\n json: [\"json\", \"jsonb\"],\n },\n mysql: {\n string: [\"varchar\", \"text\", \"uuid\", \"char\"],\n number: [\"integer\", \"int\", \"bigint\", \"smallint\", \"decimal\", \"float\", \"double\"],\n boolean: [\"boolean\", \"tinyint\", \"bit\"],\n date: [\"timestamp\", \"datetime\", \"date\"],\n json: [\"json\", \"text\", \"longtext\"],\n },\n sqlite: {\n string: [\"text\", \"varchar\"],\n number: [\"integer\", \"real\", \"numeric\"],\n boolean: [\"integer\", \"boolean\"],\n date: [\"date\", \"text\", \"integer\"],\n json: [\"text\"],\n },\n mssql: {\n string: [\"varchar\", \"nvarchar\", \"uniqueidentifier\"],\n number: [\"int\", \"bigint\", \"smallint\", \"decimal\", \"float\", \"double\", \"numeric\"],\n boolean: [\"bit\", \"smallint\"],\n date: [\"datetime2\", \"date\", \"datetime\", \"timestamp\"],\n json: [\"varchar\", \"nvarchar\"],\n },\n };\n\n return normalizedMap[dialect][expectedType].includes(normalizedDb);\n}\n\n/**\n * MigrationPlanner calculates the delta between the desired schema and the actual DB state.\n */\nexport class MigrationPlanner {\n constructor(private readonly dialect: SqlDialect) {}\n\n plan(schema: BmSchema, currentTables: TableMetadata[]): MigrationOperation[] {\n const operations: MigrationOperation[] = [];\n\n for (const [tableName, model] of Object.entries(schema)) {\n const existingTable = currentTables.find((t) => t.name === tableName);\n\n if (!existingTable) {\n // Table doesn't exist\n operations.push({ type: \"createTable\", table: tableName, definition: model });\n continue;\n }\n\n // Table exists, check for missing columns\n for (const [fieldName, fieldDef] of Object.entries(model.fields)) {\n const existingColumn = existingTable.columns.find((c) => c.name === fieldName);\n\n if (!existingColumn) {\n operations.push({\n type: \"addColumn\",\n table: tableName,\n field: fieldName,\n definition: fieldDef,\n });\n } else {\n // Optional: Check for type mismatches (logging only for now to avoid destructive changes)\n if (!matchType(existingColumn.dataType, fieldDef.type, this.dialect)) {\n console.warn(\n `[BetterMedia] Type mismatch for ${tableName}.${fieldName}: ` +\n `Expected ${fieldDef.type} but found ${existingColumn.dataType} in DB.`\n );\n }\n }\n }\n\n // Missing indexes: not yet diffed against DB metadata (createIndex ops TBD).\n }\n\n return operations;\n }\n}\n\n/**\n * Applies a list of migration operations to an existing metadata state to project\n * what the database will look like after the migration.\n */\nexport function applyOperationsToMetadata(\n currentMetadata: TableMetadata[],\n operations: MigrationOperation[],\n dialect: SqlDialect\n): TableMetadata[] {\n const metadata = JSON.parse(JSON.stringify(currentMetadata)) as TableMetadata[];\n\n for (const op of operations) {\n if (op.type === \"createTable\") {\n const columns = Object.entries(op.definition.fields).map(([name, field]) => ({\n name,\n dataType: getColumnType(field, dialect),\n isNullable: !field.required && !field.primaryKey,\n isUnique: field.unique || field.primaryKey,\n }));\n metadata.push({ name: op.table, columns });\n } else if (op.type === \"addColumn\") {\n const table = metadata.find((t) => t.name === op.table);\n if (table) {\n table.columns.push({\n name: op.field,\n dataType: getColumnType(op.definition, dialect),\n isNullable: !op.definition.required,\n isUnique: !!op.definition.unique,\n });\n }\n }\n // Handle other operation types (like createIndex) if metadata starts tracking them\n }\n\n return metadata;\n}\n","import type {\n BmSchema,\n FieldDefinition,\n ModelDefinition,\n SqlDialect,\n MigrationOperation,\n} from \"./types\";\nimport { getColumnType } from \"./plan\";\nimport { toDbFieldName } from \"./naming\";\n\nfunction quoteIdent(ident: string, dialect: SqlDialect): string {\n // Keep it simple and safe; Better Media table/field names are controlled.\n if (dialect === \"mysql\") return `\\`${ident}\\``;\n return `\"${ident}\"`;\n}\n\nfunction onDeleteSql(\n onDelete?: FieldDefinition[\"references\"] extends infer R\n ? R extends { onDelete?: infer D }\n ? D | string\n : string\n : string\n): string {\n if (!onDelete) return \"\";\n const normalized = String(onDelete).toUpperCase();\n if (normalized === \"CASCADE\") return \" ON DELETE CASCADE\";\n if (normalized === \"SET NULL\") return \" ON DELETE SET NULL\";\n if (normalized === \"RESTRICT\") return \" ON DELETE RESTRICT\";\n return \"\";\n}\n\nfunction columnSql(\n table: string,\n name: string,\n field: FieldDefinition,\n dialect: SqlDialect\n): string {\n const parts: string[] = [];\n const dbName = toDbFieldName(name);\n parts.push(quoteIdent(dbName, dialect));\n parts.push(getColumnType(field, dialect));\n\n if (field.primaryKey) parts.push(\"PRIMARY KEY\");\n if (field.required) parts.push(\"NOT NULL\");\n if (field.unique) parts.push(\"UNIQUE\");\n\n if (field.references) {\n const ref = field.references;\n const refTable = quoteIdent(ref.model, dialect);\n const refField = quoteIdent(toDbFieldName(ref.field), dialect);\n parts.push(`REFERENCES ${refTable}(${refField})${onDeleteSql(ref.onDelete)}`);\n }\n\n return parts.join(\" \");\n}\n\nfunction createTableSql(table: string, definition: ModelDefinition, dialect: SqlDialect): string {\n const tableName = quoteIdent(table, dialect);\n const cols = Object.entries(definition.fields).map(([name, field]) =>\n columnSql(table, name, field, dialect)\n );\n const ifNotExists = dialect === \"mssql\" ? \"\" : \" IF NOT EXISTS\";\n return `CREATE TABLE${ifNotExists} ${tableName} (\\n ${cols.join(\",\\n \")}\\n);`;\n}\n\nfunction createIndexSql(\n table: string,\n indexName: string,\n fields: string[],\n unique: boolean | undefined,\n dialect: SqlDialect\n): string {\n const idx = quoteIdent(indexName, dialect);\n const tbl = quoteIdent(table, dialect);\n const cols = fields.map((f) => quoteIdent(toDbFieldName(f), dialect)).join(\", \");\n const uniqueSql = unique ? \"UNIQUE \" : \"\";\n const ifNotExists = dialect === \"mssql\" ? \"\" : \" IF NOT EXISTS\";\n return `CREATE ${uniqueSql}INDEX${ifNotExists} ${idx} ON ${tbl} (${cols});`;\n}\n\nfunction addColumnSql(\n table: string,\n field: string,\n definition: FieldDefinition,\n dialect: SqlDialect\n): string {\n const tableName = quoteIdent(table, dialect);\n const columnDef = columnSql(table, field, definition, dialect);\n return `ALTER TABLE ${tableName} ADD COLUMN ${columnDef};`;\n}\n\nexport function compileMigrationOperationsSql(options: {\n operations: MigrationOperation[];\n dialect: SqlDialect;\n}): string {\n const { operations, dialect } = options;\n const statements: string[] = [];\n statements.push(`-- Better Media planned migrations (${dialect})`);\n\n if (dialect === \"sqlite\") {\n statements.push(\"PRAGMA foreign_keys = ON;\");\n }\n\n for (const op of operations) {\n if (op.type === \"createTable\") {\n statements.push(createTableSql(op.table, op.definition, dialect));\n if (op.definition.indexes) {\n for (const index of op.definition.indexes) {\n const indexName = `idx_${op.table}_${index.fields.map((f) => toDbFieldName(f)).join(\"_\")}`;\n statements.push(createIndexSql(op.table, indexName, index.fields, index.unique, dialect));\n }\n }\n continue;\n }\n if (op.type === \"addColumn\") {\n statements.push(addColumnSql(op.table, op.field, op.definition, dialect));\n continue;\n }\n if (op.type === \"createIndex\") {\n statements.push(createIndexSql(op.table, op.name, op.fields, op.unique, dialect));\n }\n }\n\n return statements.join(\"\\n\\n\") + \"\\n\";\n}\n\nexport function generateCreateSchemaSql(options: {\n schema: BmSchema;\n dialect: SqlDialect;\n}): string {\n const { schema, dialect } = options;\n\n const statements: string[] = [];\n statements.push(`-- Better Media schema (${dialect})`);\n\n // SQLite requires foreign keys enabled explicitly per-connection; harmless elsewhere.\n if (dialect === \"sqlite\") {\n statements.push(\"PRAGMA foreign_keys = ON;\");\n }\n\n // Create tables first (FKs reference earlier tables in this schema, but SQL engines allow forward refs too).\n for (const [table, def] of Object.entries(schema)) {\n statements.push(createTableSql(table, def, dialect));\n }\n\n // Create indexes after.\n for (const [table, def] of Object.entries(schema)) {\n if (!def.indexes) continue;\n for (const index of def.indexes) {\n const indexName = `idx_${table}_${index.fields.map((f) => toDbFieldName(f)).join(\"_\")}`;\n statements.push(createIndexSql(table, indexName, index.fields, index.unique, dialect));\n }\n }\n\n return statements.join(\"\\n\\n\") + \"\\n\";\n}\n","import type { DatabaseAdapter } from \"./interfaces/adapter.interface\";\nimport { schema } from \"./schema\";\nimport type { ModelDefinition, TableMetadata, MigrationOperation, SqlDialect } from \"./types\";\nimport { MigrationPlanner } from \"./plan\";\nimport { compileMigrationOperationsSql } from \"./sql\";\n\n/**\n * Internal interface used only by runMigrations. Adapter authors do NOT need to\n * declare or implement this — the migration engine discovers these methods via\n * duck-typing at runtime. Prefix `__` signals framework-internal use.\n */\ninterface MigratableAdapter extends DatabaseAdapter {\n __getMetadata?(): Promise<TableMetadata[]>;\n __executeMigration?(operation: MigrationOperation): Promise<void>;\n __getDialect?(): SqlDialect;\n // Legacy fallback paths\n __createTable?(\n model: string,\n definition: ModelDefinition,\n options: { mode: \"safe\" | \"diff\" | \"force\" }\n ): Promise<void>;\n __initCollection?(\n model: string,\n definition: ModelDefinition,\n options: { mode: \"safe\" | \"diff\" | \"force\" }\n ): Promise<void>;\n}\n\nexport interface MigrationOptions {\n /**\n * Migration mode:\n * - 'safe': Only create missing tables/collections and add missing columns/indexes.\n * - 'diff': Full schema comparison and incremental updates (Recommended).\n * - 'force': Drop and recreate all tables/collections (destructive).\n */\n mode?: \"safe\" | \"diff\" | \"force\";\n /**\n * For SQL adapters, the dialect can be manually specified.\n * If omitted, the adapter will try to detect it.\n */\n dialect?: SqlDialect;\n}\n\nexport interface PlannedMigrationTable {\n table: string;\n fields: string[];\n}\n\nexport interface PlannedMigrations {\n toBeCreated: PlannedMigrationTable[];\n toBeAdded: PlannedMigrationTable[];\n operations: MigrationOperation[];\n compileMigrations: () => string;\n runMigrations: () => Promise<void>;\n}\n\nexport async function getMigrations(\n adapter: DatabaseAdapter,\n options: MigrationOptions = {}\n): Promise<PlannedMigrations> {\n const migratable = adapter as MigratableAdapter;\n\n if (\n typeof migratable.__getMetadata !== \"function\" ||\n typeof migratable.__executeMigration !== \"function\"\n ) {\n return {\n toBeCreated: [],\n toBeAdded: [],\n operations: [],\n compileMigrations: () => \"\",\n runMigrations: async () => {\n throw new Error(\"[BetterMedia] Adapter does not support planned migrations.\");\n },\n };\n }\n\n let dialect = options.dialect;\n if (!dialect && typeof migratable.__getDialect === \"function\") {\n dialect = migratable.__getDialect();\n }\n const resolvedDialect = dialect || \"postgres\";\n const metadata = await migratable.__getMetadata();\n const planner = new MigrationPlanner(resolvedDialect);\n const operations = planner.plan(schema, metadata);\n\n const toBeCreated = operations\n .filter(\n (op): op is Extract<MigrationOperation, { type: \"createTable\" }> => op.type === \"createTable\"\n )\n .map((op) => ({ table: op.table, fields: Object.keys(op.definition.fields) }));\n\n const toBeAdded = operations\n .filter(\n (op): op is Extract<MigrationOperation, { type: \"addColumn\" }> => op.type === \"addColumn\"\n )\n .reduce<PlannedMigrationTable[]>((acc, op) => {\n const existing = acc.find((t) => t.table === op.table);\n if (existing) existing.fields.push(op.field);\n else acc.push({ table: op.table, fields: [op.field] });\n return acc;\n }, []);\n\n return {\n toBeCreated,\n toBeAdded,\n operations,\n compileMigrations: () =>\n compileMigrationOperationsSql({ operations, dialect: resolvedDialect }),\n runMigrations: async () => {\n for (const op of operations) {\n await migratable.__executeMigration!(op);\n }\n },\n };\n}\n\n/**\n * Migration engine. It iterates through the central BmSchema and invokes\n * engine-specific setup commands on the adapter.\n */\nexport async function runMigrations(\n adapter: DatabaseAdapter,\n options: MigrationOptions = {}\n): Promise<void> {\n const mode = options.mode ?? \"safe\";\n const migratable = adapter as MigratableAdapter;\n\n // Preferred path: adapter exposes __getMetadata + __executeMigration\n if (\n typeof migratable.__getMetadata === \"function\" &&\n typeof migratable.__executeMigration === \"function\"\n ) {\n console.log(\"[BetterMedia] Starting planned migration...\");\n\n const { operations, runMigrations: runPlannedMigrations } = await getMigrations(\n adapter,\n options\n );\n\n if (operations.length === 0) {\n console.log(\"[BetterMedia] Database is up to date.\");\n return;\n }\n\n console.log(`[BetterMedia] Plan: ${operations.length} operation(s) to execute.`);\n await runPlannedMigrations();\n console.log(\"[BetterMedia] Migration completed successfully.\");\n return;\n }\n\n // Legacy fallback for MongoDB or unrefactored adapters\n if (typeof migratable.__createTable === \"function\") {\n // Kysely / SQL adapter (Legacy)\n for (const [model, definition] of Object.entries(schema)) {\n await migratable.__createTable(model, definition, { mode });\n }\n } else if (typeof migratable.__initCollection === \"function\") {\n // MongoDB adapter\n for (const [model, definition] of Object.entries(schema)) {\n await migratable.__initCollection(model, definition, { mode });\n }\n } else {\n console.warn(\"[BetterMedia] Adapter does not support automatic migrations.\");\n }\n}\n","import type { WhereClause, DbHooks, DatabaseHookContext } from \"./types\";\n\n/**\n * Utility to run hooks sequentially.\n * Supports multiple handlers and passes DatabaseHookContext.\n */\nexport const runHooks = {\n async beforeCreate(\n hooks: DbHooks | undefined,\n data: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n let currentData = data;\n const handlers = hooks?.before?.create || [];\n for (const handler of handlers) {\n currentData = await handler(currentData, context);\n }\n return currentData;\n },\n\n async beforeUpdate(\n hooks: DbHooks | undefined,\n data: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n let currentData = data;\n const handlers = hooks?.before?.update || [];\n for (const handler of handlers) {\n currentData = await handler(currentData, context);\n }\n return currentData;\n },\n\n async beforeDelete(hooks: DbHooks | undefined, where: WhereClause, context: DatabaseHookContext) {\n const handlers = hooks?.before?.delete || [];\n for (const handler of handlers) {\n await handler(where, context);\n }\n },\n\n async afterCreate(\n hooks: DbHooks | undefined,\n result: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n const handlers = hooks?.after?.create || [];\n for (const handler of handlers) {\n await handler(result, context);\n }\n },\n\n async afterUpdate(\n hooks: DbHooks | undefined,\n result: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n const handlers = hooks?.after?.update || [];\n for (const handler of handlers) {\n await handler(result, context);\n }\n },\n\n async afterDelete(hooks: DbHooks | undefined, where: WhereClause, context: DatabaseHookContext) {\n const handlers = hooks?.after?.delete || [];\n for (const handler of handlers) {\n await handler(where, context);\n }\n },\n};\n","import type { DatabaseAdapter } from \"./interfaces/adapter.interface\";\n\nexport type QueryResultLike<T = unknown> = { rows: T[]; rowCount?: number | null };\n\nexport type Queryable = {\n query: (text: string, values?: unknown[]) => Promise<QueryResultLike<Record<string, unknown>>>;\n};\n\nexport type PgPoolLike = Queryable & {\n connect?: () => Promise<PgClientLike>;\n};\n\nexport type PgClientLike = Queryable & {\n release?: () => void;\n};\n\nexport function isPgPoolLike(value: unknown): value is PgPoolLike {\n return Boolean(\n value && typeof value === \"object\" && typeof (value as { query?: unknown }).query === \"function\"\n );\n}\n\n/**\n * Normalizes a database pool or adapter into a standard DatabaseAdapter.\n * Note: If using the built-in Postgres pool, this requires the actual\n * implementation to be registered or known.\n */\nexport function toDatabaseAdapter(\n database: DatabaseAdapter | PgPoolLike,\n postgresFactory?: (pool: PgPoolLike) => DatabaseAdapter\n): DatabaseAdapter {\n if (isPgPoolLike(database) && typeof (database as { create?: unknown }).create !== \"function\") {\n if (postgresFactory) return postgresFactory(database);\n throw new Error(\n \"[BetterMedia] Postgres pool detected but no adapter factory provided. \" +\n \"This typically means you should use the main @better-media/framework package.\"\n );\n }\n return database as DatabaseAdapter;\n}\n","import type { DatabaseAdapter } from \"../database/interfaces/adapter.interface\";\nimport { toDatabaseAdapter, type PgPoolLike } from \"../database/postgres-utils\";\n\nexport type GetAdapterOptions = {\n database?: DatabaseAdapter | PgPoolLike;\n createDatabase?: () => Promise<DatabaseAdapter | PgPoolLike> | DatabaseAdapter | PgPoolLike;\n dialect?: string;\n schemaOutput?: string;\n migrationsDir?: string;\n};\n\nexport async function getAdapter(options: GetAdapterOptions): Promise<DatabaseAdapter> {\n const database = options.database ?? (await options.createDatabase?.());\n const adapter = database ? toDatabaseAdapter(database) : undefined;\n if (!adapter) {\n throw new Error(\n `[media] Failed to initialize database adapter. Provide \"database\" or \"createDatabase()\".`\n );\n }\n return adapter;\n}\n","/**\n * Mapping of common file extensions to their valid MIME types.\n * Based on MDN Common Media Types: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types\n */\nexport const EXTENSION_TO_MIME_MAP: Record<string, string[]> = {\n \".aac\": [\"audio/aac\"],\n \".abw\": [\"application/x-abiword\"],\n \".apng\": [\"image/apng\"],\n \".arc\": [\"application/x-freearc\"],\n \".avif\": [\"image/avif\"],\n \".avi\": [\"video/x-msvideo\"],\n \".azw\": [\"application/vnd.amazon.ebook\"],\n \".bin\": [\"application/octet-stream\"],\n \".bmp\": [\"image/bmp\"],\n \".bz\": [\"application/x-bzip\"],\n \".bz2\": [\"application/x-bzip2\"],\n \".cda\": [\"application/x-cdf\"],\n \".csh\": [\"application/x-csh\"],\n \".css\": [\"text/css\"],\n \".csv\": [\"text/csv\"],\n \".doc\": [\"application/msword\"],\n \".docx\": [\"application/vnd.openxmlformats-officedocument.wordprocessingml.document\"],\n \".eot\": [\"application/vnd.ms-fontobject\"],\n \".epub\": [\"application/epub+zip\"],\n \".gz\": [\"application/gzip\", \"application/x-gzip\"],\n \".gif\": [\"image/gif\"],\n \".htm\": [\"text/html\"],\n \".html\": [\"text/html\"],\n \".ico\": [\"image/vnd.microsoft.icon\"],\n \".ics\": [\"text/calendar\"],\n \".jar\": [\"application/java-archive\"],\n \".jpeg\": [\"image/jpeg\"],\n \".jpg\": [\"image/jpeg\"],\n \".js\": [\"text/javascript\"],\n \".mjs\": [\"text/javascript\"],\n \".json\": [\"application/json\"],\n \".jsonld\": [\"application/ld+json\"],\n \".md\": [\"text/markdown\"],\n \".mid\": [\"audio/midi\", \"audio/x-midi\"],\n \".midi\": [\"audio/midi\", \"audio/x-midi\"],\n \".mp3\": [\"audio/mpeg\"],\n \".mp4\": [\"video/mp4\"],\n \".mpeg\": [\"video/mpeg\"],\n \".mpkg\": [\"application/vnd.apple.installer+xml\"],\n \".odp\": [\"application/vnd.oasis.opendocument.presentation\"],\n \".ods\": [\"application/vnd.oasis.opendocument.spreadsheet\"],\n \".odt\": [\"application/vnd.oasis.opendocument.text\"],\n \".oga\": [\"audio/ogg\"],\n \".ogv\": [\"video/ogg\"],\n \".ogx\": [\"application/ogg\"],\n \".opus\": [\"audio/ogg\"],\n \".otf\": [\"font/otf\"],\n \".png\": [\"image/png\"],\n \".pdf\": [\"application/pdf\"],\n \".php\": [\"application/x-httpd-php\"],\n \".ppt\": [\"application/vnd.ms-powerpoint\"],\n \".pptx\": [\"application/vnd.openxmlformats-officedocument.presentationml.presentation\"],\n \".rar\": [\"application/vnd.rar\"],\n \".rtf\": [\"application/rtf\"],\n \".sh\": [\"application/x-sh\"],\n \".svg\": [\"image/svg+xml\"],\n \".tar\": [\"application/x-tar\"],\n \".tif\": [\"image/tiff\"],\n \".tiff\": [\"image/tiff\"],\n \".ts\": [\"video/mp2t\"],\n \".ttf\": [\"font/ttf\"],\n \".txt\": [\"text/plain\"],\n \".vsd\": [\"application/vnd.visio\"],\n \".wav\": [\"audio/wav\"],\n \".weba\": [\"audio/webm\"],\n \".webm\": [\"video/webm\"],\n \".webmanifest\": [\"application/manifest+json\"],\n \".webp\": [\"image/webp\"],\n \".woff\": [\"font/woff\"],\n \".woff2\": [\"font/woff2\"],\n \".xhtml\": [\"application/xhtml+xml\"],\n \".xls\": [\"application/vnd.ms-excel\"],\n \".xlsx\": [\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\"],\n \".xml\": [\"application/xml\", \"text/xml\", \"application/atom+xml\"],\n \".xul\": [\"application/vnd.mozilla.xul+xml\"],\n \".zip\": [\"application/zip\", \"application/x-zip-compressed\"],\n \".3gp\": [\"video/3gpp\", \"audio/3gpp\"],\n \".3g2\": [\"video/3gpp2\", \"audio/3gpp2\"],\n \".7z\": [\"application/x-7z-compressed\"],\n};\n","// Core types and utilities\nexport type MediaStatus = \"PENDING_VERIFICATION\" | \"VALID\" | \"INVALID\" | \"PROCESSING\" | \"COMPLETED\";\n\nexport function sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport { HOOK_NAMES, HOOK_MODE_CONSTRAINTS, resolveHookMode } from \"./plugin/index\";\nexport type {\n PipelinePlugin,\n PipelineContext,\n FileInfo,\n FileContent,\n StorageLocation,\n ProcessingResults,\n ThumbnailResult,\n VariantResult,\n MediaDimensions,\n PluginExecutionMode,\n PluginHooks,\n HookName,\n HookHandler,\n HookHandlerOptions,\n HookModeConstraint,\n MediaPlugin,\n HookContext,\n MediaRuntime,\n MediaRuntimeHook,\n ValidationResult,\n TrustedMetadata,\n PluginManifest,\n PluginApi,\n} from \"./plugin/index\";\nexport {\n ValidationResultSchema,\n VirusScanResultSchema,\n TrustedMetadataSchema,\n markFileContentVerified,\n} from \"./plugin/index\";\nexport type { VerifiedSourceId, PipelineContextWithVerified } from \"./plugin/index\";\nexport type {\n StorageAdapter,\n GetUrlOptions,\n PresignedUploadMethod,\n PresignedUploadOptions,\n PresignedUploadResult,\n StorageObject,\n ListResult,\n ListOptions,\n} from \"./storage/index\";\nexport type {\n DatabaseAdapter,\n DatabaseTransactionAdapter,\n WhereClause,\n CreateOptions,\n FindOptions,\n UpdateOptions,\n DeleteOptions,\n CountOptions,\n} from \"./database/index\";\nexport type { JobAdapter } from \"./job/index\";\nexport * from \"./database/index\";\nexport type { DatabaseHookContext } from \"./database/index\";\nexport { getAdapter, type GetAdapterOptions } from \"./adapter/get-adapter\";\nexport { EXTENSION_TO_MIME_MAP } from \"./constants/mime-types\";\n"]}
package/dist/index.mjs CHANGED
@@ -72,22 +72,26 @@ var schema = {
72
72
  id: { type: "string", primaryKey: true, required: true },
73
73
  ownerId: { type: "string" },
74
74
  filename: { type: "string" },
75
+ extension: { type: "string" },
75
76
  mimeType: { type: "string" },
76
77
  size: { type: "number" },
77
78
  storageProvider: { type: "string" },
78
79
  storageKey: { type: "string" },
79
- checksum: { type: "string" },
80
+ checksumSha256: { type: "string" },
81
+ checksumMd5: { type: "string" },
80
82
  width: { type: "number" },
81
83
  height: { type: "number" },
82
84
  duration: { type: "number" },
83
- context: { type: "json" },
85
+ metadata: { type: "json" },
84
86
  status: { type: "string" },
87
+ // 'pending' | 'processing' | 'ready' | 'failed' | 'quarantined'
85
88
  visibility: { type: "string" },
89
+ // 'public' | 'private' | 'unlisted'
86
90
  createdAt: { type: "date" },
87
91
  updatedAt: { type: "date" },
88
92
  deletedAt: { type: "date" }
89
93
  },
90
- indexes: [{ fields: ["checksum", "storageKey"] }]
94
+ indexes: [{ fields: ["checksumSha256", "storageKey"] }]
91
95
  },
92
96
  // Different versions of the media (thumbnails, previews, etc.)
93
97
  media_versions: {
@@ -101,22 +105,25 @@ var schema = {
101
105
  onDelete: "cascade"
102
106
  }
103
107
  },
108
+ storageProvider: { type: "string" },
104
109
  storageKey: { type: "string" },
105
- checksum: { type: "string" },
110
+ checksumSha256: { type: "string" },
111
+ mimeType: { type: "string" },
112
+ size: { type: "number" },
113
+ width: { type: "number" },
114
+ height: { type: "number" },
106
115
  isOriginal: { type: "boolean" },
107
116
  type: { type: "string" },
108
- // e.g., 'thumbnail', 'preview', 'compressed'
117
+ // 'thumbnail' | 'preview' | 'compressed' | 'original'
109
118
  versionNumber: { type: "number" },
110
- createdAt: { type: "date" }
119
+ createdAt: { type: "date" },
120
+ deletedAt: { type: "date" }
111
121
  },
112
- indexes: [
113
- {
114
- fields: ["mediaId", "versionNumber"],
115
- unique: true
116
- }
117
- ]
122
+ indexes: [{ fields: ["mediaId"] }, { fields: ["mediaId", "versionNumber"], unique: true }]
118
123
  },
119
- // Background job state for media processing
124
+ // Business record for media processing jobs — not a BullMQ state mirror.
125
+ // Tracks idempotency, final outcome, and links jobs to media.
126
+ // Runtime state (queue position, locks, backoff) lives in BullMQ/Redis.
120
127
  media_jobs: {
121
128
  fields: {
122
129
  id: { type: "string", primaryKey: true, required: true },
@@ -129,18 +136,22 @@ var schema = {
129
136
  }
130
137
  },
131
138
  type: { type: "string" },
132
- // e.g., 'virus-scan', 'thumbnail'
139
+ // 'virus-scan' | 'thumbnail' | 'compress' | 'validate'
133
140
  status: { type: "string" },
134
- // e.g., 'pending', 'running', 'completed', 'failed'
141
+ // 'pending' | 'running' | 'completed' | 'failed'
135
142
  attempts: { type: "number" },
136
143
  maxAttempts: { type: "number" },
137
144
  idempotencyKey: { type: "string", unique: true },
138
145
  scheduledAt: { type: "date" },
139
146
  startedAt: { type: "date" },
140
147
  completedAt: { type: "date" },
141
- error: { type: "string" },
142
- createdAt: { type: "date" }
143
- }
148
+ error: { type: "json" },
149
+ // { message, code, stack, retryable }
150
+ result: { type: "json" },
151
+ createdAt: { type: "date" },
152
+ updatedAt: { type: "date" }
153
+ },
154
+ indexes: [{ fields: ["mediaId"] }]
144
155
  },
145
156
  media_validation_results: {
146
157
  fields: {
@@ -152,8 +163,10 @@ var schema = {
152
163
  valid: { type: "boolean" },
153
164
  pluginId: { type: "string" },
154
165
  errors: { type: "json" },
166
+ warnings: { type: "json" },
155
167
  createdAt: { type: "date" }
156
- }
168
+ },
169
+ indexes: [{ fields: ["mediaId"] }]
157
170
  },
158
171
  media_virus_scan_results: {
159
172
  fields: {
@@ -163,13 +176,13 @@ var schema = {
163
176
  references: { model: "media", field: "id", onDelete: "cascade" }
164
177
  },
165
178
  status: { type: "string" },
166
- // 'clean', 'infected', 'error'
179
+ // 'clean' | 'infected' | 'error'
167
180
  threats: { type: "json" },
168
- // List of detected threats
169
181
  scanner: { type: "string" },
170
- // clamd, etc.
182
+ metadata: { type: "json" },
171
183
  createdAt: { type: "date" }
172
- }
184
+ },
185
+ indexes: [{ fields: ["mediaId"] }]
173
186
  }
174
187
  };
175
188
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/plugin/verified-sources.ts","../src/plugin/interfaces/trusted-metadata.interface.ts","../src/plugin/interfaces/hook-name.interface.ts","../src/plugin/interfaces/hook-mode.interface.ts","../src/plugin/interfaces/media-runtime.interface.ts","../src/database/schema.ts","../src/database/naming.ts","../src/database/fields.ts","../src/database/plan.ts","../src/database/sql.ts","../src/database/migration.ts","../src/database/hooks.ts","../src/database/postgres-utils.ts","../src/adapter/get-adapter.ts","../src/constants/mime-types.ts","../src/index.ts"],"names":["z","schema"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { PipelineContext } from \"./interfaces/context.interface\";\n\n/** Provenance tokens for trusted metadata (e.g. proposeTrusted). */\nexport type VerifiedSourceId = \"file:content\";\n\nexport interface PipelineContextWithVerified extends PipelineContext {\n _verifiedSources?: Set<VerifiedSourceId>;\n}\n\n/**\n * Mark that this pipeline run has read file bytes from storage (buffer or temp path).\n * Required before trusted plugins may call proposeTrusted with file/checksums/media patches.\n */\nexport function markFileContentVerified(context: PipelineContext): void {\n const c = context as PipelineContextWithVerified;\n c._verifiedSources ??= new Set();\n c._verifiedSources.add(\"file:content\");\n}\n","import { z } from \"zod\";\n\n/**\n * Zod Schema for Trusted Metadata.\n * Strictly enforced to prevent trust injection from the database.\n */\nexport const TrustedMetadataSchema = z\n .object({\n file: z\n .object({\n mimeType: z.string().optional(),\n size: z.number().int().nonnegative().optional(),\n originalName: z.string().optional(),\n extension: z.string().optional(),\n })\n .strict()\n .optional(),\n checksums: z\n .object({\n sha256: z.string().optional(),\n md5: z.string().optional(),\n })\n .strict()\n .optional(),\n media: z\n .object({\n width: z.number().int().nonnegative().optional(),\n height: z.number().int().nonnegative().optional(),\n duration: z.number().nonnegative().optional(),\n })\n .strict()\n .optional(),\n })\n .strict();\n\n/** Metadata from DB/Trusted Sources (Schema validated) */\nexport type TrustedMetadata = z.infer<typeof TrustedMetadataSchema>;\n","/** Lifecycle hook names (aligns with AWS/Cloudinary media pipeline stages). Single source of truth. */\nexport const HOOK_NAMES = [\n \"upload:init\",\n \"validation:run\",\n \"scan:run\",\n \"process:run\",\n \"upload:complete\",\n] as const;\n\nexport type HookName = (typeof HOOK_NAMES)[number];\n","import type { HookName } from \"./hook-name.interface\";\n\n/**\n * Hook-level execution mode constraint.\n * - sync-only: Handler always runs inline. Passing background is overridden with a warning.\n * - sync-or-background: Plugin may choose either; both are valid.\n * - background-only: Handler always runs enqueued. Passing sync is overridden with a warning.\n */\nexport type HookModeConstraint = \"sync-only\" | \"sync-or-background\" | \"background-only\";\n\n/** Per-hook mode constraints. Single source of truth for hook execution rules. */\nexport const HOOK_MODE_CONSTRAINTS: Record<HookName, HookModeConstraint> = {\n \"upload:init\": \"sync-only\",\n \"validation:run\": \"sync-only\",\n \"scan:run\": \"sync-only\",\n \"process:run\": \"sync-or-background\",\n \"upload:complete\": \"sync-or-background\",\n};\n\n/**\n * Resolve effective execution mode given hook constraint and requested mode.\n * Returns the mode to use and whether it was overridden (for logging).\n */\nexport function resolveHookMode(\n hookName: HookName,\n requested: \"sync\" | \"background\"\n): { effective: \"sync\" | \"background\"; overridden: boolean } {\n const constraint = HOOK_MODE_CONSTRAINTS[hookName];\n\n if (constraint === \"sync-only\" && requested === \"background\") {\n return { effective: \"sync\", overridden: true };\n }\n if (constraint === \"background-only\" && requested === \"sync\") {\n return { effective: \"background\", overridden: true };\n }\n\n return { effective: requested, overridden: false };\n}\n","import { z } from \"zod\";\nimport type { PipelineContext, PluginApi } from \"./context.interface\";\nimport type { HookName } from \"./hook-name.interface\";\n\n/**\n * Result from validation-phase handlers; can abort pipeline.\n * Persisted to 'validation_results' table.\n */\nexport const ValidationResultSchema = z\n .object({\n valid: z.boolean(),\n pluginId: z.string().optional(),\n message: z.string().optional(),\n errors: z.array(z.string()).optional(),\n })\n .strict();\n\nexport type ValidationResult = z.infer<typeof ValidationResultSchema>;\n\n/**\n * Result from virus-scan handlers.\n * Persisted to 'virus_scan_results' table.\n */\nexport const VirusScanResultSchema = z\n .object({\n status: z.enum([\"clean\", \"infected\", \"error\"]),\n threats: z.array(z.string()).optional(),\n scanner: z.string().optional(),\n scannedAt: z.string().datetime().optional(),\n })\n .strict();\n\nexport type VirusScanResult = z.infer<typeof VirusScanResultSchema>;\n\n/** Hook interface for plugin registration (Tapable-style) */\nexport interface MediaRuntimeHook {\n tap(\n name: string,\n fn: (ctx: PipelineContext, api: PluginApi) => Promise<void | ValidationResult>,\n options?: { mode?: \"sync\" | \"background\" }\n ): void;\n}\n\n/** Runtime host passed to plugins via apply(); exposes lifecycle hooks */\nexport interface MediaRuntime {\n readonly hooks: {\n [K in HookName]: MediaRuntimeHook;\n };\n}\n","import type { BmSchema } from \"./types\";\n\n/**\n * Central schema defining all Better Media tables and relationships.\n * This is the single source of truth for the database structure.\n */\nexport const schema: BmSchema = {\n // Core media records\n media: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n ownerId: { type: \"string\" },\n filename: { type: \"string\" },\n mimeType: { type: \"string\" },\n size: { type: \"number\" },\n storageProvider: { type: \"string\" },\n storageKey: { type: \"string\" },\n checksum: { type: \"string\" },\n width: { type: \"number\" },\n height: { type: \"number\" },\n duration: { type: \"number\" },\n context: { type: \"json\" },\n status: { type: \"string\" },\n visibility: { type: \"string\" },\n createdAt: { type: \"date\" },\n updatedAt: { type: \"date\" },\n deletedAt: { type: \"date\" },\n },\n indexes: [{ fields: [\"checksum\", \"storageKey\"] }],\n },\n\n // Different versions of the media (thumbnails, previews, etc.)\n media_versions: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: {\n model: \"media\",\n field: \"id\",\n onDelete: \"cascade\",\n },\n },\n storageKey: { type: \"string\" },\n checksum: { type: \"string\" },\n isOriginal: { type: \"boolean\" },\n type: { type: \"string\" }, // e.g., 'thumbnail', 'preview', 'compressed'\n versionNumber: { type: \"number\" },\n createdAt: { type: \"date\" },\n },\n indexes: [\n {\n fields: [\"mediaId\", \"versionNumber\"],\n unique: true,\n },\n ],\n },\n\n // Background job state for media processing\n media_jobs: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: {\n model: \"media\",\n field: \"id\",\n onDelete: \"cascade\",\n },\n },\n type: { type: \"string\" }, // e.g., 'virus-scan', 'thumbnail'\n status: { type: \"string\" }, // e.g., 'pending', 'running', 'completed', 'failed'\n attempts: { type: \"number\" },\n maxAttempts: { type: \"number\" },\n idempotencyKey: { type: \"string\", unique: true },\n scheduledAt: { type: \"date\" },\n startedAt: { type: \"date\" },\n completedAt: { type: \"date\" },\n error: { type: \"string\" },\n createdAt: { type: \"date\" },\n },\n },\n\n media_validation_results: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: { model: \"media\", field: \"id\", onDelete: \"cascade\" },\n },\n valid: { type: \"boolean\" },\n pluginId: { type: \"string\" },\n errors: { type: \"json\" },\n createdAt: { type: \"date\" },\n },\n },\n\n media_virus_scan_results: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: { model: \"media\", field: \"id\", onDelete: \"cascade\" },\n },\n status: { type: \"string\" }, // 'clean', 'infected', 'error'\n threats: { type: \"json\" }, // List of detected threats\n scanner: { type: \"string\" }, // clamd, etc.\n createdAt: { type: \"date\" },\n },\n },\n};\n","export function toSnakeCase(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/[\\s-]+/g, \"_\")\n .toLowerCase();\n}\n\nexport function toCamelCase(value: string): string {\n return value.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\nexport function toDbFieldName(field: string): string {\n return toSnakeCase(field);\n}\n","import type { FieldType } from \"./types\";\n\nexport interface FieldConverter {\n serialize(value: unknown): unknown;\n deserialize(value: unknown): unknown;\n}\n\nexport const converters: Record<FieldType, FieldConverter> = {\n json: {\n serialize: (value) => (value === undefined ? undefined : JSON.stringify(value)),\n deserialize: (value) => (typeof value === \"string\" ? JSON.parse(value) : value),\n },\n date: {\n serialize: (value) =>\n value instanceof Date ? value.toISOString() : typeof value === \"string\" ? value : value,\n deserialize: (value) => (typeof value === \"string\" ? new Date(value) : value),\n },\n boolean: {\n serialize: (value) => (typeof value === \"boolean\" ? (value ? 1 : 0) : value),\n deserialize: (value) => (typeof value === \"number\" ? value === 1 : Boolean(value)),\n },\n string: {\n serialize: (value) => value,\n deserialize: (value) => (typeof value === \"number\" ? String(value) : value),\n },\n number: {\n serialize: (value) => (typeof value === \"string\" ? Number(value) : value),\n deserialize: (value) => value,\n },\n};\n\nexport function serializeField(type: FieldType, value: unknown): unknown {\n if (value === null || value === undefined) return value;\n return converters[type]?.serialize(value) ?? value;\n}\n\nexport function deserializeField(type: FieldType, value: unknown): unknown {\n if (value === null || value === undefined) return value;\n return converters[type]?.deserialize(value) ?? value;\n}\n\nexport function serializeData(\n fields: Record<string, { type: FieldType }>,\n data: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (fields[key]) {\n result[key] = serializeField(fields[key].type, value);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\nexport function deserializeData(\n fields: Record<string, { type: FieldType }>,\n data: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (fields[key]) {\n result[key] = deserializeField(fields[key].type, value);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n","import type {\n BmSchema,\n FieldDefinition,\n FieldType,\n SqlDialect,\n TableMetadata,\n MigrationOperation,\n} from \"./types\";\n\nconst dialectMap: Record<FieldType, Record<SqlDialect, string>> = {\n string: {\n postgres: \"text\",\n mysql: \"varchar(255)\",\n sqlite: \"text\",\n mssql: \"varchar(255)\",\n },\n number: {\n postgres: \"integer\",\n mysql: \"integer\",\n sqlite: \"integer\",\n mssql: \"integer\",\n },\n boolean: {\n postgres: \"boolean\",\n mysql: \"boolean\",\n sqlite: \"integer\",\n mssql: \"bit\",\n },\n date: {\n postgres: \"timestamp\",\n mysql: \"datetime\",\n sqlite: \"text\",\n mssql: \"datetime2\",\n },\n json: {\n postgres: \"jsonb\",\n mysql: \"json\",\n sqlite: \"text\",\n mssql: \"nvarchar(max)\",\n },\n};\n\nexport function getColumnType(field: FieldDefinition, dialect: SqlDialect): string {\n // Overrides for specific cases\n if (field.primaryKey && field.type === \"string\") {\n if (dialect === \"postgres\") return \"uuid\";\n return dialect === \"mysql\" || dialect === \"mssql\" ? \"varchar(36)\" : \"text\";\n }\n if (field.references && field.type === \"string\" && dialect === \"postgres\") {\n return \"uuid\";\n }\n\n const types = dialectMap[field.type];\n if (!types) return \"text\";\n\n const type = types[dialect];\n return type || \"text\";\n}\n\nexport function matchType(dbType: string, expectedType: FieldType, dialect: SqlDialect): boolean {\n const normalizedDb = (dbType.toLowerCase().split(\"(\")[0] || \"\").trim();\n const normalizedMap: Record<SqlDialect, Record<FieldType, string[]>> = {\n postgres: {\n string: [\"character varying\", \"varchar\", \"text\", \"uuid\"],\n number: [\"int4\", \"integer\", \"bigint\", \"smallint\", \"numeric\", \"real\", \"double precision\"],\n boolean: [\"bool\", \"boolean\"],\n date: [\"timestamptz\", \"timestamp\", \"date\"],\n json: [\"json\", \"jsonb\"],\n },\n mysql: {\n string: [\"varchar\", \"text\", \"uuid\", \"char\"],\n number: [\"integer\", \"int\", \"bigint\", \"smallint\", \"decimal\", \"float\", \"double\"],\n boolean: [\"boolean\", \"tinyint\", \"bit\"],\n date: [\"timestamp\", \"datetime\", \"date\"],\n json: [\"json\", \"text\", \"longtext\"],\n },\n sqlite: {\n string: [\"text\", \"varchar\"],\n number: [\"integer\", \"real\", \"numeric\"],\n boolean: [\"integer\", \"boolean\"],\n date: [\"date\", \"text\", \"integer\"],\n json: [\"text\"],\n },\n mssql: {\n string: [\"varchar\", \"nvarchar\", \"uniqueidentifier\"],\n number: [\"int\", \"bigint\", \"smallint\", \"decimal\", \"float\", \"double\", \"numeric\"],\n boolean: [\"bit\", \"smallint\"],\n date: [\"datetime2\", \"date\", \"datetime\", \"timestamp\"],\n json: [\"varchar\", \"nvarchar\"],\n },\n };\n\n return normalizedMap[dialect][expectedType].includes(normalizedDb);\n}\n\n/**\n * MigrationPlanner calculates the delta between the desired schema and the actual DB state.\n */\nexport class MigrationPlanner {\n constructor(private readonly dialect: SqlDialect) {}\n\n plan(schema: BmSchema, currentTables: TableMetadata[]): MigrationOperation[] {\n const operations: MigrationOperation[] = [];\n\n for (const [tableName, model] of Object.entries(schema)) {\n const existingTable = currentTables.find((t) => t.name === tableName);\n\n if (!existingTable) {\n // Table doesn't exist\n operations.push({ type: \"createTable\", table: tableName, definition: model });\n continue;\n }\n\n // Table exists, check for missing columns\n for (const [fieldName, fieldDef] of Object.entries(model.fields)) {\n const existingColumn = existingTable.columns.find((c) => c.name === fieldName);\n\n if (!existingColumn) {\n operations.push({\n type: \"addColumn\",\n table: tableName,\n field: fieldName,\n definition: fieldDef,\n });\n } else {\n // Optional: Check for type mismatches (logging only for now to avoid destructive changes)\n if (!matchType(existingColumn.dataType, fieldDef.type, this.dialect)) {\n console.warn(\n `[BetterMedia] Type mismatch for ${tableName}.${fieldName}: ` +\n `Expected ${fieldDef.type} but found ${existingColumn.dataType} in DB.`\n );\n }\n }\n }\n\n // Missing indexes: not yet diffed against DB metadata (createIndex ops TBD).\n }\n\n return operations;\n }\n}\n\n/**\n * Applies a list of migration operations to an existing metadata state to project\n * what the database will look like after the migration.\n */\nexport function applyOperationsToMetadata(\n currentMetadata: TableMetadata[],\n operations: MigrationOperation[],\n dialect: SqlDialect\n): TableMetadata[] {\n const metadata = JSON.parse(JSON.stringify(currentMetadata)) as TableMetadata[];\n\n for (const op of operations) {\n if (op.type === \"createTable\") {\n const columns = Object.entries(op.definition.fields).map(([name, field]) => ({\n name,\n dataType: getColumnType(field, dialect),\n isNullable: !field.required && !field.primaryKey,\n isUnique: field.unique || field.primaryKey,\n }));\n metadata.push({ name: op.table, columns });\n } else if (op.type === \"addColumn\") {\n const table = metadata.find((t) => t.name === op.table);\n if (table) {\n table.columns.push({\n name: op.field,\n dataType: getColumnType(op.definition, dialect),\n isNullable: !op.definition.required,\n isUnique: !!op.definition.unique,\n });\n }\n }\n // Handle other operation types (like createIndex) if metadata starts tracking them\n }\n\n return metadata;\n}\n","import type {\n BmSchema,\n FieldDefinition,\n ModelDefinition,\n SqlDialect,\n MigrationOperation,\n} from \"./types\";\nimport { getColumnType } from \"./plan\";\nimport { toDbFieldName } from \"./naming\";\n\nfunction quoteIdent(ident: string, dialect: SqlDialect): string {\n // Keep it simple and safe; Better Media table/field names are controlled.\n if (dialect === \"mysql\") return `\\`${ident}\\``;\n return `\"${ident}\"`;\n}\n\nfunction onDeleteSql(\n onDelete?: FieldDefinition[\"references\"] extends infer R\n ? R extends { onDelete?: infer D }\n ? D | string\n : string\n : string\n): string {\n if (!onDelete) return \"\";\n const normalized = String(onDelete).toUpperCase();\n if (normalized === \"CASCADE\") return \" ON DELETE CASCADE\";\n if (normalized === \"SET NULL\") return \" ON DELETE SET NULL\";\n if (normalized === \"RESTRICT\") return \" ON DELETE RESTRICT\";\n return \"\";\n}\n\nfunction columnSql(\n table: string,\n name: string,\n field: FieldDefinition,\n dialect: SqlDialect\n): string {\n const parts: string[] = [];\n const dbName = toDbFieldName(name);\n parts.push(quoteIdent(dbName, dialect));\n parts.push(getColumnType(field, dialect));\n\n if (field.primaryKey) parts.push(\"PRIMARY KEY\");\n if (field.required) parts.push(\"NOT NULL\");\n if (field.unique) parts.push(\"UNIQUE\");\n\n if (field.references) {\n const ref = field.references;\n const refTable = quoteIdent(ref.model, dialect);\n const refField = quoteIdent(toDbFieldName(ref.field), dialect);\n parts.push(`REFERENCES ${refTable}(${refField})${onDeleteSql(ref.onDelete)}`);\n }\n\n return parts.join(\" \");\n}\n\nfunction createTableSql(table: string, definition: ModelDefinition, dialect: SqlDialect): string {\n const tableName = quoteIdent(table, dialect);\n const cols = Object.entries(definition.fields).map(([name, field]) =>\n columnSql(table, name, field, dialect)\n );\n const ifNotExists = dialect === \"mssql\" ? \"\" : \" IF NOT EXISTS\";\n return `CREATE TABLE${ifNotExists} ${tableName} (\\n ${cols.join(\",\\n \")}\\n);`;\n}\n\nfunction createIndexSql(\n table: string,\n indexName: string,\n fields: string[],\n unique: boolean | undefined,\n dialect: SqlDialect\n): string {\n const idx = quoteIdent(indexName, dialect);\n const tbl = quoteIdent(table, dialect);\n const cols = fields.map((f) => quoteIdent(toDbFieldName(f), dialect)).join(\", \");\n const uniqueSql = unique ? \"UNIQUE \" : \"\";\n const ifNotExists = dialect === \"mssql\" ? \"\" : \" IF NOT EXISTS\";\n return `CREATE ${uniqueSql}INDEX${ifNotExists} ${idx} ON ${tbl} (${cols});`;\n}\n\nfunction addColumnSql(\n table: string,\n field: string,\n definition: FieldDefinition,\n dialect: SqlDialect\n): string {\n const tableName = quoteIdent(table, dialect);\n const columnDef = columnSql(table, field, definition, dialect);\n return `ALTER TABLE ${tableName} ADD COLUMN ${columnDef};`;\n}\n\nexport function compileMigrationOperationsSql(options: {\n operations: MigrationOperation[];\n dialect: SqlDialect;\n}): string {\n const { operations, dialect } = options;\n const statements: string[] = [];\n statements.push(`-- Better Media planned migrations (${dialect})`);\n\n if (dialect === \"sqlite\") {\n statements.push(\"PRAGMA foreign_keys = ON;\");\n }\n\n for (const op of operations) {\n if (op.type === \"createTable\") {\n statements.push(createTableSql(op.table, op.definition, dialect));\n if (op.definition.indexes) {\n for (const index of op.definition.indexes) {\n const indexName = `idx_${op.table}_${index.fields.map((f) => toDbFieldName(f)).join(\"_\")}`;\n statements.push(createIndexSql(op.table, indexName, index.fields, index.unique, dialect));\n }\n }\n continue;\n }\n if (op.type === \"addColumn\") {\n statements.push(addColumnSql(op.table, op.field, op.definition, dialect));\n continue;\n }\n if (op.type === \"createIndex\") {\n statements.push(createIndexSql(op.table, op.name, op.fields, op.unique, dialect));\n }\n }\n\n return statements.join(\"\\n\\n\") + \"\\n\";\n}\n\nexport function generateCreateSchemaSql(options: {\n schema: BmSchema;\n dialect: SqlDialect;\n}): string {\n const { schema, dialect } = options;\n\n const statements: string[] = [];\n statements.push(`-- Better Media schema (${dialect})`);\n\n // SQLite requires foreign keys enabled explicitly per-connection; harmless elsewhere.\n if (dialect === \"sqlite\") {\n statements.push(\"PRAGMA foreign_keys = ON;\");\n }\n\n // Create tables first (FKs reference earlier tables in this schema, but SQL engines allow forward refs too).\n for (const [table, def] of Object.entries(schema)) {\n statements.push(createTableSql(table, def, dialect));\n }\n\n // Create indexes after.\n for (const [table, def] of Object.entries(schema)) {\n if (!def.indexes) continue;\n for (const index of def.indexes) {\n const indexName = `idx_${table}_${index.fields.map((f) => toDbFieldName(f)).join(\"_\")}`;\n statements.push(createIndexSql(table, indexName, index.fields, index.unique, dialect));\n }\n }\n\n return statements.join(\"\\n\\n\") + \"\\n\";\n}\n","import type { DatabaseAdapter } from \"./interfaces/adapter.interface\";\nimport { schema } from \"./schema\";\nimport type { ModelDefinition, TableMetadata, MigrationOperation, SqlDialect } from \"./types\";\nimport { MigrationPlanner } from \"./plan\";\nimport { compileMigrationOperationsSql } from \"./sql\";\n\n/**\n * Internal interface used only by runMigrations. Adapter authors do NOT need to\n * declare or implement this — the migration engine discovers these methods via\n * duck-typing at runtime. Prefix `__` signals framework-internal use.\n */\ninterface MigratableAdapter extends DatabaseAdapter {\n __getMetadata?(): Promise<TableMetadata[]>;\n __executeMigration?(operation: MigrationOperation): Promise<void>;\n __getDialect?(): SqlDialect;\n // Legacy fallback paths\n __createTable?(\n model: string,\n definition: ModelDefinition,\n options: { mode: \"safe\" | \"diff\" | \"force\" }\n ): Promise<void>;\n __initCollection?(\n model: string,\n definition: ModelDefinition,\n options: { mode: \"safe\" | \"diff\" | \"force\" }\n ): Promise<void>;\n}\n\nexport interface MigrationOptions {\n /**\n * Migration mode:\n * - 'safe': Only create missing tables/collections and add missing columns/indexes.\n * - 'diff': Full schema comparison and incremental updates (Recommended).\n * - 'force': Drop and recreate all tables/collections (destructive).\n */\n mode?: \"safe\" | \"diff\" | \"force\";\n /**\n * For SQL adapters, the dialect can be manually specified.\n * If omitted, the adapter will try to detect it.\n */\n dialect?: SqlDialect;\n}\n\nexport interface PlannedMigrationTable {\n table: string;\n fields: string[];\n}\n\nexport interface PlannedMigrations {\n toBeCreated: PlannedMigrationTable[];\n toBeAdded: PlannedMigrationTable[];\n operations: MigrationOperation[];\n compileMigrations: () => string;\n runMigrations: () => Promise<void>;\n}\n\nexport async function getMigrations(\n adapter: DatabaseAdapter,\n options: MigrationOptions = {}\n): Promise<PlannedMigrations> {\n const migratable = adapter as MigratableAdapter;\n\n if (\n typeof migratable.__getMetadata !== \"function\" ||\n typeof migratable.__executeMigration !== \"function\"\n ) {\n return {\n toBeCreated: [],\n toBeAdded: [],\n operations: [],\n compileMigrations: () => \"\",\n runMigrations: async () => {\n throw new Error(\"[BetterMedia] Adapter does not support planned migrations.\");\n },\n };\n }\n\n let dialect = options.dialect;\n if (!dialect && typeof migratable.__getDialect === \"function\") {\n dialect = migratable.__getDialect();\n }\n const resolvedDialect = dialect || \"postgres\";\n const metadata = await migratable.__getMetadata();\n const planner = new MigrationPlanner(resolvedDialect);\n const operations = planner.plan(schema, metadata);\n\n const toBeCreated = operations\n .filter(\n (op): op is Extract<MigrationOperation, { type: \"createTable\" }> => op.type === \"createTable\"\n )\n .map((op) => ({ table: op.table, fields: Object.keys(op.definition.fields) }));\n\n const toBeAdded = operations\n .filter(\n (op): op is Extract<MigrationOperation, { type: \"addColumn\" }> => op.type === \"addColumn\"\n )\n .reduce<PlannedMigrationTable[]>((acc, op) => {\n const existing = acc.find((t) => t.table === op.table);\n if (existing) existing.fields.push(op.field);\n else acc.push({ table: op.table, fields: [op.field] });\n return acc;\n }, []);\n\n return {\n toBeCreated,\n toBeAdded,\n operations,\n compileMigrations: () =>\n compileMigrationOperationsSql({ operations, dialect: resolvedDialect }),\n runMigrations: async () => {\n for (const op of operations) {\n await migratable.__executeMigration!(op);\n }\n },\n };\n}\n\n/**\n * Migration engine. It iterates through the central BmSchema and invokes\n * engine-specific setup commands on the adapter.\n */\nexport async function runMigrations(\n adapter: DatabaseAdapter,\n options: MigrationOptions = {}\n): Promise<void> {\n const mode = options.mode ?? \"safe\";\n const migratable = adapter as MigratableAdapter;\n\n // Preferred path: adapter exposes __getMetadata + __executeMigration\n if (\n typeof migratable.__getMetadata === \"function\" &&\n typeof migratable.__executeMigration === \"function\"\n ) {\n console.log(\"[BetterMedia] Starting planned migration...\");\n\n const { operations, runMigrations: runPlannedMigrations } = await getMigrations(\n adapter,\n options\n );\n\n if (operations.length === 0) {\n console.log(\"[BetterMedia] Database is up to date.\");\n return;\n }\n\n console.log(`[BetterMedia] Plan: ${operations.length} operation(s) to execute.`);\n await runPlannedMigrations();\n console.log(\"[BetterMedia] Migration completed successfully.\");\n return;\n }\n\n // Legacy fallback for MongoDB or unrefactored adapters\n if (typeof migratable.__createTable === \"function\") {\n // Kysely / SQL adapter (Legacy)\n for (const [model, definition] of Object.entries(schema)) {\n await migratable.__createTable(model, definition, { mode });\n }\n } else if (typeof migratable.__initCollection === \"function\") {\n // MongoDB adapter\n for (const [model, definition] of Object.entries(schema)) {\n await migratable.__initCollection(model, definition, { mode });\n }\n } else {\n console.warn(\"[BetterMedia] Adapter does not support automatic migrations.\");\n }\n}\n","import type { WhereClause, DbHooks, DatabaseHookContext } from \"./types\";\n\n/**\n * Utility to run hooks sequentially.\n * Supports multiple handlers and passes DatabaseHookContext.\n */\nexport const runHooks = {\n async beforeCreate(\n hooks: DbHooks | undefined,\n data: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n let currentData = data;\n const handlers = hooks?.before?.create || [];\n for (const handler of handlers) {\n currentData = await handler(currentData, context);\n }\n return currentData;\n },\n\n async beforeUpdate(\n hooks: DbHooks | undefined,\n data: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n let currentData = data;\n const handlers = hooks?.before?.update || [];\n for (const handler of handlers) {\n currentData = await handler(currentData, context);\n }\n return currentData;\n },\n\n async beforeDelete(hooks: DbHooks | undefined, where: WhereClause, context: DatabaseHookContext) {\n const handlers = hooks?.before?.delete || [];\n for (const handler of handlers) {\n await handler(where, context);\n }\n },\n\n async afterCreate(\n hooks: DbHooks | undefined,\n result: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n const handlers = hooks?.after?.create || [];\n for (const handler of handlers) {\n await handler(result, context);\n }\n },\n\n async afterUpdate(\n hooks: DbHooks | undefined,\n result: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n const handlers = hooks?.after?.update || [];\n for (const handler of handlers) {\n await handler(result, context);\n }\n },\n\n async afterDelete(hooks: DbHooks | undefined, where: WhereClause, context: DatabaseHookContext) {\n const handlers = hooks?.after?.delete || [];\n for (const handler of handlers) {\n await handler(where, context);\n }\n },\n};\n","import type { DatabaseAdapter } from \"./interfaces/adapter.interface\";\n\nexport type QueryResultLike<T = unknown> = { rows: T[]; rowCount?: number | null };\n\nexport type Queryable = {\n query: (text: string, values?: unknown[]) => Promise<QueryResultLike<Record<string, unknown>>>;\n};\n\nexport type PgPoolLike = Queryable & {\n connect?: () => Promise<PgClientLike>;\n};\n\nexport type PgClientLike = Queryable & {\n release?: () => void;\n};\n\nexport function isPgPoolLike(value: unknown): value is PgPoolLike {\n return Boolean(\n value && typeof value === \"object\" && typeof (value as { query?: unknown }).query === \"function\"\n );\n}\n\n/**\n * Normalizes a database pool or adapter into a standard DatabaseAdapter.\n * Note: If using the built-in Postgres pool, this requires the actual\n * implementation to be registered or known.\n */\nexport function toDatabaseAdapter(\n database: DatabaseAdapter | PgPoolLike,\n postgresFactory?: (pool: PgPoolLike) => DatabaseAdapter\n): DatabaseAdapter {\n if (isPgPoolLike(database) && typeof (database as { create?: unknown }).create !== \"function\") {\n if (postgresFactory) return postgresFactory(database);\n throw new Error(\n \"[BetterMedia] Postgres pool detected but no adapter factory provided. \" +\n \"This typically means you should use the main @better-media/framework package.\"\n );\n }\n return database as DatabaseAdapter;\n}\n","import type { DatabaseAdapter } from \"../database/interfaces/adapter.interface\";\nimport { toDatabaseAdapter, type PgPoolLike } from \"../database/postgres-utils\";\n\nexport type GetAdapterOptions = {\n database?: DatabaseAdapter | PgPoolLike;\n createDatabase?: () => Promise<DatabaseAdapter | PgPoolLike> | DatabaseAdapter | PgPoolLike;\n dialect?: string;\n schemaOutput?: string;\n migrationsDir?: string;\n};\n\nexport async function getAdapter(options: GetAdapterOptions): Promise<DatabaseAdapter> {\n const database = options.database ?? (await options.createDatabase?.());\n const adapter = database ? toDatabaseAdapter(database) : undefined;\n if (!adapter) {\n throw new Error(\n `[media] Failed to initialize database adapter. Provide \"database\" or \"createDatabase()\".`\n );\n }\n return adapter;\n}\n","/**\n * Mapping of common file extensions to their valid MIME types.\n * Based on MDN Common Media Types: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types\n */\nexport const EXTENSION_TO_MIME_MAP: Record<string, string[]> = {\n \".aac\": [\"audio/aac\"],\n \".abw\": [\"application/x-abiword\"],\n \".apng\": [\"image/apng\"],\n \".arc\": [\"application/x-freearc\"],\n \".avif\": [\"image/avif\"],\n \".avi\": [\"video/x-msvideo\"],\n \".azw\": [\"application/vnd.amazon.ebook\"],\n \".bin\": [\"application/octet-stream\"],\n \".bmp\": [\"image/bmp\"],\n \".bz\": [\"application/x-bzip\"],\n \".bz2\": [\"application/x-bzip2\"],\n \".cda\": [\"application/x-cdf\"],\n \".csh\": [\"application/x-csh\"],\n \".css\": [\"text/css\"],\n \".csv\": [\"text/csv\"],\n \".doc\": [\"application/msword\"],\n \".docx\": [\"application/vnd.openxmlformats-officedocument.wordprocessingml.document\"],\n \".eot\": [\"application/vnd.ms-fontobject\"],\n \".epub\": [\"application/epub+zip\"],\n \".gz\": [\"application/gzip\", \"application/x-gzip\"],\n \".gif\": [\"image/gif\"],\n \".htm\": [\"text/html\"],\n \".html\": [\"text/html\"],\n \".ico\": [\"image/vnd.microsoft.icon\"],\n \".ics\": [\"text/calendar\"],\n \".jar\": [\"application/java-archive\"],\n \".jpeg\": [\"image/jpeg\"],\n \".jpg\": [\"image/jpeg\"],\n \".js\": [\"text/javascript\"],\n \".mjs\": [\"text/javascript\"],\n \".json\": [\"application/json\"],\n \".jsonld\": [\"application/ld+json\"],\n \".md\": [\"text/markdown\"],\n \".mid\": [\"audio/midi\", \"audio/x-midi\"],\n \".midi\": [\"audio/midi\", \"audio/x-midi\"],\n \".mp3\": [\"audio/mpeg\"],\n \".mp4\": [\"video/mp4\"],\n \".mpeg\": [\"video/mpeg\"],\n \".mpkg\": [\"application/vnd.apple.installer+xml\"],\n \".odp\": [\"application/vnd.oasis.opendocument.presentation\"],\n \".ods\": [\"application/vnd.oasis.opendocument.spreadsheet\"],\n \".odt\": [\"application/vnd.oasis.opendocument.text\"],\n \".oga\": [\"audio/ogg\"],\n \".ogv\": [\"video/ogg\"],\n \".ogx\": [\"application/ogg\"],\n \".opus\": [\"audio/ogg\"],\n \".otf\": [\"font/otf\"],\n \".png\": [\"image/png\"],\n \".pdf\": [\"application/pdf\"],\n \".php\": [\"application/x-httpd-php\"],\n \".ppt\": [\"application/vnd.ms-powerpoint\"],\n \".pptx\": [\"application/vnd.openxmlformats-officedocument.presentationml.presentation\"],\n \".rar\": [\"application/vnd.rar\"],\n \".rtf\": [\"application/rtf\"],\n \".sh\": [\"application/x-sh\"],\n \".svg\": [\"image/svg+xml\"],\n \".tar\": [\"application/x-tar\"],\n \".tif\": [\"image/tiff\"],\n \".tiff\": [\"image/tiff\"],\n \".ts\": [\"video/mp2t\"],\n \".ttf\": [\"font/ttf\"],\n \".txt\": [\"text/plain\"],\n \".vsd\": [\"application/vnd.visio\"],\n \".wav\": [\"audio/wav\"],\n \".weba\": [\"audio/webm\"],\n \".webm\": [\"video/webm\"],\n \".webmanifest\": [\"application/manifest+json\"],\n \".webp\": [\"image/webp\"],\n \".woff\": [\"font/woff\"],\n \".woff2\": [\"font/woff2\"],\n \".xhtml\": [\"application/xhtml+xml\"],\n \".xls\": [\"application/vnd.ms-excel\"],\n \".xlsx\": [\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\"],\n \".xml\": [\"application/xml\", \"text/xml\", \"application/atom+xml\"],\n \".xul\": [\"application/vnd.mozilla.xul+xml\"],\n \".zip\": [\"application/zip\", \"application/x-zip-compressed\"],\n \".3gp\": [\"video/3gpp\", \"audio/3gpp\"],\n \".3g2\": [\"video/3gpp2\", \"audio/3gpp2\"],\n \".7z\": [\"application/x-7z-compressed\"],\n};\n","// Core types and utilities\nexport type MediaStatus = \"PENDING_VERIFICATION\" | \"VALID\" | \"INVALID\" | \"PROCESSING\" | \"COMPLETED\";\n\nexport function sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport { HOOK_NAMES, HOOK_MODE_CONSTRAINTS, resolveHookMode } from \"./plugin/index\";\nexport type {\n PipelinePlugin,\n PipelineContext,\n FileInfo,\n FileContent,\n StorageLocation,\n ProcessingResults,\n ThumbnailResult,\n VariantResult,\n MediaDimensions,\n PluginExecutionMode,\n PluginHooks,\n HookName,\n HookHandler,\n HookHandlerOptions,\n HookModeConstraint,\n MediaPlugin,\n HookContext,\n MediaRuntime,\n MediaRuntimeHook,\n ValidationResult,\n TrustedMetadata,\n PluginManifest,\n PluginApi,\n} from \"./plugin/index\";\nexport {\n ValidationResultSchema,\n VirusScanResultSchema,\n TrustedMetadataSchema,\n markFileContentVerified,\n} from \"./plugin/index\";\nexport type { VerifiedSourceId, PipelineContextWithVerified } from \"./plugin/index\";\nexport type {\n StorageAdapter,\n GetUrlOptions,\n PresignedUploadMethod,\n PresignedUploadOptions,\n PresignedUploadResult,\n StorageObject,\n ListResult,\n ListOptions,\n} from \"./storage/index\";\nexport type {\n DatabaseAdapter,\n DatabaseTransactionAdapter,\n WhereClause,\n CreateOptions,\n FindOptions,\n UpdateOptions,\n DeleteOptions,\n CountOptions,\n} from \"./database/index\";\nexport type { JobAdapter } from \"./job/index\";\nexport * from \"./database/index\";\nexport type { DatabaseHookContext } from \"./database/index\";\nexport { getAdapter, type GetAdapterOptions } from \"./adapter/get-adapter\";\nexport { EXTENSION_TO_MIME_MAP } from \"./constants/mime-types\";\n"]}
1
+ {"version":3,"sources":["../src/plugin/verified-sources.ts","../src/plugin/interfaces/trusted-metadata.interface.ts","../src/plugin/interfaces/hook-name.interface.ts","../src/plugin/interfaces/hook-mode.interface.ts","../src/plugin/interfaces/media-runtime.interface.ts","../src/database/schema.ts","../src/database/naming.ts","../src/database/fields.ts","../src/database/plan.ts","../src/database/sql.ts","../src/database/migration.ts","../src/database/hooks.ts","../src/database/postgres-utils.ts","../src/adapter/get-adapter.ts","../src/constants/mime-types.ts","../src/index.ts"],"names":["z","schema"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { PipelineContext } from \"./interfaces/context.interface\";\n\n/** Provenance tokens for trusted metadata (e.g. proposeTrusted). */\nexport type VerifiedSourceId = \"file:content\";\n\nexport interface PipelineContextWithVerified extends PipelineContext {\n _verifiedSources?: Set<VerifiedSourceId>;\n}\n\n/**\n * Mark that this pipeline run has read file bytes from storage (buffer or temp path).\n * Required before trusted plugins may call proposeTrusted with file/checksums/media patches.\n */\nexport function markFileContentVerified(context: PipelineContext): void {\n const c = context as PipelineContextWithVerified;\n c._verifiedSources ??= new Set();\n c._verifiedSources.add(\"file:content\");\n}\n","import { z } from \"zod\";\n\n/**\n * Zod Schema for Trusted Metadata.\n * Strictly enforced to prevent trust injection from the database.\n */\nexport const TrustedMetadataSchema = z\n .object({\n file: z\n .object({\n mimeType: z.string().optional(),\n size: z.number().int().nonnegative().optional(),\n originalName: z.string().optional(),\n extension: z.string().optional(),\n })\n .strict()\n .optional(),\n checksums: z\n .object({\n sha256: z.string().optional(),\n md5: z.string().optional(),\n })\n .strict()\n .optional(),\n media: z\n .object({\n width: z.number().int().nonnegative().optional(),\n height: z.number().int().nonnegative().optional(),\n duration: z.number().nonnegative().optional(),\n })\n .strict()\n .optional(),\n })\n .strict();\n\n/** Metadata from DB/Trusted Sources (Schema validated) */\nexport type TrustedMetadata = z.infer<typeof TrustedMetadataSchema>;\n","/** Lifecycle hook names (aligns with AWS/Cloudinary media pipeline stages). Single source of truth. */\nexport const HOOK_NAMES = [\n \"upload:init\",\n \"validation:run\",\n \"scan:run\",\n \"process:run\",\n \"upload:complete\",\n] as const;\n\nexport type HookName = (typeof HOOK_NAMES)[number];\n","import type { HookName } from \"./hook-name.interface\";\n\n/**\n * Hook-level execution mode constraint.\n * - sync-only: Handler always runs inline. Passing background is overridden with a warning.\n * - sync-or-background: Plugin may choose either; both are valid.\n * - background-only: Handler always runs enqueued. Passing sync is overridden with a warning.\n */\nexport type HookModeConstraint = \"sync-only\" | \"sync-or-background\" | \"background-only\";\n\n/** Per-hook mode constraints. Single source of truth for hook execution rules. */\nexport const HOOK_MODE_CONSTRAINTS: Record<HookName, HookModeConstraint> = {\n \"upload:init\": \"sync-only\",\n \"validation:run\": \"sync-only\",\n \"scan:run\": \"sync-only\",\n \"process:run\": \"sync-or-background\",\n \"upload:complete\": \"sync-or-background\",\n};\n\n/**\n * Resolve effective execution mode given hook constraint and requested mode.\n * Returns the mode to use and whether it was overridden (for logging).\n */\nexport function resolveHookMode(\n hookName: HookName,\n requested: \"sync\" | \"background\"\n): { effective: \"sync\" | \"background\"; overridden: boolean } {\n const constraint = HOOK_MODE_CONSTRAINTS[hookName];\n\n if (constraint === \"sync-only\" && requested === \"background\") {\n return { effective: \"sync\", overridden: true };\n }\n if (constraint === \"background-only\" && requested === \"sync\") {\n return { effective: \"background\", overridden: true };\n }\n\n return { effective: requested, overridden: false };\n}\n","import { z } from \"zod\";\nimport type { PipelineContext, PluginApi } from \"./context.interface\";\nimport type { HookName } from \"./hook-name.interface\";\n\n/**\n * Result from validation-phase handlers; can abort pipeline.\n * Persisted to 'validation_results' table.\n */\nexport const ValidationResultSchema = z\n .object({\n valid: z.boolean(),\n pluginId: z.string().optional(),\n message: z.string().optional(),\n errors: z.array(z.string()).optional(),\n })\n .strict();\n\nexport type ValidationResult = z.infer<typeof ValidationResultSchema>;\n\n/**\n * Result from virus-scan handlers.\n * Persisted to 'virus_scan_results' table.\n */\nexport const VirusScanResultSchema = z\n .object({\n status: z.enum([\"clean\", \"infected\", \"error\"]),\n threats: z.array(z.string()).optional(),\n scanner: z.string().optional(),\n scannedAt: z.string().datetime().optional(),\n })\n .strict();\n\nexport type VirusScanResult = z.infer<typeof VirusScanResultSchema>;\n\n/** Hook interface for plugin registration (Tapable-style) */\nexport interface MediaRuntimeHook {\n tap(\n name: string,\n fn: (ctx: PipelineContext, api: PluginApi) => Promise<void | ValidationResult>,\n options?: { mode?: \"sync\" | \"background\" }\n ): void;\n}\n\n/** Runtime host passed to plugins via apply(); exposes lifecycle hooks */\nexport interface MediaRuntime {\n readonly hooks: {\n [K in HookName]: MediaRuntimeHook;\n };\n}\n","import type { BmSchema } from \"./types\";\n\n/**\n * Central schema defining all Better Media tables and relationships.\n * This is the single source of truth for the database structure.\n */\nexport const schema: BmSchema = {\n // Core media records\n media: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n ownerId: { type: \"string\" },\n filename: { type: \"string\" },\n extension: { type: \"string\" },\n mimeType: { type: \"string\" },\n size: { type: \"number\" },\n storageProvider: { type: \"string\" },\n storageKey: { type: \"string\" },\n checksumSha256: { type: \"string\" },\n checksumMd5: { type: \"string\" },\n width: { type: \"number\" },\n height: { type: \"number\" },\n duration: { type: \"number\" },\n metadata: { type: \"json\" },\n status: { type: \"string\" }, // 'pending' | 'processing' | 'ready' | 'failed' | 'quarantined'\n visibility: { type: \"string\" }, // 'public' | 'private' | 'unlisted'\n createdAt: { type: \"date\" },\n updatedAt: { type: \"date\" },\n deletedAt: { type: \"date\" },\n },\n indexes: [{ fields: [\"checksumSha256\", \"storageKey\"] }],\n },\n\n // Different versions of the media (thumbnails, previews, etc.)\n media_versions: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: {\n model: \"media\",\n field: \"id\",\n onDelete: \"cascade\",\n },\n },\n storageProvider: { type: \"string\" },\n storageKey: { type: \"string\" },\n checksumSha256: { type: \"string\" },\n mimeType: { type: \"string\" },\n size: { type: \"number\" },\n width: { type: \"number\" },\n height: { type: \"number\" },\n isOriginal: { type: \"boolean\" },\n type: { type: \"string\" }, // 'thumbnail' | 'preview' | 'compressed' | 'original'\n versionNumber: { type: \"number\" },\n createdAt: { type: \"date\" },\n deletedAt: { type: \"date\" },\n },\n indexes: [{ fields: [\"mediaId\"] }, { fields: [\"mediaId\", \"versionNumber\"], unique: true }],\n },\n\n // Business record for media processing jobs — not a BullMQ state mirror.\n // Tracks idempotency, final outcome, and links jobs to media.\n // Runtime state (queue position, locks, backoff) lives in BullMQ/Redis.\n media_jobs: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: {\n model: \"media\",\n field: \"id\",\n onDelete: \"cascade\",\n },\n },\n type: { type: \"string\" }, // 'virus-scan' | 'thumbnail' | 'compress' | 'validate'\n status: { type: \"string\" }, // 'pending' | 'running' | 'completed' | 'failed'\n attempts: { type: \"number\" },\n maxAttempts: { type: \"number\" },\n idempotencyKey: { type: \"string\", unique: true },\n scheduledAt: { type: \"date\" },\n startedAt: { type: \"date\" },\n completedAt: { type: \"date\" },\n error: { type: \"json\" }, // { message, code, stack, retryable }\n result: { type: \"json\" },\n createdAt: { type: \"date\" },\n updatedAt: { type: \"date\" },\n },\n indexes: [{ fields: [\"mediaId\"] }],\n },\n\n media_validation_results: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: { model: \"media\", field: \"id\", onDelete: \"cascade\" },\n },\n valid: { type: \"boolean\" },\n pluginId: { type: \"string\" },\n errors: { type: \"json\" },\n warnings: { type: \"json\" },\n createdAt: { type: \"date\" },\n },\n indexes: [{ fields: [\"mediaId\"] }],\n },\n\n media_virus_scan_results: {\n fields: {\n id: { type: \"string\", primaryKey: true, required: true },\n mediaId: {\n type: \"string\",\n references: { model: \"media\", field: \"id\", onDelete: \"cascade\" },\n },\n status: { type: \"string\" }, // 'clean' | 'infected' | 'error'\n threats: { type: \"json\" },\n scanner: { type: \"string\" },\n metadata: { type: \"json\" },\n createdAt: { type: \"date\" },\n },\n indexes: [{ fields: [\"mediaId\"] }],\n },\n};\n","export function toSnakeCase(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/[\\s-]+/g, \"_\")\n .toLowerCase();\n}\n\nexport function toCamelCase(value: string): string {\n return value.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\nexport function toDbFieldName(field: string): string {\n return toSnakeCase(field);\n}\n","import type { FieldType } from \"./types\";\n\nexport interface FieldConverter {\n serialize(value: unknown): unknown;\n deserialize(value: unknown): unknown;\n}\n\nexport const converters: Record<FieldType, FieldConverter> = {\n json: {\n serialize: (value) => (value === undefined ? undefined : JSON.stringify(value)),\n deserialize: (value) => (typeof value === \"string\" ? JSON.parse(value) : value),\n },\n date: {\n serialize: (value) =>\n value instanceof Date ? value.toISOString() : typeof value === \"string\" ? value : value,\n deserialize: (value) => (typeof value === \"string\" ? new Date(value) : value),\n },\n boolean: {\n serialize: (value) => (typeof value === \"boolean\" ? (value ? 1 : 0) : value),\n deserialize: (value) => (typeof value === \"number\" ? value === 1 : Boolean(value)),\n },\n string: {\n serialize: (value) => value,\n deserialize: (value) => (typeof value === \"number\" ? String(value) : value),\n },\n number: {\n serialize: (value) => (typeof value === \"string\" ? Number(value) : value),\n deserialize: (value) => value,\n },\n};\n\nexport function serializeField(type: FieldType, value: unknown): unknown {\n if (value === null || value === undefined) return value;\n return converters[type]?.serialize(value) ?? value;\n}\n\nexport function deserializeField(type: FieldType, value: unknown): unknown {\n if (value === null || value === undefined) return value;\n return converters[type]?.deserialize(value) ?? value;\n}\n\nexport function serializeData(\n fields: Record<string, { type: FieldType }>,\n data: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (fields[key]) {\n result[key] = serializeField(fields[key].type, value);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\nexport function deserializeData(\n fields: Record<string, { type: FieldType }>,\n data: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n if (fields[key]) {\n result[key] = deserializeField(fields[key].type, value);\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n","import type {\n BmSchema,\n FieldDefinition,\n FieldType,\n SqlDialect,\n TableMetadata,\n MigrationOperation,\n} from \"./types\";\n\nconst dialectMap: Record<FieldType, Record<SqlDialect, string>> = {\n string: {\n postgres: \"text\",\n mysql: \"varchar(255)\",\n sqlite: \"text\",\n mssql: \"varchar(255)\",\n },\n number: {\n postgres: \"integer\",\n mysql: \"integer\",\n sqlite: \"integer\",\n mssql: \"integer\",\n },\n boolean: {\n postgres: \"boolean\",\n mysql: \"boolean\",\n sqlite: \"integer\",\n mssql: \"bit\",\n },\n date: {\n postgres: \"timestamp\",\n mysql: \"datetime\",\n sqlite: \"text\",\n mssql: \"datetime2\",\n },\n json: {\n postgres: \"jsonb\",\n mysql: \"json\",\n sqlite: \"text\",\n mssql: \"nvarchar(max)\",\n },\n};\n\nexport function getColumnType(field: FieldDefinition, dialect: SqlDialect): string {\n // Overrides for specific cases\n if (field.primaryKey && field.type === \"string\") {\n if (dialect === \"postgres\") return \"uuid\";\n return dialect === \"mysql\" || dialect === \"mssql\" ? \"varchar(36)\" : \"text\";\n }\n if (field.references && field.type === \"string\" && dialect === \"postgres\") {\n return \"uuid\";\n }\n\n const types = dialectMap[field.type];\n if (!types) return \"text\";\n\n const type = types[dialect];\n return type || \"text\";\n}\n\nexport function matchType(dbType: string, expectedType: FieldType, dialect: SqlDialect): boolean {\n const normalizedDb = (dbType.toLowerCase().split(\"(\")[0] || \"\").trim();\n const normalizedMap: Record<SqlDialect, Record<FieldType, string[]>> = {\n postgres: {\n string: [\"character varying\", \"varchar\", \"text\", \"uuid\"],\n number: [\"int4\", \"integer\", \"bigint\", \"smallint\", \"numeric\", \"real\", \"double precision\"],\n boolean: [\"bool\", \"boolean\"],\n date: [\"timestamptz\", \"timestamp\", \"date\"],\n json: [\"json\", \"jsonb\"],\n },\n mysql: {\n string: [\"varchar\", \"text\", \"uuid\", \"char\"],\n number: [\"integer\", \"int\", \"bigint\", \"smallint\", \"decimal\", \"float\", \"double\"],\n boolean: [\"boolean\", \"tinyint\", \"bit\"],\n date: [\"timestamp\", \"datetime\", \"date\"],\n json: [\"json\", \"text\", \"longtext\"],\n },\n sqlite: {\n string: [\"text\", \"varchar\"],\n number: [\"integer\", \"real\", \"numeric\"],\n boolean: [\"integer\", \"boolean\"],\n date: [\"date\", \"text\", \"integer\"],\n json: [\"text\"],\n },\n mssql: {\n string: [\"varchar\", \"nvarchar\", \"uniqueidentifier\"],\n number: [\"int\", \"bigint\", \"smallint\", \"decimal\", \"float\", \"double\", \"numeric\"],\n boolean: [\"bit\", \"smallint\"],\n date: [\"datetime2\", \"date\", \"datetime\", \"timestamp\"],\n json: [\"varchar\", \"nvarchar\"],\n },\n };\n\n return normalizedMap[dialect][expectedType].includes(normalizedDb);\n}\n\n/**\n * MigrationPlanner calculates the delta between the desired schema and the actual DB state.\n */\nexport class MigrationPlanner {\n constructor(private readonly dialect: SqlDialect) {}\n\n plan(schema: BmSchema, currentTables: TableMetadata[]): MigrationOperation[] {\n const operations: MigrationOperation[] = [];\n\n for (const [tableName, model] of Object.entries(schema)) {\n const existingTable = currentTables.find((t) => t.name === tableName);\n\n if (!existingTable) {\n // Table doesn't exist\n operations.push({ type: \"createTable\", table: tableName, definition: model });\n continue;\n }\n\n // Table exists, check for missing columns\n for (const [fieldName, fieldDef] of Object.entries(model.fields)) {\n const existingColumn = existingTable.columns.find((c) => c.name === fieldName);\n\n if (!existingColumn) {\n operations.push({\n type: \"addColumn\",\n table: tableName,\n field: fieldName,\n definition: fieldDef,\n });\n } else {\n // Optional: Check for type mismatches (logging only for now to avoid destructive changes)\n if (!matchType(existingColumn.dataType, fieldDef.type, this.dialect)) {\n console.warn(\n `[BetterMedia] Type mismatch for ${tableName}.${fieldName}: ` +\n `Expected ${fieldDef.type} but found ${existingColumn.dataType} in DB.`\n );\n }\n }\n }\n\n // Missing indexes: not yet diffed against DB metadata (createIndex ops TBD).\n }\n\n return operations;\n }\n}\n\n/**\n * Applies a list of migration operations to an existing metadata state to project\n * what the database will look like after the migration.\n */\nexport function applyOperationsToMetadata(\n currentMetadata: TableMetadata[],\n operations: MigrationOperation[],\n dialect: SqlDialect\n): TableMetadata[] {\n const metadata = JSON.parse(JSON.stringify(currentMetadata)) as TableMetadata[];\n\n for (const op of operations) {\n if (op.type === \"createTable\") {\n const columns = Object.entries(op.definition.fields).map(([name, field]) => ({\n name,\n dataType: getColumnType(field, dialect),\n isNullable: !field.required && !field.primaryKey,\n isUnique: field.unique || field.primaryKey,\n }));\n metadata.push({ name: op.table, columns });\n } else if (op.type === \"addColumn\") {\n const table = metadata.find((t) => t.name === op.table);\n if (table) {\n table.columns.push({\n name: op.field,\n dataType: getColumnType(op.definition, dialect),\n isNullable: !op.definition.required,\n isUnique: !!op.definition.unique,\n });\n }\n }\n // Handle other operation types (like createIndex) if metadata starts tracking them\n }\n\n return metadata;\n}\n","import type {\n BmSchema,\n FieldDefinition,\n ModelDefinition,\n SqlDialect,\n MigrationOperation,\n} from \"./types\";\nimport { getColumnType } from \"./plan\";\nimport { toDbFieldName } from \"./naming\";\n\nfunction quoteIdent(ident: string, dialect: SqlDialect): string {\n // Keep it simple and safe; Better Media table/field names are controlled.\n if (dialect === \"mysql\") return `\\`${ident}\\``;\n return `\"${ident}\"`;\n}\n\nfunction onDeleteSql(\n onDelete?: FieldDefinition[\"references\"] extends infer R\n ? R extends { onDelete?: infer D }\n ? D | string\n : string\n : string\n): string {\n if (!onDelete) return \"\";\n const normalized = String(onDelete).toUpperCase();\n if (normalized === \"CASCADE\") return \" ON DELETE CASCADE\";\n if (normalized === \"SET NULL\") return \" ON DELETE SET NULL\";\n if (normalized === \"RESTRICT\") return \" ON DELETE RESTRICT\";\n return \"\";\n}\n\nfunction columnSql(\n table: string,\n name: string,\n field: FieldDefinition,\n dialect: SqlDialect\n): string {\n const parts: string[] = [];\n const dbName = toDbFieldName(name);\n parts.push(quoteIdent(dbName, dialect));\n parts.push(getColumnType(field, dialect));\n\n if (field.primaryKey) parts.push(\"PRIMARY KEY\");\n if (field.required) parts.push(\"NOT NULL\");\n if (field.unique) parts.push(\"UNIQUE\");\n\n if (field.references) {\n const ref = field.references;\n const refTable = quoteIdent(ref.model, dialect);\n const refField = quoteIdent(toDbFieldName(ref.field), dialect);\n parts.push(`REFERENCES ${refTable}(${refField})${onDeleteSql(ref.onDelete)}`);\n }\n\n return parts.join(\" \");\n}\n\nfunction createTableSql(table: string, definition: ModelDefinition, dialect: SqlDialect): string {\n const tableName = quoteIdent(table, dialect);\n const cols = Object.entries(definition.fields).map(([name, field]) =>\n columnSql(table, name, field, dialect)\n );\n const ifNotExists = dialect === \"mssql\" ? \"\" : \" IF NOT EXISTS\";\n return `CREATE TABLE${ifNotExists} ${tableName} (\\n ${cols.join(\",\\n \")}\\n);`;\n}\n\nfunction createIndexSql(\n table: string,\n indexName: string,\n fields: string[],\n unique: boolean | undefined,\n dialect: SqlDialect\n): string {\n const idx = quoteIdent(indexName, dialect);\n const tbl = quoteIdent(table, dialect);\n const cols = fields.map((f) => quoteIdent(toDbFieldName(f), dialect)).join(\", \");\n const uniqueSql = unique ? \"UNIQUE \" : \"\";\n const ifNotExists = dialect === \"mssql\" ? \"\" : \" IF NOT EXISTS\";\n return `CREATE ${uniqueSql}INDEX${ifNotExists} ${idx} ON ${tbl} (${cols});`;\n}\n\nfunction addColumnSql(\n table: string,\n field: string,\n definition: FieldDefinition,\n dialect: SqlDialect\n): string {\n const tableName = quoteIdent(table, dialect);\n const columnDef = columnSql(table, field, definition, dialect);\n return `ALTER TABLE ${tableName} ADD COLUMN ${columnDef};`;\n}\n\nexport function compileMigrationOperationsSql(options: {\n operations: MigrationOperation[];\n dialect: SqlDialect;\n}): string {\n const { operations, dialect } = options;\n const statements: string[] = [];\n statements.push(`-- Better Media planned migrations (${dialect})`);\n\n if (dialect === \"sqlite\") {\n statements.push(\"PRAGMA foreign_keys = ON;\");\n }\n\n for (const op of operations) {\n if (op.type === \"createTable\") {\n statements.push(createTableSql(op.table, op.definition, dialect));\n if (op.definition.indexes) {\n for (const index of op.definition.indexes) {\n const indexName = `idx_${op.table}_${index.fields.map((f) => toDbFieldName(f)).join(\"_\")}`;\n statements.push(createIndexSql(op.table, indexName, index.fields, index.unique, dialect));\n }\n }\n continue;\n }\n if (op.type === \"addColumn\") {\n statements.push(addColumnSql(op.table, op.field, op.definition, dialect));\n continue;\n }\n if (op.type === \"createIndex\") {\n statements.push(createIndexSql(op.table, op.name, op.fields, op.unique, dialect));\n }\n }\n\n return statements.join(\"\\n\\n\") + \"\\n\";\n}\n\nexport function generateCreateSchemaSql(options: {\n schema: BmSchema;\n dialect: SqlDialect;\n}): string {\n const { schema, dialect } = options;\n\n const statements: string[] = [];\n statements.push(`-- Better Media schema (${dialect})`);\n\n // SQLite requires foreign keys enabled explicitly per-connection; harmless elsewhere.\n if (dialect === \"sqlite\") {\n statements.push(\"PRAGMA foreign_keys = ON;\");\n }\n\n // Create tables first (FKs reference earlier tables in this schema, but SQL engines allow forward refs too).\n for (const [table, def] of Object.entries(schema)) {\n statements.push(createTableSql(table, def, dialect));\n }\n\n // Create indexes after.\n for (const [table, def] of Object.entries(schema)) {\n if (!def.indexes) continue;\n for (const index of def.indexes) {\n const indexName = `idx_${table}_${index.fields.map((f) => toDbFieldName(f)).join(\"_\")}`;\n statements.push(createIndexSql(table, indexName, index.fields, index.unique, dialect));\n }\n }\n\n return statements.join(\"\\n\\n\") + \"\\n\";\n}\n","import type { DatabaseAdapter } from \"./interfaces/adapter.interface\";\nimport { schema } from \"./schema\";\nimport type { ModelDefinition, TableMetadata, MigrationOperation, SqlDialect } from \"./types\";\nimport { MigrationPlanner } from \"./plan\";\nimport { compileMigrationOperationsSql } from \"./sql\";\n\n/**\n * Internal interface used only by runMigrations. Adapter authors do NOT need to\n * declare or implement this — the migration engine discovers these methods via\n * duck-typing at runtime. Prefix `__` signals framework-internal use.\n */\ninterface MigratableAdapter extends DatabaseAdapter {\n __getMetadata?(): Promise<TableMetadata[]>;\n __executeMigration?(operation: MigrationOperation): Promise<void>;\n __getDialect?(): SqlDialect;\n // Legacy fallback paths\n __createTable?(\n model: string,\n definition: ModelDefinition,\n options: { mode: \"safe\" | \"diff\" | \"force\" }\n ): Promise<void>;\n __initCollection?(\n model: string,\n definition: ModelDefinition,\n options: { mode: \"safe\" | \"diff\" | \"force\" }\n ): Promise<void>;\n}\n\nexport interface MigrationOptions {\n /**\n * Migration mode:\n * - 'safe': Only create missing tables/collections and add missing columns/indexes.\n * - 'diff': Full schema comparison and incremental updates (Recommended).\n * - 'force': Drop and recreate all tables/collections (destructive).\n */\n mode?: \"safe\" | \"diff\" | \"force\";\n /**\n * For SQL adapters, the dialect can be manually specified.\n * If omitted, the adapter will try to detect it.\n */\n dialect?: SqlDialect;\n}\n\nexport interface PlannedMigrationTable {\n table: string;\n fields: string[];\n}\n\nexport interface PlannedMigrations {\n toBeCreated: PlannedMigrationTable[];\n toBeAdded: PlannedMigrationTable[];\n operations: MigrationOperation[];\n compileMigrations: () => string;\n runMigrations: () => Promise<void>;\n}\n\nexport async function getMigrations(\n adapter: DatabaseAdapter,\n options: MigrationOptions = {}\n): Promise<PlannedMigrations> {\n const migratable = adapter as MigratableAdapter;\n\n if (\n typeof migratable.__getMetadata !== \"function\" ||\n typeof migratable.__executeMigration !== \"function\"\n ) {\n return {\n toBeCreated: [],\n toBeAdded: [],\n operations: [],\n compileMigrations: () => \"\",\n runMigrations: async () => {\n throw new Error(\"[BetterMedia] Adapter does not support planned migrations.\");\n },\n };\n }\n\n let dialect = options.dialect;\n if (!dialect && typeof migratable.__getDialect === \"function\") {\n dialect = migratable.__getDialect();\n }\n const resolvedDialect = dialect || \"postgres\";\n const metadata = await migratable.__getMetadata();\n const planner = new MigrationPlanner(resolvedDialect);\n const operations = planner.plan(schema, metadata);\n\n const toBeCreated = operations\n .filter(\n (op): op is Extract<MigrationOperation, { type: \"createTable\" }> => op.type === \"createTable\"\n )\n .map((op) => ({ table: op.table, fields: Object.keys(op.definition.fields) }));\n\n const toBeAdded = operations\n .filter(\n (op): op is Extract<MigrationOperation, { type: \"addColumn\" }> => op.type === \"addColumn\"\n )\n .reduce<PlannedMigrationTable[]>((acc, op) => {\n const existing = acc.find((t) => t.table === op.table);\n if (existing) existing.fields.push(op.field);\n else acc.push({ table: op.table, fields: [op.field] });\n return acc;\n }, []);\n\n return {\n toBeCreated,\n toBeAdded,\n operations,\n compileMigrations: () =>\n compileMigrationOperationsSql({ operations, dialect: resolvedDialect }),\n runMigrations: async () => {\n for (const op of operations) {\n await migratable.__executeMigration!(op);\n }\n },\n };\n}\n\n/**\n * Migration engine. It iterates through the central BmSchema and invokes\n * engine-specific setup commands on the adapter.\n */\nexport async function runMigrations(\n adapter: DatabaseAdapter,\n options: MigrationOptions = {}\n): Promise<void> {\n const mode = options.mode ?? \"safe\";\n const migratable = adapter as MigratableAdapter;\n\n // Preferred path: adapter exposes __getMetadata + __executeMigration\n if (\n typeof migratable.__getMetadata === \"function\" &&\n typeof migratable.__executeMigration === \"function\"\n ) {\n console.log(\"[BetterMedia] Starting planned migration...\");\n\n const { operations, runMigrations: runPlannedMigrations } = await getMigrations(\n adapter,\n options\n );\n\n if (operations.length === 0) {\n console.log(\"[BetterMedia] Database is up to date.\");\n return;\n }\n\n console.log(`[BetterMedia] Plan: ${operations.length} operation(s) to execute.`);\n await runPlannedMigrations();\n console.log(\"[BetterMedia] Migration completed successfully.\");\n return;\n }\n\n // Legacy fallback for MongoDB or unrefactored adapters\n if (typeof migratable.__createTable === \"function\") {\n // Kysely / SQL adapter (Legacy)\n for (const [model, definition] of Object.entries(schema)) {\n await migratable.__createTable(model, definition, { mode });\n }\n } else if (typeof migratable.__initCollection === \"function\") {\n // MongoDB adapter\n for (const [model, definition] of Object.entries(schema)) {\n await migratable.__initCollection(model, definition, { mode });\n }\n } else {\n console.warn(\"[BetterMedia] Adapter does not support automatic migrations.\");\n }\n}\n","import type { WhereClause, DbHooks, DatabaseHookContext } from \"./types\";\n\n/**\n * Utility to run hooks sequentially.\n * Supports multiple handlers and passes DatabaseHookContext.\n */\nexport const runHooks = {\n async beforeCreate(\n hooks: DbHooks | undefined,\n data: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n let currentData = data;\n const handlers = hooks?.before?.create || [];\n for (const handler of handlers) {\n currentData = await handler(currentData, context);\n }\n return currentData;\n },\n\n async beforeUpdate(\n hooks: DbHooks | undefined,\n data: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n let currentData = data;\n const handlers = hooks?.before?.update || [];\n for (const handler of handlers) {\n currentData = await handler(currentData, context);\n }\n return currentData;\n },\n\n async beforeDelete(hooks: DbHooks | undefined, where: WhereClause, context: DatabaseHookContext) {\n const handlers = hooks?.before?.delete || [];\n for (const handler of handlers) {\n await handler(where, context);\n }\n },\n\n async afterCreate(\n hooks: DbHooks | undefined,\n result: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n const handlers = hooks?.after?.create || [];\n for (const handler of handlers) {\n await handler(result, context);\n }\n },\n\n async afterUpdate(\n hooks: DbHooks | undefined,\n result: Record<string, unknown>,\n context: DatabaseHookContext\n ) {\n const handlers = hooks?.after?.update || [];\n for (const handler of handlers) {\n await handler(result, context);\n }\n },\n\n async afterDelete(hooks: DbHooks | undefined, where: WhereClause, context: DatabaseHookContext) {\n const handlers = hooks?.after?.delete || [];\n for (const handler of handlers) {\n await handler(where, context);\n }\n },\n};\n","import type { DatabaseAdapter } from \"./interfaces/adapter.interface\";\n\nexport type QueryResultLike<T = unknown> = { rows: T[]; rowCount?: number | null };\n\nexport type Queryable = {\n query: (text: string, values?: unknown[]) => Promise<QueryResultLike<Record<string, unknown>>>;\n};\n\nexport type PgPoolLike = Queryable & {\n connect?: () => Promise<PgClientLike>;\n};\n\nexport type PgClientLike = Queryable & {\n release?: () => void;\n};\n\nexport function isPgPoolLike(value: unknown): value is PgPoolLike {\n return Boolean(\n value && typeof value === \"object\" && typeof (value as { query?: unknown }).query === \"function\"\n );\n}\n\n/**\n * Normalizes a database pool or adapter into a standard DatabaseAdapter.\n * Note: If using the built-in Postgres pool, this requires the actual\n * implementation to be registered or known.\n */\nexport function toDatabaseAdapter(\n database: DatabaseAdapter | PgPoolLike,\n postgresFactory?: (pool: PgPoolLike) => DatabaseAdapter\n): DatabaseAdapter {\n if (isPgPoolLike(database) && typeof (database as { create?: unknown }).create !== \"function\") {\n if (postgresFactory) return postgresFactory(database);\n throw new Error(\n \"[BetterMedia] Postgres pool detected but no adapter factory provided. \" +\n \"This typically means you should use the main @better-media/framework package.\"\n );\n }\n return database as DatabaseAdapter;\n}\n","import type { DatabaseAdapter } from \"../database/interfaces/adapter.interface\";\nimport { toDatabaseAdapter, type PgPoolLike } from \"../database/postgres-utils\";\n\nexport type GetAdapterOptions = {\n database?: DatabaseAdapter | PgPoolLike;\n createDatabase?: () => Promise<DatabaseAdapter | PgPoolLike> | DatabaseAdapter | PgPoolLike;\n dialect?: string;\n schemaOutput?: string;\n migrationsDir?: string;\n};\n\nexport async function getAdapter(options: GetAdapterOptions): Promise<DatabaseAdapter> {\n const database = options.database ?? (await options.createDatabase?.());\n const adapter = database ? toDatabaseAdapter(database) : undefined;\n if (!adapter) {\n throw new Error(\n `[media] Failed to initialize database adapter. Provide \"database\" or \"createDatabase()\".`\n );\n }\n return adapter;\n}\n","/**\n * Mapping of common file extensions to their valid MIME types.\n * Based on MDN Common Media Types: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types\n */\nexport const EXTENSION_TO_MIME_MAP: Record<string, string[]> = {\n \".aac\": [\"audio/aac\"],\n \".abw\": [\"application/x-abiword\"],\n \".apng\": [\"image/apng\"],\n \".arc\": [\"application/x-freearc\"],\n \".avif\": [\"image/avif\"],\n \".avi\": [\"video/x-msvideo\"],\n \".azw\": [\"application/vnd.amazon.ebook\"],\n \".bin\": [\"application/octet-stream\"],\n \".bmp\": [\"image/bmp\"],\n \".bz\": [\"application/x-bzip\"],\n \".bz2\": [\"application/x-bzip2\"],\n \".cda\": [\"application/x-cdf\"],\n \".csh\": [\"application/x-csh\"],\n \".css\": [\"text/css\"],\n \".csv\": [\"text/csv\"],\n \".doc\": [\"application/msword\"],\n \".docx\": [\"application/vnd.openxmlformats-officedocument.wordprocessingml.document\"],\n \".eot\": [\"application/vnd.ms-fontobject\"],\n \".epub\": [\"application/epub+zip\"],\n \".gz\": [\"application/gzip\", \"application/x-gzip\"],\n \".gif\": [\"image/gif\"],\n \".htm\": [\"text/html\"],\n \".html\": [\"text/html\"],\n \".ico\": [\"image/vnd.microsoft.icon\"],\n \".ics\": [\"text/calendar\"],\n \".jar\": [\"application/java-archive\"],\n \".jpeg\": [\"image/jpeg\"],\n \".jpg\": [\"image/jpeg\"],\n \".js\": [\"text/javascript\"],\n \".mjs\": [\"text/javascript\"],\n \".json\": [\"application/json\"],\n \".jsonld\": [\"application/ld+json\"],\n \".md\": [\"text/markdown\"],\n \".mid\": [\"audio/midi\", \"audio/x-midi\"],\n \".midi\": [\"audio/midi\", \"audio/x-midi\"],\n \".mp3\": [\"audio/mpeg\"],\n \".mp4\": [\"video/mp4\"],\n \".mpeg\": [\"video/mpeg\"],\n \".mpkg\": [\"application/vnd.apple.installer+xml\"],\n \".odp\": [\"application/vnd.oasis.opendocument.presentation\"],\n \".ods\": [\"application/vnd.oasis.opendocument.spreadsheet\"],\n \".odt\": [\"application/vnd.oasis.opendocument.text\"],\n \".oga\": [\"audio/ogg\"],\n \".ogv\": [\"video/ogg\"],\n \".ogx\": [\"application/ogg\"],\n \".opus\": [\"audio/ogg\"],\n \".otf\": [\"font/otf\"],\n \".png\": [\"image/png\"],\n \".pdf\": [\"application/pdf\"],\n \".php\": [\"application/x-httpd-php\"],\n \".ppt\": [\"application/vnd.ms-powerpoint\"],\n \".pptx\": [\"application/vnd.openxmlformats-officedocument.presentationml.presentation\"],\n \".rar\": [\"application/vnd.rar\"],\n \".rtf\": [\"application/rtf\"],\n \".sh\": [\"application/x-sh\"],\n \".svg\": [\"image/svg+xml\"],\n \".tar\": [\"application/x-tar\"],\n \".tif\": [\"image/tiff\"],\n \".tiff\": [\"image/tiff\"],\n \".ts\": [\"video/mp2t\"],\n \".ttf\": [\"font/ttf\"],\n \".txt\": [\"text/plain\"],\n \".vsd\": [\"application/vnd.visio\"],\n \".wav\": [\"audio/wav\"],\n \".weba\": [\"audio/webm\"],\n \".webm\": [\"video/webm\"],\n \".webmanifest\": [\"application/manifest+json\"],\n \".webp\": [\"image/webp\"],\n \".woff\": [\"font/woff\"],\n \".woff2\": [\"font/woff2\"],\n \".xhtml\": [\"application/xhtml+xml\"],\n \".xls\": [\"application/vnd.ms-excel\"],\n \".xlsx\": [\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\"],\n \".xml\": [\"application/xml\", \"text/xml\", \"application/atom+xml\"],\n \".xul\": [\"application/vnd.mozilla.xul+xml\"],\n \".zip\": [\"application/zip\", \"application/x-zip-compressed\"],\n \".3gp\": [\"video/3gpp\", \"audio/3gpp\"],\n \".3g2\": [\"video/3gpp2\", \"audio/3gpp2\"],\n \".7z\": [\"application/x-7z-compressed\"],\n};\n","// Core types and utilities\nexport type MediaStatus = \"PENDING_VERIFICATION\" | \"VALID\" | \"INVALID\" | \"PROCESSING\" | \"COMPLETED\";\n\nexport function sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport { HOOK_NAMES, HOOK_MODE_CONSTRAINTS, resolveHookMode } from \"./plugin/index\";\nexport type {\n PipelinePlugin,\n PipelineContext,\n FileInfo,\n FileContent,\n StorageLocation,\n ProcessingResults,\n ThumbnailResult,\n VariantResult,\n MediaDimensions,\n PluginExecutionMode,\n PluginHooks,\n HookName,\n HookHandler,\n HookHandlerOptions,\n HookModeConstraint,\n MediaPlugin,\n HookContext,\n MediaRuntime,\n MediaRuntimeHook,\n ValidationResult,\n TrustedMetadata,\n PluginManifest,\n PluginApi,\n} from \"./plugin/index\";\nexport {\n ValidationResultSchema,\n VirusScanResultSchema,\n TrustedMetadataSchema,\n markFileContentVerified,\n} from \"./plugin/index\";\nexport type { VerifiedSourceId, PipelineContextWithVerified } from \"./plugin/index\";\nexport type {\n StorageAdapter,\n GetUrlOptions,\n PresignedUploadMethod,\n PresignedUploadOptions,\n PresignedUploadResult,\n StorageObject,\n ListResult,\n ListOptions,\n} from \"./storage/index\";\nexport type {\n DatabaseAdapter,\n DatabaseTransactionAdapter,\n WhereClause,\n CreateOptions,\n FindOptions,\n UpdateOptions,\n DeleteOptions,\n CountOptions,\n} from \"./database/index\";\nexport type { JobAdapter } from \"./job/index\";\nexport * from \"./database/index\";\nexport type { DatabaseHookContext } from \"./database/index\";\nexport { getAdapter, type GetAdapterOptions } from \"./adapter/get-adapter\";\nexport { EXTENSION_TO_MIME_MAP } from \"./constants/mime-types\";\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-media/core",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Core types and utilities for Better Media",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -34,7 +34,7 @@
34
34
  "type": "git",
35
35
  "url": "git+https://github.com/AbenezerAtnafu/better-media.git"
36
36
  },
37
- "homepage": "https://better-media-platform.vercel.app/",
37
+ "homepage": "https://better-media.dev/",
38
38
  "bugs": {
39
39
  "url": "https://github.com/AbenezerAtnafu/better-media/issues"
40
40
  },