##// END OF EJS Templates
core/Uuid rewritten in typescript
cin -
r8:e1c664dbc684 default
parent child
Show More
@@ -0,0 +1,280
1 // Typescript port of the uuid.js
2 // Copyright (c) 2018 Sergey Smirnov
3 // BSD-2-Clause License https://opensource.org/licenses/BSD-2-Clause
4 //
5 // uuid.js
6 // Copyright (c) 2010-2012 Robert Kieffer
7 // MIT License - http://opensource.org/licenses/mit-license.php
8
9 let _window : any = 'undefined' !== typeof window ? window : null;
10
11 // Unique ID creation requires a high quality random # generator. We
12 // feature
13 // detect to determine the best RNG source, normalizing to a function
14 // that
15 // returns 128-bits of randomness, since that's what's usually required
16 let _rng;
17
18 function setupBrowser() {
19 // Allow for MSIE11 msCrypto
20 let _crypto = _window.crypto || _window.msCrypto;
21
22 if (!_rng && _crypto && _crypto.getRandomValues) {
23 // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
24 //
25 // Moderately fast, high quality
26 try {
27 let _rnds8 = new Uint8Array(16);
28 _rng = function whatwgRNG() {
29 _crypto.getRandomValues(_rnds8);
30 return _rnds8;
31 };
32 _rng();
33 } catch (e) { /**/ }
34 }
35
36 if (!_rng) {
37 // Math.random()-based (RNG)
38 //
39 // If all else fails, use Math.random(). It's fast, but is of
40 // unspecified
41 // quality.
42 let _rnds = new Array(16);
43 _rng = function () {
44 for (var i = 0, r; i < 16; i++) {
45 if ((i & 0x03) === 0) {
46 r = Math.random() * 0x100000000;
47 }
48 _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
49 }
50
51 return _rnds;
52 };
53 if ('undefined' !== typeof console && console.warn) {
54 console.warn("[SECURITY] node-uuid: crypto not usable, falling back to insecure Math.random()");
55 }
56 }
57 }
58
59 function setupNode() {
60 // Node.js crypto-based RNG -
61 // http://nodejs.org/docs/v0.6.2/api/crypto.html
62 //
63 // Moderately fast, high quality
64 if ('function' === typeof require) {
65 try {
66 let _rb = require('crypto').randomBytes;
67 _rng = _rb && function () {
68 return _rb(16);
69 };
70 _rng();
71 } catch (e) { /**/ }
72 }
73 }
74
75 if (_window) {
76 setupBrowser();
77 } else {
78 setupNode();
79 }
80
81 // Buffer class to use
82 let BufferClass = ('function' === typeof Buffer) ? Buffer : Array;
83
84 // Maps for number <-> hex string conversion
85 let _byteToHex = [];
86 let _hexToByte = {};
87 for (let i = 0; i < 256; i++) {
88 _byteToHex[i] = (i + 0x100).toString(16).substr(1);
89 _hexToByte[_byteToHex[i]] = i;
90 }
91
92 // **`parse()` - Parse a UUID into it's component bytes**
93 function parse(s, buf?, offset?) : Array<string> {
94 let i = (buf && offset) || 0, ii = 0;
95
96 buf = buf || [];
97 s.toLowerCase().replace(/[0-9a-f]{2}/g, function (oct) {
98 if (ii < 16) { // Don't overflow!
99 buf[i + ii++] = _hexToByte[oct];
100 }
101 });
102
103 // Zero out remaining bytes if string was short
104 while (ii < 16) {
105 buf[i + ii++] = 0;
106 }
107
108 return buf;
109 }
110
111 // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
112 function unparse(buf, offset?) : string {
113 let i = offset || 0, bth = _byteToHex;
114 return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] +
115 bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' +
116 bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] +
117 bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] +
118 bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]];
119 }
120
121 // **`v1()` - Generate time-based UUID**
122 //
123 // Inspired by https://github.com/LiosK/UUID.js
124 // and http://docs.python.org/library/uuid.html
125
126 // random #'s we need to init node and clockseq
127 let _seedBytes = _rng();
128
129 // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit =
130 // 1)
131 let _nodeId = [
132 _seedBytes[0] | 0x01,
133 _seedBytes[1],
134 _seedBytes[2],
135 _seedBytes[3],
136 _seedBytes[4],
137 _seedBytes[5]
138 ];
139
140 // Per 4.2.2, randomize (14 bit) clockseq
141 let _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
142
143 // Previous uuid creation time
144 let _lastMSecs = 0, _lastNSecs = 0;
145
146 // See https://github.com/broofa/node-uuid for API details
147 function v1(options?, buf?, offset?) : string {
148 let i = buf && offset || 0;
149 let b = buf || [];
150
151 options = options || {};
152
153 let clockseq = (options.clockseq != null) ? options.clockseq : _clockseq;
154
155 // UUID timestamps are 100 nano-second units since the Gregorian
156 // epoch,
157 // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
158 // time is handled internally as 'msecs' (integer milliseconds) and
159 // 'nsecs'
160 // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01
161 // 00:00.
162 let msecs = (options.msecs != null) ? options.msecs : new Date()
163 .getTime();
164
165 // Per 4.2.1.2, use count of uuid's generated during the current
166 // clock
167 // cycle to simulate higher resolution clock
168 let nsecs = (options.nsecs != null) ? options.nsecs : _lastNSecs + 1;
169
170 // Time since last uuid creation (in msecs)
171 let dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs) / 10000;
172
173 // Per 4.2.1.2, Bump clockseq on clock regression
174 if (dt < 0 && options.clockseq == null) {
175 clockseq = clockseq + 1 & 0x3fff;
176 }
177
178 // Reset nsecs if clock regresses (new clockseq) or we've moved onto
179 // a new
180 // time interval
181 if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
182 nsecs = 0;
183 }
184
185 // Per 4.2.1.2 Throw error if too many uuids are requested
186 if (nsecs >= 10000) {
187 throw new Error(
188 'uuid.v1(): Can\'t create more than 10M uuids/sec');
189 }
190
191 _lastMSecs = msecs;
192 _lastNSecs = nsecs;
193 _clockseq = clockseq;
194
195 // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
196 msecs += 12219292800000;
197
198 // `time_low`
199 let tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
200 b[i++] = tl >>> 24 & 0xff;
201 b[i++] = tl >>> 16 & 0xff;
202 b[i++] = tl >>> 8 & 0xff;
203 b[i++] = tl & 0xff;
204
205 // `time_mid`
206 let tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
207 b[i++] = tmh >>> 8 & 0xff;
208 b[i++] = tmh & 0xff;
209
210 // `time_high_and_version`
211 b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
212 b[i++] = tmh >>> 16 & 0xff;
213
214 // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
215 b[i++] = clockseq >>> 8 | 0x80;
216
217 // `clock_seq_low`
218 b[i++] = clockseq & 0xff;
219
220 // `node`
221 let node = options.node || _nodeId;
222 for (let n = 0; n < 6; n++) {
223 b[i + n] = node[n];
224 }
225
226 return buf ? buf : unparse(b);
227 }
228
229 // **`v4()` - Generate random UUID**
230
231 // See https://github.com/broofa/node-uuid for API details
232 function v4(options?, buf?, offset?) : string {
233 // Deprecated - 'format' argument, as supported in v1.2
234 let i = buf && offset || 0;
235
236 if (typeof (options) === 'string') {
237 buf = (options === 'binary') ? new BufferClass(16) : null;
238 options = null;
239 }
240 options = options || {};
241
242 let rnds = options.random || (options.rng || _rng)();
243
244 // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
245 rnds[6] = (rnds[6] & 0x0f) | 0x40;
246 rnds[8] = (rnds[8] & 0x3f) | 0x80;
247
248 // Copy bytes to buffer, if provided
249 if (buf) {
250 for (let ii = 0; ii < 16; ii++) {
251 buf[i + ii] = rnds[ii];
252 }
253 }
254
255 return buf || unparse(rnds);
256 }
257
258 // Export public API
259 const empty = "00000000-0000-0000-0000-000000000000";
260
261 interface uuid {
262 (options?, buf?, offset?) : string;
263 v1(options?, buf?, offset?) : string;
264 v4(options?, buf?, offset?) : string;
265 readonly empty: string;
266 parse(s, buf?, offset?) : Array<string>;
267 unparse(buf, offset?) : string;
268 }
269
270 export = <uuid>(() =>{
271 var f : any = function(options?, buf?, offset?) : string {
272 return v4(options, buf, offset);
273 };
274 f.v1 = v1;
275 f.v4 = v4;
276 f.empty = empty;
277 f.parse = parse;
278 f.unparse = unparse;
279 return f;
280 })(); No newline at end of file
1 NO CONTENT: new file 100644
@@ -0,0 +1,12
1 {
2 "compilerOptions": {
3 "target": "es5",
4 "module": "amd",
5 "sourceMap": true,
6 "outDir" : "build/dist",
7 "declaration": true
8 },
9 "include" : [
10 "src/ts/**/*.ts"
11 ]
12 } No newline at end of file
@@ -1,80 +1,90
1 1
2 2 println "version: $version"
3 3
4 4 def distDir = "$buildDir/dist"
5 5 def testDir = "$buildDir/test"
6 6
7 7 task clean {
8 8 doLast {
9 9 delete buildDir
10 10 }
11 11 }
12 12
13 13 task cleanNpm {
14 14 doLast {
15 15 delete 'node_modules'
16 16 }
17 17 }
18 18
19 19 task _npmInstall() {
20 20 inputs.file("package.json")
21 21 outputs.dir("node_modules")
22 22 doLast {
23 23 exec {
24 24 commandLine 'npm', 'install'
25 25 }
26 26 }
27 27 }
28 28
29 29 task _legacyJs(type:Copy) {
30 30 from 'src/js/'
31 31 into distDir
32 32 }
33 33
34 task _buildTs(dependsOn: _npmInstall, type:Exec) {
35 inputs.dir('src/ts')
36 inputs.file('tsc.json')
37 outputs.dir(distDir)
38
39 commandLine 'node_modules/.bin/tsc', '-p', 'tsc.json'
40 }
41
34 42 task _packageMeta(type: Copy) {
35 43 inputs.property("version", version)
36 44 from('.') {
37 45 include 'package.json', 'readme.md', 'license', 'history.md'
38 46 }
39 47 into distDir
40 48 doLast {
41 49 exec {
42 50 workingDir distDir
43 51 commandLine 'npm', 'version', version
44 52 }
45 53 }
46 54 }
47 55
48 task build(dependsOn: [_npmInstall, _legacyJs, _packageMeta]) {
56 task build(dependsOn: [_npmInstall, _buildTs, _legacyJs, _packageMeta]) {
49 57
50 58 }
51 59
52 60 task _localInstall(dependsOn: build, type: Exec) {
53 61 inputs.file("$distDir/package.json")
54 outputs.upToDateWhen { true }
62 outputs.upToDateWhen {
63 new File("$projectDir/node_modules/@implab/core").exists()
64 }
55 65
56 66 commandLine 'npm', 'install', '--no-save', '--force', distDir
57 67 }
58 68
59 69 task copyJsTests(type: Copy) {
60 70 from 'test/js'
61 71 into testDir
62 72 }
63 73
64 74 task buildTests(dependsOn: _localInstall, type: Exec) {
65 75 inputs.dir('test/ts')
66 76 inputs.file('tsc.test.json')
67 77 outputs.dir(testDir)
68 78
69 79 commandLine 'node_modules/.bin/tsc', '-p', 'tsc.test.json'
70 80 }
71 81
72 82 task test(dependsOn: [copyJsTests, buildTests], type: Exec) {
73 83 commandLine 'node', 'run-amd-tests.js'
74 84 }
75 85
76 86 task pack(dependsOn: build, type: Exec) {
77 87 workingDir = distDir
78 88
79 89 commandLine 'npm', 'pack'
80 90 } No newline at end of file
@@ -1,29 +1,30
1 1 {
2 2 "name": "@implab/core",
3 3 "version": "0.0.1-dev",
4 4 "description": "Dependency injection, logging, simple and fast text template engine",
5 5 "main": "main.js",
6 6 "keywords": [
7 7 "di",
8 8 "ioc",
9 9 "logging",
10 10 "template engine",
11 11 "dependency injection"
12 12 ],
13 13 "author": "Implab team",
14 14 "license": "BSD-2-Clause",
15 15 "repository": "https://bitbucket.org/implab/implabjs",
16 16 "publishConfig": {
17 17 "access": "public"
18 18 },
19 19 "dependencies": {
20 20 "dojo": "^1.10.0"
21 21 },
22 22 "devDependencies": {
23 23 "typescript": "latest",
24 24 "tape": "latest",
25 25 "@types/tape": "latest",
26 26 "requirejs": "latest",
27 27 "faucet": "latest"
28 }
28 },
29 "types": "main.d.ts"
29 30 }
@@ -1,18 +1,23
1 1 var requirejs = require('requirejs');
2 2
3 3 requirejs.config({
4 4 baseUrl: '.',
5 map: {
6 "*": {
7 "@implab/core": "core"
8 }
9 },
5 10 packages: [{
6 11 name: "core",
7 12 location: "build/dist"
8 13 },
9 14 {
10 15 name: "test",
11 16 location: "build/test"
12 17 }
13 18 ],
14 19 nodeRequire: require
15 20 });
16 21
17 22
18 23 requirejs(['test/plan']); No newline at end of file
@@ -1,11 +1,13
1 1 import * as tape from 'tape';
2 import * as uuid from '@implab/core/Uuid';
2 3
3 4 tape('simple', function(t){
4 5 t.pass("sync assert");
5 6 setTimeout(() => {
6 7 t.pass("async assert");
7
8 t.comment(uuid());
9 t.ok(uuid() != uuid());
8 10 // end should be called after the last assertion
9 11 t.end();
10 12 }, 100);
11 13 }); No newline at end of file
@@ -1,12 +1,12
1 1 {
2 2 "compilerOptions": {
3 3 "target": "es5",
4 4 "module": "amd",
5 5 "sourceMap": true,
6 6 "outDir" : "build/test",
7 "allowJs": true
7 "moduleResolution": "node"
8 8 },
9 9 "include" : [
10 10 "test/ts/**/*.ts"
11 11 ]
12 12 } No newline at end of file
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now