Make Datomish work in a Firefox add-on on top of Sqlite.jsm. Fixes #48. r=nalexander
This commit is contained in:
commit
ac253bfea0
37 changed files with 421 additions and 175 deletions
10
.gitignore
vendored
10
.gitignore
vendored
|
@ -22,5 +22,11 @@ pom.xml
|
||||||
pom.xml.asc
|
pom.xml.asc
|
||||||
/.cljs_node_repl/
|
/.cljs_node_repl/
|
||||||
/.cljs_rhino_repl/
|
/.cljs_rhino_repl/
|
||||||
/release-js/datomish.js
|
/release-browser
|
||||||
/release-js/datomish.bare.js
|
/release-browser/datomish.js
|
||||||
|
/release-browser/datomish.bare.js
|
||||||
|
/release-node
|
||||||
|
/release-node/datomish.js
|
||||||
|
/release-node/datomish.bare.js
|
||||||
|
/addon/datomish-test.xpi
|
||||||
|
/addon/datomish.js
|
||||||
|
|
2
addon/README.md
Normal file
2
addon/README.md
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#Datomish Test
|
||||||
|
An example add-on that loads Datomish on top of Sqlite.jsm.
|
15
addon/index.js
Normal file
15
addon/index.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
var self = require("sdk/self");
|
||||||
|
|
||||||
|
console.log("Datomish Test");
|
||||||
|
console.log("This: " + this);
|
||||||
|
|
||||||
|
var datomish = require("datomish.js");
|
||||||
|
datomish.open("/tmp/foobar.db").then(function (db) {
|
||||||
|
console.log("Got " + db);
|
||||||
|
try {
|
||||||
|
db.close();
|
||||||
|
console.log("Closed.");
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Couldn't close: " + e);
|
||||||
|
}
|
||||||
|
});
|
15
addon/package.json
Normal file
15
addon/package.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"title": "Datomish Test",
|
||||||
|
"name": "datomish-test",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "An example add-on that loads Datomish on top of Sqlite.jsm.",
|
||||||
|
"main": "index.js",
|
||||||
|
"author": "Richard Newman <rnewman@mozilla.com>",
|
||||||
|
"engines": {
|
||||||
|
"firefox": ">=48.0a1"
|
||||||
|
},
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"keywords": [
|
||||||
|
"jetpack"
|
||||||
|
]
|
||||||
|
}
|
141
project.clj
141
project.clj
|
@ -3,7 +3,7 @@
|
||||||
:url "https://github.com/mozilla/datomish"
|
:url "https://github.com/mozilla/datomish"
|
||||||
:license {:name "Mozilla Public License Version 2.0"
|
:license {:name "Mozilla Public License Version 2.0"
|
||||||
:url "https://github.com/mozilla/datomish/blob/master/LICENSE"}
|
:url "https://github.com/mozilla/datomish/blob/master/LICENSE"}
|
||||||
:dependencies [[org.clojure/clojurescript "1.9.89"]
|
:dependencies [[org.clojure/clojurescript "1.9.229"]
|
||||||
[org.clojure/clojure "1.8.0"]
|
[org.clojure/clojure "1.8.0"]
|
||||||
[org.clojure/core.async "0.2.385"]
|
[org.clojure/core.async "0.2.385"]
|
||||||
[datascript "0.15.1"]
|
[datascript "0.15.1"]
|
||||||
|
@ -11,37 +11,89 @@
|
||||||
[com.taoensso/tufte "1.0.2"]
|
[com.taoensso/tufte "1.0.2"]
|
||||||
[jamesmacaulay/cljs-promises "0.1.0"]]
|
[jamesmacaulay/cljs-promises "0.1.0"]]
|
||||||
|
|
||||||
:cljsbuild {:builds {:release {
|
:cljsbuild {:builds
|
||||||
:source-paths ["src"]
|
{
|
||||||
:assert false
|
:release-node
|
||||||
:compiler {:output-to "release-js/datomish.bare.js"
|
{
|
||||||
:optimizations :advanced
|
:source-paths ["src-node" "src"]
|
||||||
:pretty-print false
|
:assert false
|
||||||
:elide-asserts true
|
:compiler
|
||||||
:output-wrapper false
|
{
|
||||||
:parallel-build true}
|
:elide-asserts true
|
||||||
:notify-command ["release-js/wrap_bare.sh"]}
|
:hashbang false
|
||||||
:advanced {:source-paths ["src"]
|
:language-in :ecmascript5
|
||||||
:compiler {:output-to "target/advanced/datomish.js"
|
:language-out :ecmascript5
|
||||||
:optimizations :advanced
|
:optimizations :advanced
|
||||||
:source-map "target/advanced/datomish.js.map"
|
:output-dir "release-node"
|
||||||
:pretty-print true
|
:output-to "release-node/datomish.bare.js"
|
||||||
:recompile-dependents true
|
:output-wrapper false
|
||||||
:parallel-build true
|
:parallel-build true
|
||||||
}}
|
:pretty-print false
|
||||||
:test {
|
:target :nodejs
|
||||||
:source-paths ["src" "test"]
|
}
|
||||||
:compiler {:output-to "target/test/datomish.js"
|
:notify-command ["release-node/wrap_bare.sh"]}
|
||||||
:output-dir "target/test"
|
|
||||||
:main datomish.test
|
:release-browser
|
||||||
:optimizations :none
|
;; Release builds for use in Firefox must:
|
||||||
:source-map true
|
;; * Use :optimizations > :none, so that a single file is generated
|
||||||
:recompile-dependents true
|
;; without a need to import Closure's own libs.
|
||||||
:parallel-build true
|
;; * Be wrapped, so that a CommonJS module is produced.
|
||||||
:target :nodejs
|
;; * Have a preload script that defines what `println` does.
|
||||||
}}
|
;;
|
||||||
}
|
;; There's no point in generating a source map -- it'll be wrong
|
||||||
}
|
;; due to wrapping.
|
||||||
|
{
|
||||||
|
:source-paths ["src-browser" "src"]
|
||||||
|
:assert false
|
||||||
|
:compiler
|
||||||
|
{
|
||||||
|
:elide-asserts true
|
||||||
|
:externs ["src-browser/externs.js"]
|
||||||
|
:language-in :ecmascript5
|
||||||
|
:language-out :ecmascript5
|
||||||
|
:optimizations :advanced
|
||||||
|
:output-dir "release-browser"
|
||||||
|
:output-to "release-browser/datomish.bare.js"
|
||||||
|
:output-wrapper false
|
||||||
|
:parallel-build true
|
||||||
|
:preloads [datomish.preload]
|
||||||
|
:pretty-print true
|
||||||
|
:pseudo-names true
|
||||||
|
:static-fns true
|
||||||
|
}
|
||||||
|
:notify-command ["release-browser/wrap_bare.sh"]}
|
||||||
|
|
||||||
|
:advanced
|
||||||
|
{:source-paths ["src-node" "src"]
|
||||||
|
:compiler
|
||||||
|
{
|
||||||
|
:language-in :ecmascript5
|
||||||
|
:language-out :ecmascript5
|
||||||
|
:output-dir "target/advanced"
|
||||||
|
:output-to "target/advanced/datomish.js"
|
||||||
|
:optimizations :advanced
|
||||||
|
:parallel-build true
|
||||||
|
:pretty-print true
|
||||||
|
:source-map "target/advanced/datomish.js.map"
|
||||||
|
:target :nodejs
|
||||||
|
}}
|
||||||
|
|
||||||
|
:test
|
||||||
|
{
|
||||||
|
:source-paths ["src-node" "src" "test"]
|
||||||
|
:compiler
|
||||||
|
{
|
||||||
|
:language-in :ecmascript5
|
||||||
|
:language-out :ecmascript5
|
||||||
|
:main datomish.test
|
||||||
|
:optimizations :none
|
||||||
|
:output-dir "target/test"
|
||||||
|
:output-to "target/test/datomish.js"
|
||||||
|
:parallel-build true
|
||||||
|
:source-map true
|
||||||
|
:target :nodejs
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
|
||||||
:profiles {:dev {:dependencies [[cljsbuild "1.1.3"]
|
:profiles {:dev {:dependencies [[cljsbuild "1.1.3"]
|
||||||
[tempfile "0.2.0"]
|
[tempfile "0.2.0"]
|
||||||
|
@ -59,7 +111,26 @@
|
||||||
|
|
||||||
:doo {:build "test"}
|
:doo {:build "test"}
|
||||||
|
|
||||||
:clean-targets ^{:protect false} ["target"
|
:clean-targets ^{:protect false}
|
||||||
"release-js/datomish.bare.js"
|
[
|
||||||
"release-js/datomish.js"]
|
"target"
|
||||||
|
"release-node/cljs/"
|
||||||
|
"release-node/cljs_promises/"
|
||||||
|
"release-node/clojure/"
|
||||||
|
"release-node/datascript/"
|
||||||
|
"release-node/datomish/"
|
||||||
|
"release-node/honeysql/"
|
||||||
|
"release-node/taoensso/"
|
||||||
|
"release-node/datomish.bare.js"
|
||||||
|
"release-node/datomish.js"
|
||||||
|
"release-browser/cljs/"
|
||||||
|
"release-browser/cljs_promises/"
|
||||||
|
"release-browser/clojure/"
|
||||||
|
"release-browser/datascript/"
|
||||||
|
"release-browser/datomish/"
|
||||||
|
"release-browser/honeysql/"
|
||||||
|
"release-browser/taoensso/"
|
||||||
|
"release-browser/datomish.bare.js"
|
||||||
|
"release-browser/datomish.js"
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
7
release-browser/wrap_bare.sh
Executable file
7
release-browser/wrap_bare.sh
Executable file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
(cat release-browser/wrapper.prefix; cat release-browser/datomish.bare.js; cat release-browser/wrapper.suffix) > release-browser/datomish.js
|
||||||
|
|
||||||
|
echo "Packed release-browser/datomish.js"
|
34
release-browser/wrapper.prefix
Normal file
34
release-browser/wrapper.prefix
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
// Datomish 0.1.0-SNAPSHOT
|
||||||
|
|
||||||
|
(function (definition) {
|
||||||
|
// This file will function properly as a <script> tag, or a module
|
||||||
|
// using CommonJS and NodeJS or RequireJS module formats.
|
||||||
|
|
||||||
|
// Wrapper gratefully adapted from:
|
||||||
|
// https://github.com/kriskowal/q/blob/v1/q.js
|
||||||
|
// https://github.com/swannodette/mori/blob/master/support/wrapper.js
|
||||||
|
// https://github.com/tonsky/datascript/blob/master/release-js/wrapper.js
|
||||||
|
|
||||||
|
// CommonJS
|
||||||
|
if (typeof exports === "object") {
|
||||||
|
module.exports = definition();
|
||||||
|
|
||||||
|
// RequireJS
|
||||||
|
} else if (typeof define === "function" && define.amd) {
|
||||||
|
define(definition);
|
||||||
|
|
||||||
|
// <script>
|
||||||
|
} else {
|
||||||
|
datomish = definition();
|
||||||
|
}
|
||||||
|
})(function () {
|
||||||
|
return function () {
|
||||||
|
|
||||||
|
// Monkeypatch setTimeout so that the Closure Compiler
|
||||||
|
// output can use it in a Sandbox context.
|
||||||
|
var { setTimeout } = require("sdk/timers");
|
||||||
|
this.setTimeout = setTimeout;
|
|
@ -1,7 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
(cat release-js/wrapper.prefix; cat release-js/datomish.bare.js; cat release-js/wrapper.suffix) > release-js/datomish.js
|
|
||||||
|
|
||||||
echo "Packed release-js/datomish.js"
|
|
5
release-node/README.md
Normal file
5
release-node/README.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Datomish
|
||||||
|
|
||||||
|
Datomish is a persistent, embedded knowledge base. It's written in ClojureScript, and draws heavily on [DataScript](https://github.com/tonsky/datascript) and [Datomic](http://datomic.com).
|
||||||
|
|
||||||
|
For more info, check out the [project page](https://github.com/mozila/datomish).
|
2
release-node/test_include_node.js
Normal file
2
release-node/test_include_node.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
var d = require('./datomish');
|
||||||
|
console.log(d.q("[:find ?e ?v :where [?e \"name\" ?v] {:x :y}]"));
|
7
release-node/wrap_bare.sh
Executable file
7
release-node/wrap_bare.sh
Executable file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
(cat release-node/wrapper.prefix && cat release-node/datomish.bare.js && cat release-node/wrapper.suffix) > release-node/datomish.js
|
||||||
|
|
||||||
|
echo "Packed release-node/datomish.js"
|
6
release-node/wrapper.suffix
Normal file
6
release-node/wrapper.suffix
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
;return this.datomish.js;
|
||||||
|
|
||||||
|
}.call({});
|
||||||
|
|
||||||
|
});
|
13
src-browser/datomish/core.cljs
Normal file
13
src-browser/datomish/core.cljs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
(ns datomish.core
|
||||||
|
(:require
|
||||||
|
[honeysql.format :as sql]
|
||||||
|
[datomish.db :as db]
|
||||||
|
[datomish.db-factory :as db-factory]
|
||||||
|
[datomish.js-sqlite :as js-sqlite]
|
||||||
|
[datomish.sqlite :as sqlite]
|
||||||
|
[datomish.transact :as transact]))
|
||||||
|
|
20
src-browser/datomish/js_sqlite.cljs
Normal file
20
src-browser/datomish/js_sqlite.cljs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
(ns datomish.js-sqlite
|
||||||
|
(:require
|
||||||
|
[datomish.sqlite :as s]
|
||||||
|
[datomish.js-util :refer [is-node?]]
|
||||||
|
[datomish.sqlitejsm-sqlite :as sqlitejsm-sqlite]))
|
||||||
|
|
||||||
|
(def open sqlitejsm-sqlite/open)
|
||||||
|
|
||||||
|
(extend-protocol s/ISQLiteConnectionFactory
|
||||||
|
string
|
||||||
|
(<sqlite-connection [path]
|
||||||
|
(open path))
|
||||||
|
|
||||||
|
object
|
||||||
|
(<sqlite-connection [tempfile]
|
||||||
|
(open (.-name tempfile))))
|
8
src-browser/datomish/preload.cljs
Normal file
8
src-browser/datomish/preload.cljs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
(ns datomish.preload)
|
||||||
|
|
||||||
|
(enable-console-print!)
|
||||||
|
(println "Console printing enabled.")
|
57
src-browser/datomish/sqlitejsm_sqlite.cljs
Normal file
57
src-browser/datomish/sqlitejsm_sqlite.cljs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
(ns datomish.sqlitejsm-sqlite
|
||||||
|
(:require
|
||||||
|
[cljs-promises.async]
|
||||||
|
[datomish.sqlite :as s]))
|
||||||
|
|
||||||
|
(def sqlite (.import (aget (js/require "chrome") "Cu") "resource://gre/modules/Sqlite.jsm"))
|
||||||
|
|
||||||
|
(println "sqlite is" (pr-str sqlite))
|
||||||
|
|
||||||
|
;; mozIStorageRow instances expose two methods: getResultByIndex and getResultByName.
|
||||||
|
;; Our code expects to treat rows as associative containers, from keyword to value.
|
||||||
|
;; So we implement ILookup (which has a different signature for ClojureScript than
|
||||||
|
;; Clojure!), hope that we handle nil/NULL correctly, and switch between integers
|
||||||
|
;; and keywords.
|
||||||
|
(deftype
|
||||||
|
StorageRow
|
||||||
|
[row]
|
||||||
|
|
||||||
|
ILookup
|
||||||
|
(-lookup [o k]
|
||||||
|
(-lookup o k nil))
|
||||||
|
|
||||||
|
(-lookup [o k not-found]
|
||||||
|
(or (if (integer? k)
|
||||||
|
(.getResultByIndex row k)
|
||||||
|
(.getResultByName row (clj->js (name k))))
|
||||||
|
not-found)))
|
||||||
|
|
||||||
|
(defrecord SQLite3Connection [db]
|
||||||
|
s/ISQLiteConnection
|
||||||
|
(-execute!
|
||||||
|
[db sql bindings]
|
||||||
|
(cljs-promises.async/pair-port
|
||||||
|
(.execute (.-db db) sql (or (clj->js bindings) #js []))))
|
||||||
|
|
||||||
|
(-each
|
||||||
|
[db sql bindings row-cb]
|
||||||
|
(let [cb (fn [row]
|
||||||
|
(row-cb (StorageRow. row)))]
|
||||||
|
(cljs-promises.async/pair-port
|
||||||
|
(.execute (.-db db) sql (or (clj->js bindings) #js []) (when row-cb cb)))))
|
||||||
|
|
||||||
|
(close
|
||||||
|
[db]
|
||||||
|
(cljs-promises.async/pair-port
|
||||||
|
(.close (.-db db)))))
|
||||||
|
|
||||||
|
(defn open
|
||||||
|
[path & {:keys [mode] :or {mode 6}}]
|
||||||
|
(cljs-promises.async/pair-port
|
||||||
|
(->
|
||||||
|
(.openConnection (aget sqlite "Sqlite") (clj->js {:path path :sharedMemoryCache false}))
|
||||||
|
(.then ->SQLite3Connection))))
|
33
src-browser/externs.js
Normal file
33
src-browser/externs.js
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
var SqliteStatic = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} options
|
||||||
|
* @return {Promise.<Sqlite>}
|
||||||
|
*/
|
||||||
|
SqliteStatic.openConnection = function (options) {}
|
||||||
|
|
||||||
|
var Sqlite = {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} sql
|
||||||
|
* @param {Array} bindings
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
Sqlite.execute = function (sql, bindings) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
Sqlite.close = function() {}
|
||||||
|
|
||||||
|
var StorageRow = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} index
|
||||||
|
*/
|
||||||
|
StorageRow.getResultByIndex = function (index) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} name
|
||||||
|
*/
|
||||||
|
StorageRow.getResultByName = function (name) {}
|
20
src-node/datomish/js_sqlite.cljs
Normal file
20
src-node/datomish/js_sqlite.cljs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
(ns datomish.js-sqlite
|
||||||
|
(:require
|
||||||
|
[datomish.sqlite :as s]
|
||||||
|
[datomish.js-util :refer [is-node?]]
|
||||||
|
[datomish.promise-sqlite :as promise-sqlite]))
|
||||||
|
|
||||||
|
(def open promise-sqlite/open)
|
||||||
|
|
||||||
|
(extend-protocol s/ISQLiteConnectionFactory
|
||||||
|
string
|
||||||
|
(<sqlite-connection [path]
|
||||||
|
(open path))
|
||||||
|
|
||||||
|
object ;; TODO: narrow this to the result of node-tempfile/tempfile.
|
||||||
|
(<sqlite-connection [tempfile]
|
||||||
|
(open (.-name tempfile))))
|
|
@ -35,12 +35,3 @@
|
||||||
(->
|
(->
|
||||||
(.open sqlite.DB path (clj->js {:mode mode}))
|
(.open sqlite.DB path (clj->js {:mode mode}))
|
||||||
(.then ->SQLite3Connection))))
|
(.then ->SQLite3Connection))))
|
||||||
|
|
||||||
(extend-protocol s/ISQLiteConnectionFactory
|
|
||||||
string
|
|
||||||
(<sqlite-connection [path]
|
|
||||||
(open path))
|
|
||||||
|
|
||||||
object ;; TODO: narrow this to the result of node-tempfile/tempfile.
|
|
||||||
(<sqlite-connection [tempfile]
|
|
||||||
(open (.-name tempfile))))
|
|
|
@ -1,111 +0,0 @@
|
||||||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
(ns datomish.exec-repl
|
|
||||||
#?(:cljs
|
|
||||||
(:require-macros
|
|
||||||
[datomish.util :refer [while-let]]
|
|
||||||
[datomish.pair-chan :refer [go-pair <?]]
|
|
||||||
[cljs.core.async.macros :refer [go]]))
|
|
||||||
(:require
|
|
||||||
[datomish.db-factory]
|
|
||||||
[datomish.db :as db]
|
|
||||||
[datomish.sqlite :as s]
|
|
||||||
[datomish.sqlite-schema :as ss]
|
|
||||||
[datomish.query :as dq]
|
|
||||||
#?@(:clj
|
|
||||||
[[datomish.jdbc-sqlite]
|
|
||||||
[datomish.pair-chan :refer [go-pair <?]]
|
|
||||||
[datomish.util :refer [while-let]]
|
|
||||||
[clojure.core.async :refer [<!]]])
|
|
||||||
#?@(:cljs
|
|
||||||
[[datomish.promise-sqlite]
|
|
||||||
[datomish.pair-chan]
|
|
||||||
[datomish.util]
|
|
||||||
[cljs.core.async :refer [<!]]])))
|
|
||||||
|
|
||||||
#?(:clj
|
|
||||||
(defn pair-channel->lazy-seq
|
|
||||||
"Returns a blocking lazy sequence of items taken from the provided channel."
|
|
||||||
[channel]
|
|
||||||
(lazy-seq
|
|
||||||
(when-let [v (clojure.core.async/<!! channel)]
|
|
||||||
(if (second v)
|
|
||||||
(cons v nil)
|
|
||||||
(cons v (pair-channel->lazy-seq channel)))))))
|
|
||||||
|
|
||||||
#?(:clj
|
|
||||||
(defn run-to-pair-seq
|
|
||||||
"Given an open database, returns a lazy sequence of results.
|
|
||||||
When fully consumed, underlying resources will be released."
|
|
||||||
[db find]
|
|
||||||
(pair-channel->lazy-seq (db/<?run db find))))
|
|
||||||
|
|
||||||
#_
|
|
||||||
(defn xxopen []
|
|
||||||
(datomish.pair-chan/go-pair
|
|
||||||
(let [d (datomish.pair-chan/<? (s/<sqlite-connection "/tmp/import.sqlite"))]
|
|
||||||
(clojure.core.async/<!! (ss/<ensure-current-version d))
|
|
||||||
(def db d))))
|
|
||||||
|
|
||||||
;; With an open DB…
|
|
||||||
#_(run-to-pair-seq
|
|
||||||
db
|
|
||||||
'[:find ?page :in $ :where [?page :page/starred true ?t]])
|
|
||||||
|
|
||||||
;; In a Clojure REPL with no open DB…
|
|
||||||
#_(clojure.core.async/<!!
|
|
||||||
(datomish.exec-repl/<open-and-run-to-seq-promise
|
|
||||||
"/tmp/foo.sqlite"
|
|
||||||
'[:find ?page :in $ :where [?page :page/starred true ?t]]))
|
|
||||||
|
|
||||||
#_(require 'datomish.exec-repl)
|
|
||||||
#_(in-ns 'datomish.exec-repl)
|
|
||||||
#_
|
|
||||||
(go-pair
|
|
||||||
(let [connection (<? (s/<sqlite-connection "/tmp/bigport.db"))
|
|
||||||
d (<? (datomish.db-factory/<db-with-sqlite-connection connection))]
|
|
||||||
(def db d)))
|
|
||||||
|
|
||||||
#_
|
|
||||||
(go-pair
|
|
||||||
(println (count (first (time
|
|
||||||
(<! (db/<?q db
|
|
||||||
'[:find ?url ?title :in $ :where
|
|
||||||
[?page :page/visitAt ?v] [(> ?v 1438748166567751)] [?page :page/title ?title] [?page :page/url ?url] ] {})))))))
|
|
||||||
|
|
||||||
|
|
||||||
#_
|
|
||||||
(go-pair
|
|
||||||
(let [connection (<? (s/<sqlite-connection "/tmp/foo.sqlite"))
|
|
||||||
dd (<? (datomish.db-factory/<db-with-sqlite-connection connection))]
|
|
||||||
(def *db* dd)))
|
|
||||||
#_
|
|
||||||
(clojure.core.async/<!!
|
|
||||||
(go-pair
|
|
||||||
(let [now -1
|
|
||||||
forms (mapcat (fn [i]
|
|
||||||
(map (fn [j]
|
|
||||||
[:db/add i :x j true])
|
|
||||||
(range 1000 (* i 2000) i)))
|
|
||||||
(range 1 10))]
|
|
||||||
(println "Adding" (count forms) "forms")
|
|
||||||
(<? (transact/<transact! *db* forms nil now)))))
|
|
||||||
|
|
||||||
#_
|
|
||||||
(go-pair
|
|
||||||
(let [connection (<? (s/<sqlite-connection "/tmp/foo.sqlite"))
|
|
||||||
dd (<? (db/<with-sqlite-connection connection))]
|
|
||||||
(println
|
|
||||||
(count
|
|
||||||
(<? (db/<?q dd
|
|
||||||
'[:find ?e ?v :in $ :where
|
|
||||||
[?e :x ?v]
|
|
||||||
#_[(> ?v 1000)]] {}))))))
|
|
||||||
|
|
||||||
(dq/parse '[:find ?entity ?tx ?score
|
|
||||||
:in $ ?search
|
|
||||||
:where [(foobar $ :artist/name ?search) [[?entity _ ?tx ?score]]]])
|
|
||||||
|
|
||||||
(honeysql.core/format {:select [:?foo] :from [:foo] :where [:match :foo.x "Bar"]})
|
|
|
@ -1,11 +1,47 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
(ns datomish.js
|
(ns datomish.js
|
||||||
(:refer-clojure :exclude [])
|
(:refer-clojure :exclude [])
|
||||||
|
(:require-macros
|
||||||
|
[datomish.pair-chan :refer [go-pair <?]])
|
||||||
(:require
|
(:require
|
||||||
[datomish.core :as d]
|
[cljs.core.async :as a :refer [take! <! >!]]
|
||||||
[cljs.reader]))
|
[cljs.reader]
|
||||||
|
[cljs-promises.core :refer [promise]]
|
||||||
|
[datomish.db :as db]
|
||||||
|
[datomish.db-factory :as db-factory]
|
||||||
|
[datomish.pair-chan]
|
||||||
|
[datomish.sqlite :as sqlite]
|
||||||
|
[datomish.js-sqlite :as js-sqlite]
|
||||||
|
[datomish.transact :as transact]))
|
||||||
|
|
||||||
|
(defn- take-pair-as-promise! [ch]
|
||||||
|
;; Just like take-as-promise!, but aware that it's handling a pair channel.
|
||||||
|
(promise
|
||||||
|
(fn [resolve reject]
|
||||||
|
(letfn [(split-pair [[v e]]
|
||||||
|
(if e
|
||||||
|
(reject e)
|
||||||
|
(resolve v)))]
|
||||||
|
(cljs.core.async/take! ch split-pair)))))
|
||||||
|
|
||||||
;; Public API.
|
;; Public API.
|
||||||
|
|
||||||
|
(defn ^:export open [path]
|
||||||
|
;; Eventually, URI. For now, just a plain path (no file://).
|
||||||
|
(take-pair-as-promise!
|
||||||
|
(go-pair
|
||||||
|
(let [conn (<? (sqlite/<sqlite-connection path))
|
||||||
|
db (<? (db-factory/<db-with-sqlite-connection conn))]
|
||||||
|
(let [c (transact/connection-with-db db)]
|
||||||
|
(clj->js
|
||||||
|
{:conn c
|
||||||
|
:close (fn [] (db/close-db db))
|
||||||
|
:toString (fn [] (str "#<DB " path ">"))
|
||||||
|
:path path}))))))
|
||||||
|
|
||||||
(defn ^:export q [query & sources]
|
(defn ^:export q [query & sources]
|
||||||
(let [query (cljs.reader/read-string query)]
|
(let [query (cljs.reader/read-string query)]
|
||||||
(clj->js query)))
|
(clj->js query)))
|
||||||
|
|
14
src/datomish/js_util.cljs
Normal file
14
src/datomish/js_util.cljs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
(ns datomish.js-util)
|
||||||
|
|
||||||
|
(defn is-node? []
|
||||||
|
(try
|
||||||
|
(= "[object process]"
|
||||||
|
(.toString (aget js/global "process")))
|
||||||
|
(catch js/ReferenceError e
|
||||||
|
false)
|
||||||
|
(catch js/TypeError e
|
||||||
|
false)))
|
|
@ -126,8 +126,8 @@
|
||||||
"Transform a DataScript Pattern instance into the parts needed
|
"Transform a DataScript Pattern instance into the parts needed
|
||||||
to build a SQL expression.
|
to build a SQL expression.
|
||||||
|
|
||||||
@arg cc A CC instance.
|
@param cc A CC instance.
|
||||||
@arg pattern The pattern instance.
|
@param pattern The pattern instance.
|
||||||
@return an augmented CC"
|
@return an augmented CC"
|
||||||
[cc pattern]
|
[cc pattern]
|
||||||
(when-not (instance? Pattern pattern)
|
(when-not (instance? Pattern pattern)
|
||||||
|
|
|
@ -101,7 +101,9 @@
|
||||||
(defn get-user-version [db]
|
(defn get-user-version [db]
|
||||||
(go-pair
|
(go-pair
|
||||||
(let [row (first (<? (all-rows db ["PRAGMA user_version"])))]
|
(let [row (first (<? (all-rows db ["PRAGMA user_version"])))]
|
||||||
(:user_version row))))
|
(or
|
||||||
|
(:user_version row)
|
||||||
|
0))))
|
||||||
|
|
||||||
(defn set-user-version [db version]
|
(defn set-user-version [db version]
|
||||||
(execute! db [(str "PRAGMA user_version = " version)]))
|
(execute! db [(str "PRAGMA user_version = " version)]))
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
[datomish.test-macros :refer [deftest-async deftest-db]]
|
[datomish.test-macros :refer [deftest-async deftest-db]]
|
||||||
[clojure.test :as t :refer [is are deftest testing]]
|
[clojure.test :as t :refer [is are deftest testing]]
|
||||||
[clojure.core.async :refer [go <! >!]]])
|
[clojure.core.async :refer [go <! >!]]])
|
||||||
#?@(:cljs [[datomish.promise-sqlite]
|
#?@(:cljs [[datomish.js-sqlite]
|
||||||
[datomish.pair-chan]
|
[datomish.pair-chan]
|
||||||
[datomish.test-macros :refer-macros [deftest-async deftest-db]]
|
[datomish.test-macros :refer-macros [deftest-async deftest-db]]
|
||||||
[datomish.node-tempfile :refer [tempfile]]
|
[datomish.node-tempfile :refer [tempfile]]
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
[datomish.test-macros :refer [deftest-async]]
|
[datomish.test-macros :refer [deftest-async]]
|
||||||
[clojure.test :as t :refer [is are deftest testing]]
|
[clojure.test :as t :refer [is are deftest testing]]
|
||||||
[clojure.core.async :refer [go <! >!]]])
|
[clojure.core.async :refer [go <! >!]]])
|
||||||
#?@(:cljs [[datomish.promise-sqlite]
|
#?@(:cljs [[datomish.js-sqlite]
|
||||||
[datomish.pair-chan]
|
[datomish.pair-chan]
|
||||||
[datomish.test-macros :refer-macros [deftest-async]]
|
[datomish.test-macros :refer-macros [deftest-async]]
|
||||||
[datomish.node-tempfile :refer [tempfile]]
|
[datomish.node-tempfile :refer [tempfile]]
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
[cljs.test :refer-macros [is are deftest testing async]]
|
[cljs.test :refer-macros [is are deftest testing async]]
|
||||||
[datomish.pair-chan]
|
[datomish.pair-chan]
|
||||||
[datomish.sqlite :as s]
|
[datomish.sqlite :as s]
|
||||||
[datomish.promise-sqlite :as ps]))
|
[datomish.js-sqlite :as ps]))
|
||||||
|
|
||||||
(deftest-async test-all-rows
|
(deftest-async test-all-rows
|
||||||
(with-tempfile [t (tempfile)]
|
(with-tempfile [t (tempfile)]
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
[datomish.test-macros :refer [deftest-async]]
|
[datomish.test-macros :refer [deftest-async]]
|
||||||
[clojure.test :as t :refer [is are deftest testing]]
|
[clojure.test :as t :refer [is are deftest testing]]
|
||||||
[clojure.core.async :refer [go <! >!]]])
|
[clojure.core.async :refer [go <! >!]]])
|
||||||
#?@(:cljs [[datomish.promise-sqlite]
|
#?@(:cljs [[datomish.js-sqlite]
|
||||||
[datomish.pair-chan]
|
[datomish.pair-chan]
|
||||||
[datomish.test-macros :refer-macros [deftest-async]]
|
[datomish.test-macros :refer-macros [deftest-async]]
|
||||||
[datomish.node-tempfile :refer [tempfile]]
|
[datomish.node-tempfile :refer [tempfile]]
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
[tempfile.core :refer [tempfile with-tempfile]]
|
[tempfile.core :refer [tempfile with-tempfile]]
|
||||||
[clojure.test :as t :refer [is are deftest testing]]])
|
[clojure.test :as t :refer [is are deftest testing]]])
|
||||||
#?@(:cljs
|
#?@(:cljs
|
||||||
[[datomish.promise-sqlite]
|
[[datomish.js-sqlite]
|
||||||
[datomish.test-macros :refer-macros [deftest-db]]
|
[datomish.test-macros :refer-macros [deftest-db]]
|
||||||
[honeysql.core :as sql :refer-macros [param]]
|
[honeysql.core :as sql :refer-macros [param]]
|
||||||
[datomish.node-tempfile :refer [tempfile]]
|
[datomish.node-tempfile :refer [tempfile]]
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
[datomish.test-macros :refer [deftest-async deftest-db]]
|
[datomish.test-macros :refer [deftest-async deftest-db]]
|
||||||
[clojure.test :as t :refer [is are deftest testing]]
|
[clojure.test :as t :refer [is are deftest testing]]
|
||||||
[clojure.core.async :refer [go <! >!]]])
|
[clojure.core.async :refer [go <! >!]]])
|
||||||
#?@(:cljs [[datomish.promise-sqlite]
|
#?@(:cljs [[datomish.js-sqlite]
|
||||||
[datomish.pair-chan]
|
[datomish.pair-chan]
|
||||||
[datomish.test-macros :refer-macros [deftest-async deftest-db]]
|
[datomish.test-macros :refer-macros [deftest-async deftest-db]]
|
||||||
[datomish.node-tempfile :refer [tempfile]]
|
[datomish.node-tempfile :refer [tempfile]]
|
||||||
|
|
Loading…
Reference in a new issue