subfork 0.1.0 → 0.1.2

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
@@ -5,7 +5,13 @@ Javascript client library used to connect to [Subfork](https://subfork.com) site
5
5
  Usage:
6
6
 
7
7
  ```html
8
- <script src="https://cdn.jsdelivr.net/gh/subforkdev/subfork.js/subfork.min.js"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/subfork@latest/dist/subfork.min.js"></script>
9
+ ```
10
+
11
+ To use the latest unstable dev version:
12
+
13
+ ```html
14
+ <script src="https://code.fork.io/subfork.js"></script>
9
15
  ```
10
16
 
11
17
  Instantiate [Subfork](https://subfork.com) client:
@@ -53,3 +59,13 @@ subfork.task("test").create({
53
59
 
54
60
  See the [test.fork.io](https://github.com/subforkdev/test.fork.io) project for more
55
61
  usage examples.
62
+
63
+ ## badge.js
64
+
65
+ Used for displaying [Subfork](https://subfork.com) attribution badge on sites.
66
+
67
+ Usage:
68
+
69
+ ```html
70
+ <script src="https://cdn.jsdelivr.net/npm/subfork@latest/dist/badge.min.js"></script>
71
+ ```
package/dist/badge.js ADDED
@@ -0,0 +1,55 @@
1
+ /*
2
+ Copyright (c) Subfork. All rights reserved.
3
+
4
+ To use, simply include this file at the bottom of your html:
5
+
6
+ <script src="https://code.subfork.com/badge.js"></script>
7
+ */
8
+
9
+ (function() {
10
+ function createAttributionBadge() {
11
+ // Create the badge container
12
+ const badge = document.createElement("div");
13
+ badge.className = "attribution-badge";
14
+
15
+ // Create the image element
16
+ const image = document.createElement("img");
17
+ image.src = "https://subfork.com/static/logo.png";
18
+ image.title = "Built with Subfork";
19
+ image.alt = "Subfork";
20
+ image.className = "attribution-image";
21
+
22
+ // Add click event listener
23
+ image.addEventListener("click", () => {
24
+ window.open("https://subfork.com", "_blank");
25
+ });
26
+
27
+ // Append the image to the badge container
28
+ badge.appendChild(image);
29
+
30
+ // Append the badge container to the body
31
+ document.body.appendChild(badge);
32
+
33
+ // Style the badge using CSS
34
+ const style = document.createElement("style");
35
+ style.textContent = `
36
+ .attribution-badge {
37
+ position: fixed;
38
+ bottom: 10px;
39
+ right: 10px;
40
+ background-color: rgba(0.2, 0.2, 0.25, 0.25);
41
+ padding: 5px 10px 2px 10px;
42
+ border-radius: 12px;
43
+ z-index: 1000;
44
+ }
45
+ .attribution-image {
46
+ width: 80px;
47
+ cursor: pointer;
48
+ }
49
+ `;
50
+ document.head.appendChild(style);
51
+ }
52
+
53
+ // Automatically create the badge when loaded
54
+ document.addEventListener("DOMContentLoaded", createAttributionBadge);
55
+ })();
@@ -0,0 +1 @@
1
+ document.addEventListener("DOMContentLoaded",(function(){const t=document.createElement("div");t.className="attribution-badge";const n=document.createElement("img");n.src="https://subfork.com/static/logo.png",n.title="Built with Subfork",n.alt="Subfork",n.className="attribution-image",n.addEventListener("click",(()=>{window.open("https://subfork.com","_blank")})),t.appendChild(n),document.body.appendChild(t);const e=document.createElement("style");e.textContent="\n .attribution-badge {\n position: fixed;\n bottom: 10px;\n right: 10px;\n background-color: rgba(0.2, 0.2, 0.25, 0.25);\n padding: 5px 10px 2px 10px;\n border-radius: 12px;\n z-index: 1000;\n }\n .attribution-image {\n width: 80px;\n cursor: pointer;\n }\n ",document.head.appendChild(e)}));
package/dist/subfork.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Copyright (c) Subfork. All rights reserved.
3
3
 
4
4
  TODO:
5
+ - use webpack to bundle client side dependencies
5
6
  - replace post-request with non-jquery function
6
7
  - refactor to immediately-invoked function expression (IIFE)
7
8
 
@@ -47,19 +48,19 @@ Set on "done" callback when creating task:
47
48
  */
48
49
 
49
50
  // define some constants
50
- const version = "0.1.0";
51
+ const version = "0.1.2";
51
52
  const api_version = "api";
52
53
  const hostname = window.location.hostname;
53
54
  const port = window.location.port;
54
55
  const protocol = window.location.protocol;
55
- const socket_loaded = false;
56
- const socket_script = "https://code.subfork.com/socket.io.min.js";
56
+ const socket_script = "https://cdn.jsdelivr.net/npm/socket.io@4.5.4/client-dist/socket.io.min.js";
57
57
  const wait_time = 100;
58
58
 
59
59
  // init some variables
60
60
  var message;
61
61
  var server;
62
62
  var socket;
63
+ var socket_loaded = false;
63
64
 
64
65
  // async returns a sha256 string (only works with https)
65
66
  async function sha256(message) {
@@ -1 +1 @@
1
- const version="0.1.0",api_version="api",hostname=window.location.hostname,port=window.location.port,protocol=window.location.protocol,socket_loaded=!1,socket_script="https://code.subfork.com/socket.io.min.js",wait_time=100;var message,server,socket;async function sha256(t){const e=new TextEncoder("utf-8").encode(t),s=await window.crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(s)).map((t=>("00"+t.toString(16)).slice(-2))).join("")}function load_socket_library(t,e){if(socket_loaded)e(t);else{var s=document.createElement("script");s.src=socket_script,document.head.appendChild(s),s.onload=function(){socket_loaded=!0,e(t)}}}function wait_for(t,e){t()?e():window.setTimeout(wait_for.bind(null,t,e),100)}function build_url(t){return"/api/"+t}function is_local(){return!("http:"!==protocol||"localhost"!==hostname&&"0.0.0.0"!==hostname&&"127.0.0.1"!==hostname||"8000"!==port&&"8080"!==port)}function post_request(t,e={},s=null,o=!0){$.ajax({type:"POST",contentType:"application/json; charset=utf-8",url:t,async:o,data:JSON.stringify(e),success:function(t){s?s(t):console.debug("no callback")},dataType:"json"})}class Datatype{constructor(t){this.name=t}create(t,e=null){let s={collection:this.name,data:t,version:"0.1.0"};return post_request(build_url("data/create"),t=s,(function(t){e&&e(t)})),!1}delete(t,e=null){let s={collection:this.name,params:t,version:"0.1.0"};return post_request(build_url("data/delete"),s,(function(t){e&&e(t)})),!1}find(t,e=null,s=!1,o=!0){let a={collection:this.name,expand:s,params:t,version:"0.1.0"};return post_request(build_url("data/get"),a,(function(t){e&&e(t)}),o),!1}update(t,e,s=null){let o={collection:this.name,id:t,data:e,version:"0.1.0"};return post_request(build_url("data/update"),e=o,(function(t){s&&s(t)})),!1}}class SubforkEvent{constructor(t,e){this.name=t,this.type=e.type,this.message=e.message,this.event_data=e}data(){if("data"==this.type)return new Datatype(this.name)}task(){if("task"==this.type){let t=new SubforkTaskQueue(this.event_data.queue);return new SubforkTask(t,this.event_data.task)}}user(){if("user"==this.type)return new SubforkUser(queue,this.event_data.task)}}class SubforkTask{constructor(t,e){this.queue=t,this.data=e}get_error(){return this.data.error}get_results(){try{return JSON.parse(this.data.results)}catch{return this.data.results}}on(t,e){return this.queue.on(t,e)}}class SubforkTaskQueue{constructor(t,e){this.conn=t,this.name=e}create(t){var e=new SubforkTask(this,t);if(this.enqueue(e))return e}enqueue(t){let e={queue:this.name,data:t.data,version:"0.1.0"},s=!1;return post_request(build_url("task/create"),e,(function(t){t.success&&(s=!0)})),s}get(t){let e={queue:this.name,taskid:t,version:"0.1.0"};var s;return post_request(build_url("task/get"),e,(function(t){t.success?s=new SubforkTask(this,t.data):console.error(t.error)}),async=!1),s}on(t,e){let s=this.conn.session.sessionid+":task:"+this.name+":"+t;return socket.on(s,(function(s,o){let a=new SubforkEvent(t,s);e(a)})),!0}}class SubforkUser{constructor(t){this.data=t}}class SubforkCache{constructor(t){this.parent=t,this._cache={}}add(t,e,s){t in this._cache||(this._cache[t]={}),this._cache[t][e]=s}clear(){Object.keys(this._cache).forEach((t=>{delete this._cache[t]}))}del(t,e){t in this._cache&&e in this._cache[t]&&delete this._cache[t][e]}get(t,e){if(t in this._cache&&e in this._cache[t])return this._cache[t][e]}update(t,e){t in this._cache||(this._cache[t]={}),Object.assign(this._cache[t],e)}}class Subfork{constructor(t={}){this.cache=new SubforkCache(this),this.session={},this.set_config(t),this.connect()}set_config(t){this.config=t,this.config.host=this.config.host??window.location.hostname,this.config.port=this.config.port??window.location.port}connect(){this.session=this.get_session_data(),console.debug("sessionid",this.session.sessionid),load_socket_library(this.config.host,(function(t){socket=io("https://events.fork.io"),console.debug("connected to event server")}))}get_session_data(){let t={source:this.config.host,version:"api"},e={};return post_request(build_url("get_session_data"),t,(function(t){t.success&&t.data?e=t.data:console.error(t.error)}),!1),e}data(t){if(!this.cache.get("data",t)){var e=new Datatype(t);this.cache.add("data",t,e)}return this.cache.get("data",t)}is_connected(){return socket_loaded&&socket.connected}ready(t){wait_for((()=>window.socket),(()=>t()))}task(t){if(!this.cache.get("task",t)){var e=new SubforkTaskQueue(this,t);this.cache.add("task",t,e)}return this.cache.get("task",t)}user(t){if(!this.cache.get("user",t)){let s={username:t,version:"0.1.0"};var e;post_request(build_url("user/get"),s,(function(t){t.success&&(e=new SubforkUser(t.data))}),!1),this.cache.add("user",t,e)}return this.cache.get("user",t)}}
1
+ const version="0.1.2",api_version="api",hostname=window.location.hostname,port=window.location.port,protocol=window.location.protocol,socket_script="https://cdn.jsdelivr.net/npm/socket.io@4.5.4/client-dist/socket.io.min.js",wait_time=100;var message,server,socket,socket_loaded=!1;async function sha256(t){const e=new TextEncoder("utf-8").encode(t),s=await window.crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(s)).map((t=>("00"+t.toString(16)).slice(-2))).join("")}function load_socket_library(t,e){if(socket_loaded)e(t);else{var s=document.createElement("script");s.src=socket_script,document.head.appendChild(s),s.onload=function(){socket_loaded=!0,e(t)}}}function wait_for(t,e){t()?e():window.setTimeout(wait_for.bind(null,t,e),100)}function build_url(t){return"/api/"+t}function is_local(){return!("http:"!==protocol||"localhost"!==hostname&&"0.0.0.0"!==hostname&&"127.0.0.1"!==hostname||"8000"!==port&&"8080"!==port)}function post_request(t,e={},s=null,n=!0){$.ajax({type:"POST",contentType:"application/json; charset=utf-8",url:t,async:n,data:JSON.stringify(e),success:function(t){s?s(t):console.debug("no callback")},dataType:"json"})}class Datatype{constructor(t){this.name=t}create(t,e=null){let s={collection:this.name,data:t,version:"0.1.2"};return post_request(build_url("data/create"),t=s,(function(t){e&&e(t)})),!1}delete(t,e=null){let s={collection:this.name,params:t,version:"0.1.2"};return post_request(build_url("data/delete"),s,(function(t){e&&e(t)})),!1}find(t,e=null,s=!1,n=!0){let a={collection:this.name,expand:s,params:t,version:"0.1.2"};return post_request(build_url("data/get"),a,(function(t){e&&e(t)}),n),!1}update(t,e,s=null){let n={collection:this.name,id:t,data:e,version:"0.1.2"};return post_request(build_url("data/update"),e=n,(function(t){s&&s(t)})),!1}}class SubforkEvent{constructor(t,e){this.name=t,this.type=e.type,this.message=e.message,this.event_data=e}data(){if("data"==this.type)return new Datatype(this.name)}task(){if("task"==this.type){let t=new SubforkTaskQueue(this.event_data.queue);return new SubforkTask(t,this.event_data.task)}}user(){if("user"==this.type)return new SubforkUser(queue,this.event_data.task)}}class SubforkTask{constructor(t,e){this.queue=t,this.data=e}get_error(){return this.data.error}get_results(){try{return JSON.parse(this.data.results)}catch{return this.data.results}}on(t,e){return this.queue.on(t,e)}}class SubforkTaskQueue{constructor(t,e){this.conn=t,this.name=e}create(t){var e=new SubforkTask(this,t);if(this.enqueue(e))return e}enqueue(t){let e={queue:this.name,data:t.data,version:"0.1.2"},s=!1;return post_request(build_url("task/create"),e,(function(t){t.success&&(s=!0)})),s}get(t){let e={queue:this.name,taskid:t,version:"0.1.2"};var s;return post_request(build_url("task/get"),e,(function(t){t.success?s=new SubforkTask(this,t.data):console.error(t.error)}),async=!1),s}on(t,e){let s=this.conn.session.sessionid+":task:"+this.name+":"+t;return socket.on(s,(function(s,n){let a=new SubforkEvent(t,s);e(a)})),!0}}class SubforkUser{constructor(t){this.data=t}}class SubforkCache{constructor(t){this.parent=t,this._cache={}}add(t,e,s){t in this._cache||(this._cache[t]={}),this._cache[t][e]=s}clear(){Object.keys(this._cache).forEach((t=>{delete this._cache[t]}))}del(t,e){t in this._cache&&e in this._cache[t]&&delete this._cache[t][e]}get(t,e){if(t in this._cache&&e in this._cache[t])return this._cache[t][e]}update(t,e){t in this._cache||(this._cache[t]={}),Object.assign(this._cache[t],e)}}class Subfork{constructor(t={}){this.cache=new SubforkCache(this),this.session={},this.set_config(t),this.connect()}set_config(t){this.config=t,this.config.host=this.config.host??window.location.hostname,this.config.port=this.config.port??window.location.port}connect(){this.session=this.get_session_data(),console.debug("sessionid",this.session.sessionid),load_socket_library(this.config.host,(function(t){socket=io("https://events.fork.io"),console.debug("connected to event server")}))}get_session_data(){let t={source:this.config.host,version:"api"},e={};return post_request(build_url("get_session_data"),t,(function(t){t.success&&t.data?e=t.data:console.error(t.error)}),!1),e}data(t){if(!this.cache.get("data",t)){var e=new Datatype(t);this.cache.add("data",t,e)}return this.cache.get("data",t)}is_connected(){return socket_loaded&&socket.connected}ready(t){wait_for((()=>window.socket),(()=>t()))}task(t){if(!this.cache.get("task",t)){var e=new SubforkTaskQueue(this,t);this.cache.add("task",t,e)}return this.cache.get("task",t)}user(t){if(!this.cache.get("user",t)){let s={username:t,version:"0.1.2"};var e;post_request(build_url("user/get"),s,(function(t){t.success&&(e=new SubforkUser(t.data))}),!1),this.cache.add("user",t,e)}return this.cache.get("user",t)}}
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "subfork",
3
- "version": "0.1.0",
4
- "description": "Subfork Javascript client",
3
+ "version": "0.1.2",
4
+ "description": "Subfork Javascript libraries",
5
5
  "main": "dist/subfork.js",
6
6
  "scripts": {
7
- "build": "mkdir -p dist && cp subfork.js dist/subfork.js && terser subfork.js -o dist/subfork.min.js --compress --mangle",
8
- "prepublishOnly": "npm run build",
9
- "test": "echo \"Error: no test specified\" && exit 1"
7
+ "build": "npm run clean && npm run copy && npm run minify",
8
+ "clean": "shx rm -rf dist",
9
+ "copy": "shx mkdir -p dist && shx cp src/*.js dist/",
10
+ "minify": "for file in src/*.js; do terser \"$file\" -o \"dist/$(basename \"$file\" .js).min.js\" --compress --mangle; done"
10
11
  },
11
12
  "repository": {
12
13
  "type": "git",
@@ -19,6 +20,10 @@
19
20
  },
20
21
  "homepage": "https://subfork.com",
21
22
  "devDependencies": {
23
+ "shx": "^0.3.4",
22
24
  "terser": "^5.31.3"
23
- }
25
+ },
26
+ "files": [
27
+ "dist/"
28
+ ]
24
29
  }
package/subfork.js DELETED
@@ -1,442 +0,0 @@
1
- /*
2
- Copyright (c) Subfork. All rights reserved.
3
-
4
- TODO:
5
- - replace post-request with non-jquery function
6
- - refactor to immediately-invoked function expression (IIFE)
7
-
8
- const Subfork = (() => {
9
- ...
10
- return {
11
- subfork: Subfork
12
- }
13
- })();
14
-
15
- Instantiate client:
16
-
17
- const subfork = Subfork();
18
-
19
- or pass in some config values:
20
-
21
- const subfork = Subfork({
22
- host: "test.fork.io",
23
- on: {
24
- "message": function(msg) {
25
- console.log(msg);
26
- },
27
- }
28
- });
29
-
30
- Connect "test" task "done" event callback:
31
-
32
- subfork.task("test").on("done", function(e) {
33
- console.log(e.message + ": " + e.task.results);
34
- });
35
-
36
- Create a "test" task with some data:
37
-
38
- subfork.task("test").create({t:2});
39
-
40
- Set on "done" callback when creating task:
41
-
42
- subfork.task("test").create({
43
- "t": 3
44
- }).on("done", function(event) {
45
- console.log(event);
46
- });
47
- */
48
-
49
- // define some constants
50
- const version = "0.1.0";
51
- const api_version = "api";
52
- const hostname = window.location.hostname;
53
- const port = window.location.port;
54
- const protocol = window.location.protocol;
55
- const socket_loaded = false;
56
- const socket_script = "https://code.subfork.com/socket.io.min.js";
57
- const wait_time = 100;
58
-
59
- // init some variables
60
- var message;
61
- var server;
62
- var socket;
63
-
64
- // async returns a sha256 string (only works with https)
65
- async function sha256(message) {
66
- const msgBuffer = new TextEncoder("utf-8").encode(message);
67
- // hash the message
68
- const hashBuffer = await window.crypto.subtle.digest("SHA-256", msgBuffer);
69
- // convert ArrayBuffer to Array
70
- const hashArray = Array.from(new Uint8Array(hashBuffer));
71
- // convert bytes to hex string
72
- const hashHex = hashArray.map(b => ("00" + b.toString(16)).slice(-2)).join("");
73
- return hashHex;
74
- };
75
-
76
- // load socket library (required for events)
77
- function load_socket_library(host, callback) {
78
- if (socket_loaded) {
79
- callback(host);
80
- } else {
81
- var script = document.createElement("script");
82
- script.src = socket_script;
83
- document.head.appendChild(script);
84
- script.onload = function () {
85
- socket_loaded = true;
86
- callback(host);
87
- };
88
- };
89
- };
90
-
91
- // waits for condition to be true
92
- function wait_for(condition, callback) {
93
- if(!condition()) {
94
- window.setTimeout(wait_for.bind(null, condition, callback), wait_time);
95
- } else {
96
- callback();
97
- };
98
- };
99
-
100
- // returns a local api url, e.g.: /api/task/create
101
- function build_url(endpoint) {
102
- return "/" + api_version + "/" + endpoint;
103
- };
104
-
105
- // returns true if is running locally
106
- function is_local() {
107
- return (
108
- (protocol === "http:") &&
109
- (hostname === "localhost" || hostname === "0.0.0.0" || hostname === "127.0.0.1") &&
110
- (port === "8000" || port === "8080")
111
- );
112
- };
113
-
114
- // post request to server
115
- // function _request(url, data={}) {
116
- // fetch(url, {
117
- // method: "POST",
118
- // headers: {
119
- // "Accept": "application/json",
120
- // "Content-Type': 'application/json"
121
- // },
122
- // body: JSON.stringify(data)
123
- // })
124
- // .then(response => response.json())
125
- // .then(response => console.log(JSON.stringify(response)))
126
- // };
127
- function post_request(url, data={}, func=null, async=true) {
128
- $.ajax({
129
- type: "POST",
130
- contentType: "application/json; charset=utf-8",
131
- url: url,
132
- async: async,
133
- data: JSON.stringify(data),
134
- success: function (resp) {
135
- if (func) {
136
- func(resp);
137
- } else {
138
- console.debug("no callback");
139
- };
140
- },
141
- dataType: "json"
142
- });
143
- };
144
-
145
- // datatype class
146
- class Datatype {
147
- constructor(name) {
148
- this.name = name;
149
- }
150
- create(data, callback=null) {
151
- let row_data = {
152
- "collection": this.name,
153
- "data": data,
154
- "version": version,
155
- };
156
- let success = false;
157
- let url = build_url("data/create");
158
- post_request(url, data=row_data, function(resp) {
159
- if (callback) {
160
- callback(resp);
161
- };
162
- })
163
- return success;
164
- }
165
- delete(params, callback=null) {
166
- let data = {
167
- "collection": this.name,
168
- "params": params,
169
- "version": version,
170
- };
171
- let success = false;
172
- let url = build_url("data/delete");
173
- post_request(url, data=data, function(resp) {
174
- if (callback) {
175
- callback(resp);
176
- };
177
- })
178
- return success;
179
- }
180
- find(params, callback=null, expand=false, async=true) {
181
- let data = {
182
- "collection": this.name,
183
- "expand": expand,
184
- "params": params,
185
- "version": version,
186
- };
187
- let success = false;
188
- let url = build_url("data/get");
189
- post_request(url, data=data, function(resp) {
190
- if (callback) {
191
- callback(resp);
192
- };
193
- }, async=async)
194
- return success;
195
- }
196
- update(id, data, callback=null) {
197
- let row_data = {
198
- "collection": this.name,
199
- "id": id,
200
- "data": data,
201
- "version": version,
202
- };
203
- let success = false;
204
- let url = build_url("data/update");
205
- post_request(url, data=row_data, function(resp) {
206
- if (callback) {
207
- callback(resp);
208
- };
209
- })
210
- return success;
211
- }
212
- };
213
-
214
- // event class
215
- class SubforkEvent {
216
- constructor(event_name, event_data) {
217
- this.name = event_name;
218
- this.type = event_data.type;
219
- this.message = event_data.message;
220
- this.event_data = event_data;
221
- }
222
- data() {
223
- if (this.type == "data") {
224
- return new Datatype(this.name);
225
- }
226
- }
227
- task() {
228
- if (this.type == "task") {
229
- let queue = new SubforkTaskQueue(this.event_data.queue);
230
- return new SubforkTask(queue, this.event_data.task);
231
- }
232
- }
233
- user() {
234
- if (this.type == "user") {
235
- return new SubforkUser(queue, this.event_data.task);
236
- }
237
- }
238
- };
239
-
240
- // task class
241
- class SubforkTask {
242
- constructor(queue, data) {
243
- this.queue = queue;
244
- this.data = data;
245
- }
246
- get_error() {
247
- return this.data.error;
248
- }
249
- get_results() {
250
- try {
251
- return JSON.parse(this.data.results);
252
- } catch {
253
- return this.data.results;
254
- };
255
- }
256
- // TODO: hash the event signature
257
- on(event_name, callback) {
258
- return this.queue.on(event_name, callback);
259
- }
260
- };
261
-
262
- // task queue class
263
- class SubforkTaskQueue {
264
- constructor(conn, name) {
265
- this.conn = conn;
266
- this.name = name;
267
- }
268
- // create and enqueue new task
269
- create(data) {
270
- var t = new SubforkTask(this, data);
271
- if (this.enqueue(t)) {
272
- return t;
273
- }
274
- }
275
- // enqueue a task
276
- enqueue(task) {
277
- let data = {
278
- "queue": this.name,
279
- "data": task.data,
280
- "version": version,
281
- };
282
- let success = false;
283
- let url = build_url("task/create");
284
- post_request(url, data=data, function(resp) {
285
- if (resp.success) {
286
- success = true;
287
- };
288
- })
289
- return success;
290
- }
291
- // find and return a task by id
292
- get(taskid) {
293
- let data = {
294
- "queue": this.name,
295
- "taskid": taskid,
296
- "version": version,
297
- };
298
- let url = build_url("task/get");
299
- var task;
300
- post_request(url, data=data, function(resp) {
301
- if (resp.success) {
302
- task = new SubforkTask(this, resp.data);
303
- } else {
304
- console.error(resp.error);
305
- };
306
- }, async=false);
307
- return task;
308
- }
309
- // listen for task events
310
- // TODO: hash the event signature
311
- on(event_name, callback) {
312
- let sig = this.conn.session.sessionid + ":task:" + this.name + ":" + event_name;
313
- socket.on(sig, function(event_data, cb) {
314
- let event = new SubforkEvent(event_name, event_data);
315
- callback(event);
316
- });
317
- return true;
318
- }
319
- };
320
-
321
- // user class
322
- class SubforkUser {
323
- constructor(data) {
324
- this.data = data;
325
- }
326
- };
327
-
328
- // in-memory only data cache class
329
- class SubforkCache {
330
- constructor(parent) {
331
- this.parent = parent;
332
- this._cache = {};
333
- }
334
- add(type, name, value) {
335
- if (!(type in this._cache)) {
336
- this._cache[type] = {};
337
- };
338
- this._cache[type][name] = value;
339
- }
340
- clear() {
341
- Object.keys(this._cache).forEach(key => {
342
- delete this._cache[key];
343
- });
344
- }
345
- del(type, name) {
346
- if (type in this._cache && name in this._cache[type]) {
347
- delete this._cache[type][name];
348
- }
349
- }
350
- get(type, name) {
351
- if (type in this._cache && name in this._cache[type]) {
352
- return this._cache[type][name];
353
- };
354
- }
355
- update(type, other) {
356
- if (!(type in this._cache)) {
357
- this._cache[type] = {};
358
- };
359
- Object.assign(this._cache[type], other);
360
- }
361
- }
362
-
363
- // subfork client class
364
- class Subfork {
365
- constructor(config={}) {
366
- this.cache = new SubforkCache(this);
367
- this.session = {};
368
- this.set_config(config);
369
- this.connect();
370
- }
371
- // checks config values for default overrides
372
- set_config(config) {
373
- this.config = config;
374
- this.config.host = this.config["host"] ?? window.location.hostname;
375
- this.config.port = this.config["port"] ?? window.location.port;
376
- }
377
- // connect to event server
378
- connect() {
379
- this.session = this.get_session_data();
380
- console.debug("sessionid", this.session.sessionid);
381
- load_socket_library(this.config.host, function(host) {
382
- socket = io("https://events.fork.io");
383
- console.debug("connected to event server");
384
- });
385
- }
386
- // get session data from the server
387
- get_session_data() {
388
- let data = {"source": this.config.host, "version": api_version};
389
- let session_data = {};
390
- let url = build_url("get_session_data");
391
- post_request(url, data, function(resp) {
392
- if (resp.success && resp.data) {
393
- session_data = resp.data;
394
- } else {
395
- console.error(resp.error);
396
- };
397
- }, false);
398
- return session_data;
399
- };
400
- // datatype accessor
401
- data(name) {
402
- if (!(this.cache.get("data", name))) {
403
- var dt = new Datatype(name);
404
- this.cache.add("data", name, dt);
405
- };
406
- return this.cache.get("data", name);
407
- }
408
- // return true if connected to event server
409
- is_connected() {
410
- return (socket_loaded && socket.connected);
411
- }
412
- // on ready wait for socket connection
413
- ready(callback) {
414
- wait_for(() => window.socket, () => callback());
415
- }
416
- // task queue accessor
417
- task(name) {
418
- if (!(this.cache.get("task", name))) {
419
- var q = new SubforkTaskQueue(this, name);
420
- this.cache.add("task", name, q);
421
- };
422
- return this.cache.get("task", name);
423
- }
424
- // user accessor
425
- user(username) {
426
- if (!(this.cache.get("user", username))) {
427
- let data = {
428
- "username": username,
429
- "version": version,
430
- };
431
- let url = build_url("user/get");
432
- var user;
433
- post_request(url, data=data, function(resp) {
434
- if (resp.success) {
435
- user = new SubforkUser(resp.data);
436
- };
437
- }, false);
438
- this.cache.add("user", username, user);
439
- };
440
- return this.cache.get("user", username);
441
- }
442
- };