@makano/rew 1.1.7 → 1.1.8
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 +1 -1
- package/bin/ui +0 -0
- package/build.sh +3 -1
- package/lib/rew/cli/cli.js +54 -36
- package/lib/rew/cli/utils.js +1 -0
- package/lib/rew/const/config_path.js +5 -0
- package/lib/rew/functions/import.js +6 -1
- package/lib/rew/misc/findAppInfo.js +16 -0
- package/lib/rew/misc/findAppPath.js +21 -0
- package/lib/rew/misc/seededid.js +15 -0
- package/lib/rew/modules/context.js +2 -1
- package/lib/rew/pkgs/conf.js +9 -2
- package/lib/rew/pkgs/rune.js +376 -0
- package/meson.build +13 -0
- package/package.json +9 -2
package/README.md
CHANGED
@@ -12,7 +12,7 @@ Rew
|
|
12
12
|
<a href="https://www.npmjs.com/package/rayous"> <img src="https://img.shields.io/npm/v/@makano/rew?style=for-the-badge&logo=npm&color=b4befe&logoColor=9399b2&labelColor=181825" alt="npm version" /></a>
|
13
13
|
</p>
|
14
14
|
|
15
|
-
|
15
|
+
Rew is a simple lightweight coffeescript runtime, made to simply using coffescript and revive it
|
16
16
|
in the process.
|
17
17
|
|
18
18
|
## Getting Started
|
package/bin/ui
CHANGED
Binary file
|
package/build.sh
CHANGED
@@ -3,4 +3,6 @@ opath=./bin/ui
|
|
3
3
|
if [ $1 ]; then
|
4
4
|
opath=$1
|
5
5
|
fi
|
6
|
-
g++ ./cpp/ui.cpp -o $opath `pkg-config --cflags --libs gtk+-3.0 webkit2gtk-4.0 libwebsockets jsoncpp`
|
6
|
+
# g++ ./cpp/ui.cpp -o $opath `pkg-config --cflags --libs gtk+-3.0 webkit2gtk-4.0 libwebsockets jsoncpp`
|
7
|
+
meson build
|
8
|
+
cd build && ninja && mv ./ui $opath && cd ../ && rm -r ./build
|
package/lib/rew/cli/cli.js
CHANGED
@@ -8,12 +8,13 @@ const { watch } = require('chokidar');
|
|
8
8
|
const utils = require('./utils');
|
9
9
|
const { existsSync, readFileSync, writeFileSync, mkdirSync } = require('fs');
|
10
10
|
const { log } = require('./log');
|
11
|
-
const {
|
11
|
+
const { compile } = require('../modules/compiler');
|
12
|
+
const crypto = require('crypto');
|
12
13
|
|
13
14
|
yargs(hideBin(process.argv))
|
14
15
|
.command(
|
15
|
-
'$0 <file>',
|
16
|
-
'Run the specified file',
|
16
|
+
'$0 <file>',
|
17
|
+
'Run the specified file',
|
17
18
|
(yargs) => {
|
18
19
|
yargs
|
19
20
|
.positional('file', {
|
@@ -28,36 +29,36 @@ yargs(hideBin(process.argv))
|
|
28
29
|
},
|
29
30
|
(argv) => {
|
30
31
|
const filePath = path.resolve(process.cwd(), argv.file);
|
31
|
-
if(!existsSync(filePath)){
|
32
|
+
if (!existsSync(filePath)) {
|
32
33
|
log('File not found:', argv.file, ':end');
|
33
34
|
return;
|
34
35
|
}
|
35
36
|
const watching = [];
|
36
37
|
const watchIt = (file) => {
|
37
|
-
if(watching.includes(file)) return;
|
38
|
+
if (watching.includes(file)) return;
|
38
39
|
watch(file).on('change', () => runIt());
|
39
40
|
watching.push(file);
|
40
41
|
}
|
41
42
|
let prevFork;
|
42
43
|
const runIt = () => {
|
43
|
-
if(argv.watch) console.clear();
|
44
|
-
if(prevFork && !prevFork.killed) prevFork.kill?.();
|
44
|
+
if (argv.watch) console.clear();
|
45
|
+
if (prevFork && !prevFork.killed) prevFork.kill?.();
|
45
46
|
prevFork = fork(path.resolve(__dirname, './run.js'))
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
if(argv.watch) watchIt(filePath);
|
47
|
+
.on('message', (data) => {
|
48
|
+
if (argv.watch) {
|
49
|
+
data.forEach(file => {
|
50
|
+
watchIt(file);
|
51
|
+
});
|
52
|
+
}
|
53
|
+
}).send({ filePath, watch: argv.watch });
|
54
|
+
if (argv.watch) watchIt(filePath);
|
54
55
|
}
|
55
56
|
runIt();
|
56
57
|
}
|
57
58
|
)
|
58
59
|
.command(
|
59
|
-
'conf <command> [path] [key] [value]',
|
60
|
-
'Configuration management',
|
60
|
+
'conf <command> [path] [key] [value]',
|
61
|
+
'Configuration management',
|
61
62
|
(yargs) => {
|
62
63
|
yargs
|
63
64
|
.positional('command', {
|
@@ -84,51 +85,68 @@ yargs(hideBin(process.argv))
|
|
84
85
|
(argv) => {
|
85
86
|
const { command, path, key, value } = argv;
|
86
87
|
const result = utils.conf(command, path, key, value);
|
87
|
-
if(result) console.log(result);
|
88
|
+
if (result) console.log(result);
|
88
89
|
}
|
89
90
|
)
|
90
|
-
.command('create <path>',
|
91
|
+
.command('create <path>', 'Create a new project', (yargs) => {
|
91
92
|
yargs
|
92
93
|
.positional('path', {
|
93
94
|
describe: 'Path of the project to create',
|
94
95
|
type: 'string',
|
95
96
|
});
|
96
|
-
|
97
|
+
},
|
97
98
|
(argv) => {
|
98
99
|
utils.createProject(argv.path);
|
99
100
|
}
|
100
101
|
)
|
101
|
-
.command('
|
102
|
+
.command('rune-keygen <secret>', 'Generate a rune encryption key', (yargs) => {
|
103
|
+
yargs.option('secret', {
|
104
|
+
describe: 'Secret used to generate encryption key',
|
105
|
+
type: 'string'
|
106
|
+
});
|
107
|
+
}, (argv) => {
|
108
|
+
const generateEncryptionKey = (secret) => {
|
109
|
+
if (secret) {
|
110
|
+
return crypto.createHash('sha256').update(secret).digest('hex');
|
111
|
+
} else {
|
112
|
+
return crypto.randomBytes(32).toString('hex');
|
113
|
+
}
|
114
|
+
};
|
115
|
+
|
116
|
+
const encryptionKey = generateEncryptionKey(argv.secret);
|
117
|
+
console.log('Encryption Key:', encryptionKey);
|
118
|
+
})
|
119
|
+
.command('ui-bin <path>', 'Build the UI bin for your own app', (yargs) => {
|
102
120
|
yargs
|
103
121
|
.positional('path', {
|
104
122
|
describe: 'Path of the output bin',
|
105
123
|
type: 'string',
|
106
124
|
});
|
107
|
-
|
125
|
+
},
|
108
126
|
(argv) => {
|
109
|
-
execSync('sh '+path.resolve(__dirname, '../../../build.sh')+' '+argv.path);
|
127
|
+
execSync('sh ' + path.resolve(__dirname, '../../../build.sh') + ' ' + argv.path);
|
110
128
|
}
|
111
129
|
)
|
112
|
-
.command('run <path | package>',
|
130
|
+
.command('run <path | package>', 'Run an app', (yargs) => {
|
113
131
|
yargs
|
114
132
|
.positional('path', {
|
115
133
|
describe: 'Path of the app to run',
|
116
134
|
type: 'string',
|
117
135
|
});
|
118
|
-
|
136
|
+
},
|
119
137
|
(argv) => {
|
120
138
|
utils.runApp(argv.path);
|
121
139
|
}
|
122
140
|
)
|
123
|
-
.command('install <path>',
|
141
|
+
.command('install <path>', 'Install an app', (yargs) => {
|
124
142
|
yargs
|
125
143
|
.positional('path', {
|
126
144
|
describe: 'Path of the app to install',
|
127
145
|
type: 'string',
|
128
146
|
});
|
129
|
-
|
147
|
+
},
|
130
148
|
async (argv) => {
|
131
|
-
if(argv.path.startsWith('github:')) utils.installApp(await utils.cloneGit(argv.path), true, true);
|
149
|
+
if (argv.path.startsWith('github:')) utils.installApp(await utils.cloneGit(argv.path), true, true);
|
132
150
|
else utils.installApp(argv.path);
|
133
151
|
}
|
134
152
|
)
|
@@ -161,7 +179,7 @@ yargs(hideBin(process.argv))
|
|
161
179
|
|
162
180
|
function writeCompiledFile(filePath, compiledCode) {
|
163
181
|
const dirName = outputDir ? outputDir : path.dirname(filePath);
|
164
|
-
if(!existsSync(dirName)) mkdirSync(dirName, { recursive: true });
|
182
|
+
if (!existsSync(dirName)) mkdirSync(dirName, { recursive: true });
|
165
183
|
const baseName = path.basename(filePath, path.extname(filePath));
|
166
184
|
const newFilePath = path.join(dirName, `${baseName}.js`);
|
167
185
|
writeFileSync(newFilePath, compiledCode, { encoding: 'utf-8' });
|
@@ -171,20 +189,20 @@ yargs(hideBin(process.argv))
|
|
171
189
|
function processFile(filePath, importsArray) {
|
172
190
|
const content = readFile(filePath);
|
173
191
|
const imports = extractImports(content);
|
174
|
-
|
192
|
+
|
175
193
|
imports.forEach(importStatement => {
|
176
194
|
const importedFilePath = path.resolve(path.dirname(filePath), importStatement.url);
|
177
195
|
if (!importsArray.some(importObj => importObj.url === importStatement.url)) {
|
178
|
-
|
179
|
-
if(existsSync(importedFilePath)){
|
196
|
+
|
197
|
+
if (existsSync(importedFilePath)) {
|
180
198
|
importsArray.push(importStatement);
|
181
199
|
processFile(importedFilePath, importsArray);
|
182
|
-
} else if(existsSync(importedFilePath+'.coffee')){
|
200
|
+
} else if (existsSync(importedFilePath + '.coffee')) {
|
183
201
|
importsArray.push(importStatement);
|
184
|
-
processFile(importedFilePath+'.coffee', importsArray);
|
185
|
-
} else if(existsSync(importedFilePath+'.js')){
|
202
|
+
processFile(importedFilePath + '.coffee', importsArray);
|
203
|
+
} else if (existsSync(importedFilePath + '.js')) {
|
186
204
|
importsArray.push(importStatement);
|
187
|
-
processFile(importedFilePath+'.js', importsArray);
|
205
|
+
processFile(importedFilePath + '.js', importsArray);
|
188
206
|
}
|
189
207
|
|
190
208
|
}
|
package/lib/rew/cli/utils.js
CHANGED
@@ -30,6 +30,10 @@ module.exports.imp = function (runPath, context) {
|
|
30
30
|
let exports,
|
31
31
|
ispkg = findPackage(filename);
|
32
32
|
|
33
|
+
if(filename.startsWith('@') && context.app){
|
34
|
+
filename = filename.replace('@', context.app.path);
|
35
|
+
}
|
36
|
+
|
33
37
|
let filepath = path.resolve(path.dirname(context.module.filepath), filename);
|
34
38
|
|
35
39
|
// console.log(typeof runPath);
|
@@ -74,7 +78,8 @@ module.exports.imp = function (runPath, context) {
|
|
74
78
|
).context.module.exports;
|
75
79
|
|
76
80
|
if (ispkg) {
|
77
|
-
|
81
|
+
const pkg = getPackage(filename)(context);
|
82
|
+
exports = pkg._onImport ? pkg._onImport() : pkg;
|
78
83
|
} else if (foundCache) {
|
79
84
|
|
80
85
|
} else if (type == "coffee") {
|
@@ -0,0 +1,16 @@
|
|
1
|
+
const jsYaml = require("js-yaml");
|
2
|
+
const { findAppPath } = require("./findAppPath");
|
3
|
+
const path = require('path');
|
4
|
+
const { readFileSync } = require("fs");
|
5
|
+
|
6
|
+
module.exports.findAppInfo = function(filepath){
|
7
|
+
const appPath = findAppPath(path.dirname(filepath));
|
8
|
+
if(appPath){
|
9
|
+
const config = jsYaml.load(readFileSync(path.join(appPath, 'app.yaml')));
|
10
|
+
return {
|
11
|
+
path: appPath,
|
12
|
+
config
|
13
|
+
}
|
14
|
+
}
|
15
|
+
return null;
|
16
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
const path = require('path'); // Import the 'path' module
|
2
|
+
const fs = require('fs'); // Import the 'path' module
|
3
|
+
|
4
|
+
module.exports.findAppPath = (currentDir = __dirname) => {
|
5
|
+
// Check if app.yaml exists in the current directory
|
6
|
+
const appYamlPath = path.join(currentDir, 'app.yaml');
|
7
|
+
if (fs.existsSync(appYamlPath)) {
|
8
|
+
return currentDir;
|
9
|
+
}
|
10
|
+
|
11
|
+
// If not found, move up a directory level
|
12
|
+
const parentDir = path.dirname(currentDir);
|
13
|
+
|
14
|
+
// Check if we reached the root directory
|
15
|
+
if (parentDir === currentDir) {
|
16
|
+
return null; // Not found
|
17
|
+
}
|
18
|
+
|
19
|
+
// Recursively call the function on the parent directory
|
20
|
+
return module.exports.findAppPath(parentDir);
|
21
|
+
};
|
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module.exports.seededID = function (seed) {
|
4
|
+
const charCodes = seed.split('').map(char => char.charCodeAt(0));
|
5
|
+
|
6
|
+
let result = '';
|
7
|
+
let sum = 0;
|
8
|
+
|
9
|
+
for (let i = 0; i < charCodes.length; i++) {
|
10
|
+
sum += charCodes[i];
|
11
|
+
result += String.fromCharCode((charCodes[i] + sum) % 26 + 97);
|
12
|
+
}
|
13
|
+
|
14
|
+
return result.slice(0, 12);
|
15
|
+
}
|
@@ -1,12 +1,12 @@
|
|
1
1
|
const defaultContext = require("../const/default");
|
2
2
|
const { execOptions } = require("../const/opt");
|
3
|
-
const emitter = require("../functions/emitter");
|
4
3
|
const { exportsFunction, pubFunction } = require("../functions/export");
|
5
4
|
const { imp } = require("../functions/import");
|
6
5
|
const { customRequire } = require("../functions/require");
|
7
6
|
const fsLib = require('../functions/fs');
|
8
7
|
const pathLib = require('../functions/path');
|
9
8
|
const execLib = require('../functions/exec');
|
9
|
+
const { findAppInfo } = require("../misc/findAppInfo");
|
10
10
|
|
11
11
|
let mainFile = "";
|
12
12
|
const isMainFile = filepath => filepath == mainFile;
|
@@ -28,6 +28,7 @@ module.exports.prepareContext = function (
|
|
28
28
|
meta: {},
|
29
29
|
assert: options.import ?? {}
|
30
30
|
},
|
31
|
+
app: findAppInfo(filepath),
|
31
32
|
...fsLib(filepath),
|
32
33
|
};
|
33
34
|
if (options.useContext) {
|
package/lib/rew/pkgs/conf.js
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
const fs = require('fs');
|
2
2
|
const jsYaml = require('js-yaml');
|
3
3
|
const path = require('path');
|
4
|
-
|
5
|
-
const
|
4
|
+
const { CONFIG_PATH } = require('../const/config_path');
|
5
|
+
const { seededID } = require('../misc/seededid');
|
6
6
|
|
7
7
|
const createPackageRoot = (packageName) => {
|
8
8
|
const rootPath = path.join(CONFIG_PATH, packageName);
|
@@ -12,6 +12,13 @@ const createPackageRoot = (packageName) => {
|
|
12
12
|
|
13
13
|
module.exports = (context) => ({
|
14
14
|
CONFIG_PATH,
|
15
|
+
_onImport(){
|
16
|
+
if(context.app){
|
17
|
+
return this.create(context.app.config.package);
|
18
|
+
} else {
|
19
|
+
return this.create(seededID(path.basename(context.module.filepath).replace(/[-_/\.]/g, '')));
|
20
|
+
}
|
21
|
+
},
|
15
22
|
create: (packageName) => {
|
16
23
|
const rootPath = createPackageRoot(packageName);
|
17
24
|
|
@@ -0,0 +1,376 @@
|
|
1
|
+
const fs = require('fs');
|
2
|
+
const { v4: uuidv4 } = require('uuid');
|
3
|
+
const path = require('path');
|
4
|
+
const msgpack = require('tiny-msgpack');
|
5
|
+
const crypto = require('crypto');
|
6
|
+
const { CONFIG_PATH } = require('../const/config_path');
|
7
|
+
|
8
|
+
const ENCRYPTION_KEY = 'e6ad8b0792b9e0472ea44d1f3adfd1d503182efcce25991b05cc5ef83f307ffc';
|
9
|
+
|
10
|
+
|
11
|
+
class Change {
|
12
|
+
constructor(values) {
|
13
|
+
this.values = values;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
class PopChange extends Change { };
|
18
|
+
|
19
|
+
class PushChange extends Change { };
|
20
|
+
|
21
|
+
const runePush = (...values) => new PushChange(values);
|
22
|
+
const runePop = (...values) => new PopChange(values);
|
23
|
+
|
24
|
+
|
25
|
+
function makeRef(value, props = '') {
|
26
|
+
if (!value['@rune.id']) return null;
|
27
|
+
const collection = getCollectionFromID(value['@rune.id']);
|
28
|
+
const ref = collection + '.' + value['@rune.id'];
|
29
|
+
return '@rune.ref ' + ref + props;
|
30
|
+
}
|
31
|
+
|
32
|
+
const eid = (s, diff) => s.split('')
|
33
|
+
.map(i => {
|
34
|
+
let charCode = i.charCodeAt(0) + diff;
|
35
|
+
if (charCode > 122) {
|
36
|
+
charCode -= 26;
|
37
|
+
}
|
38
|
+
return String.fromCharCode(charCode);
|
39
|
+
})
|
40
|
+
.join('');
|
41
|
+
|
42
|
+
function generateID(id, collection) {
|
43
|
+
return eid(collection, 5) + '+' + id;
|
44
|
+
}
|
45
|
+
|
46
|
+
function getCollectionFromID(id) {
|
47
|
+
return eid(id.split('+')[0], -5);
|
48
|
+
}
|
49
|
+
|
50
|
+
const createDB = (dbName, dirname, encryptionKey) => {
|
51
|
+
const dbDirPath = path.join(dirname, dbName);
|
52
|
+
const mainFilePath = path.join(dbDirPath, 'main.bin');
|
53
|
+
const algorithm = 'aes-256-ctr';
|
54
|
+
|
55
|
+
if (!fs.existsSync(dbDirPath)) {
|
56
|
+
fs.mkdirSync(dbDirPath);
|
57
|
+
}
|
58
|
+
|
59
|
+
const encrypt = (data) => {
|
60
|
+
const iv = crypto.randomBytes(16);
|
61
|
+
const cipher = crypto.createCipheriv(algorithm, Buffer.from(encryptionKey, 'hex'), iv);
|
62
|
+
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
|
63
|
+
return Buffer.concat([iv, encrypted]);
|
64
|
+
};
|
65
|
+
|
66
|
+
const decrypt = (data) => {
|
67
|
+
const iv = data.slice(0, 16);
|
68
|
+
const encryptedData = data.slice(16);
|
69
|
+
const decipher = crypto.createDecipheriv(algorithm, Buffer.from(encryptionKey, 'hex'), iv);
|
70
|
+
const decrypted = Buffer.concat([decipher.update(encryptedData), decipher.final()]);
|
71
|
+
return decrypted;
|
72
|
+
};
|
73
|
+
|
74
|
+
const serializeData = (data) => {
|
75
|
+
return msgpack.encode(data);
|
76
|
+
};
|
77
|
+
|
78
|
+
const deserializeData = (buffer) => {
|
79
|
+
return msgpack.decode(decrypt(buffer));
|
80
|
+
};
|
81
|
+
|
82
|
+
const readMainData = () => {
|
83
|
+
if (!fs.existsSync(mainFilePath)) {
|
84
|
+
writeMainData({ collections: [], maps: [] });
|
85
|
+
}
|
86
|
+
const buffer = fs.readFileSync(mainFilePath);
|
87
|
+
return deserializeData(buffer);
|
88
|
+
};
|
89
|
+
|
90
|
+
const writeMainData = (data) => {
|
91
|
+
const buffer = encrypt(serializeData(data));
|
92
|
+
fs.writeFileSync(mainFilePath, buffer);
|
93
|
+
};
|
94
|
+
|
95
|
+
const readDataFile = (filePath) => {
|
96
|
+
const buffer = fs.readFileSync(filePath);
|
97
|
+
return deserializeData(buffer);
|
98
|
+
};
|
99
|
+
|
100
|
+
const writeDataFile = (filePath, data) => {
|
101
|
+
const buffer = encrypt(serializeData(data));
|
102
|
+
fs.writeFileSync(filePath, buffer);
|
103
|
+
};
|
104
|
+
|
105
|
+
const collection = (collectionName) => {
|
106
|
+
const collectionFilePath = path.join(dbDirPath, `${collectionName}.col`);
|
107
|
+
|
108
|
+
const create = (record) => {
|
109
|
+
const mainData = readMainData();
|
110
|
+
if (!mainData.collections.includes(collectionName)) {
|
111
|
+
mainData.collections.push(collectionName);
|
112
|
+
writeMainData(mainData);
|
113
|
+
}
|
114
|
+
|
115
|
+
let data = [];
|
116
|
+
if (fs.existsSync(collectionFilePath)) {
|
117
|
+
data = readDataFile(collectionFilePath);
|
118
|
+
}
|
119
|
+
const id = uuidv4();
|
120
|
+
record['@rune.id'] = generateID(id, collectionName);
|
121
|
+
data.push(record);
|
122
|
+
writeDataFile(collectionFilePath, data);
|
123
|
+
return record;
|
124
|
+
};
|
125
|
+
|
126
|
+
const read = (id, evaluate = true) => {
|
127
|
+
if (typeof id == "object" && '@rune.id' in id) id = id['@rune.id'];
|
128
|
+
if (!fs.existsSync(collectionFilePath)) return null;
|
129
|
+
const data = readDataFile(collectionFilePath);
|
130
|
+
const record = data.find(record => record['@rune.id'] === id);
|
131
|
+
if (record) {
|
132
|
+
return evaluateRecord(record);
|
133
|
+
}
|
134
|
+
return null;
|
135
|
+
};
|
136
|
+
|
137
|
+
const evaluateRecord = (record, prevRecord) => {
|
138
|
+
const evaluateValue = (val) => {
|
139
|
+
if (typeof val == "string" && val.startsWith('@rune.ref')) {
|
140
|
+
const ref = val.split('@rune.ref')[1].trim();
|
141
|
+
const refData = findRef(ref, false);
|
142
|
+
if (!refData) {
|
143
|
+
return null;
|
144
|
+
} else {
|
145
|
+
let value = refData;
|
146
|
+
if (refData['@rune.id']) {
|
147
|
+
value = prevRecord && prevRecord['@rune.id'] == refData['@rune.id'] ? prevRecord : evaluateRecord(refData, record);
|
148
|
+
}
|
149
|
+
return value;
|
150
|
+
}
|
151
|
+
}
|
152
|
+
if (Array.isArray(val)) {
|
153
|
+
val = val.map(i => evaluateValue(i));
|
154
|
+
}
|
155
|
+
return val;
|
156
|
+
}
|
157
|
+
for (let i in record) {
|
158
|
+
const val = record[i];
|
159
|
+
record[i] = evaluateValue(val);
|
160
|
+
}
|
161
|
+
return record;
|
162
|
+
}
|
163
|
+
|
164
|
+
const update = (caseRecord, newRecord) => {
|
165
|
+
let id;
|
166
|
+
if (typeof caseRecord === 'string') {
|
167
|
+
id = caseRecord;
|
168
|
+
} else if (typeof caseRecord === 'object') {
|
169
|
+
const data = readDataFile(collectionFilePath);
|
170
|
+
const record = data.find(record => {
|
171
|
+
for (const key in caseRecord) {
|
172
|
+
if (record[key] !== caseRecord[key]) return false;
|
173
|
+
}
|
174
|
+
return true;
|
175
|
+
});
|
176
|
+
if (record) {
|
177
|
+
id = record['@rune.id'];
|
178
|
+
} else {
|
179
|
+
return null; // No matching record found
|
180
|
+
}
|
181
|
+
}
|
182
|
+
|
183
|
+
if (!id) return null;
|
184
|
+
|
185
|
+
const data = readDataFile(collectionFilePath);
|
186
|
+
const index = data.findIndex(record => record['@rune.id'] === id);
|
187
|
+
if (index !== -1) {
|
188
|
+
const oldRecord = data[index];
|
189
|
+
for (const key in newRecord) {
|
190
|
+
const value = newRecord[key];
|
191
|
+
if (value instanceof PushChange) {
|
192
|
+
if (!oldRecord[key] || !Array.isArray(oldRecord[key])) {
|
193
|
+
oldRecord[key] = [];
|
194
|
+
}
|
195
|
+
oldRecord[key].push(...value.values);
|
196
|
+
} else if (value instanceof PopChange) {
|
197
|
+
if (oldRecord[key] && Array.isArray(oldRecord[key])) {
|
198
|
+
value.values.forEach(val => {
|
199
|
+
const index = oldRecord[key].indexOf(val);
|
200
|
+
if (index !== -1) {
|
201
|
+
oldRecord[key].splice(index, 1);
|
202
|
+
}
|
203
|
+
});
|
204
|
+
}
|
205
|
+
} else {
|
206
|
+
oldRecord[key] = value;
|
207
|
+
}
|
208
|
+
}
|
209
|
+
data[index] = oldRecord;
|
210
|
+
writeDataFile(collectionFilePath, data);
|
211
|
+
return data[index];
|
212
|
+
}
|
213
|
+
return null;
|
214
|
+
};
|
215
|
+
|
216
|
+
const find = (criteria) => {
|
217
|
+
if (typeof criteria == "string") return read(criteria);
|
218
|
+
if (!criteria || typeof criteria !== 'object') return null;
|
219
|
+
|
220
|
+
const data = readDataFile(collectionFilePath);
|
221
|
+
const record = data.find(record => {
|
222
|
+
for (const key in criteria) {
|
223
|
+
if (record[key] !== criteria[key]) return false;
|
224
|
+
}
|
225
|
+
return true;
|
226
|
+
}) || null;
|
227
|
+
if (record) {
|
228
|
+
evaluateRecord();
|
229
|
+
}
|
230
|
+
return null;
|
231
|
+
};
|
232
|
+
|
233
|
+
const remove = (id) => {
|
234
|
+
if ('@rune.id' in id) id = id['@rune.id'];
|
235
|
+
if (!fs.existsSync(collectionFilePath)) return false;
|
236
|
+
let data = readDataFile(collectionFilePath);
|
237
|
+
const index = data.findIndex(record => record['@rune.id'] === id);
|
238
|
+
if (index !== -1) {
|
239
|
+
data.splice(index, 1);
|
240
|
+
writeDataFile(collectionFilePath, data);
|
241
|
+
return true;
|
242
|
+
}
|
243
|
+
return false;
|
244
|
+
};
|
245
|
+
|
246
|
+
const list = () => {
|
247
|
+
if (!fs.existsSync(collectionFilePath)) return [];
|
248
|
+
const data = readDataFile(collectionFilePath);
|
249
|
+
return data.map(rec => evaluateRecord(rec));
|
250
|
+
};
|
251
|
+
|
252
|
+
const map = (cb, mutate = false) => {
|
253
|
+
const data = readDataFile(collectionFilePath);
|
254
|
+
const mappedData = data.map(cb);
|
255
|
+
if (mutate) {
|
256
|
+
writeDataFile(collectionFilePath, mappedData);
|
257
|
+
}
|
258
|
+
return mappedData;
|
259
|
+
};
|
260
|
+
|
261
|
+
const transform = (cb, mutate = false) => {
|
262
|
+
const data = readDataFile(collectionFilePath);
|
263
|
+
const transformedData = cb(cb);
|
264
|
+
if (mutate) {
|
265
|
+
writeDataFile(collectionFilePath, mappedData);
|
266
|
+
}
|
267
|
+
return transformedData;
|
268
|
+
}
|
269
|
+
|
270
|
+
const filter = (cb, mutate = false) => {
|
271
|
+
const data = readDataFile(collectionFilePath);
|
272
|
+
const filteredData = data.filter(cb);
|
273
|
+
if (mutate) {
|
274
|
+
writeDataFile(collectionFilePath, filteredData);
|
275
|
+
}
|
276
|
+
return filteredData;
|
277
|
+
};
|
278
|
+
|
279
|
+
const sort = (cb, mutate = false) => {
|
280
|
+
const data = readDataFile(collectionFilePath);
|
281
|
+
const sortedData = data.sort(cb);
|
282
|
+
if (mutate) {
|
283
|
+
writeDataFile(collectionFilePath, sortedData);
|
284
|
+
}
|
285
|
+
return sortedData;
|
286
|
+
};
|
287
|
+
|
288
|
+
return { create, findRef, read, update, remove, find, map, transform, filter, sort, list };
|
289
|
+
};
|
290
|
+
|
291
|
+
const findRef = (ref, evaluate = true) => {
|
292
|
+
const [name, id, ...rest] = ref.split('.');
|
293
|
+
const col = collection(name);
|
294
|
+
const record = col.read(id, evaluate);
|
295
|
+
if (rest.length === 0) return record;
|
296
|
+
let value = record;
|
297
|
+
for (const prop of rest) {
|
298
|
+
if (typeof value != "object") break;
|
299
|
+
if (!(prop in value)) return null;
|
300
|
+
value = value[prop];
|
301
|
+
}
|
302
|
+
return value;
|
303
|
+
};
|
304
|
+
|
305
|
+
const map = (mapName) => {
|
306
|
+
const mapFilePath = path.join(dbDirPath, `${mapName}.map`);
|
307
|
+
|
308
|
+
const set = (key, value) => {
|
309
|
+
const mainData = readMainData();
|
310
|
+
if (!mainData.maps.includes(mapName)) {
|
311
|
+
mainData.maps.push(mapName);
|
312
|
+
writeMainData(mainData);
|
313
|
+
}
|
314
|
+
|
315
|
+
let data = {};
|
316
|
+
if (fs.existsSync(mapFilePath)) {
|
317
|
+
data = readDataFile(mapFilePath);
|
318
|
+
}
|
319
|
+
data[key] = value;
|
320
|
+
writeDataFile(mapFilePath, data);
|
321
|
+
};
|
322
|
+
|
323
|
+
const get = (key) => {
|
324
|
+
if (!fs.existsSync(mapFilePath)) return null;
|
325
|
+
const data = readDataFile(mapFilePath);
|
326
|
+
return data[key] || null;
|
327
|
+
};
|
328
|
+
|
329
|
+
const remove = (key) => {
|
330
|
+
if (!fs.existsSync(mapFilePath)) return false;
|
331
|
+
const data = readDataFile(mapFilePath);
|
332
|
+
if (data[key]) {
|
333
|
+
delete data[key];
|
334
|
+
writeDataFile(mapFilePath, data);
|
335
|
+
return true;
|
336
|
+
}
|
337
|
+
return false;
|
338
|
+
};
|
339
|
+
|
340
|
+
const transform = (cb, mutate = false) => {
|
341
|
+
const data = readDataFile(mapFilePath);
|
342
|
+
const transformedData = cb(data);
|
343
|
+
if (mutate) {
|
344
|
+
writeDataFile(mapFilePath, transformedData);
|
345
|
+
}
|
346
|
+
return transformedData;
|
347
|
+
};
|
348
|
+
|
349
|
+
const list = () => {
|
350
|
+
if (!fs.existsSync(mapFilePath)) return {};
|
351
|
+
const data = readDataFile(mapFilePath);
|
352
|
+
return data;
|
353
|
+
};
|
354
|
+
|
355
|
+
return { set, get, remove, list, transform };
|
356
|
+
};
|
357
|
+
|
358
|
+
return { collection, findRef, makeRef, map };
|
359
|
+
};
|
360
|
+
|
361
|
+
module.exports = (context) => ({
|
362
|
+
_onImport() {
|
363
|
+
delete this.createDB;
|
364
|
+
return this;
|
365
|
+
},
|
366
|
+
db(dbname, encryptionKey) {
|
367
|
+
if (!context.app) throw new Error('rune can only be used in apps');
|
368
|
+
const pkg = path.join(CONFIG_PATH, context.app.config.package, 'db');
|
369
|
+
if (!fs.existsSync(pkg)) fs.mkdirSync(pkg, { recursive: true });
|
370
|
+
return createDB(dbname, pkg, encryptionKey || ENCRYPTION_KEY);
|
371
|
+
},
|
372
|
+
makeRef,
|
373
|
+
runePop,
|
374
|
+
runePush,
|
375
|
+
createDB
|
376
|
+
});
|
package/meson.build
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
project('rew', 'cpp',
|
2
|
+
version : '0.1',
|
3
|
+
default_options : ['warning_level=3', 'cpp_std=c++14'])
|
4
|
+
|
5
|
+
gtk3 = dependency('gtk+-3.0', method : 'pkg-config')
|
6
|
+
webkit2gtk = dependency('webkit2gtk-4.0', method : 'pkg-config')
|
7
|
+
libwebsockets = dependency('libwebsockets', method : 'pkg-config')
|
8
|
+
jsoncpp = dependency('jsoncpp', method : 'pkg-config')
|
9
|
+
|
10
|
+
executable('ui',
|
11
|
+
'cpp/ui.cpp',
|
12
|
+
install : true,
|
13
|
+
dependencies : [gtk3, webkit2gtk, libwebsockets, jsoncpp])
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@makano/rew",
|
3
|
-
"version": "1.1.
|
3
|
+
"version": "1.1.8",
|
4
4
|
"description": "A simple coffescript runtime",
|
5
5
|
"main": "lib/rew/main.js",
|
6
6
|
"directories": {
|
@@ -13,6 +13,7 @@
|
|
13
13
|
"lib/",
|
14
14
|
"cpp/",
|
15
15
|
"bin/",
|
16
|
+
"meson.build",
|
16
17
|
"build.sh",
|
17
18
|
"README.md"
|
18
19
|
],
|
@@ -23,7 +24,11 @@
|
|
23
24
|
"type": "git",
|
24
25
|
"url": "git+https://github.com/kevinj045/rew.git"
|
25
26
|
},
|
26
|
-
"keywords": [
|
27
|
+
"keywords": [
|
28
|
+
"coffescript",
|
29
|
+
"rew",
|
30
|
+
"runtime"
|
31
|
+
],
|
27
32
|
"author": "makano",
|
28
33
|
"license": "ISC",
|
29
34
|
"dependencies": {
|
@@ -33,6 +38,8 @@
|
|
33
38
|
"chalk": "^5.3.0",
|
34
39
|
"chokidar": "^3.6.0",
|
35
40
|
"js-yaml": "^4.1.0",
|
41
|
+
"tiny-msgpack": "^2.2.0",
|
42
|
+
"uuid": "^9.0.1",
|
36
43
|
"vm": "^0.1.0",
|
37
44
|
"yargs": "^17.7.2"
|
38
45
|
},
|