@iebh/tera-fy 2.0.21 → 2.2.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.
Files changed (75) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/api.md +68 -66
  3. package/dist/lib/projectFile.d.ts +182 -0
  4. package/dist/lib/projectFile.js +157 -0
  5. package/dist/lib/projectFile.js.map +1 -0
  6. package/dist/lib/syncro/entities.d.ts +28 -0
  7. package/dist/lib/syncro/entities.js +203 -0
  8. package/dist/lib/syncro/entities.js.map +1 -0
  9. package/dist/lib/syncro/keyed.d.ts +95 -0
  10. package/dist/lib/syncro/keyed.js +286 -0
  11. package/dist/lib/syncro/keyed.js.map +1 -0
  12. package/dist/lib/syncro/syncro.d.ts +328 -0
  13. package/dist/lib/syncro/syncro.js +633 -0
  14. package/dist/lib/syncro/syncro.js.map +1 -0
  15. package/dist/lib/terafy.bootstrapper.d.ts +42 -0
  16. package/dist/lib/terafy.bootstrapper.js +130 -0
  17. package/dist/lib/terafy.bootstrapper.js.map +1 -0
  18. package/dist/lib/terafy.client.d.ts +532 -0
  19. package/dist/lib/terafy.client.js +1110 -0
  20. package/dist/lib/terafy.client.js.map +1 -0
  21. package/dist/lib/terafy.proxy.d.ts +66 -0
  22. package/dist/lib/terafy.proxy.js +123 -0
  23. package/dist/lib/terafy.proxy.js.map +1 -0
  24. package/dist/lib/terafy.server.d.ts +607 -0
  25. package/dist/lib/terafy.server.js +1774 -0
  26. package/dist/lib/terafy.server.js.map +1 -0
  27. package/dist/plugin.vue2.es2019.js +30 -13
  28. package/dist/plugins/base.d.ts +20 -0
  29. package/dist/plugins/base.js +21 -0
  30. package/dist/plugins/base.js.map +1 -0
  31. package/dist/plugins/firebase.d.ts +62 -0
  32. package/dist/plugins/firebase.js +111 -0
  33. package/dist/plugins/firebase.js.map +1 -0
  34. package/dist/plugins/vite.d.ts +12 -0
  35. package/dist/plugins/vite.js +22 -0
  36. package/dist/plugins/vite.js.map +1 -0
  37. package/dist/plugins/vue2.d.ts +68 -0
  38. package/dist/plugins/vue2.js +96 -0
  39. package/dist/plugins/vue2.js.map +1 -0
  40. package/dist/plugins/vue3.d.ts +64 -0
  41. package/dist/plugins/vue3.js +96 -0
  42. package/dist/plugins/vue3.js.map +1 -0
  43. package/dist/terafy.bootstrapper.es2019.js +2 -2
  44. package/dist/terafy.bootstrapper.js +2 -2
  45. package/dist/terafy.es2019.js +2 -2
  46. package/dist/terafy.js +1 -1
  47. package/dist/utils/mixin.d.ts +11 -0
  48. package/dist/utils/mixin.js +15 -0
  49. package/dist/utils/mixin.js.map +1 -0
  50. package/dist/utils/pDefer.d.ts +12 -0
  51. package/dist/utils/pDefer.js +14 -0
  52. package/dist/utils/pDefer.js.map +1 -0
  53. package/dist/utils/pathTools.d.ts +70 -0
  54. package/dist/utils/pathTools.js +120 -0
  55. package/dist/utils/pathTools.js.map +1 -0
  56. package/eslint.config.js +44 -8
  57. package/lib/{projectFile.js → projectFile.ts} +83 -40
  58. package/lib/syncro/entities.ts +288 -0
  59. package/lib/syncro/{keyed.js → keyed.ts} +114 -57
  60. package/lib/syncro/{syncro.js → syncro.ts} +204 -169
  61. package/lib/{terafy.bootstrapper.js → terafy.bootstrapper.ts} +49 -31
  62. package/lib/{terafy.client.js → terafy.client.ts} +94 -86
  63. package/lib/{terafy.proxy.js → terafy.proxy.ts} +43 -16
  64. package/lib/{terafy.server.js → terafy.server.ts} +364 -223
  65. package/package.json +65 -26
  66. package/plugins/{base.js → base.ts} +3 -1
  67. package/plugins/{firebase.js → firebase.ts} +34 -16
  68. package/plugins/{vite.js → vite.ts} +3 -3
  69. package/plugins/{vue2.js → vue2.ts} +17 -10
  70. package/plugins/{vue3.js → vue3.ts} +11 -9
  71. package/tsconfig.json +30 -0
  72. package/utils/{mixin.js → mixin.ts} +1 -1
  73. package/utils/{pDefer.js → pDefer.ts} +10 -3
  74. package/utils/{pathTools.js → pathTools.ts} +11 -9
  75. package/lib/syncro/entities.js +0 -232
@@ -0,0 +1,182 @@
1
+ import type TeraFy from './terafy.client.ts';
2
+ interface TeraClient extends TeraFy {
3
+ getProjectFileContents: (id: any, options?: any) => any;
4
+ setProjectFileContents: (id: any, contents: any, options?: any) => any;
5
+ getProjectLibrary: (id: any, options?: any) => any;
6
+ setProjectLibrary: (id: any, refs: any, options?: any) => any;
7
+ }
8
+ type SupabaseFile = any;
9
+ type RefLibRef = any;
10
+ /**
11
+ * A project file fetched from TERA
12
+ * @class ProjectFile
13
+ */
14
+ export default class ProjectFile {
15
+ /**
16
+ * Parent TeraClient instance used by all helper functions
17
+ * @type {TeraClient}
18
+ * @private
19
+ */
20
+ _tera: TeraClient;
21
+ /**
22
+ * The TERA compatible unique ID of the file
23
+ * NOTE: This is computed each time from the Base64 of the file path
24
+ * @type {String}
25
+ */
26
+ id: string;
27
+ /**
28
+ * The raw Supabase UUID of the file
29
+ * @type {String}
30
+ */
31
+ sbId: string;
32
+ /**
33
+ * Relative name path (can contain prefix directories) for the human readable file name
34
+ * @type {String}
35
+ */
36
+ name: string;
37
+ /**
38
+ * CSS class to use as the file icon
39
+ * @type {String}
40
+ */
41
+ icon: string;
42
+ /**
43
+ * Full path to the file
44
+ * This is also used as the unique identifier within the project
45
+ * @type {String}
46
+ */
47
+ path: string;
48
+ /**
49
+ * Fully qualified URL to view / access / download the file from TERA
50
+ * This will usually open an edit UI within the TERA site
51
+ * @type {String}
52
+ */
53
+ url: string;
54
+ /**
55
+ * Rewrite of the URL where the absolute URL has been removed in place of a relative path, assuming the owner project is active
56
+ * This is used to direct to the edit/view/download UI when the files project is active and is usually used in place of URL for TERA related operations
57
+ * @type {String}
58
+ */
59
+ teraUrl: string;
60
+ /**
61
+ * An object representing meta file parts of a file name
62
+ * @type {Object}
63
+ * @property {String} basename The filename + extention (i.e. everything without directory name)
64
+ * @property {String} filename The file portion of the name (basename without the extension)
65
+ * @property {String} ext The extension portion of the name (always lower case)
66
+ * @property {String} dirName The directory path portion of the name
67
+ */
68
+ parsedName: any;
69
+ /**
70
+ * A date representing when the file was created
71
+ * @type {Date}
72
+ */
73
+ created: Date | undefined;
74
+ /**
75
+ * A human readable, formatted version of "created"
76
+ * @type {String}
77
+ */
78
+ createdFormatted: string;
79
+ /**
80
+ * A date representing when the file was created
81
+ * @type {Date}
82
+ */
83
+ modified: Date | undefined;
84
+ /**
85
+ * A human readable, formatted version of "modified"
86
+ * @type {String}
87
+ */
88
+ modifiedFormatted: string;
89
+ /**
90
+ * A date representing when the file was last accessed
91
+ * @type {Date}
92
+ */
93
+ accessed: Date | undefined;
94
+ /**
95
+ * A human readable, formatted version of "accessed"
96
+ * @type {String}
97
+ */
98
+ accessedFormatted: string;
99
+ /**
100
+ * Size, in bytes, of the file
101
+ * @type {Number}
102
+ */
103
+ size: number | undefined;
104
+ /**
105
+ * A human readable, formatted version of the file size
106
+ * @type {String}
107
+ */
108
+ sizeFormatted: string;
109
+ /**
110
+ * The associated mime type for the file
111
+ * @type {String}
112
+ */
113
+ mime: string;
114
+ /**
115
+ * Additional meta information for the file
116
+ * @type {Object}
117
+ */
118
+ meta: Record<string, any>;
119
+ /**
120
+ * ProjectFile constructor
121
+ * Takes the input basic file type from Supabase and adds additional formatted fields
122
+ * @param {SupabaseFile} baseFile The basic Supabase file to extend
123
+ * @param {TeraFyClient} baseFile.tera The associated TeraFyClient instance to use for some file methods
124
+ */
125
+ constructor(baseFile: SupabaseFile);
126
+ /**
127
+ * Fetch the raw file contents as a Blob
128
+ *
129
+ * @param {Object} [options] Additioanl options to mutate behaviour
130
+ *
131
+ * @returns {Promise<Blob>} The eventual raw file contents as a Blob
132
+ *
133
+ * @see getProjectFile()
134
+ */
135
+ getContents(options?: any): Promise<Blob>;
136
+ /**
137
+ * Overwrite the contents of a file with new content
138
+ *
139
+ * @param {File|Blob|FormData|Object|Array} contents The new file contents
140
+ *
141
+ * @returns {Promise<void>} A promise which resolves when the operation has completed
142
+ *
143
+ * @see setProjectFileContents()
144
+ */
145
+ setContents(contents: File | Blob | FormData | object | any[]): Promise<void>;
146
+ /**
147
+ * Fetch the file contents as an array of Reflib refs
148
+ *
149
+ * @returns {Promise<Array<RefLibRef>>} An eventual array of RefLib references
150
+ *
151
+ * @see getProjectLibrary()
152
+ */
153
+ getRefs(): Promise<Array<RefLibRef>>;
154
+ /**
155
+ * Overwrite the contents of a file with a new collection of Reflib refs
156
+ *
157
+ * @param {Array<RefLibRef>} refs Collection of references for the selected library
158
+ *
159
+ * @returns {Promise<void>} A promise which resolves when the operation has completed
160
+ *
161
+ * @see setProjectLibrary()
162
+ */
163
+ setRefs(refs: Array<RefLibRef>): Promise<void>;
164
+ /**
165
+ * Compress a file state down into a serializable entity
166
+ * By default this computes a Structured Clone which can be stringified
167
+ *
168
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
169
+ * @returns {Object} A Structured Clone compatible representation of this ProjectFile instance
170
+ */
171
+ serialize(): Partial<ProjectFile>;
172
+ /**
173
+ * Restore an entity created with serialize
174
+ * NOTE: This requires the 'tera' instance to be manually added to the 'data' object before calling deserialize,
175
+ * as it's not included in the serialized output.
176
+ *
177
+ * @param {Object} data An input object created via `ProjectFiles.serialize()` (MUST include a 'tera' property added manually)
178
+ * @returns {ProjectFile} A ProjectFile instance setup against the deserializzed data
179
+ */
180
+ static deserialize(data: any): ProjectFile;
181
+ }
182
+ export {};
@@ -0,0 +1,157 @@
1
+ import { filesize } from 'filesize';
2
+ import { pick } from 'lodash-es';
3
+ ;
4
+ /**
5
+ * A project file fetched from TERA
6
+ * @class ProjectFile
7
+ */
8
+ export default class ProjectFile {
9
+ /**
10
+ * ProjectFile constructor
11
+ * Takes the input basic file type from Supabase and adds additional formatted fields
12
+ * @param {SupabaseFile} baseFile The basic Supabase file to extend
13
+ * @param {TeraFyClient} baseFile.tera The associated TeraFyClient instance to use for some file methods
14
+ */
15
+ constructor(baseFile) {
16
+ /**
17
+ * Additional meta information for the file
18
+ * @type {Object}
19
+ */
20
+ // Using Record<string, any> for a generic object, adjust if meta has a known structure
21
+ this.meta = {};
22
+ // Note: baseFile.tera is assumed to exist based on the check below and the SupabaseFile type definition above
23
+ if (!baseFile.tera)
24
+ throw new Error('Basic file requires a `tera` key to access the Tera instance');
25
+ Object.assign(this, baseFile);
26
+ // Translate baseFile.tera -> this._tera (non-enumerable, non-configurable)
27
+ const tera = this.tera;
28
+ Object.defineProperty(this, '_tera', {
29
+ enumerable: false,
30
+ configurable: false,
31
+ get() {
32
+ // NOTE: We can't just set {value:tera} as it upsets how Vue uses proxies
33
+ return tera;
34
+ },
35
+ });
36
+ delete this.tera; // Remove original ref we merged above
37
+ // Calculate `teraUrl` from URL
38
+ // Assuming this.url is always defined after Object.assign
39
+ this.teraUrl = this.url.replace(/^https?:\/\/(?:.+?)\/projects\/(?:.+?)\/project\/(.+)$/, '/project/$1');
40
+ // Set all `*Formatted` fields
41
+ this.sizeFormatted = filesize(this.size || 0, { spacer: '' });
42
+ this.createdFormatted = this.created ? this.created.toLocaleDateString() : 'Unknown created date';
43
+ this.modifiedFormatted = this.modified ? this.modified.toLocaleDateString() : 'Unknown modified date';
44
+ this.accessedFormatted = this.accessed ? this.accessed.toLocaleDateString() : 'Unknown access date';
45
+ }
46
+ /**
47
+ * Fetch the raw file contents as a Blob
48
+ *
49
+ * @param {Object} [options] Additioanl options to mutate behaviour
50
+ *
51
+ * @returns {Promise<Blob>} The eventual raw file contents as a Blob
52
+ *
53
+ * @see getProjectFile()
54
+ */
55
+ getContents(options) {
56
+ // Assuming _tera has this method and it returns Promise<Blob>
57
+ return this._tera.getProjectFileContents(this.id, options);
58
+ }
59
+ /**
60
+ * Overwrite the contents of a file with new content
61
+ *
62
+ * @param {File|Blob|FormData|Object|Array} contents The new file contents
63
+ *
64
+ * @returns {Promise<void>} A promise which resolves when the operation has completed
65
+ *
66
+ * @see setProjectFileContents()
67
+ */
68
+ setContents(contents) {
69
+ // Assuming _tera has this method and it returns Promise<void> or similar
70
+ return this._tera.setProjectFileContents(this.id, contents, {});
71
+ }
72
+ /**
73
+ * Fetch the file contents as an array of Reflib refs
74
+ *
75
+ * @returns {Promise<Array<RefLibRef>>} An eventual array of RefLib references
76
+ *
77
+ * @see getProjectLibrary()
78
+ */
79
+ getRefs() {
80
+ // Assuming _tera has this method and it returns Promise<Array<RefLibRef>>
81
+ return this._tera.getProjectLibrary(this.id);
82
+ }
83
+ /**
84
+ * Overwrite the contents of a file with a new collection of Reflib refs
85
+ *
86
+ * @param {Array<RefLibRef>} refs Collection of references for the selected library
87
+ *
88
+ * @returns {Promise<void>} A promise which resolves when the operation has completed
89
+ *
90
+ * @see setProjectLibrary()
91
+ */
92
+ setRefs(refs) {
93
+ // Assuming _tera has this method and it returns Promise<void> or similar
94
+ return this._tera.setProjectLibrary(this.id, refs);
95
+ }
96
+ /**
97
+ * Compress a file state down into a serializable entity
98
+ * By default this computes a Structured Clone which can be stringified
99
+ *
100
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
101
+ * @returns {Object} A Structured Clone compatible representation of this ProjectFile instance
102
+ */
103
+ serialize() {
104
+ return pick(this, [
105
+ 'id',
106
+ 'sbId',
107
+ 'name',
108
+ 'icon',
109
+ 'path',
110
+ 'url',
111
+ 'parsedName',
112
+ 'created',
113
+ 'modified',
114
+ 'accessed',
115
+ 'size',
116
+ 'mime',
117
+ 'meta',
118
+ // Note that computed values such as `*Formatted` are omitted as they can be computed during the constructor stage
119
+ ]);
120
+ }
121
+ /**
122
+ * Restore an entity created with serialize
123
+ * NOTE: This requires the 'tera' instance to be manually added to the 'data' object before calling deserialize,
124
+ * as it's not included in the serialized output.
125
+ *
126
+ * @param {Object} data An input object created via `ProjectFiles.serialize()` (MUST include a 'tera' property added manually)
127
+ * @returns {ProjectFile} A ProjectFile instance setup against the deserializzed data
128
+ */
129
+ static deserialize(data) {
130
+ // TODO: Check the below
131
+ // WARNING: The original 'serialize' method does NOT include 'tera'.
132
+ // The caller of 'deserialize' MUST add the correct 'tera' instance to the 'data' object
133
+ // before passing it here, otherwise the constructor will fail.
134
+ // e.g., const serializedData = file.serialize();
135
+ // serializedData.tera = myTeraClientInstance;
136
+ // const restoredFile = ProjectFile.deserialize(serializedData);
137
+ // This pick includes 'tera', assuming it was added to 'data' externally.
138
+ const constructorArg = pick(data, [
139
+ 'tera', // Assumes 'tera' exists on the input 'data' object
140
+ 'id',
141
+ 'sbId',
142
+ 'name',
143
+ 'icon',
144
+ 'path',
145
+ 'url',
146
+ 'parsedName',
147
+ 'created',
148
+ 'modified',
149
+ 'accessed',
150
+ 'size',
151
+ 'mime',
152
+ 'meta',
153
+ ]);
154
+ return new ProjectFile(constructorArg);
155
+ }
156
+ }
157
+ //# sourceMappingURL=projectFile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectFile.js","sourceRoot":"","sources":["../../lib/projectFile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { BoundSupabaseyFunction } from '@iebh/supabasey';
2
+ interface SyncroEntityConfig {
3
+ singular: string;
4
+ initState: (args: {
5
+ supabasey: BoundSupabaseyFunction;
6
+ id: string;
7
+ relation?: string;
8
+ }) => Promise<any>;
9
+ flushState: (args: {
10
+ supabasey: BoundSupabaseyFunction;
11
+ state: any;
12
+ id?: string;
13
+ fsId?: string;
14
+ relation?: string;
15
+ }) => Promise<any>;
16
+ }
17
+ type SyncroConfig = Record<string, SyncroEntityConfig>;
18
+ /**
19
+ * Entities we support Syncro paths for, each should correspond directly with a Firebase/Firestore collection name
20
+ *
21
+ * @type {Object} An object lookup of entities
22
+ *
23
+ * @property {String} singular The singular noun for the item
24
+ * @property {Function} initState Function called to initialize state when Firestore has no existing document. Called as `({supabase:BoundSupabaseyFunction, entity:String, id:String, relation?:string})` and expected to return the initial data object state
25
+ * @property {Function} flushState Function called to flush state from Firebase to Supabase. Called the same as `initState` + `{state:Object}`
26
+ */
27
+ declare const syncroConfig: SyncroConfig;
28
+ export default syncroConfig;
@@ -0,0 +1,203 @@
1
+ // @ts-ignore
2
+ import Reflib from '@iebh/reflib';
3
+ import { v4 as uuid4 } from 'uuid';
4
+ import { nanoid } from 'nanoid';
5
+ /**
6
+ * Entities we support Syncro paths for, each should correspond directly with a Firebase/Firestore collection name
7
+ *
8
+ * @type {Object} An object lookup of entities
9
+ *
10
+ * @property {String} singular The singular noun for the item
11
+ * @property {Function} initState Function called to initialize state when Firestore has no existing document. Called as `({supabase:BoundSupabaseyFunction, entity:String, id:String, relation?:string})` and expected to return the initial data object state
12
+ * @property {Function} flushState Function called to flush state from Firebase to Supabase. Called the same as `initState` + `{state:Object}`
13
+ */
14
+ const syncroConfig = {
15
+ projects: {
16
+ singular: 'project',
17
+ async initState({ supabasey, id }) {
18
+ let projectData = await supabasey((supabase) => supabase
19
+ .from('projects')
20
+ .select('data')
21
+ .eq('id', id)
22
+ .maybeSingle());
23
+ if (!projectData)
24
+ throw new Error(`Syncro project "${id}" not found`);
25
+ let data = projectData.data;
26
+ // MIGRATION - Move data.temp{} into Supabase files + add pointer to filename {{{
27
+ if (data.temp // Project contains temp subkey
28
+ && Object.values(data.temp).some((t) => typeof t == 'object') // Some of the temp keys are objects
29
+ ) {
30
+ console.log('[MIGRATION] tera-fy project v1 -> v2', data.temp);
31
+ const tempObject = data.temp;
32
+ await Promise.all(Object.entries(data.temp)
33
+ .filter(([, branch]) => typeof branch == 'object')
34
+ .map(([toolKey,]) => {
35
+ console.log(`[MIGRATION] Converting data.temp[${toolKey}]...`);
36
+ const toolName = toolKey.split('-')[0];
37
+ const fileName = `data-${toolName}-${nanoid()}.json`;
38
+ console.log('[MIGRATION] Creating filename:', fileName);
39
+ return Promise.resolve()
40
+ .then(() => supabasey((supabase) => supabase // Split data.temp[toolKey] -> file {{{
41
+ .storage
42
+ .from('projects')
43
+ .upload(`${id}/${fileName}`, new File([
44
+ new Blob([
45
+ JSON.stringify(tempObject[toolKey], null, '\t'),
46
+ ], {
47
+ type: 'application/json',
48
+ }),
49
+ ], fileName, {
50
+ type: 'application/json',
51
+ }), {
52
+ cacheControl: '3600',
53
+ upsert: true,
54
+ }))) // }}}
55
+ .then(() => tempObject[toolKey] = fileName) // Replace data.temp[toolKey] with new filename
56
+ .catch(e => {
57
+ console.warn('[MIGRATION] Failed to create file', fileName, '-', e);
58
+ throw e;
59
+ });
60
+ }));
61
+ } // }}}
62
+ return data;
63
+ },
64
+ flushState({ supabasey, state, fsId }) {
65
+ // Import Supabasey because 'supabasey' lowercase is just a function
66
+ return supabasey(supabase => supabase.rpc('syncro_merge_data', {
67
+ table_name: 'projects',
68
+ entity_id: fsId,
69
+ new_data: state,
70
+ }));
71
+ },
72
+ }, // }}}
73
+ project_libraries: {
74
+ singular: 'project library',
75
+ async initState({ supabasey, id, relation }) {
76
+ if (!relation || !/_\*$/.test(relation))
77
+ throw new Error('Project library relation missing, path should resemble "project_library::${PROJECT}::${LIBRARY_FILE_ID}_*"');
78
+ let fileId = relation.replace(/_\*$/, '');
79
+ const files = await supabasey((supabase) => supabase
80
+ .storage
81
+ .from('projects')
82
+ .list(id));
83
+ const file = files?.find((f) => f.id == fileId);
84
+ if (!file)
85
+ return Promise.reject(`Invalid file ID "${fileId}"`);
86
+ const blob = await supabasey((supabase) => supabase
87
+ .storage
88
+ .from('projects')
89
+ .download(`${id}/${file.name}`));
90
+ if (!blob)
91
+ throw new Error('Failed to download file blob');
92
+ const refs = await Reflib.uploadFile({
93
+ file: new File([blob], file.name.replace(/^.*[/\\]/, '')),
94
+ });
95
+ return Object.fromEntries(refs // Transform Reflib Ref array into a keyed UUID object
96
+ .map((ref) => [
97
+ uuid4(), // TODO: This should really be using V5 with some-kind of namespacing but I can't get my head around the documentation - MC 2025-02-21
98
+ ref, // The actual ref payload
99
+ ]));
100
+ },
101
+ flushState() {
102
+ throw new Error('Flushing project_libraries::* namespace is not yet supported');
103
+ },
104
+ }, // }}}
105
+ project_namespaces: {
106
+ singular: 'project namespace',
107
+ async initState({ supabasey, id, relation }) {
108
+ if (!relation)
109
+ throw new Error('Project namespace relation missing, path should resemble "project_namespaces::${PROJECT}::${RELATION}"');
110
+ let rows = await supabasey((supabase) => supabase
111
+ .from('project_namespaces')
112
+ .select('data')
113
+ .eq('project', id)
114
+ .eq('name', relation)
115
+ .limit(1));
116
+ if (rows && rows.length == 1) {
117
+ return rows[0].data;
118
+ }
119
+ else {
120
+ const newItem = await supabasey((supabase) => supabase
121
+ .from('project_namespaces') // Doesn't exist - create it
122
+ .insert({
123
+ project: id,
124
+ name: relation,
125
+ data: {},
126
+ })
127
+ .select('data')
128
+ .single() // Assuming insert returns the single inserted row
129
+ );
130
+ if (!newItem)
131
+ throw new Error('Failed to create project namespace');
132
+ return newItem.data;
133
+ }
134
+ },
135
+ flushState({ supabasey, state, id, relation }) {
136
+ return supabasey((supabase) => supabase
137
+ .from('project_namespaces')
138
+ .update({
139
+ edited_at: new Date().toISOString(),
140
+ data: state,
141
+ })
142
+ .eq('project', id)
143
+ .eq('name', relation));
144
+ },
145
+ }, // }}}
146
+ test: {
147
+ singular: 'test',
148
+ async initState({ supabasey, id }) {
149
+ let rows = await supabasey((supabase) => supabase
150
+ .from('test')
151
+ .select('data')
152
+ .eq('id', id)
153
+ .limit(1));
154
+ if (!rows || rows.length !== 1)
155
+ return Promise.reject(`Syncro test item "${id}" not found`);
156
+ return rows[0].data;
157
+ },
158
+ flushState({ supabasey, state, fsId }) {
159
+ return supabasey(supabase => supabase.rpc('syncro_merge_data', {
160
+ table_name: 'test',
161
+ entity_id: fsId,
162
+ new_data: state,
163
+ }));
164
+ },
165
+ }, // }}}
166
+ users: {
167
+ singular: 'user',
168
+ async initState({ supabasey, id }) {
169
+ let user = await supabasey((supabase) => supabase
170
+ .from('users')
171
+ .select('data')
172
+ .eq('id', id)
173
+ .maybeSingle());
174
+ if (user)
175
+ return user.data; // User is valid and already exists
176
+ // User row doesn't already exist - need to create stub
177
+ let newUser = await supabasey((supabase) => supabase
178
+ .from('users')
179
+ .insert({
180
+ id,
181
+ data: {
182
+ id,
183
+ credits: 1000,
184
+ },
185
+ })
186
+ .select('data')
187
+ .single() // Assuming insert returns the single inserted row
188
+ );
189
+ if (!newUser)
190
+ throw new Error('Failed to create user');
191
+ return newUser.data; // Return back the data that eventually got created - allowing for database triggers, default field values etc.
192
+ },
193
+ flushState({ supabasey, state, fsId }) {
194
+ return supabasey(supabase => supabase.rpc('syncro_merge_data', {
195
+ table_name: 'users',
196
+ entity_id: fsId,
197
+ new_data: state,
198
+ }));
199
+ },
200
+ }, // }}}
201
+ };
202
+ export default syncroConfig;
203
+ //# sourceMappingURL=entities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entities.js","sourceRoot":"","sources":["../../../lib/syncro/entities.ts"],"names":[],"mappings":"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"}