@iebh/tera-fy 1.6.0 → 1.7.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/CHANGELOG.md +15 -0
- package/api.md +484 -426
- package/dist/terafy.es2019.js +2 -2
- package/dist/terafy.js +2 -2
- package/lib/projectFile.js +25 -4
- package/lib/terafy.client.js +48 -12
- package/lib/terafy.server.js +105 -44
- package/package.json +1 -1
package/lib/terafy.server.js
CHANGED
|
@@ -868,7 +868,7 @@ export default class TeraFyServer {
|
|
|
868
868
|
}
|
|
869
869
|
// }}}
|
|
870
870
|
|
|
871
|
-
// Project files - selectProjectFile(), getProjectFiles(), getProjectFile(), setProjectFile() {{{
|
|
871
|
+
// Project files - selectProjectFile(), getProjectFiles(), getProjectFile(), createProjectFile(), deleteProjectFile(), setProjectFile() {{{
|
|
872
872
|
|
|
873
873
|
/**
|
|
874
874
|
* Data structure for a project file
|
|
@@ -914,7 +914,7 @@ export default class TeraFyServer {
|
|
|
914
914
|
* @param {Boolean} [options.autoRequire=true] Run `requireProject()` automatically before continuing
|
|
915
915
|
* @param {FileFilters} [options.filter] Optional file filters
|
|
916
916
|
*
|
|
917
|
-
* @returns {Promise<ProjectFile>} The eventually selected file
|
|
917
|
+
* @returns {Promise<ProjectFile>} The eventually selected file, if in save mode new files are created as stubs
|
|
918
918
|
*/
|
|
919
919
|
selectProjectFile(options) {
|
|
920
920
|
let settings = {
|
|
@@ -949,8 +949,8 @@ export default class TeraFyServer {
|
|
|
949
949
|
filters: settings.filters,
|
|
950
950
|
},
|
|
951
951
|
componentEvents: {
|
|
952
|
-
fileSave(
|
|
953
|
-
app.service('$prompt').close(true,
|
|
952
|
+
fileSave(file) {
|
|
953
|
+
app.service('$prompt').close(true, file);
|
|
954
954
|
},
|
|
955
955
|
fileSelect(file) {
|
|
956
956
|
app.service('$prompt').close(true, file);
|
|
@@ -989,26 +989,91 @@ export default class TeraFyServer {
|
|
|
989
989
|
|
|
990
990
|
|
|
991
991
|
/**
|
|
992
|
-
* Fetch a project file
|
|
993
|
-
*
|
|
994
|
-
* @
|
|
992
|
+
* Fetch a project file by its name
|
|
993
|
+
*
|
|
994
|
+
* @param {String} name The name + relative directory path component
|
|
995
|
+
*
|
|
996
|
+
* @param {Object|String} [options] Additional options to mutate behaviour, if a string is given `options.subkey` is assumed
|
|
997
|
+
* @param {String} [options.subkey] If specified only the extracted subkey is returned rather than the full object
|
|
998
|
+
* @param {Boolean} [options.cache=true] Use the existing file cache if possible, set to false to force a refresh of files from the server first
|
|
999
|
+
*
|
|
1000
|
+
* @returns {Promise<ProjectFile>} The eventual fetched ProjectFile (or requested subkey)
|
|
995
1001
|
*/
|
|
996
|
-
getProjectFile(
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1002
|
+
getProjectFile(name, options) {
|
|
1003
|
+
let settings = {
|
|
1004
|
+
subkey: null,
|
|
1005
|
+
cache: true,
|
|
1006
|
+
...(typeof options == 'string' ? {subkey: options} : options),
|
|
1007
|
+
};
|
|
1008
|
+
|
|
1009
|
+
return Promise.resolve()
|
|
1010
|
+
.then(()=>
|
|
1011
|
+
app.service('$projects').activeFiles.length == 0 // If we have no files in the cache
|
|
1012
|
+
|| !settings.cache // OR caching is disabled
|
|
1013
|
+
? app.service('$projects').refreshFiles({ // Go refresh files first
|
|
1014
|
+
lazy: false,
|
|
1015
|
+
})
|
|
1016
|
+
: app.service('$projects').activeFiles // Otherwise use file cache
|
|
1017
|
+
)
|
|
1018
|
+
.then(files =>
|
|
1019
|
+
files.find(file =>
|
|
1020
|
+
file.name == name
|
|
1021
|
+
)
|
|
1022
|
+
)
|
|
1023
|
+
.then(file => file && settings.subkey ? file[settings.subkey] : file) // Provide subkey if asked
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
/**
|
|
1028
|
+
* Create a new file
|
|
1029
|
+
* This creates an empty file which can then be written to
|
|
1030
|
+
* This function also forces a local file list cache update
|
|
1031
|
+
*
|
|
1032
|
+
* @param {String} name The name + relative directory path component
|
|
1033
|
+
* @returns {Promise<ProjectFile>} The eventual ProjectFile created
|
|
1034
|
+
*/
|
|
1035
|
+
createProjectFile(name) {
|
|
1036
|
+
return Promise.resolve()
|
|
1037
|
+
.then(()=> app.service('$supabase').fileUpload(app.service('$projects').convertRelativePath(name), {
|
|
1038
|
+
file: new Blob([''], {type: 'text/plain'}),
|
|
1039
|
+
mode: 'encoded',
|
|
1040
|
+
overwrite: false,
|
|
1041
|
+
multiple: false,
|
|
1042
|
+
toast: false,
|
|
1043
|
+
transcoders: false,
|
|
1044
|
+
}))
|
|
1045
|
+
.then(()=> this.getProjectFile(name, {
|
|
1046
|
+
cache: false, // Force cache to update, as this is a new file
|
|
1047
|
+
}))
|
|
1048
|
+
.then(file => file || Promise.reject(`Could not create new file "${name}"`))
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
/**
|
|
1053
|
+
* Remove a project file by its ID
|
|
1054
|
+
*
|
|
1055
|
+
* @param {String} id The File ID to remove
|
|
1056
|
+
*
|
|
1057
|
+
* @returns {Promise} A promise which resolves when the operation has completed
|
|
1058
|
+
*/
|
|
1059
|
+
deleteProjectFile(id) {
|
|
1060
|
+
return app.service('$supabase').fileRemove(app.service('$projects').decodeFilePath(id))
|
|
1061
|
+
.then(()=> app.service('$projects').refreshFiles({ // Force a local file list update
|
|
1062
|
+
lazy: false,
|
|
1063
|
+
}))
|
|
1064
|
+
.then(()=> null)
|
|
1000
1065
|
}
|
|
1001
1066
|
|
|
1002
1067
|
|
|
1003
1068
|
/**
|
|
1004
1069
|
* Replace a project files contents
|
|
1005
1070
|
*
|
|
1006
|
-
* @param {String}
|
|
1071
|
+
* @param {String} id File to overwrite
|
|
1007
1072
|
* @param {File|Blob|FormData|Object|Array} contents The new file contents
|
|
1008
1073
|
* @returns {Promise} A promise which will resolve when the write operation has completed
|
|
1009
1074
|
*/
|
|
1010
|
-
setProjectFile(
|
|
1011
|
-
return app.service('$supabase').fileSet(
|
|
1075
|
+
setProjectFile(id, contents) {
|
|
1076
|
+
return app.service('$supabase').fileSet(app.service('$projects').decodeFilePath(id), contents, {
|
|
1012
1077
|
overwrite: true,
|
|
1013
1078
|
toast: false,
|
|
1014
1079
|
});
|
|
@@ -1051,14 +1116,14 @@ export default class TeraFyServer {
|
|
|
1051
1116
|
|
|
1052
1117
|
return app.service('$projects').promise()
|
|
1053
1118
|
.then(()=> this.selectProjectFile(settings))
|
|
1054
|
-
.then(selectedFile => this.getProjectLibrary(selectedFile.
|
|
1119
|
+
.then(selectedFile => this.getProjectLibrary(selectedFile.id, settings))
|
|
1055
1120
|
}
|
|
1056
1121
|
|
|
1057
1122
|
|
|
1058
1123
|
/**
|
|
1059
1124
|
* Fetch + convert a project file into a library of citations
|
|
1060
1125
|
*
|
|
1061
|
-
* @param {String}
|
|
1126
|
+
* @param {String} id File ID to read
|
|
1062
1127
|
*
|
|
1063
1128
|
* @param {Object} [options] Additional options to mutate behaviour
|
|
1064
1129
|
* @param {String} [options.format='json'] Format for the file. ENUM: 'pojo' (return a parsed JS collection), 'blob' (raw JS Blob object), 'file' (named JS File object)
|
|
@@ -1068,7 +1133,7 @@ export default class TeraFyServer {
|
|
|
1068
1133
|
*
|
|
1069
1134
|
* @returns {Promise<Array<Ref>>|Promise<*>} A collection of references (default bevahiour) or a whatever format was requested
|
|
1070
1135
|
*/
|
|
1071
|
-
getProjectLibrary(
|
|
1136
|
+
getProjectLibrary(id, options) {
|
|
1072
1137
|
let settings = {
|
|
1073
1138
|
format: 'pojo',
|
|
1074
1139
|
autoRequire: true,
|
|
@@ -1077,9 +1142,11 @@ export default class TeraFyServer {
|
|
|
1077
1142
|
...options,
|
|
1078
1143
|
};
|
|
1079
1144
|
|
|
1145
|
+
let filePath = app.service('$projects').decodeFilePath(id);
|
|
1146
|
+
|
|
1080
1147
|
return Promise.resolve()
|
|
1081
1148
|
.then(()=> settings.autoRequire && this.requireProject())
|
|
1082
|
-
.then(()=> app.service('$supabase').fileGet(
|
|
1149
|
+
.then(()=> app.service('$supabase').fileGet(filePath, {
|
|
1083
1150
|
toast: false,
|
|
1084
1151
|
}))
|
|
1085
1152
|
.then(blob => {
|
|
@@ -1089,7 +1156,7 @@ export default class TeraFyServer {
|
|
|
1089
1156
|
return Reflib.uploadFile({
|
|
1090
1157
|
file: new File(
|
|
1091
1158
|
[blob],
|
|
1092
|
-
app.service('$supabase')._parsePath(
|
|
1159
|
+
app.service('$supabase')._parsePath(filePath).basename,
|
|
1093
1160
|
),
|
|
1094
1161
|
});
|
|
1095
1162
|
case 'blob':
|
|
@@ -1097,7 +1164,7 @@ export default class TeraFyServer {
|
|
|
1097
1164
|
case 'file':
|
|
1098
1165
|
return new File(
|
|
1099
1166
|
[blob],
|
|
1100
|
-
app.service('$supabase')._parsePath(
|
|
1167
|
+
app.service('$supabase')._parsePath(filePath).basename,
|
|
1101
1168
|
);
|
|
1102
1169
|
default:
|
|
1103
1170
|
throw new Error(`Unsupported library format "${settings.format}"`);
|
|
@@ -1109,23 +1176,23 @@ export default class TeraFyServer {
|
|
|
1109
1176
|
/**
|
|
1110
1177
|
* Save back a citation library from some input
|
|
1111
1178
|
*
|
|
1112
|
-
* @param {String} [
|
|
1179
|
+
* @param {String} [id] File ID to save back to, if omitted a file will be prompted for
|
|
1113
1180
|
* @param {Array<RefLibRef>|Blob|File} [refs] Collection of references for the selected library or the raw Blob/File
|
|
1114
1181
|
*
|
|
1115
1182
|
* @param {Object} [options] Additional options to mutate behaviour
|
|
1116
|
-
* @param {String} [options.
|
|
1183
|
+
* @param {String} [options.id] Alternate method to specify the file ID to save as, if omitted one will be prompted for
|
|
1117
1184
|
* @param {Array<RefLibRef>|Blob|File} [options.refs] Alternate method to specify the refs to save as an array or raw Blob/File
|
|
1118
1185
|
* @param {String} [options.format='auto'] Input format used. ENUM: 'auto' (try to figure it out from context), 'pojo' (JS array of RefLib references), 'blob' (raw JS Blob object), 'file' (named JS File object)
|
|
1119
1186
|
* @param {Boolean} [options.autoRequire=true] Run `requireProject()` automatically before continuing
|
|
1120
1187
|
* @param {String|Array<String>} [options.hint] Hint(s) to store against the library. Generally corresponds to the current operation being performed - e.g. 'deduped'
|
|
1121
|
-
* @param {String} [options.filename] Suggested filename if
|
|
1122
|
-
* @param {String} [options.title='Save citation library'] Dialog title if
|
|
1188
|
+
* @param {String} [options.filename] Suggested filename if `id` is unspecified
|
|
1189
|
+
* @param {String} [options.title='Save citation library'] Dialog title if `id` is unspecified and a prompt is necessary
|
|
1123
1190
|
* @param {Boolean} [options.overwrite=true] Allow existing file upsert
|
|
1124
1191
|
* @param {Object} [options.meta] Optional meta data to merge into the file data
|
|
1125
1192
|
*
|
|
1126
1193
|
* @returns {Promise} A promise which resolves when the save operation has completed
|
|
1127
1194
|
*/
|
|
1128
|
-
setProjectLibrary(
|
|
1195
|
+
setProjectLibrary(id, refs, options) {
|
|
1129
1196
|
let settings = {
|
|
1130
1197
|
format: 'auto',
|
|
1131
1198
|
autoRequire: true,
|
|
@@ -1135,17 +1202,18 @@ export default class TeraFyServer {
|
|
|
1135
1202
|
overwrite: true,
|
|
1136
1203
|
meta: null,
|
|
1137
1204
|
...(
|
|
1138
|
-
typeof
|
|
1139
|
-
: Array.isArray(
|
|
1140
|
-
:
|
|
1205
|
+
typeof id == 'string' && Array.isArray(refs) ? {id, refs, ...options} // Called as (id, refs, options?)
|
|
1206
|
+
: Array.isArray(id) || refs instanceof Blob || refs instanceof File ? {refs: id, ...refs} // Called as (refs, options?)
|
|
1207
|
+
: id // Called as (options?)
|
|
1141
1208
|
)
|
|
1142
1209
|
};
|
|
1143
1210
|
if (!settings.refs) throw new Error('No refs to save');
|
|
1144
1211
|
|
|
1212
|
+
let filePath; // Eventual Supabase path to use
|
|
1145
1213
|
return Promise.resolve()
|
|
1146
1214
|
.then(()=> settings.autoRequire && this.requireProject())
|
|
1147
1215
|
.then(()=> {
|
|
1148
|
-
if (settings.
|
|
1216
|
+
if (settings.id) return; // We already have a file ID specified - skip
|
|
1149
1217
|
|
|
1150
1218
|
// Prompt for a save filename
|
|
1151
1219
|
return this.selectProjectFile({
|
|
@@ -1158,14 +1226,10 @@ export default class TeraFyServer {
|
|
|
1158
1226
|
},
|
|
1159
1227
|
autoRequire: false, // Handled above anyway
|
|
1160
1228
|
})
|
|
1161
|
-
.then(
|
|
1229
|
+
.then(file => settings.id = file.id)
|
|
1162
1230
|
})
|
|
1163
|
-
.then(()=> { //
|
|
1164
|
-
|
|
1165
|
-
settings.path = `/projects/${app.service('$projects').active.id}/${settings.path}`;
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
this.debug('INFO', 2, 'Save citation library as', path);
|
|
1231
|
+
.then(()=> { // Compute filePath
|
|
1232
|
+
filePath = app.service('$projects').decodeFilePath(settings.id);
|
|
1169
1233
|
})
|
|
1170
1234
|
.then(()=> {
|
|
1171
1235
|
// Mutate settings.ref -> Blob or File format needed by Supabase
|
|
@@ -1184,12 +1248,12 @@ export default class TeraFyServer {
|
|
|
1184
1248
|
|
|
1185
1249
|
// Get Reflib to encode the POJO into a Blob/File
|
|
1186
1250
|
return Reflib.downloadFile(settings.refs, {
|
|
1187
|
-
filename:
|
|
1251
|
+
filename: app.service('$supabase')._parsePath(filePath).basename,
|
|
1188
1252
|
promptDownload: false, // Just return the fileBlob we hand to Supabase
|
|
1189
1253
|
})
|
|
1190
1254
|
case 'blob':
|
|
1191
1255
|
if (!(settings.refs instanceof Blob)) throw new Error("setProjectLibrary({format: 'blob'} but non-Blob provided as `refs`");
|
|
1192
|
-
return new File([settings.refs], app.service('$supabase')._parsePath(
|
|
1256
|
+
return new File([settings.refs], app.service('$supabase')._parsePath(filePath).basename);
|
|
1193
1257
|
case 'file':
|
|
1194
1258
|
if (!(settings.ref instanceof File)) throw new Error("setProjectLibrary({format: 'file'} but non-File provided as `refs`");
|
|
1195
1259
|
return settings.refs;
|
|
@@ -1197,12 +1261,10 @@ export default class TeraFyServer {
|
|
|
1197
1261
|
throw new Error(`Unsupported library format "${settings.format}"`);
|
|
1198
1262
|
}
|
|
1199
1263
|
})
|
|
1200
|
-
.then(fileBlob => app.service('$supabase').fileUpload(
|
|
1264
|
+
.then(fileBlob => app.service('$supabase').fileUpload(filePath, {
|
|
1201
1265
|
file: fileBlob,
|
|
1202
|
-
mode: 'encoded',
|
|
1203
1266
|
overwrite: true,
|
|
1204
|
-
|
|
1205
|
-
transcoders: false, // We can skip transcoders as we are supplying the meta information above anyway
|
|
1267
|
+
mode: 'encoded',
|
|
1206
1268
|
}))
|
|
1207
1269
|
}
|
|
1208
1270
|
|
|
@@ -1222,7 +1284,7 @@ export default class TeraFyServer {
|
|
|
1222
1284
|
}
|
|
1223
1285
|
// }}}
|
|
1224
1286
|
|
|
1225
|
-
// Webpages - setPageUrl() {{{
|
|
1287
|
+
// Webpages - setPageUrl(), setPageTitle {{{
|
|
1226
1288
|
|
|
1227
1289
|
/**
|
|
1228
1290
|
* Set an active tools URL (or path) so that it survives a refresh
|
|
@@ -1430,6 +1492,5 @@ export default class TeraFyServer {
|
|
|
1430
1492
|
...msg,
|
|
1431
1493
|
);
|
|
1432
1494
|
}
|
|
1433
|
-
|
|
1434
1495
|
// }}}
|
|
1435
1496
|
}
|
package/package.json
CHANGED