prostgles-server 2.0.188 → 2.0.191

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.
Files changed (40) hide show
  1. package/dist/DboBuilder/insertDataParse.d.ts.map +1 -1
  2. package/dist/DboBuilder/insertDataParse.js +14 -4
  3. package/dist/DboBuilder/insertDataParse.js.map +1 -1
  4. package/dist/DboBuilder.d.ts +5 -3
  5. package/dist/DboBuilder.d.ts.map +1 -1
  6. package/dist/DboBuilder.js +67 -161
  7. package/dist/DboBuilder.js.map +1 -1
  8. package/dist/FileManager.d.ts +20 -72
  9. package/dist/FileManager.d.ts.map +1 -1
  10. package/dist/FileManager.js +232 -164
  11. package/dist/FileManager.js.map +1 -1
  12. package/dist/Prostgles.d.ts +13 -2
  13. package/dist/Prostgles.d.ts.map +1 -1
  14. package/dist/Prostgles.js.map +1 -1
  15. package/dist/TableConfig.d.ts +1 -2
  16. package/dist/TableConfig.d.ts.map +1 -1
  17. package/dist/TableConfig.js.map +1 -1
  18. package/lib/DboBuilder/insertDataParse.d.ts.map +1 -1
  19. package/lib/DboBuilder/insertDataParse.js +14 -4
  20. package/lib/DboBuilder/insertDataParse.ts +14 -4
  21. package/lib/DboBuilder.d.ts +5 -3
  22. package/lib/DboBuilder.d.ts.map +1 -1
  23. package/lib/DboBuilder.js +67 -161
  24. package/lib/DboBuilder.ts +84 -191
  25. package/lib/FileManager.d.ts +19 -71
  26. package/lib/FileManager.d.ts.map +1 -1
  27. package/lib/FileManager.js +232 -164
  28. package/lib/FileManager.ts +272 -191
  29. package/lib/Prostgles.d.ts +13 -2
  30. package/lib/Prostgles.d.ts.map +1 -1
  31. package/lib/Prostgles.ts +2 -2
  32. package/lib/TableConfig.d.ts +1 -2
  33. package/lib/TableConfig.d.ts.map +1 -1
  34. package/lib/TableConfig.ts +2 -4
  35. package/lib/fileType/core.js +1527 -0
  36. package/lib/fileType/supported.js +278 -0
  37. package/package.json +5 -5
  38. package/tests/client/PID.txt +1 -1
  39. package/tests/server/DBoGenerated.d.ts +1 -1
  40. package/tests/server/package-lock.json +9 -9
@@ -1,6 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  import { S3 } from 'aws-sdk';
3
3
  import { DB, DBHandlerServer, Prostgles } from './Prostgles';
4
+ import { ALLOWED_CONTENT_TYPE, ALLOWED_EXTENSION, ValidatedColumnInfo } from 'prostgles-types';
4
5
  export declare const asSQLIdentifier: (name: string, db: DB) => Promise<string>;
5
6
  export declare type ImageOptions = {
6
7
  keepMetadata?: boolean;
@@ -60,10 +61,14 @@ export default class FileManager {
60
61
  tableName?: string;
61
62
  private fileRoute?;
62
63
  constructor(config: FileManager["config"], imageOptions?: ImageOptions);
63
- getMIME(file: Buffer | String, fileName: string, allowedExtensions?: Array<ALLOWED_EXTENSION>, dissallowedExtensions?: Array<ALLOWED_EXTENSION>, onlyFromName?: boolean): Promise<{
64
- mime: string;
65
- ext: string | ALLOWED_EXTENSION;
64
+ parseFile(args: {
65
+ file: Buffer | string;
66
66
  fileName: string;
67
+ colName?: string;
68
+ tableName?: string;
69
+ }): Promise<{
70
+ mime: string | ALLOWED_CONTENT_TYPE;
71
+ ext: string | ALLOWED_EXTENSION;
67
72
  }>;
68
73
  private upload;
69
74
  uploadAsMedia: (params: {
@@ -74,77 +79,20 @@ export default class FileManager {
74
79
  }) => Promise<UploadedItem>;
75
80
  private getFileURL;
76
81
  private parseSQLIdentifier;
82
+ getColInfo: (args: {
83
+ tableName: string;
84
+ colName: string;
85
+ }) => ValidatedColumnInfo["file"] | undefined;
77
86
  init: (prg: Prostgles) => Promise<void>;
78
87
  }
79
- declare const CONTENT_TYPE_TO_EXT: {
80
- readonly "text/html": readonly ["html", "htm", "shtml"];
81
- readonly "text/css": readonly ["css"];
82
- readonly "text/xml": readonly ["xml"];
83
- readonly "text/mathml": readonly ["mml"];
84
- readonly "text/plain": readonly ["txt"];
85
- readonly "text/vnd.sun.j2me.app-descriptor": readonly ["jad"];
86
- readonly "text/vnd.wap.wml": readonly ["wml"];
87
- readonly "text/x-component": readonly ["htc"];
88
- readonly "image/gif": readonly ["gif"];
89
- readonly "image/jpeg": readonly ["jpeg", "jpg"];
90
- readonly "image/png": readonly ["png"];
91
- readonly "image/tiff": readonly ["tif", "tiff"];
92
- readonly "image/vnd.wap.wbmp": readonly ["wbmp"];
93
- readonly "image/x-icon": readonly ["ico"];
94
- readonly "image/x-jng": readonly ["jng"];
95
- readonly "image/x-ms-bmp": readonly ["bmp"];
96
- readonly "image/svg+xml": readonly ["svg"];
97
- readonly "image/webp": readonly ["webp"];
98
- readonly "application/x-javascript": readonly ["js"];
99
- readonly "application/atom+xml": readonly ["atom"];
100
- readonly "application/rss+xml": readonly ["rss"];
101
- readonly "application/java-archive": readonly ["jar", "war", "ear"];
102
- readonly "application/mac-binhex40": readonly ["hqx"];
103
- readonly "application/msword": readonly ["doc", "docx"];
104
- readonly "application/pdf": readonly ["pdf"];
105
- readonly "application/postscript": readonly ["ps", "eps", "ai"];
106
- readonly "application/rtf": readonly ["rtf"];
107
- readonly "application/vnd.ms-excel": readonly ["xls", "xlsx"];
108
- readonly "application/vnd.ms-powerpoint": readonly ["ppt", "pptx"];
109
- readonly "application/vnd.wap.wmlc": readonly ["wmlc"];
110
- readonly "application/vnd.google-earth.kml+xml": readonly ["kml"];
111
- readonly "application/vnd.google-earth.kmz": readonly ["kmz"];
112
- readonly "application/x-7z-compressed": readonly ["7z"];
113
- readonly "application/x-cocoa": readonly ["cco"];
114
- readonly "application/x-java-archive-diff": readonly ["jardiff"];
115
- readonly "application/x-java-jnlp-file": readonly ["jnlp"];
116
- readonly "application/x-makeself": readonly ["run"];
117
- readonly "application/x-perl": readonly ["pl", "pm"];
118
- readonly "application/x-pilot": readonly ["prc", "pdb"];
119
- readonly "application/x-rar-compressed": readonly ["rar"];
120
- readonly "application/x-redhat-package-manager": readonly ["rpm"];
121
- readonly "application/x-sea": readonly ["sea"];
122
- readonly "application/x-shockwave-flash": readonly ["swf"];
123
- readonly "application/x-stuffit": readonly ["sit"];
124
- readonly "application/x-tcl": readonly ["tcl", "tk"];
125
- readonly "application/x-x509-ca-cert": readonly ["der", "pem", "crt"];
126
- readonly "application/x-xpinstall": readonly ["xpi"];
127
- readonly "application/xhtml+xml": readonly ["xhtml"];
128
- readonly "application/zip": readonly ["zip"];
129
- readonly "application/octet-stream": readonly ["bin", "exe", "dll", "deb", "dmg", "eot", "iso", "img", "msi", "msp", "msm"];
130
- readonly "audio/midi": readonly ["mid", "midi", "kar"];
131
- readonly "audio/mpeg": readonly ["mp3"];
132
- readonly "audio/ogg": readonly ["ogg"];
133
- readonly "audio/x-realaudio": readonly ["ra"];
134
- readonly "video/3gpp": readonly ["3gpp", "3gp"];
135
- readonly "video/mpeg": readonly ["mpeg", "mpg"];
136
- readonly "video/quicktime": readonly ["mov"];
137
- readonly "video/x-flv": readonly ["flv"];
138
- readonly "video/x-mng": readonly ["mng"];
139
- readonly "video/x-ms-asf": readonly ["asx", "asf"];
140
- readonly "video/x-ms-wmv": readonly ["wmv"];
141
- readonly "video/x-msvideo": readonly ["avi"];
142
- readonly "video/mp4": readonly ["m4v", "mp4"];
143
- readonly "video/webm": readonly ["webm"];
144
- };
145
- export declare type ALLOWED_CONTENT_TYPE = keyof typeof CONTENT_TYPE_TO_EXT;
146
- export declare type ALLOWED_EXTENSION = (typeof CONTENT_TYPE_TO_EXT)[ALLOWED_CONTENT_TYPE][number];
147
- export {};
88
+ export declare const getFileTypeFromFilename: (fileName: string) => {
89
+ mime: ALLOWED_CONTENT_TYPE;
90
+ ext: ALLOWED_EXTENSION;
91
+ } | undefined;
92
+ export declare const getFileType: (file: Buffer | string, fileName: string) => Promise<{
93
+ mime: ALLOWED_CONTENT_TYPE;
94
+ ext: ALLOWED_EXTENSION;
95
+ }>;
148
96
  /**
149
97
  *
150
98
 
@@ -1 +1 @@
1
- {"version":3,"file":"FileManager.d.ts","sourceRoot":"","sources":["../lib/FileManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FileManager.d.ts","sourceRoot":"","sources":["../lib/FileManager.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAM7B,OAAO,EAAE,EAAE,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAkD,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAK/I,eAAO,MAAM,eAAe,SAAgB,MAAM,aAAW,QAAQ,MAAM,CAE1E,CAAA;AAED,oBAAY,YAAY,GAAG;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC;IACV;;OAEG;IACD;QAAE,MAAM,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,GAC7C;QAAE,OAAO,EACL;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,GACjB;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,CAAA;KACrB,CAAA;CACN,CAAA;AAED,oBAAY,QAAQ,GAAG;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CAEzB,CAAA;AAED,oBAAY,WAAW,GAAG;IACxB;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAC;CACzB,CAAA;AAED,oBAAY,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AACF,oBAAY,YAAY,GAAG;IACzB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,WAAW;IAE9B,QAAQ,CAAC,EAAE,EAAE,CAAC;IAEd,MAAM,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAE5B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,IAAI,GAAG,IAAI,eAAe,CAGzB;IACD,IAAI,EAAE,IAAI,EAAE,CAGX;IAED,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,OAAO,CAAC,SAAS,CAAC,CAAS;gBAEf,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC,EAAE,YAAY;IAahE,SAAS,CAAC,IAAI,EAAE;QACpB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;QACtB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC;QACV,IAAI,EAAE,MAAM,GAAG,oBAAoB,CAAC;QACpC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC;KAIjC,CAAC;YAwIY,MAAM;IAiEpB,aAAa,WAAkB;QAC7B,IAAI,EAAE,UAAU,CAAC;QACjB,iBAAiB,CAAC,EAAE,MAAM,iBAAiB,CAAC,CAAC;QAC7C,qBAAqB,CAAC,EAAE,MAAM,iBAAiB,CAAC,CAAC;QACjD,YAAY,CAAC,EAAE,YAAY,CAAC;KAC7B,KAAG,QAAQ,YAAY,CAAC,CA6CxB;YAEa,UAAU;IASxB,OAAO,CAAC,kBAAkB,CAAuE;IAEjG,UAAU,SAAU;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAG,mBAAmB,CAAC,MAAM,CAAC,GAAG,SAAS,CAWnG;IAED,IAAI,QAAe,SAAS,mBAoN3B;CACF;AAED,eAAO,MAAM,uBAAuB,aAAc,MAAM;UAAW,oBAAoB;SAAO,iBAAiB;aAe9G,CAAA;AAKD,eAAO,MAAM,WAAW,SAAgB,MAAM,GAAG,MAAM,YAAY,MAAM,KAAG,QAAQ;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,GAAG,EAAE,iBAAiB,CAAA;CAAE,CAwBzI,CAAA;AAGD;;;;;;;;;;;;;;;;;;;GAmBG"}
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.asSQLIdentifier = void 0;
3
+ exports.getFileType = exports.getFileTypeFromFilename = exports.asSQLIdentifier = void 0;
4
4
  const aws_sdk_1 = require("aws-sdk");
5
5
  const fs = require("fs");
6
- const FileType = require("file-type");
7
6
  const sharp = require("sharp");
8
7
  const prostgles_types_1 = require("prostgles-types");
8
+ const DboBuilder_1 = require("./DboBuilder");
9
9
  const HOUR = 3600 * 1000;
10
10
  const asSQLIdentifier = async (name, db) => {
11
11
  return (await db.one("select format('%I', $1) as name", [name]))?.name;
@@ -58,6 +58,18 @@ class FileManager {
58
58
  return res;
59
59
  };
60
60
  this.parseSQLIdentifier = async (name) => (0, exports.asSQLIdentifier)(name, this.prostgles.db); // this.prostgles.dbo.sql<"value">("select format('%I', $1)", [name], { returnType: "value" } )
61
+ this.getColInfo = (args) => {
62
+ const { colName, tableName } = args;
63
+ const tableConfig = this.prostgles?.opts.fileTable?.referencedTables?.[tableName];
64
+ const isReferencingFileTable = this.dbo[tableName]?.columns?.some(c => c.name === colName && c.references && c.references?.ftable === this.tableName);
65
+ if (isReferencingFileTable) {
66
+ if (tableConfig && typeof tableConfig !== "string") {
67
+ return tableConfig.referenceColumns[colName];
68
+ }
69
+ return { acceptedContent: "*" };
70
+ }
71
+ return undefined;
72
+ };
61
73
  this.init = async (prg) => {
62
74
  this.prostgles = prg;
63
75
  // const { dbo, db, opts } = prg;
@@ -98,56 +110,96 @@ class FileManager {
98
110
  /**
99
111
  * 2. Create media lookup tables
100
112
  */
101
- await Promise.all(Object.keys(referencedTables).map(async (refTable) => {
113
+ await Promise.all((0, prostgles_types_1.getKeys)(referencedTables).map(async (refTable) => {
102
114
  if (!this.dbo[refTable])
103
- throw `Referenced table (${refTable}) from fileTable.referencedTables record is missing`;
104
- // const lookupTableName = asName(`lookup_${tableName}_${refTable}`);
105
- const lookupTableName = await this.parseSQLIdentifier(`prostgles_lookup_${tableName}_${refTable}`);
106
- const pKeyFields = (await this.dbo[refTable].getColumns()).filter(f => f.is_pkey);
107
- if (pKeyFields.length !== 1)
108
- throw `Could not make link table for ${refTable}. ${pKeyFields} must have exactly one primary key column. Current pkeys: ${pKeyFields.map(f => f.name)}`;
109
- const pkField = pKeyFields[0];
110
- const refType = referencedTables[refTable];
111
- if (!this.dbo[lookupTableName]) {
112
- // if(!(await dbo[lookupTableName].count())) await db.any(`DROP TABLE IF EXISTS ${lookupTableName};`);
113
- const action = ` (${tableName} <-> ${refTable}) join table ${lookupTableName}`; // PRIMARY KEY
114
- const query = `
115
- CREATE TABLE ${lookupTableName} (
116
- foreign_id ${pkField.udt_name} ${refType === "one" ? " PRIMARY KEY " : ""} REFERENCES ${(0, prostgles_types_1.asName)(refTable)}(${(0, prostgles_types_1.asName)(pkField.name)}),
117
- media_id UUID NOT NULL REFERENCES ${(0, prostgles_types_1.asName)(tableName)}(id)
118
- )
119
- `;
120
- console.log(`Creating ${action} ...`, lookupTableName);
121
- await this.db.any(query);
122
- console.log(`Created ${action}`);
123
- }
124
- else {
125
- const cols = await this.dbo[lookupTableName].getColumns();
126
- const badCols = cols.filter(c => !c.references);
127
- await Promise.all(badCols.map(async (badCol) => {
128
- console.error(`Prostgles: media ${lookupTableName} joining table has lost a reference constraint for column ${badCol.name}.` +
129
- ` This may have been caused by a DROP TABLE ... CASCADE.`);
130
- let q = `
131
- ALTER TABLE ${(0, prostgles_types_1.asName)(lookupTableName)}
132
- ADD CONSTRAINT ${(lookupTableName + "_" + badCol.name + "_r")} FOREIGN KEY (${badCol.name})
133
- `;
134
- console.log("Trying to add the missing constraint back");
135
- if (badCol.name === "foreign_id") {
136
- q += `REFERENCES ${(0, prostgles_types_1.asName)(refTable)}(${(0, prostgles_types_1.asName)(pkField.name)}) `;
137
- }
138
- else if (badCol.name === "media_id") {
139
- q += `REFERENCES ${(0, prostgles_types_1.asName)(tableName)}(id) `;
115
+ throw `Referenced table (${refTable}) from fileTable.referencedTables prostgles init config is missing`;
116
+ const cols = await this.dbo[refTable].getColumns();
117
+ const tableConfig = referencedTables[refTable];
118
+ if (typeof tableConfig !== "string") {
119
+ for await (const colName of (0, prostgles_types_1.getKeys)(tableConfig.referenceColumns)) {
120
+ const existingCol = cols.find(c => c.name === colName);
121
+ if (existingCol) {
122
+ if (existingCol.references?.ftable === tableName) {
123
+ // All ok
124
+ }
125
+ else {
126
+ if (existingCol.udt_name === "uuid") {
127
+ try {
128
+ const query = `ALTER TABLE ${(0, prostgles_types_1.asName)(tableName)} ADD CONSTRAINT FOREIGN KEY (${(0, prostgles_types_1.asName)(colName)}) REFERENCES ${(0, prostgles_types_1.asName)(tableName)} (id);`;
129
+ console.log(`Referenced file column ${refTable} (${colName}) exists but is not referencing file table. Trying to add REFERENCE constraing...\n${query}`);
130
+ await this.db.any(query);
131
+ console.log("SUCCESS: " + query);
132
+ }
133
+ catch (e) {
134
+ throw new Error(`Could not add constraing. Err: ${e instanceof Error ? e.message : JSON.stringify(e)}`);
135
+ }
136
+ }
137
+ else {
138
+ throw new Error(`Referenced file column ${refTable} (${colName}) exists but is not of required type (UUID). Choose a different column name or ALTER the existing column to match the type and the data found in file table ${tableName}(id)`);
139
+ }
140
+ }
140
141
  }
141
- if (q) {
142
+ else {
142
143
  try {
143
- await this.db.any(q);
144
- console.log("Added missing constraint back");
144
+ const query = `ALTER TABLE ${(0, prostgles_types_1.asName)(tableName)} ADD COLUMN ${(0, prostgles_types_1.asName)(colName)} UUID REFERENCES ${(0, prostgles_types_1.asName)(tableName)} (id);`;
145
+ console.log(`Creating referenced file column ${refTable} (${colName})...\n${query}`);
146
+ await this.db.any(query);
147
+ console.log("SUCCESS: " + query);
145
148
  }
146
149
  catch (e) {
147
- console.error("Failed to add missing constraint", e);
150
+ throw new Error(`FAILED. Err: ${e instanceof Error ? e.message : JSON.stringify(e)}`);
148
151
  }
149
152
  }
150
- }));
153
+ }
154
+ }
155
+ else {
156
+ const lookupTableName = await this.parseSQLIdentifier(`prostgles_lookup_${tableName}_${refTable}`);
157
+ const pKeyFields = cols.filter(f => f.is_pkey);
158
+ if (pKeyFields.length !== 1)
159
+ throw `Could not make link table for ${refTable}. ${pKeyFields} must have exactly one primary key column. Current pkeys: ${pKeyFields.map(f => f.name)}`;
160
+ const pkField = pKeyFields[0];
161
+ const refType = referencedTables[refTable];
162
+ if (!this.dbo[lookupTableName]) {
163
+ // if(!(await dbo[lookupTableName].count())) await db.any(`DROP TABLE IF EXISTS ${lookupTableName};`);
164
+ const action = ` (${tableName} <-> ${refTable}) join table ${lookupTableName}`; // PRIMARY KEY
165
+ const query = `
166
+ CREATE TABLE ${lookupTableName} (
167
+ foreign_id ${pkField.udt_name} ${refType === "one" ? " PRIMARY KEY " : ""} REFERENCES ${(0, prostgles_types_1.asName)(refTable)}(${(0, prostgles_types_1.asName)(pkField.name)}),
168
+ media_id UUID NOT NULL REFERENCES ${(0, prostgles_types_1.asName)(tableName)}(id)
169
+ )
170
+ `;
171
+ console.log(`Creating ${action} ...`, lookupTableName);
172
+ await this.db.any(query);
173
+ console.log(`Created ${action}`);
174
+ }
175
+ else {
176
+ const cols = await this.dbo[lookupTableName].getColumns();
177
+ const badCols = cols.filter(c => !c.references);
178
+ await Promise.all(badCols.map(async (badCol) => {
179
+ console.error(`Prostgles: media ${lookupTableName} joining table has lost a reference constraint for column ${badCol.name}.` +
180
+ ` This may have been caused by a DROP TABLE ... CASCADE.`);
181
+ let q = `
182
+ ALTER TABLE ${(0, prostgles_types_1.asName)(lookupTableName)}
183
+ ADD CONSTRAINT ${(lookupTableName + "_" + badCol.name + "_r")} FOREIGN KEY (${badCol.name})
184
+ `;
185
+ console.log("Trying to add the missing constraint back");
186
+ if (badCol.name === "foreign_id") {
187
+ q += `REFERENCES ${(0, prostgles_types_1.asName)(refTable)}(${(0, prostgles_types_1.asName)(pkField.name)}) `;
188
+ }
189
+ else if (badCol.name === "media_id") {
190
+ q += `REFERENCES ${(0, prostgles_types_1.asName)(tableName)}(id) `;
191
+ }
192
+ if (q) {
193
+ try {
194
+ await this.db.any(q);
195
+ console.log("Added missing constraint back");
196
+ }
197
+ catch (e) {
198
+ console.error("Failed to add missing constraint", e);
199
+ }
200
+ }
201
+ }));
202
+ }
151
203
  }
152
204
  await prg.refreshDBO();
153
205
  return true;
@@ -228,63 +280,108 @@ class FileManager {
228
280
  return this.prostgles.db;
229
281
  }
230
282
  ;
231
- async getMIME(file, fileName, allowedExtensions, dissallowedExtensions, onlyFromName = true) {
232
- const nameParts = fileName.split(".");
233
- const nameExt = nameParts[nameParts.length - 1].toLowerCase(), mime = (0, prostgles_types_1.getKeys)(CONTENT_TYPE_TO_EXT).find(k => CONTENT_TYPE_TO_EXT[k].includes(nameExt));
234
- let type = {
235
- fileName,
236
- mime,
237
- ext: nameExt,
238
- };
239
- if (onlyFromName && !mime)
240
- throw `Invalid file extension: content_type could not be found for extension(${nameExt})`;
241
- if (!mime) {
242
- /* Set correct/missing extension */
243
- if (["xml", "txt", "csv", "tsv", "doc"].includes(nameExt)) {
244
- type = { ...type, mime: ("text/" + nameExt), ext: nameExt };
245
- }
246
- else if (["svg"].includes(nameExt)) {
247
- type = { ...type, mime: "image/svg+xml", ext: nameExt };
248
- }
249
- else if (Buffer.isBuffer(file)) {
250
- const res = await FileType.fromBuffer(file);
251
- type = {
252
- ...res,
253
- fileName,
254
- };
255
- }
256
- else if (typeof file === "string") {
257
- const res = await FileType.fromFile(file);
258
- type = {
259
- ...res,
260
- fileName,
261
- };
262
- }
263
- else {
264
- throw "Unexpected file. Expecting: Buffer | String";
283
+ async parseFile(args) {
284
+ const { file, fileName, tableName, colName } = args;
285
+ const config = this.prostgles?.opts.fileTable;
286
+ if (!config)
287
+ throw new Error("File table config missing");
288
+ const buffer = typeof file === "string" ? Buffer.from(file, 'utf8') : file;
289
+ const mime = await (0, exports.getFileType)(buffer, fileName);
290
+ if (tableName && colName) {
291
+ const tableConfig = config.referencedTables?.[tableName];
292
+ if (tableConfig && (0, prostgles_types_1.isObject)(tableConfig) && tableConfig.referenceColumns[colName]) {
293
+ const colConfig = tableConfig.referenceColumns[colName];
294
+ if (colConfig.maxFileSizeMB) {
295
+ const actualBufferSize = Buffer.byteLength(buffer);
296
+ if ((actualBufferSize / 1e6) > colConfig.maxFileSizeMB) {
297
+ throw new Error(`Provided file is larger than the ${colConfig.maxFileSizeMB}MB limit`);
298
+ }
299
+ }
300
+ if ("acceptedContent" in colConfig && colConfig.acceptedContent) {
301
+ const CONTENTS = [
302
+ "image",
303
+ "audio",
304
+ "video",
305
+ "text",
306
+ "application",
307
+ ];
308
+ const allowedContent = DboBuilder_1.ViewHandler._parseFieldFilter(colConfig.acceptedContent, false, CONTENTS);
309
+ if (!allowedContent.some(c => mime.mime.startsWith(c))) {
310
+ throw new Error(`Dissallowed content type provided: ${mime.mime.split("/")[0]}. Allowed content types: ${allowedContent} `);
311
+ }
312
+ }
313
+ else if ("acceptedContentType" in colConfig && colConfig.acceptedContentType) {
314
+ const allowedContentTypes = DboBuilder_1.ViewHandler._parseFieldFilter(colConfig.acceptedContentType, false, (0, prostgles_types_1.getKeys)(prostgles_types_1.CONTENT_TYPE_TO_EXT));
315
+ if (!allowedContentTypes.some(c => c === mime.mime)) {
316
+ throw new Error(`Dissallowed MIME provided: ${mime.mime}. Allowed MIME values: ${allowedContentTypes} `);
317
+ }
318
+ }
319
+ else if ("acceptedFileTypes" in colConfig && colConfig.acceptedFileTypes) {
320
+ const allowedExtensions = DboBuilder_1.ViewHandler._parseFieldFilter(colConfig.acceptedFileTypes, false, Object.values(prostgles_types_1.CONTENT_TYPE_TO_EXT).flat());
321
+ if (!allowedExtensions.some(c => c === mime.ext)) {
322
+ throw new Error(`Dissallowed extension provided: ${mime.ext}. Allowed extension values: ${allowedExtensions} `);
323
+ }
324
+ }
265
325
  }
266
326
  }
267
- if (allowedExtensions &&
268
- !allowedExtensions.map(v => v.toLowerCase())?.includes(type.ext)) {
269
- throw fileName + " -> File type ( " + type.ext + " ) not allowed. Expecting one of: " + allowedExtensions.map(v => v.toLowerCase()).join(", ");
270
- }
271
- else if (dissallowedExtensions &&
272
- dissallowedExtensions.map(v => v.toLowerCase())?.includes(type.ext)) {
273
- throw fileName + " -> File type ( " + type.ext + " ) not allowed";
274
- }
275
- if (!onlyFromName) {
276
- let { ext } = type;
277
- if (nameExt !== ext)
278
- fileName = nameParts.slice(0, -1).join('') + "." + ext;
279
- }
280
- const res = {
281
- ...type,
282
- fileName
283
- };
284
- if (!res.mime)
285
- throw "Could not find mime";
286
- return res;
327
+ return mime;
287
328
  }
329
+ // private async getMIME(
330
+ // file: Buffer | string,
331
+ // fileName: string,
332
+ // allowedExtensions?: Array<ALLOWED_EXTENSION>,
333
+ // dissallowedExtensions?: Array<ALLOWED_EXTENSION>,
334
+ // onlyFromName = true
335
+ // ): Promise<{
336
+ // mime: string;
337
+ // ext: string | ALLOWED_EXTENSION;
338
+ // fileName: string;
339
+ // }> {
340
+ // const nameParts = fileName.split(".");
341
+ // const nameExt = nameParts[nameParts.length - 1].toLowerCase(),
342
+ // mime = getKeys(CONTENT_TYPE_TO_EXT).find(k => (CONTENT_TYPE_TO_EXT[k] as readonly string[]).includes(nameExt));
343
+ // let type = {
344
+ // fileName,
345
+ // mime,
346
+ // ext: nameExt,
347
+ // }
348
+ // if(onlyFromName && !mime) throw `Invalid file extension: content_type could not be found for extension(${nameExt})`;
349
+ // if(!mime){
350
+ // /* Set correct/missing extension */
351
+ // if(["xml", "txt", "csv", "tsv"].includes(nameExt)){
352
+ // type = { ...type, mime: ("text/" + nameExt) as any, ext: nameExt };
353
+ // } else if(["svg"].includes(nameExt)){
354
+ // type = { ...type, mime: "image/svg+xml", ext: nameExt };
355
+ // } else {
356
+ // const res = await getFileTypeFromBuffer(file);
357
+ // type = {
358
+ // ...(res as any),
359
+ // fileName,
360
+ // }
361
+ // }
362
+ // }
363
+ // if(
364
+ // allowedExtensions &&
365
+ // !allowedExtensions.map(v => v.toLowerCase())?.includes(type.ext)
366
+ // ){
367
+ // throw fileName + " -> File type ( " + type.ext + " ) not allowed. Expecting one of: " + allowedExtensions.map(v => v.toLowerCase()).join(", ");
368
+ // } else if(
369
+ // dissallowedExtensions &&
370
+ // dissallowedExtensions.map(v => v.toLowerCase())?.includes(type.ext)
371
+ // ){
372
+ // throw fileName + " -> File type ( " + type.ext + " ) not allowed";
373
+ // }
374
+ // if(!onlyFromName){
375
+ // let { ext } = type;
376
+ // if(nameExt !== ext) fileName = nameParts.slice(0, -1).join('') + "." + ext;
377
+ // }
378
+ // const res = {
379
+ // ...type,
380
+ // fileName
381
+ // }
382
+ // if(!res.mime) throw "Could not find mime"
383
+ // return res as any;
384
+ // }
288
385
  // async getUploadURL(fileName: string): Promise<string> {
289
386
  // const thisHour = new Date();
290
387
  // thisHour.setMilliseconds(0);
@@ -368,72 +465,43 @@ class FileManager {
368
465
  }
369
466
  }
370
467
  exports.default = FileManager;
371
- const CONTENT_TYPE_TO_EXT = {
372
- "text/html": ["html", "htm", "shtml"],
373
- "text/css": ["css"],
374
- "text/xml": ["xml"],
375
- "text/mathml": ["mml"],
376
- "text/plain": ["txt"],
377
- "text/vnd.sun.j2me.app-descriptor": ["jad"],
378
- "text/vnd.wap.wml": ["wml"],
379
- "text/x-component": ["htc"],
380
- "image/gif": ["gif"],
381
- "image/jpeg": ["jpeg", "jpg"],
382
- "image/png": ["png"],
383
- "image/tiff": ["tif", "tiff"],
384
- "image/vnd.wap.wbmp": ["wbmp"],
385
- "image/x-icon": ["ico"],
386
- "image/x-jng": ["jng"],
387
- "image/x-ms-bmp": ["bmp"],
388
- "image/svg+xml": ["svg"],
389
- "image/webp": ["webp"],
390
- "application/x-javascript": ["js"],
391
- "application/atom+xml": ["atom"],
392
- "application/rss+xml": ["rss"],
393
- "application/java-archive": ["jar", "war", "ear"],
394
- "application/mac-binhex40": ["hqx"],
395
- "application/msword": ["doc", "docx"],
396
- "application/pdf": ["pdf"],
397
- "application/postscript": ["ps", "eps", "ai"],
398
- "application/rtf": ["rtf"],
399
- "application/vnd.ms-excel": ["xls", "xlsx"],
400
- "application/vnd.ms-powerpoint": ["ppt", "pptx"],
401
- "application/vnd.wap.wmlc": ["wmlc"],
402
- "application/vnd.google-earth.kml+xml": ["kml"],
403
- "application/vnd.google-earth.kmz": ["kmz"],
404
- "application/x-7z-compressed": ["7z"],
405
- "application/x-cocoa": ["cco"],
406
- "application/x-java-archive-diff": ["jardiff"],
407
- "application/x-java-jnlp-file": ["jnlp"],
408
- "application/x-makeself": ["run"],
409
- "application/x-perl": ["pl", "pm"],
410
- "application/x-pilot": ["prc", "pdb"],
411
- "application/x-rar-compressed": ["rar"],
412
- "application/x-redhat-package-manager": ["rpm"],
413
- "application/x-sea": ["sea"],
414
- "application/x-shockwave-flash": ["swf"],
415
- "application/x-stuffit": ["sit"],
416
- "application/x-tcl": ["tcl", "tk"],
417
- "application/x-x509-ca-cert": ["der", "pem", "crt"],
418
- "application/x-xpinstall": ["xpi"],
419
- "application/xhtml+xml": ["xhtml"],
420
- "application/zip": ["zip"],
421
- "application/octet-stream": ["bin", "exe", "dll", "deb", "dmg", "eot", "iso", "img", "msi", "msp", "msm"],
422
- "audio/midi": ["mid", "midi", "kar"],
423
- "audio/mpeg": ["mp3"],
424
- "audio/ogg": ["ogg"],
425
- "audio/x-realaudio": ["ra"],
426
- "video/3gpp": ["3gpp", "3gp"],
427
- "video/mpeg": ["mpeg", "mpg"],
428
- "video/quicktime": ["mov"],
429
- "video/x-flv": ["flv"],
430
- "video/x-mng": ["mng"],
431
- "video/x-ms-asf": ["asx", "asf"],
432
- "video/x-ms-wmv": ["wmv"],
433
- "video/x-msvideo": ["avi"],
434
- "video/mp4": ["m4v", "mp4"],
435
- "video/webm": ["webm"],
468
+ const getFileTypeFromFilename = (fileName) => {
469
+ const nameParts = fileName.split(".");
470
+ if (!nameParts.length)
471
+ return undefined;
472
+ const nameExt = nameParts[nameParts.length - 1].toLowerCase(), mime = (0, prostgles_types_1.getKeys)(prostgles_types_1.CONTENT_TYPE_TO_EXT).find(k => prostgles_types_1.CONTENT_TYPE_TO_EXT[k].includes(nameExt));
473
+ if (!mime)
474
+ return undefined;
475
+ return {
476
+ mime,
477
+ ext: nameExt,
478
+ };
479
+ };
480
+ exports.getFileTypeFromFilename = getFileTypeFromFilename;
481
+ // const fileType = require("file-type");
482
+ // const res = await fileType.fromBuffer(typeof file === "string"? Buffer.from(file, 'utf8') : file);
483
+ const getFileType = async (file, fileName) => {
484
+ const { fileTypeFromBuffer } = await eval('import("file-type")');
485
+ const fileNameMime = (0, exports.getFileTypeFromFilename)(fileName);
486
+ if (!fileNameMime?.ext)
487
+ throw new Error("File name must contain extenions");
488
+ const res = await fileTypeFromBuffer(typeof file === "string" ? Buffer.from(file, 'utf8') : file);
489
+ if (!res) {
490
+ /* Set correct/missing extension */
491
+ const nameExt = fileNameMime?.ext;
492
+ if (["xml", "txt", "csv", "tsv", "svg"].includes(nameExt)) {
493
+ return fileNameMime;
494
+ }
495
+ throw new Error("Could not get the file type from file buffer");
496
+ }
497
+ else {
498
+ if (!res.ext || fileNameMime?.ext.toLowerCase() !== res.ext.toLowerCase()) {
499
+ throw new Error(`There is a mismatch between file name extension and actual buffer extension: ${fileNameMime?.ext} vs ${res.ext}`);
500
+ }
501
+ }
502
+ return res;
436
503
  };
504
+ exports.getFileType = getFileType;
437
505
  /**
438
506
  *
439
507