JavaScript for Automation, FWIW, allows us to write:
ObjC.import('sqlite3')
and then, things like:
(() => {
'use strict';
ObjC.import('sqlite3');
// GENERIC FUNCTIONS -----------------------------------------------------
// Just :: a -> Just a
const Just = x => ({
type: 'Maybe',
Nothing: false,
Just: x
});
// Left :: a -> Either a b
const Left = x => ({
type: 'Either',
Left: x
});
// Nothing :: () -> Nothing
const Nothing = () => ({
type: 'Maybe',
Nothing: true,
});
// Right :: b -> Either a b
const Right = x => ({
type: 'Either',
Right: x
});
// Tuple (,) :: a -> b -> (a, b)
const Tuple = (a, b) => ({
type: 'Tuple',
'0': a,
'1': b
});
// bindEither (>>=) :: Either a -> (a -> Either b) -> Either b
const bindEither = (m, mf) =>
m.Right !== undefined ? (
mf(m.Right)
) : m;
// filePath :: String -> FilePath
const filePath = s =>
ObjC.unwrap(ObjC.wrap(s)
.stringByStandardizingPath);
// showJSON :: a -> String
const showJSON = x => JSON.stringify(x, null, 2);
// (x => Maybe [value, remainder] -> initial value -> values
// unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
const unfoldr = (f, v) => {
let xs = [];
return (
until(
mb => mb.Nothing,
mb => (
xs.push(mb.Just[0]),
f(mb.Just[1])
), Just(Tuple(v, v))
),
xs.slice(1)
);
};
// until :: (a -> Bool) -> (a -> a) -> a -> a
const until = (p, f, x) => {
let v = x;
while (!p(v)) v = f(v);
return v;
};
//------------------------------------------------------------------------
// MAIN: SIMPLE EXAMPLE OF TABLE-READING FROM JAVASCRIPT FOR AUTOMATION
const
strPath = '~/Library/Containers/com.culturedcode.ThingsMac/' +
'Data/Library/Application\ Support/' +
'Cultured\ Code/Things/Things.sqlite3',
strSQL = 'SELECT title FROM TMTask';
const
SQLITE_OK = parseInt($.SQLITE_OK, 10),
SQLITE_ROW = parseInt($.SQLITE_ROW, 10),
ppDb = Ref();
const lrRows = (
bindEither(
bindEither(
$.sqlite3_open(filePath(strPath), ppDb) !== SQLITE_OK ? (
Left($.sqlite3_errmsg(ppDb[0]))
) : Right(ppDb[0]),
db => {
const ppStmt = Ref();
return $.sqlite3_prepare_v2(
db, strSQL, -1, ppStmt, Ref()
) !== SQLITE_OK ? (
Left($.sqlite3_errmsg(db))
) : Right(Tuple(db, ppStmt[0]));
}
),
tpl => Right(unfoldr(
stmt => SQLITE_ROW === $.sqlite3_step(stmt) ? (
Just(Tuple(
$.sqlite3_column_text(stmt, 0),
stmt
))
) : (
$.sqlite3_finalize(stmt),
$.sqlite3_close(tpl[0]),
Nothing()
),
tpl[1]
))
)
);
return showJSON(
lrRows.Right || lrRows.Left
);
})();