├── packages ├── kikko-doc │ ├── static │ │ ├── .nojekyll │ │ └── wasm │ │ │ └── sql-wasm.wasm │ ├── docs │ │ ├── reactivity │ │ │ └── howItWotks.mdx │ │ ├── deployingToNetlify.mdx │ │ ├── buildingSql.md │ │ ├── backends │ │ │ ├── tauri.md │ │ │ ├── reactNative.md │ │ │ ├── ionic.md │ │ │ ├── electron.md │ │ │ ├── web.md │ │ │ ├── d1.md │ │ │ └── expo.md │ │ ├── reactIntegration │ │ │ ├── hooks.md │ │ │ └── installationAndUsage.md │ │ ├── plugins │ │ │ ├── reactivePlugin.md │ │ │ └── migrationPlugin.md │ │ ├── vueIntegration │ │ │ └── installationAndUsage.md │ │ └── core │ │ │ ├── usage.md │ │ │ └── transactions.md │ ├── babel.config.js │ ├── tsconfig.json │ ├── .gitignore │ ├── netlify.toml │ ├── .eslintrc.js │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── css │ │ │ └── custom.css │ ├── sidebars.js │ └── docusaurus.config.js ├── vue │ ├── .eslintignore │ ├── .npmignore │ ├── vite.config.js │ ├── tsconfig.json │ ├── src │ │ └── index.ts │ ├── .eslintrc.js │ ├── package.json │ └── CHANGELOG.md ├── kikko │ ├── .eslintignore │ ├── src │ │ ├── measurePerformance.ts │ │ ├── index.ts │ │ ├── errors.ts │ │ ├── suppressLog.ts │ │ ├── utils.ts │ │ ├── afterTransaction.ts │ │ └── createNanoEvents.ts │ ├── .npmignore │ ├── tsconfig.json │ ├── vite.config.js │ ├── .eslintrc.js │ ├── package.json │ └── CHANGELOG.md ├── react │ ├── .eslintignore │ ├── src │ │ ├── vite-env.d.ts │ │ └── index.ts │ ├── .npmignore │ ├── tsconfig.json │ ├── vite.config.js │ ├── .eslintrc.js │ └── package.json ├── d1-backend │ ├── .eslintignore │ ├── src │ │ ├── index.ts │ │ └── d1Backend.ts │ ├── .npmignore │ ├── vite.config.js │ ├── tsconfig.json │ ├── .eslintrc.js │ ├── package.json │ └── CHANGELOG.md ├── absurd-web-backend │ ├── .eslintignore │ ├── .npmignore │ ├── tsconfig.json │ ├── vite.config.js │ ├── src │ │ ├── index.ts │ │ ├── worker │ │ │ ├── DB.worker.ts │ │ │ └── DbBackend.ts │ │ └── absurdWebBackend.ts │ ├── .eslintrc.js │ └── package.json ├── migrations-plugin │ ├── .eslintignore │ ├── src │ │ ├── index.ts │ │ ├── types.ts │ │ └── migrationPlugin.ts │ ├── .npmignore │ ├── tsconfig.json │ ├── vite.config.js │ ├── .eslintrc.js │ └── package.json ├── wa-sqlite-backend │ ├── .eslintignore │ ├── src │ │ └── index.ts │ ├── .npmignore │ ├── tsconfig.json │ ├── vite.config.ts │ ├── vite.node.json │ ├── .eslintrc.cjs │ ├── CHANGELOG.md │ ├── rollup.config.js │ ├── package.json │ └── .gitignore ├── react-queries-hooks │ ├── .eslintignore │ ├── .npmignore │ ├── src │ │ ├── index.ts │ │ └── hooks │ │ │ └── types.ts │ ├── tsconfig.json │ ├── vite.config.js │ ├── .eslintrc.js │ └── package.json ├── tauri-backend │ ├── src │ │ ├── index.ts │ │ └── tauriBackend.ts │ ├── tsconfig.json │ ├── vite.config.js │ ├── .eslintrc.js │ ├── package.json │ └── CHANGELOG.md ├── native-expo-backend │ ├── src │ │ ├── index.ts │ │ └── nativeExpoBackend.ts │ ├── tsconfig.json │ ├── vite.config.js │ ├── .eslintrc.js │ ├── package.json │ └── CHANGELOG.md ├── native-ionic-backend │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ ├── vite.config.js │ ├── .eslintrc.js │ ├── package.json │ └── CHANGELOG.md ├── react-native-backend │ ├── src │ │ ├── index.ts │ │ └── reactNativeBackend.ts │ ├── tsconfig.json │ ├── vite.config.js │ ├── .eslintrc.js │ ├── package.json │ └── CHANGELOG.md ├── vite-react-example │ ├── src │ │ ├── vite-env.d.ts │ │ ├── migrations │ │ │ ├── createKV.ts │ │ │ └── createNotesTable.ts │ │ ├── AppRoutes.tsx │ │ ├── main.tsx │ │ ├── quick-react-example.tsx │ │ ├── hooks │ │ │ └── usePaginator.ts │ │ ├── benchmark │ │ │ ├── AppBenchmark.tsx │ │ │ └── Benchmark.tsx │ │ └── list │ │ │ └── AppList.tsx │ ├── tsconfig.node.json │ ├── .gitignore │ ├── index.html │ ├── netlify.toml │ ├── .eslintrc.js │ ├── tsconfig.json │ ├── vite.config.ts │ ├── package.json │ └── CHANGELOG.md ├── electron-better-sqlite3-backend │ ├── src │ │ ├── index.ts │ │ └── initSqliteBridge.ts │ ├── tsconfig.json │ ├── .eslintrc.js │ ├── vite.config.js │ └── package.json ├── common-scripts │ ├── eslintrc.cjs │ ├── tsconfig.json │ ├── CHANGELOG.md │ ├── tsconfig.base.json │ ├── vite.cjs │ ├── .eslintrc.cjs │ ├── package.json │ └── src │ │ └── publish.ts ├── reactive-queries-plugin │ ├── .npmignore │ ├── src │ │ ├── index.ts │ │ ├── types.ts │ │ ├── utils.ts │ │ ├── listenQueries.ts │ │ ├── getBroadcastCh.ts │ │ └── reactivePlugin.ts │ ├── tsconfig.json │ ├── vite.config.js │ ├── .eslintrc.js │ └── package.json └── d1-example │ ├── wrangler.toml │ ├── CHANGELOG.md │ ├── schema.sql │ ├── .eslintrc.js │ ├── package.json │ ├── tsconfig.json │ └── src │ └── index.ts ├── .npmignore ├── turbo.json ├── .changeset ├── config.json └── README.md ├── .github ├── dependabot.yml └── workflows │ ├── node.js.yml │ └── release.yml ├── package.json ├── LICENSE └── .gitignore /packages/kikko-doc/static/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/vue/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /packages/kikko/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /packages/react/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /packages/d1-backend/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /packages/kikko-doc/docs/reactivity/howItWotks.mdx: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/absurd-web-backend/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /packages/migrations-plugin/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /packages/wa-sqlite-backend/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /packages/react-queries-hooks/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | vite.config.js 3 | tsconfig.json 4 | -------------------------------------------------------------------------------- /packages/d1-backend/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./d1Backend"; 2 | -------------------------------------------------------------------------------- /packages/tauri-backend/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./tauriBackend"; 2 | -------------------------------------------------------------------------------- /packages/react/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/native-expo-backend/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./nativeExpoBackend"; 2 | -------------------------------------------------------------------------------- /packages/wa-sqlite-backend/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./waSqliteWebBackend"; 2 | -------------------------------------------------------------------------------- /packages/kikko/src/measurePerformance.ts: -------------------------------------------------------------------------------- 1 | export const getTime = () => Date.now(); 2 | -------------------------------------------------------------------------------- /packages/native-ionic-backend/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./nativeIonicBackend"; 2 | -------------------------------------------------------------------------------- /packages/react-native-backend/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./reactNativeBackend"; 2 | -------------------------------------------------------------------------------- /packages/vite-react-example/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/electron-better-sqlite3-backend/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./electronBetterSqlite3Backend"; 2 | -------------------------------------------------------------------------------- /packages/migrations-plugin/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./migrationPlugin"; 2 | export * from "./types"; 3 | -------------------------------------------------------------------------------- /packages/vue/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | vite.config.js 3 | tsconfig.json 4 | .eslintrc.js 5 | .eslintignore 6 | -------------------------------------------------------------------------------- /packages/kikko/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | vite.config.js 3 | tsconfig.json 4 | .eslintrc.js 5 | .eslintignore 6 | -------------------------------------------------------------------------------- /packages/react/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | vite.config.js 3 | tsconfig.json 4 | .eslintrc.js 5 | .eslintignore 6 | -------------------------------------------------------------------------------- /packages/common-scripts/eslintrc.cjs: -------------------------------------------------------------------------------- 1 | const eslintrc = require("./.eslintrc.cjs"); 2 | 3 | module.exports = eslintrc; 4 | -------------------------------------------------------------------------------- /packages/d1-backend/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | vite.config.js 3 | tsconfig.json 4 | .eslintrc.js 5 | .eslintignore 6 | -------------------------------------------------------------------------------- /packages/absurd-web-backend/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | vite.config.js 3 | tsconfig.json 4 | .eslintrc.js 5 | .eslintignore 6 | -------------------------------------------------------------------------------- /packages/migrations-plugin/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | vite.config.js 3 | tsconfig.json 4 | .eslintrc.js 5 | .eslintignore 6 | -------------------------------------------------------------------------------- /packages/react-queries-hooks/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | vite.config.js 3 | tsconfig.json 4 | .eslintrc.js 5 | .eslintignore 6 | -------------------------------------------------------------------------------- /packages/wa-sqlite-backend/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | vite.config.js 3 | tsconfig.json 4 | .eslintrc.js 5 | .eslintignore 6 | -------------------------------------------------------------------------------- /packages/kikko/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@kikko-land/common-scripts/tsconfig.base.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/reactive-queries-plugin/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | vite.config.js 3 | tsconfig.json 4 | .eslintrc.js 5 | .eslintignore 6 | -------------------------------------------------------------------------------- /packages/kikko-doc/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /packages/kikko-doc/static/wasm/sql-wasm.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kikko-land/kikko/HEAD/packages/kikko-doc/static/wasm/sql-wasm.wasm -------------------------------------------------------------------------------- /packages/react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@kikko-land/common-scripts/tsconfig.base.json", 3 | "include": ["src", "types"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/tauri-backend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@kikko-land/common-scripts/tsconfig.base.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/absurd-web-backend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@kikko-land/common-scripts/tsconfig.base.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/kikko/vite.config.js: -------------------------------------------------------------------------------- 1 | const { buildConfig } = require("@kikko-land/common-scripts/vite.cjs"); 2 | 3 | module.exports = buildConfig(); 4 | -------------------------------------------------------------------------------- /packages/native-expo-backend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@kikko-land/common-scripts/tsconfig.base.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/native-ionic-backend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@kikko-land/common-scripts/tsconfig.base.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/react-native-backend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@kikko-land/common-scripts/tsconfig.base.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/react/vite.config.js: -------------------------------------------------------------------------------- 1 | const { buildConfig } = require("@kikko-land/common-scripts/vite.cjs"); 2 | 3 | module.exports = buildConfig(); 4 | -------------------------------------------------------------------------------- /packages/reactive-queries-plugin/src/index.ts: -------------------------------------------------------------------------------- 1 | import "./types"; 2 | 3 | export * from "./listenQueries"; 4 | export * from "./reactivePlugin"; 5 | -------------------------------------------------------------------------------- /packages/vue/vite.config.js: -------------------------------------------------------------------------------- 1 | const { buildConfig } = require("@kikko-land/common-scripts/vite.cjs"); 2 | 3 | module.exports = buildConfig(); 4 | -------------------------------------------------------------------------------- /packages/migrations-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@kikko-land/common-scripts/tsconfig.base.json", 3 | "include": ["src", "types"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/react-queries-hooks/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./DbProvider"; 2 | export * from "./hooks/types"; 3 | export * from "./hooks/useQueries"; 4 | -------------------------------------------------------------------------------- /packages/reactive-queries-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@kikko-land/common-scripts/tsconfig.base.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/electron-better-sqlite3-backend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@kikko-land/common-scripts/tsconfig.base.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/migrations-plugin/vite.config.js: -------------------------------------------------------------------------------- 1 | const { buildConfig } = require("@kikko-land/common-scripts/vite.cjs"); 2 | 3 | module.exports = buildConfig(); 4 | -------------------------------------------------------------------------------- /packages/react-queries-hooks/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@kikko-land/common-scripts/tsconfig.base.json", 3 | "include": ["src", "types"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/tauri-backend/vite.config.js: -------------------------------------------------------------------------------- 1 | const { buildConfig } = require("@kikko-land/common-scripts/vite.cjs"); 2 | 3 | module.exports = buildConfig(); 4 | -------------------------------------------------------------------------------- /packages/native-expo-backend/vite.config.js: -------------------------------------------------------------------------------- 1 | const { buildConfig } = require("@kikko-land/common-scripts/vite.cjs"); 2 | 3 | module.exports = buildConfig(); 4 | -------------------------------------------------------------------------------- /packages/native-ionic-backend/vite.config.js: -------------------------------------------------------------------------------- 1 | const { buildConfig } = require("@kikko-land/common-scripts/vite.cjs"); 2 | 3 | module.exports = buildConfig(); 4 | -------------------------------------------------------------------------------- /packages/react-native-backend/vite.config.js: -------------------------------------------------------------------------------- 1 | const { buildConfig } = require("@kikko-land/common-scripts/vite.cjs"); 2 | 3 | module.exports = buildConfig(); 4 | -------------------------------------------------------------------------------- /packages/react-queries-hooks/vite.config.js: -------------------------------------------------------------------------------- 1 | const { buildConfig } = require("@kikko-land/common-scripts/vite.cjs"); 2 | 3 | module.exports = buildConfig(); 4 | -------------------------------------------------------------------------------- /packages/reactive-queries-plugin/vite.config.js: -------------------------------------------------------------------------------- 1 | const { buildConfig } = require("@kikko-land/common-scripts/vite.cjs"); 2 | 3 | module.exports = buildConfig(); 4 | -------------------------------------------------------------------------------- /packages/d1-backend/vite.config.js: -------------------------------------------------------------------------------- 1 | const { buildConfig } = require("@kikko-land/common-scripts/vite.cjs"); 2 | 3 | module.exports = buildConfig({ disableAutoExternal: true }); 4 | -------------------------------------------------------------------------------- /packages/absurd-web-backend/vite.config.js: -------------------------------------------------------------------------------- 1 | const { buildConfig } = require("@kikko-land/common-scripts/vite.cjs"); 2 | 3 | module.exports = buildConfig({ disableAutoExternal: true }); 4 | -------------------------------------------------------------------------------- /packages/absurd-web-backend/src/index.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/triple-slash-reference 2 | /// 3 | export * from "./absurdWebBackend"; 4 | -------------------------------------------------------------------------------- /packages/vite-react-example/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "esnext", 5 | "moduleResolution": "node" 6 | }, 7 | "include": ["vite.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/wa-sqlite-backend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@kikko-land/common-scripts/tsconfig.base.json", 3 | "include": ["src", "examples"], 4 | "compilerOptions": { 5 | "skipLibCheck": true 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/vue/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@kikko-land/common-scripts/tsconfig.base.json", 3 | "compilerOptions": { 4 | "skipLibCheck": true 5 | }, 6 | "include": [ 7 | "src", 8 | "types" 9 | ] 10 | } -------------------------------------------------------------------------------- /packages/wa-sqlite-backend/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import react from "@vitejs/plugin-react"; 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }); 8 | -------------------------------------------------------------------------------- /packages/kikko-doc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // This file is not used in compilation. It is here just for a nice editor experience. 3 | "extends": "@tsconfig/docusaurus/tsconfig.json", 4 | "compilerOptions": { 5 | "baseUrl": "." 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/vue/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./hooks/useQueries"; 2 | export * from "@kikko-land/boono-sql"; 3 | export * from "@kikko-land/kikko"; 4 | export * from "@kikko-land/migrations-plugin"; 5 | export * from "@kikko-land/reactive-queries-plugin"; 6 | -------------------------------------------------------------------------------- /packages/react/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "@kikko-land/boono-sql"; 2 | export * from "@kikko-land/kikko"; 3 | export * from "@kikko-land/migrations-plugin"; 4 | export * from "@kikko-land/react-queries-hooks"; 5 | export * from "@kikko-land/reactive-queries-plugin"; 6 | -------------------------------------------------------------------------------- /packages/wa-sqlite-backend/vite.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/d1-backend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@kikko-land/common-scripts/tsconfig.base.json", 3 | "compilerOptions": { 4 | "skipLibCheck": true, 5 | "types": [ 6 | "@cloudflare/workers-types" 7 | ], 8 | }, 9 | "include": [ 10 | "src" 11 | ] 12 | } -------------------------------------------------------------------------------- /packages/d1-example/wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "d1-example" 2 | main = "src/index.ts" 3 | compatibility_date = "2022-11-10" 4 | 5 | [[ d1_databases ]] 6 | binding = "DB" # i.e. available in your Worker on env.DB 7 | database_name = "kikko" 8 | database_id = "e78430ab-3739-40ab-9e23-168ba7ebd0c0" 9 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turborepo.org/schema.json", 3 | "pipeline": { 4 | "build": { 5 | "outputs": ["dist/**"], 6 | "dependsOn": ["^build"] 7 | }, 8 | "check-typing": { 9 | "outputs": [] 10 | }, 11 | "lint": { 12 | "outputs": [] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.1.1/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } 12 | 13 | -------------------------------------------------------------------------------- /packages/d1-example/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # d1-example 2 | 3 | ## 0.1.0 4 | 5 | ### Minor Changes 6 | 7 | - 185ca8f: Version bump 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [e331160] 12 | - Updated dependencies [185ca8f] 13 | - @kikko-land/kikko@0.10.0 14 | - @kikko-land/d1-backend@0.2.0 15 | - @kikko-land/migrations-plugin@0.7.0 16 | -------------------------------------------------------------------------------- /packages/kikko-doc/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /packages/reactive-queries-plugin/src/types.ts: -------------------------------------------------------------------------------- 1 | import { ReactiveVar } from "@kikko-land/kikko"; 2 | 3 | import { INotifyChannel } from "./getBroadcastCh"; 4 | 5 | declare module "@kikko-land/kikko" { 6 | export interface ISharedDbState { 7 | reactiveQueriesState?: { 8 | rEventsCh: ReactiveVar; 9 | }; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/vite-react-example/src/migrations/createKV.ts: -------------------------------------------------------------------------------- 1 | import { IMigration, sql } from "@kikko-land/react"; 2 | 3 | export const createKVMigration: IMigration = { 4 | up: async (db) => { 5 | await db.runQuery( 6 | sql` 7 | CREATE TABLE kv (key TEXT, value TEXT); 8 | ` 9 | ); 10 | }, 11 | id: 19, 12 | name: "createKV", 13 | }; 14 | -------------------------------------------------------------------------------- /packages/kikko/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./backend"; 2 | export * from "./errors"; 3 | export * from "./initDb"; 4 | export * from "./measurePerformance"; 5 | export * from "./reactiveVar"; 6 | export * from "./suppressLog"; 7 | export * from "./transactionJobs"; 8 | export * from "./types"; 9 | export { makeId } from "./utils"; 10 | export * from "@kikko-land/boono-sql"; 11 | -------------------------------------------------------------------------------- /packages/common-scripts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "ESNext", 5 | "moduleResolution": "node", 6 | "esModuleInterop": true, 7 | "allowSyntheticDefaultImports": true, 8 | "isolatedModules": true, 9 | "allowJs": true, 10 | "noEmit": true, 11 | "strict": true, 12 | "lib": ["es2020"] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/kikko/src/errors.ts: -------------------------------------------------------------------------------- 1 | export class QueryRunError extends Error { 2 | constructor( 3 | initialError: Error, 4 | public dbName: string, 5 | public queries: string[] 6 | ) { 7 | super(initialError.message, { cause: initialError }); 8 | this.cause = initialError; 9 | this.stack = initialError.stack; 10 | this.name = "QueryRunError"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/d1-example/schema.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS Customers; 2 | CREATE TABLE Customers (CustomerID INT, CompanyName TEXT, ContactName TEXT, PRIMARY KEY (`CustomerID`)); 3 | INSERT INTO Customers (CustomerID, CompanyName, ContactName) VALUES (1, 'Alfreds Futterkiste', 'Maria Anders'),(4, 'Around the Horn', 'Thomas Hardy'),(11, 'Bs Beverages', 'Victoria Ashworth'),(13, 'Bs Beverages', 'Random Name'); 4 | -------------------------------------------------------------------------------- /packages/kikko-doc/netlify.toml: -------------------------------------------------------------------------------- 1 | # The following redirect is intended for use with most SPAs that handle 2 | # routing internally. 3 | [[redirects]] 4 | from = "/*" 5 | to = "/index.html" 6 | status = 200 7 | 8 | [[headers]] 9 | # Define which paths this specific [[headers]] block will cover. 10 | for = "wasm/*" 11 | [headers.values] 12 | Access-Control-Allow-Origin = "*" 13 | -------------------------------------------------------------------------------- /packages/migrations-plugin/src/types.ts: -------------------------------------------------------------------------------- 1 | import { IAtomicTransactionScope, IDb } from "@kikko-land/kikko"; 2 | 3 | export type IMigration = { 4 | up: (state: IDb) => Promise; 5 | id: number; 6 | name: string; 7 | }; 8 | 9 | export type IAtomicMigration = { 10 | up: (tr: IAtomicTransactionScope, db: IDb) => Promise | void; 11 | id: number; 12 | name: string; 13 | }; 14 | -------------------------------------------------------------------------------- /packages/vite-react-example/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /packages/reactive-queries-plugin/src/utils.ts: -------------------------------------------------------------------------------- 1 | import { IDb } from "@kikko-land/kikko"; 2 | 3 | export const getReactiveState = (db: IDb) => { 4 | const reactiveState = db.__state.sharedState.reactiveQueriesState; 5 | 6 | if (!reactiveState) { 7 | throw new Error( 8 | "Internal error, maybe you forget to connect the 'reactiveQueries' plugin?" 9 | ); 10 | } 11 | 12 | return reactiveState; 13 | }; 14 | -------------------------------------------------------------------------------- /packages/vue/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/vue") 2 | ? "./" 3 | : "./packages/vue"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/kikko/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/kikko") 2 | ? "./" 3 | : "./packages/kikko"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/react/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/react") 2 | ? "./" 3 | : "./packages/react"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/vite-react-example/src/AppRoutes.tsx: -------------------------------------------------------------------------------- 1 | import { Route, Routes } from "react-router-dom"; 2 | 3 | import { AppBenchmark } from "./benchmark/AppBenchmark"; 4 | import { AppList } from "./list/AppList"; 5 | 6 | export const AppRoutes = () => { 7 | return ( 8 | 9 | } /> 10 | } /> 11 | 12 | ); 13 | }; 14 | -------------------------------------------------------------------------------- /packages/kikko-doc/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/trong-doc") 2 | ? "./" 3 | : "./packages/trong-doc"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/d1-backend/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/d1-backend") 2 | ? "./" 3 | : "./packages/d1-backend"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/d1-example/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/d1-example") 2 | ? "./" 3 | : "./packages/d1-example"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/vite-react-example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/tauri-backend/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/tauri-backend") 2 | ? "./" 3 | : "./packages/tauri-backend"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/vite-react-example/netlify.toml: -------------------------------------------------------------------------------- 1 | # The following redirect is intended for use with most SPAs that handle 2 | # routing internally. 3 | [[redirects]] 4 | from = "/*" 5 | to = "/index.html" 6 | status = 200 7 | 8 | [[headers]] 9 | # Define which paths this specific [[headers]] block will cover. 10 | for = "/*" 11 | [headers.values] 12 | Cross-Origin-Opener-Policy = "same-origin" 13 | Cross-Origin-Embedder-Policy = "require-corp" 14 | -------------------------------------------------------------------------------- /packages/migrations-plugin/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/migrations-plugin") 2 | ? "./" 3 | : "./packages/migrations-plugin"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/wa-sqlite-backend/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/wa-sqlite-backend") 2 | ? "./" 3 | : "./packages/wa-sqlite-backend"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/absurd-web-backend/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/absurd-web-backend") 2 | ? "./" 3 | : "./packages/absurd-web-backend"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/native-expo-backend/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/native-expo-backend") 2 | ? "./" 3 | : "./packages/native-expo-backend"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/react-queries-hooks/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/react-queries-hooks") 2 | ? "./" 3 | : "./packages/react-queries-hooks"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/vite-react-example/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/vite-react-example") 2 | ? "./" 3 | : "./packages/vite-react-example"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/native-ionic-backend/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/native-ionic-backend") 2 | ? "./" 3 | : "./packages/native-ionic-backend"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/react-native-backend/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/react-native-backend") 2 | ? "./" 3 | : "./packages/react-native-backend"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/reactive-queries-plugin/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process.cwd().includes("packages/reactive-queries-plugin") 2 | ? "./" 3 | : "./packages/reactive-queries-plugin"; 4 | 5 | module.exports = { 6 | extends: ["../common-scripts/eslintrc.cjs"], 7 | parserOptions: { 8 | ecmaFeatures: { 9 | jsx: true, 10 | }, 11 | ecmaVersion: 12, 12 | sourceType: "module", 13 | tsconfigRootDir: rootDir, 14 | project: "./tsconfig.json", 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/electron-better-sqlite3-backend/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const rootDir = process 2 | .cwd() 3 | .includes("packages/electron-better-sqlite3-backend") 4 | ? "./" 5 | : "./packages/electron-better-sqlite3-backend"; 6 | 7 | module.exports = { 8 | extends: ["../common-scripts/eslintrc.cjs"], 9 | parserOptions: { 10 | ecmaFeatures: { 11 | jsx: true, 12 | }, 13 | ecmaVersion: 12, 14 | sourceType: "module", 15 | tsconfigRootDir: rootDir, 16 | project: "./tsconfig.json", 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /packages/vite-react-example/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import { BrowserRouter } from "react-router-dom"; 4 | 5 | import { AppRoutes } from "./AppRoutes"; 6 | 7 | const el = document.getElementById("root"); 8 | if (!el) { 9 | throw new Error("Failed to find root el #root"); 10 | } 11 | 12 | ReactDOM.createRoot(el).render( 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /packages/d1-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "d1-example", 3 | "version": "0.1.0", 4 | "devDependencies": { 5 | "@cloudflare/workers-types": "^3.18.0", 6 | "wrangler": "2.2.1" 7 | }, 8 | "private": true, 9 | "scripts": { 10 | "start": "wrangler dev", 11 | "deploy": "wrangler publish", 12 | "lint": "echo 1", 13 | "check-typing": "echo 1" 14 | }, 15 | "dependencies": { 16 | "@kikko-land/kikko": "*", 17 | "@kikko-land/migrations-plugin": "*", 18 | "@kikko-land/d1-backend": "*" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | 13 | -------------------------------------------------------------------------------- /packages/kikko-doc/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # kikko-doc 2 | 3 | ## 0.5.0 4 | 5 | ### Minor Changes 6 | 7 | - 185ca8f: Version bump 8 | 9 | ## 0.4.0 10 | 11 | ### Minor Changes 12 | 13 | - 8ffc4e0: Rename atomicTtransaction -> runInAtomicTransaction 14 | 15 | ## 0.3.0 16 | 17 | ### Minor Changes 18 | 19 | - 056a744: Add new fluent api 20 | 21 | ## 0.2.0 22 | 23 | ### Minor Changes 24 | 25 | - a52a3cb: Upgrade packages 26 | 27 | ## 0.1.0 28 | 29 | ### Minor Changes 30 | 31 | - 174767c: Rename kikko to core 32 | 33 | ## 0.0.1 34 | 35 | ### Patch Changes 36 | 37 | - 81605a8: Trong renamed to kikko 38 | -------------------------------------------------------------------------------- /packages/kikko/src/suppressLog.ts: -------------------------------------------------------------------------------- 1 | import { IDb } from "./types"; 2 | 3 | export const suppressLog = (db: IDb, func: (state: IDb) => T): T => { 4 | return func({ 5 | ...db, 6 | __state: { 7 | ...db.__state, 8 | localState: { 9 | ...db.__state.localState, 10 | suppressLog: true, 11 | }, 12 | }, 13 | }); 14 | }; 15 | 16 | export const withSuppressedLog = (db: IDb): IDb => { 17 | return { 18 | ...db, 19 | __state: { 20 | ...db.__state, 21 | localState: { ...db.__state.localState, suppressLog: true }, 22 | }, 23 | }; 24 | }; 25 | -------------------------------------------------------------------------------- /packages/d1-example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "src" 4 | ], 5 | "compilerOptions": { 6 | "target": "es2021", 7 | "lib": [ 8 | "es2021" 9 | ], 10 | "jsx": "react", 11 | "module": "es2022", 12 | "moduleResolution": "node", 13 | "types": [ 14 | "@cloudflare/workers-types" 15 | ], 16 | "resolveJsonModule": true, 17 | "allowJs": true, 18 | "checkJs": false, 19 | "noEmit": true, 20 | "isolatedModules": true, 21 | "allowSyntheticDefaultImports": true, 22 | "forceConsistentCasingInFileNames": true, 23 | "strict": true, 24 | "skipLibCheck": true 25 | } 26 | } -------------------------------------------------------------------------------- /packages/common-scripts/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @kikko-land/common-scripts 2 | 3 | ## 0.5.0 4 | 5 | ### Minor Changes 6 | 7 | - 185ca8f: Version bump 8 | 9 | ## 0.4.0 10 | 11 | ### Minor Changes 12 | 13 | - 056a744: Add new fluent api 14 | 15 | ## 0.3.0 16 | 17 | ### Minor Changes 18 | 19 | - a52a3cb: Upgrade packages 20 | 21 | ## 0.2.0 22 | 23 | ### Minor Changes 24 | 25 | - dd36c9e: Remove rxjs 26 | 27 | ## 0.1.1 28 | 29 | ### Patch Changes 30 | 31 | - 81605a8: Trong renamed to kikko 32 | 33 | ## 1.3.1 34 | 35 | ### Patch Changes 36 | 37 | - 3c0419b: Releasing with changesets 38 | 39 | ## 1.3.0 40 | 41 | ### Minor Changes 42 | 43 | - 63fa2da: Changeset package set 44 | -------------------------------------------------------------------------------- /packages/kikko-doc/docs/deployingToNetlify.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | slug: /deploying-to-netlify 4 | --- 5 | 6 | # Deploying to Netlify 7 | 8 | Here is the `netlify.toml` file that you need to put in the root of the repo. 9 | It puts headers in the server responses to support absurd-sql SQL backend. 10 | 11 | ```toml 12 | # The following redirect is intended for use with most SPAs that handle 13 | # routing internally. 14 | [[redirects]] 15 | from = "/*" 16 | to = "/index.html" 17 | status = 200 18 | 19 | [[headers]] 20 | for = "/*" 21 | [headers.values] 22 | Cross-Origin-Opener-Policy = "same-origin" 23 | Cross-Origin-Embedder-Policy = "require-corp" 24 | ``` 25 | -------------------------------------------------------------------------------- /packages/vite-react-example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src", "../absurd-web-backend/types"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /packages/common-scripts/tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["DOM", "ESNext", "dom.iterable"], 4 | "jsx": "react", 5 | "module": "esnext", 6 | "target": "esnext", 7 | "moduleResolution": "node", 8 | "declaration": true, 9 | "baseUrl": "./", 10 | "paths": {}, 11 | "noEmit": true, 12 | "strict": true, 13 | "skipLibCheck": false, 14 | "forceConsistentCasingInFileNames": true, 15 | "resolveJsonModule": true, 16 | "allowSyntheticDefaultImports": true, 17 | "importsNotUsedAsValues": "remove", 18 | "experimentalDecorators": true, 19 | "isolatedModules": true, 20 | "esModuleInterop": false, 21 | "noImplicitAny": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/electron-better-sqlite3-backend/vite.config.js: -------------------------------------------------------------------------------- 1 | const { buildConfig } = require("@kikko-land/common-scripts/vite.cjs"); 2 | 3 | module.exports = buildConfig({ 4 | ...(() => { 5 | if (process.env.TO_BUILD === "index") { 6 | return { 7 | entry: "src/index.ts", 8 | fileName: (format) => `index.${format}.js`, 9 | }; 10 | } else if (process.env.TO_BUILD === "preload") { 11 | return { 12 | entry: "src/initSqliteBridge.ts", 13 | fileName: (format) => `initSqliteBridge.${format}.js`, 14 | outDir: "preload-dist", 15 | }; 16 | } else { 17 | throw new Error("env TO_BUILD not set"); 18 | } 19 | })(), 20 | external: ["electron"], 21 | }); 22 | -------------------------------------------------------------------------------- /packages/electron-better-sqlite3-backend/src/initSqliteBridge.ts: -------------------------------------------------------------------------------- 1 | import Database from "better-sqlite3"; 2 | import { contextBridge } from "electron"; 3 | 4 | export const initSqliteBridge = () => { 5 | contextBridge.exposeInMainWorld("sqliteDb", (file: string) => { 6 | const db = new Database(file); 7 | 8 | return { 9 | close: () => { 10 | db.close(); 11 | }, 12 | all: function (sql: string, params: (null | number | string | Buffer)[]) { 13 | const stmt = db.prepare(sql); 14 | 15 | if (stmt.reader) { 16 | return stmt.all(params) as unknown[]; 17 | } else { 18 | stmt.run(params); 19 | 20 | return []; 21 | } 22 | }, 23 | }; 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kikko", 3 | "version": "0.1.0", 4 | "author": "Sergey Popov", 5 | "license": "MIT", 6 | "private": true, 7 | "scripts": { 8 | "add-changeset": "yarn changeset", 9 | "bump-versions": "yarn changeset version", 10 | "publish-packages": "yarn turbo run lint && yarn turbo run build && yarn workspace @kikko-land/common-scripts publish-packages", 11 | "build": "yarn turbo run build", 12 | "lint": "yarn turbo run lint", 13 | "check-typing": "yarn turbo run check-typing" 14 | }, 15 | "workspaces": [ 16 | "packages/*" 17 | ], 18 | "dependencies": {}, 19 | "devDependencies": { 20 | "@changesets/cli": "^2.25.0", 21 | "turbo": "^1.5.6" 22 | }, 23 | "publishConfig": { 24 | "access": "public" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/vite-react-example/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import react from "@vitejs/plugin-react"; 3 | import checker from "vite-plugin-checker"; 4 | import { visualizer } from "rollup-plugin-visualizer"; 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | server: { 9 | headers: { 10 | "Cross-Origin-Embedder-Policy": "require-corp", 11 | "Cross-Origin-Opener-Policy": "same-origin", 12 | }, 13 | }, 14 | plugins: [ 15 | react(), 16 | checker({ typescript: true, enableBuild: false }), 17 | visualizer({ open: true, filename: "dist/stats.html" }), 18 | ], 19 | optimizeDeps: { 20 | esbuildOptions: { 21 | target: "es2020", 22 | }, 23 | }, 24 | build: { 25 | target: "es2020", 26 | }, 27 | }); 28 | -------------------------------------------------------------------------------- /packages/wa-sqlite-backend/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @kikko-land/wa-sqlite-web-backend 2 | 3 | ## 0.11.0 4 | 5 | ### Minor Changes 6 | 7 | - 71c1bea: Upgrade boono-sql 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [71c1bea] 12 | - @kikko-land/kikko@0.19.0 13 | 14 | ## 0.10.0 15 | 16 | ### Minor Changes 17 | 18 | - eb496a0: Add original batched vfs 19 | 20 | ### Patch Changes 21 | 22 | - Updated dependencies [eb496a0] 23 | - @kikko-land/kikko@0.18.0 24 | 25 | ## 0.9.0 26 | 27 | ### Minor Changes 28 | 29 | - 59cb7a1: Fix wa-sqlite typing 30 | 31 | ## 0.8.0 32 | 33 | ### Minor Changes 34 | 35 | - 2c9a6f4: Remove console.trace 36 | - a44c084: Add wa-sqlite backend 37 | 38 | ### Patch Changes 39 | 40 | - Updated dependencies [15a9a4d] 41 | - Updated dependencies [a44c084] 42 | - @kikko-land/kikko@0.17.0 43 | -------------------------------------------------------------------------------- /packages/wa-sqlite-backend/rollup.config.js: -------------------------------------------------------------------------------- 1 | import typescript from "rollup-plugin-typescript2"; 2 | import { nodeResolve } from "@rollup/plugin-node-resolve"; 3 | import commonjs from "@rollup/plugin-commonjs"; 4 | 5 | function getConfig(entry, filename) { 6 | return { 7 | input: entry, 8 | output: { 9 | dir: "dist", 10 | }, 11 | external: [ 12 | "wa-sqlite", 13 | "wa-sqlite/src/VFS.js", 14 | "wa-sqlite/dist/wa-sqlite-async.mjs", 15 | "@kikko-land/kikko", 16 | ], 17 | plugins: [ 18 | nodeResolve(), 19 | typescript({}), 20 | commonjs({ 21 | include: /node_modules/, 22 | requireReturnsDefault: "auto", // <---- this solves default issue 23 | }), 24 | ], 25 | }; 26 | } 27 | 28 | export default [getConfig("src/index.ts", "index.js")]; 29 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Lint and tsc check 5 | 6 | on: [push, pull_request] 7 | 8 | jobs: 9 | check: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Use Node.js ${{ matrix.node-version }} 15 | uses: actions/setup-node@v2 16 | with: 17 | node-version: 18.x 18 | - uses: actions/cache@v2 19 | with: 20 | path: "**/node_modules" 21 | key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}-2 22 | - run: yarn 23 | - run: yarn lint 24 | - run: yarn check-typing 25 | -------------------------------------------------------------------------------- /packages/react-queries-hooks/src/hooks/types.ts: -------------------------------------------------------------------------------- 1 | export type ISingleQueryHookResult = 2 | | { 3 | type: "loading"; 4 | data?: D; 5 | } 6 | | { 7 | type: "waitingDb"; 8 | data?: D; 9 | } 10 | | { type: "loaded"; data: D } 11 | | { type: "noSqlPresent"; data?: D }; 12 | 13 | export type IRunQueryHookResult = 14 | | { 15 | type: "running"; 16 | data?: D; 17 | } 18 | | { 19 | type: "waitingDb"; 20 | data?: D; 21 | } 22 | | { type: "done"; data: D } 23 | | { type: "idle"; data?: D }; 24 | 25 | export type IQueryHookResult = 26 | | { 27 | type: "loading"; 28 | data: D[]; 29 | } 30 | | { 31 | type: "waitingDb"; 32 | data: D[]; 33 | } 34 | | { type: "loaded"; data: D[] } 35 | | { type: "noSqlPresent"; data: D[] }; 36 | 37 | export type Falsy = false | 0 | "" | null | undefined; 38 | -------------------------------------------------------------------------------- /packages/kikko/src/utils.ts: -------------------------------------------------------------------------------- 1 | import { ISql } from "@kikko-land/boono-sql"; 2 | 3 | import { IDb, IQuery } from "./types"; 4 | 5 | export const assureDbIsRunning = (state: IDb, toStart: () => string) => { 6 | const { 7 | __state: { 8 | sharedState: { runningState, dbName }, 9 | }, 10 | } = state; 11 | 12 | if (runningState.value !== "running") { 13 | throw new Error(`Failed to start ${toStart()}, db ${dbName} is stopping`); 14 | } 15 | }; 16 | 17 | export const unwrapQueries = (queries: ISql[]): IQuery[] => { 18 | return queries.map((q) => q.preparedQuery); 19 | }; 20 | 21 | export function makeId() { 22 | let result = ""; 23 | const characters = 24 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 25 | const charactersLength = characters.length; 26 | for (let i = 0; i < 32; i++) { 27 | result += characters.charAt(Math.floor(Math.random() * charactersLength)); 28 | } 29 | 30 | return result; 31 | } 32 | -------------------------------------------------------------------------------- /packages/kikko-doc/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | Using SSH: 30 | 31 | ``` 32 | $ USE_SSH=true yarn deploy 33 | ``` 34 | 35 | Not using SSH: 36 | 37 | ``` 38 | $ GIT_USER= yarn deploy 39 | ``` 40 | 41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 kikko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/common-scripts/vite.cjs: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const { defineConfig } = require("vite"); 3 | const autoExternal = require("rollup-plugin-auto-external"); 4 | const dts = require("vite-plugin-dts"); 5 | 6 | exports.buildConfig = function (config) { 7 | config = config || {}; 8 | config.entry = config.entry || "src/index.ts"; 9 | config.fileName = config.fileName || ((format) => `index.${format}.js`); 10 | config.outDir = config.outDir || "dist"; 11 | 12 | return defineConfig({ 13 | build: { 14 | outDir: config.outDir, 15 | sourcemap: true, 16 | lib: { 17 | entry: path.resolve("./", config.entry), 18 | name: "core", 19 | fileName: config.fileName, 20 | }, 21 | rollupOptions: { 22 | // make sure to externalize deps that shouldn't be bundled 23 | // into your library 24 | output: { 25 | inlineDynamicImports: true, 26 | }, 27 | plugins: [...(config.disableAutoExternal ? [] : [autoExternal()])], 28 | external: config.external || [], 29 | }, 30 | }, 31 | plugins: [dts()], 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /packages/kikko-doc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kikko-doc", 3 | "version": "0.5.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids", 15 | "check-typing": "echo \"1\"", 16 | "lint": "echo \"1\"" 17 | }, 18 | "dependencies": { 19 | "@docusaurus/core": "2.1.0", 20 | "@docusaurus/preset-classic": "2.1.0", 21 | "@mdx-js/react": "^1.6.22", 22 | "clsx": "^1.1.1", 23 | "prism-react-renderer": "^1.3.3", 24 | "react": "^17.0.2", 25 | "react-dom": "^17.0.2" 26 | }, 27 | "browserslist": { 28 | "production": [ 29 | ">0.5%", 30 | "not dead", 31 | "not op_mini all" 32 | ], 33 | "development": [ 34 | "last 1 chrome version", 35 | "last 1 firefox version", 36 | "last 1 safari version" 37 | ] 38 | } 39 | } -------------------------------------------------------------------------------- /packages/common-scripts/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true, 5 | }, 6 | extends: [ 7 | // "airbnb", 8 | // "airbnb-typescript", 9 | // "eslint:recommended", 10 | "plugin:@typescript-eslint/recommended", 11 | "plugin:jsx-a11y/recommended", 12 | "plugin:promise/recommended", 13 | "plugin:@typescript-eslint/recommended-requiring-type-checking", 14 | "plugin:react-hooks/recommended", 15 | "plugin:prettier/recommended", 16 | "prettier", 17 | ], 18 | parser: "@typescript-eslint/parser", 19 | plugins: ["jsx-a11y", "simple-import-sort", "promise"], 20 | rules: { 21 | "simple-import-sort/imports": "warn", 22 | "simple-import-sort/exports": "warn", 23 | "@typescript-eslint/no-floating-promises": ["warn"], 24 | "import/prefer-default-export": "off", 25 | "no-console": "off", 26 | "no-bitwise": "off", 27 | "import/extensions": "off", 28 | "no-use-before-define": "off", 29 | "no-await-in-loop": "off", 30 | "import/no-unresolved": "off", 31 | "class-methods-use-this": "off", 32 | "no-restricted-syntax": "off", 33 | }, 34 | }; 35 | -------------------------------------------------------------------------------- /packages/kikko-doc/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #2e8555; 10 | --ifm-color-primary-dark: #29784c; 11 | --ifm-color-primary-darker: #277148; 12 | --ifm-color-primary-darkest: #205d3b; 13 | --ifm-color-primary-light: #33925d; 14 | --ifm-color-primary-lighter: #359962; 15 | --ifm-color-primary-lightest: #3cad6e; 16 | --ifm-code-font-size: 95%; 17 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); 18 | } 19 | 20 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 21 | [data-theme='dark'] { 22 | --ifm-color-primary: #25c2a0; 23 | --ifm-color-primary-dark: #21af90; 24 | --ifm-color-primary-darker: #1fa588; 25 | --ifm-color-primary-darkest: #1a8870; 26 | --ifm-color-primary-light: #29d5b0; 27 | --ifm-color-primary-lighter: #32d8b4; 28 | --ifm-color-primary-lightest: #4fddbf; 29 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); 30 | } 31 | -------------------------------------------------------------------------------- /packages/kikko/src/afterTransaction.ts: -------------------------------------------------------------------------------- 1 | import { IDb, ITransaction } from "./types"; 2 | 3 | export const runAfterTransaction = ( 4 | db: IDb, 5 | func: ( 6 | event: "committed" | "rollbacked", 7 | db: IDb, 8 | transaction: ITransaction 9 | ) => void 10 | ) => { 11 | if (!db.__state.localState.transactionState.current) { 12 | throw new Error("Not in transaction."); 13 | } 14 | const transaction = db.__state.localState.transactionState.current; 15 | 16 | const unsubscribes: (() => void)[] = []; 17 | 18 | const listener = 19 | (event: "committed" | "rollbacked") => 20 | (db: IDb, evTransaction: ITransaction) => { 21 | if (transaction.id !== evTransaction.id) return; 22 | 23 | func(event, db, transaction); 24 | 25 | for (const unsubscribe of unsubscribes) { 26 | unsubscribe(); 27 | } 28 | }; 29 | 30 | unsubscribes.push( 31 | db.__state.sharedState.eventsEmitter.on( 32 | "transactionCommitted", 33 | listener("committed") 34 | ) 35 | ); 36 | 37 | unsubscribes.push( 38 | db.__state.sharedState.eventsEmitter.on( 39 | "transactionRollbacked", 40 | listener("rollbacked") 41 | ) 42 | ); 43 | }; 44 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | concurrency: ${{ github.workflow }}-${{ github.ref }} 9 | 10 | jobs: 11 | release: 12 | name: Release 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout Repo 16 | uses: actions/checkout@v2 17 | 18 | - name: Setup Node.js 17.x 19 | uses: actions/setup-node@v2 20 | with: 21 | node-version: 17.x 22 | 23 | - name: Creating .npmrc 24 | run: | 25 | cat << EOF > "$HOME/.npmrc" 26 | //registry.npmjs.org/:_authToken=$NPM_TOKEN 27 | EOF 28 | env: 29 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 30 | 31 | - name: Install Dependencies 32 | run: yarn 33 | 34 | - name: Create Release Pull Request or Publish to npm 35 | id: changesets 36 | uses: changesets/action@v1 37 | with: 38 | # This expects you to have a script called release which does a build for your packages and calls changeset publish 39 | publish: yarn publish-packages 40 | env: 41 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 42 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 43 | -------------------------------------------------------------------------------- /packages/vite-react-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/vite-react-example", 3 | "private": true, 4 | "version": "0.13.1", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "echo \"\"", 8 | "build-site": "vite build", 9 | "preview": "vite preview", 10 | "lint": "echo \"\"", 11 | "check-typing": "echo \"\"" 12 | }, 13 | "dependencies": { 14 | "@kikko-land/absurd-web-backend": "*", 15 | "@kikko-land/boono": "^0.2.1", 16 | "@kikko-land/react": "*", 17 | "@kikko-land/sql.js": "^1.6.8", 18 | "@kikko-land/wa-sqlite-web-backend": "^0.11.0", 19 | "kysely": "^0.24.2", 20 | "lodash-es": "^4.17.21", 21 | "lorem-ipsum": "^2.0.8", 22 | "react": "^18.2.0", 23 | "react-dom": "^18.2.0", 24 | "react-highlight-words": "^0.18.0", 25 | "react-router-dom": "^6.4.2", 26 | "react-use": "^17.4.0" 27 | }, 28 | "devDependencies": { 29 | "@types/lodash-es": "^4.17.6", 30 | "@types/react": "^18.0.21", 31 | "@types/react-dom": "^18.0.6", 32 | "@types/react-highlight-words": "^0.16.4", 33 | "@vitejs/plugin-react": "^2.1.0", 34 | "rollup-plugin-visualizer": "^5.8.3", 35 | "vite": "^3.1.8", 36 | "vite-plugin-checker": "^0.5.1" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/kikko/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/kikko", 3 | "version": "0.19.1", 4 | "author": "Sergey Popov", 5 | "license": "MIT", 6 | "main": "./src/index.ts", 7 | "module": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./src/index.ts", 12 | "import": "./src/index.ts" 13 | } 14 | }, 15 | "publishConfig": { 16 | "exports": { 17 | ".": { 18 | "types": "./dist/index.d.ts", 19 | "es2015": "./dist/index.es.js", 20 | "require": "./dist/index.umd.js", 21 | "import": "./dist/index.es.js", 22 | "default": "./dist/index.es.js" 23 | } 24 | }, 25 | "main": "./dist/index.umd.js", 26 | "module": "./dist/index.es.js", 27 | "types": "./dist/index.d.ts" 28 | }, 29 | "scripts": { 30 | "build": "yarn vite build", 31 | "lint": "eslint \"src/**/*.{tsx,ts}\" --max-warnings=0", 32 | "check-typing": "tsc --noEmit" 33 | }, 34 | "dependencies": { 35 | "@kikko-land/boono-sql": "^0.4.0", 36 | "fast-equals": "^4.0.3", 37 | "ts-essentials": "^9.3.0" 38 | }, 39 | "devDependencies": { 40 | "@kikko-land/common-scripts": "^0.5.0", 41 | "@types/emscripten": "^1.39.6" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/migrations-plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/migrations-plugin", 3 | "version": "0.11.0", 4 | "main": "./src/index.ts", 5 | "module": "./src/index.ts", 6 | "types": "./src/index.ts", 7 | "exports": { 8 | ".": { 9 | "types": "./src/index.ts", 10 | "import": "./src/index.ts" 11 | } 12 | }, 13 | "publishConfig": { 14 | "exports": { 15 | ".": { 16 | "types": "./dist/migrations-plugin/src/index.d.ts", 17 | "es2015": "./dist/index.es.js", 18 | "require": "./dist/index.umd.js", 19 | "import": "./dist/index.es.js", 20 | "default": "./dist/index.es.js" 21 | } 22 | }, 23 | "main": "./dist/index.umd.js", 24 | "module": "./dist/index.es.js", 25 | "types": "./dist/migrations-plugin/src/index.d.ts" 26 | }, 27 | "author": "Sergey Popov", 28 | "license": "MIT", 29 | "scripts": { 30 | "build": "yarn vite build", 31 | "lint": "eslint \"src/**/*.{tsx,ts}\" --max-warnings=0", 32 | "check-typing": "tsc --noEmit" 33 | }, 34 | "dependencies": { 35 | "@kikko-land/kikko": "^0.19.0", 36 | "@kikko-land/boono-sql": "^0.4.0" 37 | }, 38 | "devDependencies": { 39 | "@kikko-land/common-scripts": "^0.5.0", 40 | "@types/emscripten": "^1.39.6" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/common-scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/common-scripts", 3 | "version": "0.5.0", 4 | "author": "Sergey Popov", 5 | "license": "MIT", 6 | "type": "module", 7 | "scripts": { 8 | "publish-packages": "node --loader ts-node/esm ./src/publish.ts", 9 | "lint": "echo \"\"", 10 | "build": "echo \"\"", 11 | "check-typing": "echo \"\"" 12 | }, 13 | "dependencies": { 14 | "@typescript-eslint/eslint-plugin": "^5.40.0", 15 | "eslint": "^8.25.0", 16 | "eslint-config-airbnb": "^19.0.4", 17 | "eslint-config-prettier": "^8.5.0", 18 | "eslint-config-react-app": "^7.0.1", 19 | "eslint-plugin-flowtype": "^8.0.3", 20 | "eslint-plugin-import": "^2.26.0", 21 | "eslint-plugin-jsx-a11y": "^6.6.1", 22 | "eslint-plugin-prettier": "^4.2.1", 23 | "eslint-plugin-promise": "^6.1.0", 24 | "eslint-plugin-react": "^7.31.10", 25 | "eslint-plugin-react-hooks": "^4.6.0", 26 | "eslint-plugin-simple-import-sort": "^8.0.0", 27 | "inquirer": "^9.1.3", 28 | "rollup-plugin-auto-external": "^2.0.0", 29 | "ts-node": "^10.9.1", 30 | "typescript": "^4.8.4" 31 | }, 32 | "devDependencies": { 33 | "@types/inquirer": "^9.0.2", 34 | "prettier": "^2.7.1", 35 | "type-fest": "^3.1.0", 36 | "vite-plugin-dts": "^1.6.6" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/reactive-queries-plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/reactive-queries-plugin", 3 | "version": "0.12.0", 4 | "author": "Sergey Popov", 5 | "license": "MIT", 6 | "main": "./src/index.ts", 7 | "module": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./src/index.ts", 12 | "import": "./src/index.ts" 13 | } 14 | }, 15 | "publishConfig": { 16 | "exports": { 17 | ".": { 18 | "types": "./dist/reactive-queries-plugin/src/index.d.ts", 19 | "es2015": "./dist/index.es.js", 20 | "require": "./dist/index.umd.js", 21 | "import": "./dist/index.es.js", 22 | "default": "./dist/index.es.js" 23 | } 24 | }, 25 | "main": "./dist/index.umd.js", 26 | "module": "./dist/index.es.js", 27 | "types": "./dist/reactive-queries-plugin/src/index.d.ts" 28 | }, 29 | "scripts": { 30 | "build": "yarn vite build", 31 | "lint": "eslint \"src/**/*.{tsx,ts}\" --max-warnings=0", 32 | "check-typing": "tsc --noEmit" 33 | }, 34 | "dependencies": { 35 | "@kikko-land/kikko": "^0.19.0", 36 | "@kikko-land/boono-sql": "^0.4.0", 37 | "broadcast-channel": "^4.18.0" 38 | }, 39 | "devDependencies": { 40 | "@kikko-land/common-scripts": "^0.5.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/d1-backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/d1-backend", 3 | "version": "0.4.3", 4 | "author": "Sergey Popov", 5 | "license": "MIT", 6 | "main": "./src/index.ts", 7 | "module": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./src/index.ts", 12 | "import": "./src/index.ts" 13 | } 14 | }, 15 | "publishConfig": { 16 | "exports": { 17 | ".": { 18 | "types": "./dist/d1-backend/src/index.d.ts", 19 | "es2015": "./dist/index.es.js", 20 | "require": "./dist/index.umd.js", 21 | "import": "./dist/index.es.js", 22 | "default": "./dist/index.es.js" 23 | } 24 | }, 25 | "main": "./dist/index.umd.js", 26 | "module": "./dist/index.es.js", 27 | "types": "./dist/d1-backend/src/index.d.ts" 28 | }, 29 | "scripts": { 30 | "build": "yarn vite build", 31 | "lint": "eslint \"src/**/*.{tsx,ts}\" --max-warnings=0", 32 | "check-typing": "tsc --noEmit" 33 | }, 34 | "dependencies": { 35 | "@kikko-land/boono": "^0.2.1", 36 | "@kikko-land/kikko": "^0.19.0" 37 | }, 38 | "devDependencies": { 39 | "@cloudflare/workers-types": "^3.18.0", 40 | "@kikko-land/common-scripts": "^0.5.0", 41 | "@types/emscripten": "^1.39.6", 42 | "ts-essentials": "^9.3.0" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/vue", 3 | "version": "0.7.0", 4 | "author": "Sergey Popov", 5 | "license": "MIT", 6 | "main": "./src/index.ts", 7 | "module": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./src/index.ts", 12 | "import": "./src/index.ts" 13 | } 14 | }, 15 | "publishConfig": { 16 | "exports": { 17 | ".": { 18 | "types": "./dist/vue/src/index.d.ts", 19 | "es2015": "./dist/index.es.js", 20 | "require": "./dist/index.umd.js", 21 | "import": "./dist/index.es.js", 22 | "default": "./dist/index.es.js" 23 | } 24 | }, 25 | "main": "./dist/index.umd.js", 26 | "module": "./dist/index.es.js", 27 | "types": "./dist/vue/src/index.d.ts" 28 | }, 29 | "scripts": { 30 | "build": "yarn vite build", 31 | "lint": "eslint \"src/**/*.{tsx,ts}\" --max-warnings=0", 32 | "check-typing": "tsc --noEmit" 33 | }, 34 | "dependencies": { 35 | "@kikko-land/kikko": "^0.19.0", 36 | "@kikko-land/reactive-queries-plugin": "^0.12.0", 37 | "@kikko-land/boono-sql": "^0.4.0" 38 | }, 39 | "peerDependencies": { 40 | "vue": ">=3.2.41" 41 | }, 42 | "devDependencies": { 43 | "@kikko-land/common-scripts": "^0.5.0", 44 | "vue": "^3.2.39" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/react-native-backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/react-native-backend", 3 | "version": "0.10.0", 4 | "author": "Sergey Popov", 5 | "license": "MIT", 6 | "main": "./src/index.ts", 7 | "module": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./src/index.ts", 12 | "import": "./src/index.ts" 13 | } 14 | }, 15 | "publishConfig": { 16 | "exports": { 17 | ".": { 18 | "types": "./dist/react-native-backend/src/index.d.ts", 19 | "es2015": "./dist/index.es.js", 20 | "require": "./dist/index.umd.js", 21 | "import": "./dist/index.es.js", 22 | "default": "./dist/index.es.js" 23 | } 24 | }, 25 | "main": "./dist/index.umd.js", 26 | "module": "./dist/index.es.js", 27 | "types": "./dist/react-native-backend/src/index.d.ts" 28 | }, 29 | "scripts": { 30 | "build": "yarn vite build", 31 | "lint": "eslint \"src/**/*.{tsx,ts}\" --max-warnings=0", 32 | "check-typing": "tsc --noEmit" 33 | }, 34 | "dependencies": { 35 | "@kikko-land/kikko": "^0.19.0", 36 | "@kikko-land/boono-sql": "^0.4.0", 37 | "react-native-sqlite-storage": "^6.0.1" 38 | }, 39 | "devDependencies": { 40 | "@kikko-land/common-scripts": "^0.5.0", 41 | "@types/react-native-sqlite-storage": "^5.0.2" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/react-queries-hooks/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/react-queries-hooks", 3 | "version": "0.12.0", 4 | "author": "Sergey Popov", 5 | "license": "MIT", 6 | "main": "./src/index.ts", 7 | "module": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./src/index.ts", 12 | "import": "./src/index.ts" 13 | } 14 | }, 15 | "publishConfig": { 16 | "exports": { 17 | ".": { 18 | "types": "./dist/react-queries-hooks/src/index.d.ts", 19 | "es2015": "./dist/index.es.js", 20 | "require": "./dist/index.umd.js", 21 | "import": "./dist/index.es.js", 22 | "default": "./dist/index.es.js" 23 | } 24 | }, 25 | "main": "./dist/index.umd.js", 26 | "module": "./dist/index.es.js", 27 | "types": "./dist/react-queries-hooks/src/index.d.ts" 28 | }, 29 | "scripts": { 30 | "build": "yarn vite build", 31 | "lint": "eslint \"src/**/*.{tsx,ts}\" --max-warnings=0", 32 | "check-typing": "tsc --noEmit" 33 | }, 34 | "dependencies": { 35 | "@kikko-land/kikko": "^0.19.0", 36 | "@kikko-land/reactive-queries-plugin": "^0.12.0", 37 | "@kikko-land/boono-sql": "^0.4.0" 38 | }, 39 | "peerDependencies": { 40 | "react": ">=18.2.0" 41 | }, 42 | "devDependencies": { 43 | "@kikko-land/common-scripts": "^0.5.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/vite-react-example/src/migrations/createNotesTable.ts: -------------------------------------------------------------------------------- 1 | import { IAtomicMigration, IMigration, sql } from "@kikko-land/react"; 2 | 3 | export const createNotesTableMigration: IMigration = { 4 | up: async (db) => { 5 | await db.runQuery( 6 | sql` 7 | CREATE TABLE IF NOT EXISTS notes ( 8 | id varchar(20) PRIMARY KEY, 9 | title TEXT NOT NULL, 10 | content TEXT NOT NULL, 11 | updatedAt INTEGER NOT NULL, 12 | createdAt INTEGER NOT NULL 13 | ); 14 | ` 15 | ); 16 | 17 | await db.runQuery( 18 | sql` 19 | CREATE INDEX IF NOT EXISTS idx_note_title ON notes(title); 20 | ` 21 | ); 22 | }, 23 | id: 1668365362401, 24 | name: "createNotesTable", 25 | }; 26 | 27 | export const createNotesTableAtomicMigration: IAtomicMigration = { 28 | up: (db) => { 29 | db.addQuery( 30 | sql` 31 | CREATE TABLE IF NOT EXISTS notes ( 32 | id varchar(20) PRIMARY KEY, 33 | title TEXT NOT NULL, 34 | content TEXT NOT NULL, 35 | isDone INTEGER NOT NULL, 36 | updatedAt INTEGER NOT NULL, 37 | createdAt INTEGER NOT NULL 38 | ); 39 | ` 40 | ); 41 | 42 | db.addQuery( 43 | sql` 44 | CREATE INDEX IF NOT EXISTS idx_note_title ON notes(title); 45 | ` 46 | ); 47 | }, 48 | id: 1668365362401, 49 | name: "createNotesTable", 50 | }; 51 | -------------------------------------------------------------------------------- /packages/react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/react", 3 | "version": "0.9.0", 4 | "author": "Sergey Popov", 5 | "license": "MIT", 6 | "main": "./src/index.ts", 7 | "module": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./src/index.ts", 12 | "import": "./src/index.ts", 13 | "default": "./src/index.ts" 14 | } 15 | }, 16 | "publishConfig": { 17 | "exports": { 18 | ".": { 19 | "types": "./dist/react/src/index.d.ts", 20 | "es2015": "./dist/index.es.js", 21 | "require": "./dist/index.umd.js", 22 | "import": "./dist/index.es.js", 23 | "default": "./dist/index.es.js" 24 | } 25 | }, 26 | "main": "./dist/index.umd.js", 27 | "module": "./dist/index.es.js", 28 | "types": "./dist/react/src/index.d.ts" 29 | }, 30 | "scripts": { 31 | "build": "yarn vite build", 32 | "lint": "eslint \"src/**/*.{tsx,ts}\" --max-warnings=0", 33 | "check-typing": "tsc --noEmit" 34 | }, 35 | "dependencies": { 36 | "@kikko-land/kikko": "^0.19.0", 37 | "@kikko-land/migrations-plugin": "^0.11.0", 38 | "@kikko-land/react-queries-hooks": "^0.12.0", 39 | "@kikko-land/reactive-queries-plugin": "^0.12.0", 40 | "@kikko-land/boono-sql": "^0.4.0" 41 | }, 42 | "devDependencies": { 43 | "@kikko-land/common-scripts": "^0.5.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/native-expo-backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/native-expo-backend", 3 | "version": "0.10.0", 4 | "author": "Sergey Popov", 5 | "license": "MIT", 6 | "main": "./src/index.ts", 7 | "module": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./src/index.ts", 12 | "import": "./src/index.ts" 13 | } 14 | }, 15 | "publishConfig": { 16 | "exports": { 17 | ".": { 18 | "types": "./dist/native-expo-backend/src/index.d.ts", 19 | "es2015": "./dist/index.es.js", 20 | "require": "./dist/index.umd.js", 21 | "import": "./dist/index.es.js", 22 | "default": "./dist/index.es.js" 23 | } 24 | }, 25 | "main": "./dist/index.umd.js", 26 | "module": "./dist/index.es.js", 27 | "types": "./dist/native-expo-backend/src/index.d.ts" 28 | }, 29 | "scripts": { 30 | "build": "yarn vite build", 31 | "lint": "eslint \"src/**/*.{tsx,ts}\" --max-warnings=0", 32 | "check-typing": "tsc --noEmit" 33 | }, 34 | "dependencies": { 35 | "@kikko-land/kikko": "^0.19.0", 36 | "@kikko-land/boono-sql": "^0.4.0", 37 | "@kikko-land/sql.js": "^1.6.8", 38 | "expo-sqlite": ">=10.3.0" 39 | }, 40 | "devDependencies": { 41 | "@kikko-land/common-scripts": "^0.5.0", 42 | "@types/emscripten": "^1.39.6", 43 | "ts-essentials": "^9.3.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/native-ionic-backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/native-ionic-backend", 3 | "version": "0.10.0", 4 | "author": "Sergey Popov", 5 | "license": "MIT", 6 | "main": "./src/index.ts", 7 | "module": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./src/index.ts", 12 | "import": "./src/index.ts" 13 | } 14 | }, 15 | "publishConfig": { 16 | "exports": { 17 | ".": { 18 | "types": "./dist/native-ionic-backend/src/index.d.ts", 19 | "es2015": "./dist/index.es.js", 20 | "require": "./dist/index.umd.js", 21 | "import": "./dist/index.es.js", 22 | "default": "./dist/index.es.js" 23 | } 24 | }, 25 | "main": "./dist/index.umd.js", 26 | "module": "./dist/index.es.js", 27 | "types": "./dist/native-ionic-backend/src/index.d.ts" 28 | }, 29 | "scripts": { 30 | "build": "yarn vite build", 31 | "lint": "eslint \"src/**/*.{tsx,ts}\" --max-warnings=0", 32 | "check-typing": "tsc --noEmit" 33 | }, 34 | "dependencies": { 35 | "@kikko-land/kikko": "^0.19.0", 36 | "@kikko-land/boono-sql": "^0.4.0", 37 | "@awesome-cordova-plugins/core": "^6.0.0", 38 | "@awesome-cordova-plugins/sqlite": "^6.0.0", 39 | "cordova-sqlite-storage": "^6.0.0" 40 | }, 41 | "devDependencies": { 42 | "@kikko-land/common-scripts": "^0.5.0" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/kikko-doc/docs/buildingSql.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: /building-sql 3 | --- 4 | 5 | # Building sql 6 | 7 | The idea taken from [sql-template-tag](https://github.com/blakeembrey/sql-template-tag), big thanks to the author! It uses the power of ES2015 tagged template string for preparing SQL statements. 8 | 9 | When you build queries, you need to follow one rule to keep your queries reactive: 10 | 11 | :::info 12 | Always use `sql.table('tableName')` or `` sql.table`tableName` `` when you reference to the table in the query. It allows to keep your queries reactive. 13 | 14 | ```typescript 15 | import { sql } from "@kikko-land/kikko"; 16 | 17 | const booksTables = sql.table`books`; 18 | sql`SELECT * FROM ${booksTables}`; 19 | sql`INSERT INTO ${booksTables} VALUES (1, 2, 3)`; 20 | ``` 21 | 22 | ::: 23 | 24 | ## Usage examples 25 | 26 | 39 | -------------------------------------------------------------------------------- /packages/tauri-backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/tauri-backend", 3 | "version": "0.10.0", 4 | "author": "Sergey Popov", 5 | "license": "MIT", 6 | "main": "./src/index.ts", 7 | "module": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./src/index.ts", 12 | "import": "./src/index.ts" 13 | } 14 | }, 15 | "publishConfig": { 16 | "exports": { 17 | ".": { 18 | "types": "./dist/tauri-backend/src/index.d.ts", 19 | "es2015": "./dist/index.es.js", 20 | "require": "./dist/index.umd.js", 21 | "import": "./dist/index.es.js", 22 | "default": "./dist/index.es.js" 23 | } 24 | }, 25 | "main": "./dist/index.umd.js", 26 | "module": "./dist/index.es.js", 27 | "types": "./dist/tauri-backend/src/index.d.ts" 28 | }, 29 | "scripts": { 30 | "build": "yarn vite build", 31 | "lint": "eslint \"src/**/*.{tsx,ts}\" --max-warnings=0", 32 | "check-typing": "tsc --noEmit" 33 | }, 34 | "dependencies": { 35 | "@kikko-land/kikko": "^0.19.0", 36 | "@kikko-land/boono-sql": "^0.4.0", 37 | "@kikko-land/sql.js": "^1.6.8", 38 | "tauri-plugin-sqlite-api": "github:lzdyes/tauri-plugin-sqlite#v0.1.1" 39 | }, 40 | "devDependencies": { 41 | "@kikko-land/common-scripts": "^0.5.0", 42 | "@types/emscripten": "^1.39.6", 43 | "ts-essentials": "^9.3.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/absurd-web-backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/absurd-web-backend", 3 | "version": "0.10.3", 4 | "author": "Sergey Popov", 5 | "license": "MIT", 6 | "main": "./src/index.ts", 7 | "module": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./src/index.ts", 12 | "import": "./src/index.ts" 13 | } 14 | }, 15 | "publishConfig": { 16 | "exports": { 17 | ".": { 18 | "types": "./dist/absurd-web-backend/src/index.d.ts", 19 | "es2015": "./dist/index.es.js", 20 | "require": "./dist/index.umd.js", 21 | "import": "./dist/index.es.js", 22 | "default": "./dist/index.es.js" 23 | } 24 | }, 25 | "main": "./dist/index.umd.js", 26 | "module": "./dist/index.es.js", 27 | "types": "./dist/absurd-web-backend/src/index.d.ts" 28 | }, 29 | "scripts": { 30 | "build": "yarn vite build", 31 | "lint": "eslint \"src/**/*.{tsx,ts}\" --max-warnings=0", 32 | "check-typing": "tsc --noEmit" 33 | }, 34 | "dependencies": { 35 | "@kikko-land/better-absurd-sql": "^0.0.57", 36 | "@kikko-land/boono": "^0.2.1", 37 | "@kikko-land/kikko": "^0.19.0", 38 | "@kikko-land/sql.js": "^1.6.8", 39 | "comlink": "^4.3.1" 40 | }, 41 | "devDependencies": { 42 | "@kikko-land/common-scripts": "^0.5.0", 43 | "@types/emscripten": "^1.39.6", 44 | "ts-essentials": "^9.3.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/vite-react-example/src/quick-react-example.tsx: -------------------------------------------------------------------------------- 1 | import { absurdWebBackend } from "@kikko-land/absurd-web-backend"; 2 | import { 3 | DbProvider, 4 | EnsureDbLoaded, 5 | IInitDbClientConfig, 6 | IMigration, 7 | migrationsPlugin, 8 | reactiveQueriesPlugin, 9 | sql, 10 | } from "@kikko-land/react"; 11 | // For Vite: 12 | import sqlWasmUrl from "@kikko-land/sql.js/dist/sql-wasm.wasm?url"; 13 | 14 | import { List } from "./list/List"; 15 | 16 | const createNotesTable: IMigration = { 17 | up: async (db) => { 18 | await db.runQuery( 19 | sql` 20 | CREATE TABLE IF NOT EXISTS notes ( 21 | id varchar(20) PRIMARY KEY, 22 | title TEXT NOT NULL, 23 | content TEXT NOT NULL, 24 | ); 25 | ` 26 | ); 27 | 28 | await db.runQuery( 29 | sql` 30 | CREATE INDEX IF NOT EXISTS idx_note_title ON notes(title); 31 | ` 32 | ); 33 | }, 34 | id: 1653668686076, 35 | name: "createNotesTable", 36 | }; 37 | 38 | const config: IInitDbClientConfig = { 39 | dbName: "quick-example-db", 40 | dbBackend: absurdWebBackend({ 41 | wasmUrl: sqlWasmUrl, 42 | }), 43 | plugins: [ 44 | reactiveQueriesPlugin(), 45 | migrationsPlugin({ migrations: [createNotesTable] }), 46 | ], 47 | }; 48 | 49 | export const App = () => { 50 | return ( 51 | 52 | Loading db...}> 53 | 54 | 55 | 56 | ); 57 | }; 58 | -------------------------------------------------------------------------------- /packages/kikko/src/createNanoEvents.ts: -------------------------------------------------------------------------------- 1 | // Adopted from https://github.com/ai/nanoevents/blob/main/index.js 2 | 3 | // Adopted from https://github.com/ai/nanoevents 4 | // I didn't use original due to lack of cjs support 5 | 6 | export type EventsMap = { 7 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 8 | [eventName: string]: (...args: any[]) => Promise | void; 9 | }; 10 | 11 | export interface INanoEmitter { 12 | emit( 13 | event: K, 14 | ...args: Parameters 15 | ): Promise; 16 | 17 | on(event: K, cb: Events[K]): () => void; 18 | } 19 | 20 | export function createNanoEvents< 21 | Events extends EventsMap 22 | >(): INanoEmitter { 23 | const events: Partial<{ [E in keyof Events]: Events[E][] }> = {}; 24 | 25 | return { 26 | async emit( 27 | event: K, 28 | ...args: Parameters 29 | ) { 30 | const all: Array = events[event] || []; 31 | for (const toCall of all) { 32 | await toCall(...args); 33 | } 34 | }, 35 | on(event: K, cb: Events[K]): () => void { 36 | ((events[event] = events[event] || []) as Events[K][]).push(cb); 37 | 38 | return () => { 39 | const eventsArray: Events[K][] = events[event] || []; 40 | 41 | events[event] = eventsArray.filter((i: unknown) => i !== cb); 42 | }; 43 | }, 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /packages/kikko-doc/docs/backends/tauri.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | slug: /backends/tauri 4 | --- 5 | 6 | import Tabs from "@theme/Tabs"; 7 | import TabItem from "@theme/TabItem"; 8 | 9 | # Tauri 10 | 11 | This backend uses [tauri-plugin-sqlite](https://github.com/lzdyes/tauri-plugin-sqlite). 12 | 13 | ## Installation 14 | 15 | Edit `src-tauri/Cargo.toml`: 16 | 17 | ```toml 18 | [dependencies.tauri-plugin-sqlite] 19 | git = "https://github.com/lzdyes/tauri-plugin-sqlite" 20 | tag = "v0.1.0" 21 | ``` 22 | 23 | Edit `src-tauri/src/main.rs`: 24 | 25 | ```rust 26 | fn main() { 27 | let context = tauri::generate_context!(); 28 | tauri::Builder::default() 29 | .plugin(tauri_plugin_sqlite::init()) 30 | .run(context) 31 | .expect("error while running tauri application"); 32 | } 33 | ``` 34 | 35 | Install Kikko packages: 36 | 37 | 38 | 39 | 40 | ```bash 41 | yarn add @kikko-land/sql.js @kikko-land/tauri-backend 42 | ``` 43 | 44 | 45 | 46 | 47 | ```bash 48 | npm i -S @kikko-land/tauri-backend 49 | ``` 50 | 51 | 52 | 53 | 54 | Configure Kikko: 55 | 56 | ```tsx 57 | import { tauriBackend } from "@kikko-land/tauri-backend"; 58 | 59 | const config: IInitDbClientConfig = { 60 | dbName: "helloWorld", 61 | dbBackend: tauriBackend((dbName) => `${dbName}.db`), 62 | plugins: [migrationsPlugin({ migrations: [] }), reactiveQueriesPlugin()], 63 | }; 64 | ``` 65 | 66 | Usage example repo: https://github.com/kikko-land/kikko-tauri-example 67 | -------------------------------------------------------------------------------- /packages/d1-backend/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @kikko-land/d1-backend 2 | 3 | ## 0.4.3 4 | 5 | ### Patch Changes 6 | 7 | - Updated dependencies [71c1bea] 8 | - @kikko-land/kikko@0.19.0 9 | 10 | ## 0.4.2 11 | 12 | ### Patch Changes 13 | 14 | - Updated dependencies [eb496a0] 15 | - @kikko-land/kikko@0.18.0 16 | 17 | ## 0.4.1 18 | 19 | ### Patch Changes 20 | 21 | - Updated dependencies [15a9a4d] 22 | - Updated dependencies [a44c084] 23 | - @kikko-land/kikko@0.17.0 24 | 25 | ## 0.4.0 26 | 27 | ### Minor Changes 28 | 29 | - a0170a6: Introduce new backend API 30 | 31 | ### Patch Changes 32 | 33 | - Updated dependencies [dc4ac77] 34 | - Updated dependencies [a0170a6] 35 | - Updated dependencies [bf55118] 36 | - @kikko-land/kikko@0.16.0 37 | 38 | ## 0.3.4 39 | 40 | ### Patch Changes 41 | 42 | - Updated dependencies [c0ac90e] 43 | - @kikko-land/kikko@0.15.0 44 | 45 | ## 0.3.3 46 | 47 | ### Patch Changes 48 | 49 | - Updated dependencies [0ac4b28] 50 | - @kikko-land/kikko@0.14.0 51 | 52 | ## 0.3.2 53 | 54 | ### Patch Changes 55 | 56 | - Updated dependencies [085297e] 57 | - @kikko-land/kikko@0.13.0 58 | 59 | ## 0.3.1 60 | 61 | ### Patch Changes 62 | 63 | - Updated dependencies [fc7a4e2] 64 | - @kikko-land/kikko@0.12.0 65 | 66 | ## 0.3.0 67 | 68 | ### Minor Changes 69 | 70 | - d6204b9: Add preparedQueries support 71 | 72 | ### Patch Changes 73 | 74 | - Updated dependencies [de4fd98] 75 | - Updated dependencies [d6204b9] 76 | - @kikko-land/kikko@0.11.0 77 | 78 | ## 0.2.0 79 | 80 | ### Minor Changes 81 | 82 | - 185ca8f: Version bump 83 | 84 | ### Patch Changes 85 | 86 | - Updated dependencies [e331160] 87 | - Updated dependencies [185ca8f] 88 | - @kikko-land/kikko@0.10.0 89 | -------------------------------------------------------------------------------- /packages/kikko-doc/sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creating a sidebar enables you to: 3 | - create an ordered group of docs 4 | - render a sidebar for each doc of that group 5 | - provide next/previous navigation 6 | 7 | The sidebars can be generated from the filesystem, or explicitly defined here. 8 | 9 | Create as many sidebars as you want. 10 | */ 11 | 12 | // @ts-check 13 | 14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 15 | const sidebars = { 16 | // By default, Docusaurus generates a sidebar from the docs folder structure 17 | docs: [ 18 | "intro", 19 | { 20 | type: "category", 21 | label: "Vue integration", 22 | items: [{ type: "autogenerated", dirName: "vueIntegration" }], 23 | }, 24 | { 25 | type: "category", 26 | label: "React integration", 27 | items: [{ type: "autogenerated", dirName: "reactIntegration" }], 28 | }, 29 | { 30 | type: "category", 31 | label: "Framework agnostic usage", 32 | items: [{ type: "autogenerated", dirName: "core" }], 33 | collapsed: false, 34 | }, 35 | { 36 | type: "category", 37 | label: "Plugins", 38 | items: [{ type: "autogenerated", dirName: "plugins" }], 39 | collapsed: false, 40 | }, 41 | "buildingSql", 42 | { 43 | type: "category", 44 | label: "SQLite backends configuration", 45 | items: [{ type: "autogenerated", dirName: "backends" }], 46 | collapsed: false, 47 | }, 48 | "deployingToNetlify", 49 | ], 50 | 51 | // But you can create a sidebar manually 52 | /* 53 | tutorialSidebar: [ 54 | { 55 | type: 'category', 56 | label: 'Tutorial', 57 | items: ['hello'], 58 | }, 59 | ], 60 | */ 61 | }; 62 | 63 | module.exports = sidebars; 64 | -------------------------------------------------------------------------------- /packages/reactive-queries-plugin/src/listenQueries.ts: -------------------------------------------------------------------------------- 1 | import { ISqlAdapter } from "@kikko-land/boono-sql"; 2 | import { IDb } from "@kikko-land/kikko"; 3 | 4 | import { IMessage } from "./getBroadcastCh"; 5 | import { getReactiveState } from "./utils"; 6 | 7 | export const listenQueries = >( 8 | db: IDb, 9 | queries: ISqlAdapter[], 10 | subscriber: (evs: D[][]) => void 11 | ): (() => void) => { 12 | const { rEventsCh } = getReactiveState(db); 13 | 14 | const readingTables = new Set( 15 | queries 16 | .map((q) => q.toSql()) 17 | .flatMap((q) => q.tables) 18 | .map((t) => t.name) 19 | ); 20 | 21 | let currentChannelUnsub: (() => void) | undefined; 22 | 23 | const runAndEmitQuery = async () => { 24 | subscriber(await db.runQueries(queries)); 25 | }; 26 | 27 | const chChangeUnsub = rEventsCh.subscribe((ch) => { 28 | if (currentChannelUnsub) currentChannelUnsub(); 29 | 30 | if (!ch) return; 31 | 32 | const func = ({ changesInTables }: IMessage) => { 33 | if (!changesInTables.some((table) => readingTables.has(table))) return; 34 | void runAndEmitQuery(); 35 | }; 36 | 37 | ch.addEventListener(func); 38 | 39 | currentChannelUnsub = () => { 40 | ch.removeEventListener(func); 41 | }; 42 | }); 43 | 44 | // Emit first value 45 | void runAndEmitQuery(); 46 | 47 | const unsubRunningState = db.__state.sharedState.runningState.subscribe( 48 | (v) => { 49 | queueMicrotask(() => { 50 | if (v === "stopping" || v === "stopped") { 51 | unsubAll(); 52 | } 53 | }); 54 | } 55 | ); 56 | 57 | const unsubAll = () => { 58 | unsubRunningState(); 59 | currentChannelUnsub?.(); 60 | chChangeUnsub(); 61 | }; 62 | 63 | return unsubAll; 64 | }; 65 | -------------------------------------------------------------------------------- /packages/kikko-doc/docs/backends/reactNative.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 6 3 | slug: /backends/react-native 4 | --- 5 | 6 | import Tabs from "@theme/Tabs"; 7 | import TabItem from "@theme/TabItem"; 8 | 9 | # React Native 10 | 11 | This backend uses [react-native-sqlite-storage](https://github.com/andpor/react-native-sqlite-storage). 12 | 13 | ## Installation 14 | 15 | Install Kikko packages and react-native-sqlite-storage: 16 | 17 | 18 | 19 | 20 | ```bash 21 | yarn add @kikko-land/react @kikko-land/react-native-backend react-native-sqlite-storage 22 | ``` 23 | 24 | 25 | 26 | 27 | ```bash 28 | npm i -S @kikko-land/react @kikko-land/react-native-backend react-native-sqlite-storage 29 | ``` 30 | 31 | 32 | 33 | 34 | Then configure Kikko: 35 | 36 | ```typescript 37 | import { 38 | DbProvider, 39 | EnsureDbLoaded, 40 | IInitDbClientConfig, 41 | migrationsPlugin, 42 | reactiveQueriesPlugin, 43 | } from "@kikko-land/react"; 44 | import { reactNativeBackend } from "@kikko-land/react-native-backend"; 45 | 46 | const config: IInitDbClientConfig = { 47 | dbName: "kikko-db", 48 | dbBackend: reactNativeBackend({ name: (dbName) => `${dbName}.db` }), 49 | plugins: [ 50 | migrationsPlugin({ migrations: [createNotesTable] }), 51 | reactiveQueriesPlugin({ webMultiTabSupport: false }), 52 | ], 53 | }; 54 | ``` 55 | 56 | And then wrap your with DbProvider and EnsureDbLoaded(optional): 57 | 58 | ```tsx 59 | import { DbProvider, EnsureDbLoaded } from "@kikko-land/react"; 60 | 61 | 62 | Loading db...}> 63 | 64 | 65 | ; 66 | ``` 67 | 68 | Code example: https://github.com/kikko-land/kikko-react-native-example 69 | -------------------------------------------------------------------------------- /packages/vite-react-example/src/hooks/usePaginator.ts: -------------------------------------------------------------------------------- 1 | import { ISelectStatement, select } from "@kikko-land/boono"; 2 | import { sql, useFirstRowDbQuery } from "@kikko-land/react"; 3 | import { useCallback, useEffect, useState } from "react"; 4 | 5 | export const usePaginator = ({ 6 | perPage, 7 | baseQuery, 8 | }: { 9 | perPage: number; 10 | baseQuery: ISelectStatement; 11 | }) => { 12 | const [currentPage, setPage] = useState(1); 13 | 14 | const countResult = useFirstRowDbQuery<{ count: number }>( 15 | select({ count: sql`COUNT(*)` }).from(baseQuery) 16 | ); 17 | 18 | const totalCount = countResult.data?.count; 19 | 20 | const totalPages = 21 | totalCount !== undefined ? Math.ceil(totalCount / perPage) || 1 : undefined; 22 | 23 | useEffect(() => { 24 | if (totalPages === undefined) return; 25 | if (totalPages === 0) { 26 | setPage(1); 27 | 28 | return; 29 | } 30 | 31 | if (currentPage > totalPages) { 32 | setPage(totalPages); 33 | } 34 | }, [currentPage, totalPages]); 35 | 36 | const isNextPageAvailable = 37 | totalPages !== undefined ? currentPage < totalPages : false; 38 | const isPrevPageAvailable = currentPage > 1; 39 | 40 | const nextPage = useCallback(() => { 41 | if (isNextPageAvailable) { 42 | setPage(currentPage + 1); 43 | } 44 | }, [currentPage, isNextPageAvailable]); 45 | 46 | const prevPage = useCallback(() => { 47 | if (isPrevPageAvailable) { 48 | setPage(currentPage - 1); 49 | } 50 | }, [currentPage, isPrevPageAvailable]); 51 | 52 | return { 53 | paginatedQuery: baseQuery 54 | .limit(perPage) 55 | .offset(perPage * (currentPage - 1)), 56 | totalPages, 57 | currentPage, 58 | totalCount, 59 | isNextPageAvailable, 60 | isPrevPageAvailable, 61 | nextPage, 62 | prevPage, 63 | }; 64 | }; 65 | -------------------------------------------------------------------------------- /packages/wa-sqlite-backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/wa-sqlite-web-backend", 3 | "version": "0.11.0", 4 | "author": "Sergey Popov", 5 | "license": "MIT", 6 | "main": "./src/index.ts", 7 | "module": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "type": "module", 10 | "publishConfig": { 11 | "exports": { 12 | ".": { 13 | "types": "./dist/wa-sqlite-backend/src/index.d.ts", 14 | "es2015": "./dist/index.js", 15 | "require": "./dist/index.js", 16 | "import": "./dist/index.js", 17 | "default": "./dist/index.js" 18 | } 19 | }, 20 | "main": "./dist/index.js", 21 | "module": "./dist/index.js", 22 | "types": "./dist/wa-sqlite-backend/src/index.d.ts" 23 | }, 24 | "scripts": { 25 | "build": "yarn rollup --config", 26 | "lint": "eslint \"src/**/*.{tsx,ts}\"", 27 | "check-typing": "tsc --noEmit" 28 | }, 29 | "dependencies": { 30 | "@kikko-land/boono-sql": "^0.4.0", 31 | "@kikko-land/kikko": "^0.19.0", 32 | "@kikko-land/sql.js": "^1.6.8", 33 | "wa-sqlite": "rhashimoto/wa-sqlite#buildless" 34 | }, 35 | "devDependencies": { 36 | "@kikko-land/boono": "^0.2.1", 37 | "@kikko-land/common-scripts": "*", 38 | "@kikko-land/react": "^0.9.0", 39 | "@rollup/plugin-commonjs": "^23.0.2", 40 | "@rollup/plugin-node-resolve": "^15.0.1", 41 | "@types/emscripten": "^1.39.6", 42 | "@types/lodash-es": "^4.17.6", 43 | "@types/react": "^18.0.25", 44 | "@types/react-dom": "^18.0.8", 45 | "@vitejs/plugin-react": "^2.2.0", 46 | "await-lock": "^2.2.2", 47 | "lodash-es": "^4.17.21", 48 | "patch-package": "^6.5.0", 49 | "postinstall-postinstall": "^2.1.0", 50 | "prettier": "^2.7.1", 51 | "react": "^18.2.0", 52 | "react-dom": "^18.2.0", 53 | "rollup": "^3.2.5", 54 | "rollup-plugin-dts": "^5.0.0", 55 | "rollup-plugin-typescript2": "^0.34.1", 56 | "ts-essentials": "^9.3.0", 57 | "tslib": "^2.4.1", 58 | "typescript": "^4.8.4", 59 | "vite": "^3.2.2" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/kikko-doc/docs/backends/ionic.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | slug: /backends/ionic 4 | --- 5 | 6 | import Tabs from "@theme/Tabs"; 7 | import TabItem from "@theme/TabItem"; 8 | 9 | # Ionic (Angular, React only) 10 | 11 | This backend uses [better-absurd-sql](https://github.com/kikko-land/better-absurd-sql) for web and [@awesome-cordova-plugins/sqlite](https://www.npmjs.com/package/@awesome-cordova-plugins/sqlite) for native. 12 | 13 | ## Installation 14 | 15 | Install Kikko packages: 16 | 17 | 18 | 19 | 20 | ```bash 21 | yarn add @kikko-land/sql.js @kikko-land/native-ionic-backend @kikko-land/absurd-web-backend cordova-sqlite-storage 22 | ``` 23 | 24 | 25 | 26 | 27 | ```bash 28 | npm i -S @kikko-land/sql.js @kikko-land/native-ionic-backend @kikko-land/absurd-web-backend cordova-sqlite-storage 29 | ``` 30 | 31 | 32 | 33 | 34 | Then configure Kikko: 35 | 36 | ```typescript 37 | import { isPlatform } from "@ionic/react"; 38 | // @ts-ignore 39 | import sqlWasmUrl from "@kikko-land/sql.js/dist/sql-wasm.wasm"; 40 | 41 | const config: IInitDbClientConfig = { 42 | dbName: "test-db", 43 | dbBackend: (async () => 44 | isPlatform("hybrid") 45 | ? (await import("@kikko-land/native-ionic-backend")).ionicBackend( 46 | (name) => `${name}.db` 47 | ) 48 | : (await import("@kikko-land/absurd-web-backend")).absurdWebBackend({ 49 | wasmUrl: sqlWasmUrl, 50 | }))(), 51 | plugins: [migrationsPlugin({ migrations: [] }), reactiveQueriesPlugin()], 52 | }; 53 | ``` 54 | 55 | If you using `create-react-app` create `src/setupProxy.js`: 56 | 57 | ```javascript 58 | module.exports = function (app) { 59 | app.use(function (req, res, next) { 60 | res.setHeader("Cross-Origin-Opener-Policy", "same-origin"); 61 | res.setHeader("Cross-Origin-Embedder-Policy", "require-corp"); 62 | next(); 63 | }); 64 | }; 65 | ``` 66 | 67 | Code example with react + ionic: https://github.com/kikko-land/kikko-ionic-example 68 | -------------------------------------------------------------------------------- /packages/kikko-doc/docs/reactIntegration/hooks.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | slug: /react-integration/hooks 4 | --- 5 | 6 | # Hooks 7 | 8 | ## useDbQuery / useFirstRowDbQuery 9 | 10 | Usage example: 11 | 12 | TODO 13 | 14 | ## useRunDbQuery 15 | 16 | Usage example: 17 | 18 | ```tsx 19 | type IRow = { 20 | id: string; 21 | title: string; 22 | }; 23 | 24 | const notesTable = sql.table("notes"); 25 | 26 | const RunComponent = () => { 27 | const [createRow, _createState] = useRunDbQuery( 28 | (db) => async (data: IRow) => { 29 | await runQuery( 30 | db, 31 | sql`INSERT INTO ${notesTable}(id, title) VALUES(${data.id}, ${data.title})` 32 | ); 33 | } 34 | ); 35 | 36 | const [updateRow, _updateState] = useRunDbQuery( 37 | (db) => async (data: Partial & { id: string }) => { 38 | await runQuery( 39 | db, 40 | sql`UPDATE ${notesTable} SET id=${data.id}, title=${data.title} WHERE id=${data.id}` 41 | ); 42 | } 43 | ); 44 | 45 | const run = useCallback(async () => { 46 | const row = { id: "123", title: "HEY!" }; 47 | 48 | await runQuery( 49 | db, 50 | sql`INSERT INTO ${notesTable}(id, title) VALUES(${row.id}, ${row.title})` 51 | ); 52 | 53 | await updateRow({ ...row, title: "updated" }); 54 | }, [createRow, updateRow]); 55 | 56 | return ; 57 | }; 58 | ``` 59 | 60 | :::info 61 | By default all queries in `useRunDbQuery` will run in transaction. You can disable it in the second argument with `{ inTransaction?: boolean }`. 62 | ::: 63 | 64 | ## useDb / useDbStrict 65 | 66 | ```typescript 67 | const Component = () => { 68 | // Or you can use `useDbStrict`, it will throw exception if DB not initialized 69 | const db = useDb(); 70 | 71 | const exec = async () => { 72 | if (!db) return; 73 | 74 | await db.runQuery(sql`SELECT * FROM ${sql.table`notes`}`); 75 | }; 76 | }; 77 | ``` 78 | 79 | This hook is used internally, but you still can access db 80 | if you need. Usually you need `useDbQuery`/`useRunDbQuery` to run queries. 81 | -------------------------------------------------------------------------------- /packages/electron-better-sqlite3-backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kikko-land/electron-better-sqlite3-backend", 3 | "version": "0.10.0", 4 | "author": "Sergey Popov", 5 | "license": "MIT", 6 | "main": "./src/index.ts", 7 | "module": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./src/index.ts", 12 | "import": "./src/index.ts" 13 | }, 14 | "./preload": { 15 | "types": "./src/electronBetterSqlite3Backend.ts", 16 | "import": "./src/electronBetterSqlite3Backend.ts" 17 | } 18 | }, 19 | "publishConfig": { 20 | "exports": { 21 | ".": { 22 | "types": "./dist/electron-better-sqlite3-backend/src/index.d.ts", 23 | "es2015": "./dist/index.es.js", 24 | "require": "./dist/index.umd.js", 25 | "import": "./dist/index.es.js", 26 | "default": "./dist/index.es.js" 27 | }, 28 | "./preload": { 29 | "types": "./preload-dist/initSqliteBridge.d.ts", 30 | "es2015": "./preload-dist/initSqliteBridge.es.js", 31 | "require": "./preload-dist/initSqliteBridge.umd.js", 32 | "import": "./preload-dist/initSqliteBridge.es.js", 33 | "default": "./preload-dist/initSqliteBridge.es.js" 34 | } 35 | }, 36 | "main": "./dist/index.umd.js", 37 | "module": "./dist/index.es.js", 38 | "types": "./dist/electron-better-sqlite3-backend/src/index.d.ts", 39 | "typesVersions": { 40 | "*": { 41 | "preload": [ 42 | "./preload-dist/initSqliteBridge.d.ts" 43 | ] 44 | } 45 | } 46 | }, 47 | "scripts": { 48 | "build": "run-s build:index build:preload", 49 | "build:index": "TO_BUILD=index yarn vite build", 50 | "build:preload": "TO_BUILD=preload yarn vite build", 51 | "lint": "eslint \"src/**/*.{tsx,ts}\" --max-warnings=0", 52 | "check-typing": "tsc --noEmit" 53 | }, 54 | "dependencies": { 55 | "@kikko-land/kikko": "^0.19.0", 56 | "@kikko-land/boono-sql": "^0.4.0", 57 | "@kikko-land/d1-backend": "^0.4.3", 58 | "@kikko-land/sql.js": "^1.6.8", 59 | "better-sqlite3": ">=7.6.2" 60 | }, 61 | "devDependencies": { 62 | "@kikko-land/common-scripts": "^0.5.0", 63 | "@types/better-sqlite3": "^7.6.2", 64 | "@types/emscripten": "^1.39.6", 65 | "electron": "^21.1.1", 66 | "npm-run-all": "^4.1.5", 67 | "ts-essentials": "^9.3.0" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /packages/absurd-web-backend/src/worker/DB.worker.ts: -------------------------------------------------------------------------------- 1 | import { 2 | buildSyncQueryRunner, 3 | initJobsState, 4 | IPrimitiveValue, 5 | IQuery, 6 | ITransactionOpts, 7 | whenAllJobsDone, 8 | } from "@kikko-land/kikko"; 9 | import * as Comlink from "comlink"; 10 | 11 | import { DbBackend } from "./DbBackend"; 12 | 13 | let db: DbBackend | undefined; 14 | 15 | const jobsState = initJobsState(); 16 | 17 | let isStopped = false; 18 | 19 | const initialize = async ( 20 | dbName: string, 21 | wasmUrl: string, 22 | pageSize: number, 23 | cacheSize: number 24 | ) => { 25 | if (db) { 26 | // TODO: send error response 27 | throw new Error("DB already initialized!"); 28 | } 29 | 30 | db = new DbBackend(dbName, wasmUrl, pageSize, cacheSize); 31 | 32 | await db.init(); 33 | }; 34 | 35 | const queriesRunner = buildSyncQueryRunner({ 36 | execPrepared: (query: IQuery, preparedValues: IPrimitiveValue[][]) => { 37 | if (!db) { 38 | throw new Error("DB not initialized!"); 39 | } 40 | 41 | return db.execPrepared(query.text, preparedValues); 42 | }, 43 | execUsual: (q: IQuery) => { 44 | if (!db) { 45 | throw new Error("DB not initialized!"); 46 | } 47 | 48 | return db.sqlExec(q.text, q.values); 49 | }, 50 | rollback: () => { 51 | if (!db) { 52 | throw new Error("DB not initialized!"); 53 | } 54 | 55 | db.sqlExec("ROLLBACK"); 56 | }, 57 | }); 58 | 59 | const runQueries = async ( 60 | queries: 61 | | { type: "usual"; values: IQuery[] } 62 | | { type: "prepared"; query: IQuery; preparedValues: IPrimitiveValue[][] }, 63 | sentAt: number, 64 | transactionOpts?: ITransactionOpts 65 | ) => { 66 | if (isStopped) { 67 | throw new Error("DB is stopped!"); 68 | } 69 | 70 | if (!db) { 71 | throw new Error("DB not initialized!"); 72 | } 73 | 74 | const sendTime = new Date().getTime() - sentAt; 75 | 76 | const res = await queriesRunner.run(jobsState, queries, transactionOpts); 77 | 78 | return { 79 | ...res, 80 | performance: { 81 | ...res.performance, 82 | sendTime, 83 | }, 84 | sentAt: new Date().getTime(), 85 | }; 86 | }; 87 | 88 | const stop = async () => { 89 | isStopped = true; 90 | 91 | await whenAllJobsDone(jobsState); 92 | }; 93 | 94 | const DbWorker = { runQueries, initialize, stop }; 95 | 96 | Comlink.expose(DbWorker); 97 | 98 | export type DbWorker = typeof DbWorker; 99 | -------------------------------------------------------------------------------- /packages/kikko-doc/docs/backends/electron.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | slug: /backends/electron 4 | --- 5 | 6 | import Tabs from "@theme/Tabs"; 7 | import TabItem from "@theme/TabItem"; 8 | 9 | # Electron 10 | 11 | This backend uses [better-sqlite3](https://github.com/WiseLibs/better-sqlite3). 12 | 13 | This guide is for https://www.electronforge.io/ , but it still will be helpful if you have custom electron configuration. 14 | 15 | ## Installation 16 | 17 | Install Kikko packages : 18 | 19 | 20 | 21 | 22 | ```bash 23 | yarn add @kikko-land/sql.js @kikko-land/electron-better-sqlite3-backend 24 | ``` 25 | 26 | 27 | 28 | 29 | ```bash 30 | npm i -S @kikko-land/sql.js @kikko-land/electron-better-sqlite3-backend 31 | ``` 32 | 33 | 34 | 35 | 36 | Fix native modules webpack [issue](https://github.com/electron-userland/electron-forge/issues/2412) in `webpack.plugins.js`: 37 | 38 | ```js 39 | const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin"); 40 | // highlight-start 41 | const relocateLoader = require("@vercel/webpack-asset-relocator-loader"); 42 | // highlight-end 43 | 44 | module.exports = [ 45 | new ForkTsCheckerWebpackPlugin(), 46 | // highlight-start 47 | { 48 | apply(compiler) { 49 | compiler.hooks.compilation.tap( 50 | "webpack-asset-relocator-loader", 51 | (compilation) => { 52 | relocateLoader.initAssetCache(compilation, "native_modules"); 53 | } 54 | ); 55 | }, 56 | }, 57 | // highlight-end 58 | ]; 59 | ``` 60 | 61 | Add this to `preload.ts`: 62 | 63 | ```typescript 64 | // See https://github.com/import-js/eslint-plugin-import/issues/1810 65 | // eslint-disable-next-line import/no-unresolved 66 | import { initSqliteBridge } from "@kikko-land/electron-better-sqlite3-backend/preload"; 67 | 68 | initSqliteBridge(); 69 | ``` 70 | 71 | And init Kikko: 72 | 73 | ```tsx 74 | import { electronBetterSqlite3Backend } from "@kikko-land/electron-better-sqlite3-backend"; 75 | 76 | const config: IInitDbClientConfig = { 77 | dbName: "helloWorld", 78 | dbBackend: electronBetterSqlite3Backend((dbName) => `${dbName}.db`), 79 | plugins: [migrationsPlugin({ migrations: [] }), reactiveQueriesPlugin()], 80 | }; 81 | ``` 82 | 83 | Usage example repo: https://github.com/kikko-land/kikko-electron-better-sqlite3-example 84 | -------------------------------------------------------------------------------- /packages/kikko-doc/docusaurus.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // Note: type annotations allow type checking and IDEs autocompletion 3 | 4 | const lightCodeTheme = require("prism-react-renderer/themes/github"); 5 | const darkCodeTheme = require("prism-react-renderer/themes/dracula"); 6 | 7 | /** @type {import('@docusaurus/types').Config} */ 8 | const config = { 9 | title: "Kikko", 10 | tagline: "Kikko", 11 | url: "https://kikko-doc.netlify.app", 12 | baseUrl: "/", 13 | onBrokenLinks: "throw", 14 | onBrokenMarkdownLinks: "warn", 15 | 16 | // GitHub pages deployment config. 17 | // If you aren't using GitHub pages, you don't need these. 18 | organizationName: "Kikko", // Usually your GitHub org/user name. 19 | projectName: "kikko", // Usually your repo name. 20 | 21 | // Even if you don't use internalization, you can use this field to set useful 22 | // metadata like html lang. For example, if your site is Chinese, you may want 23 | // to replace "en" with "zh-Hans". 24 | i18n: { 25 | defaultLocale: "en", 26 | locales: ["en"], 27 | }, 28 | 29 | presets: [ 30 | [ 31 | "classic", 32 | /** @type {import('@docusaurus/preset-classic').Options} */ 33 | ({ 34 | docs: { 35 | routeBasePath: "/", 36 | sidebarPath: require.resolve("./sidebars.js"), 37 | // Please change this to your repo. 38 | // Remove this to remove the "edit this page" links. 39 | editUrl: 40 | "https://github.com/kikko-land/kikko/tree/main/packages/kikko-doc", 41 | }, 42 | blog: false, 43 | theme: { 44 | customCss: require.resolve("./src/css/custom.css"), 45 | }, 46 | }), 47 | ], 48 | ], 49 | 50 | themeConfig: 51 | /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ 52 | ({ 53 | colorMode: { 54 | defaultMode: "dark", 55 | }, 56 | navbar: { 57 | title: "Kikko Doc", 58 | items: [ 59 | { 60 | href: "https://github.com/kikko-land/kikko", 61 | label: "GitHub", 62 | position: "right", 63 | }, 64 | ], 65 | }, 66 | footer: { 67 | style: "dark", 68 | copyright: `Copyright © ${new Date().getFullYear()} Popov Sergey`, 69 | }, 70 | prism: { 71 | theme: lightCodeTheme, 72 | darkTheme: darkCodeTheme, 73 | }, 74 | }), 75 | }; 76 | 77 | module.exports = config; 78 | -------------------------------------------------------------------------------- /packages/kikko-doc/docs/plugins/reactivePlugin.md: -------------------------------------------------------------------------------- 1 | import Tabs from "@theme/Tabs"; 2 | import TabItem from "@theme/TabItem"; 3 | 4 | # Reactive queries plugin 5 | 6 | ## Installation And Usage 7 | 8 | Install it: 9 | 10 | 11 | 12 | 13 | ```bash 14 | yarn add @kikko-land/reactive-queries-plugin 15 | ``` 16 | 17 | 18 | 19 | 20 | ```bash 21 | npm i -S @kikko-land/reactive-queries-plugin 22 | ``` 23 | 24 | 25 | 26 | 27 | Add this plugin to initDb: 28 | 29 | ```ts 30 | const db = await initDbClient({ 31 | dbName: "helloWorld4", 32 | dbBackend: absurdWebBackend({ 33 | wasmUrl: "https://kikko-doc.netlify.app/wasm/sql-wasm.wasm", 34 | }), 35 | plugins: [reactiveQueriesPlugin()], 36 | }); 37 | ``` 38 | 39 | And then listen your queries: 40 | 41 | ```typescript 42 | const unsubscribe = listenQueries(db, [sql`SELECT * FROM ${sql.table`notes`}`], (res) => { 43 | console.log("Queries result: ", res); 44 | }); 45 | 46 | // You can also unsubscribe lately 47 | setTimeout(() => { 48 | unsubscribe(); 49 | }, 1000); 50 | ``` 51 | 52 | CodeSandbox example: 53 | 54 | 60 | 61 | ## How reactivity works 62 | 63 | This plugin gathers information about which tables are used when you build queries. 64 | 65 | ```typescript 66 | console.log( 67 | sql`SELECT * FROM ${sql.table`notes`} WHERE id = (SELECT noteId FROM ${ 68 | sql.table`comments` 69 | )} LIMIT 1)`.tables.map(({ name }) => name) 70 | ); 71 | // => ["notes", "comments"] 72 | ``` 73 | 74 | `reactive-plugin` will hook on each query run 75 | and determine if read or write query will be executed by SQLite. 76 | When write query finished executing, `reactive-plugin` will notify all other tabs (using [broadcast-channel](https://github.com/pubkey/broadcast-channel)) which tables were changed. 77 | Then all queries that are subscribed to changed tables will be notified. 78 | -------------------------------------------------------------------------------- /packages/vite-react-example/src/benchmark/AppBenchmark.tsx: -------------------------------------------------------------------------------- 1 | import { absurdWebBackend } from "@kikko-land/absurd-web-backend"; 2 | import { 3 | DbProvider, 4 | EnsureDbLoaded, 5 | IInitDbClientConfig, 6 | makeId, 7 | migrationsPlugin, 8 | } from "@kikko-land/react"; 9 | import absurdSqlWasmUrl from "@kikko-land/sql.js/dist/sql-wasm.wasm?url"; 10 | import { waSqliteWebBackend } from "@kikko-land/wa-sqlite-web-backend"; 11 | import { useMemo } from "react"; 12 | import { useLocation } from "react-use"; 13 | import sqlWasmUrl from "wa-sqlite/dist/wa-sqlite-async.wasm?url"; 14 | 15 | import { createKVMigration } from "./../migrations/createKV"; 16 | import { Benchmark } from "./Benchmark"; 17 | 18 | const buildConfig = (config: IBackendConfig): IInitDbClientConfig => { 19 | return { 20 | dbName: `benchmark-${config.type}-${makeId().slice(0, 5)}`, 21 | dbBackend: 22 | config.type === "absurd" 23 | ? absurdWebBackend({ 24 | wasmUrl: absurdSqlWasmUrl, 25 | pageSize: 8 * 1024, 26 | cacheSize: -100, 27 | }) 28 | : waSqliteWebBackend({ 29 | wasmUrl: sqlWasmUrl, 30 | pageSize: 8 * 1024, 31 | cacheSize: -100, 32 | }), 33 | plugins: [ 34 | migrationsPlugin({ 35 | migrations: [createKVMigration], 36 | }), 37 | ], 38 | }; 39 | }; 40 | 41 | export type IBackendConfig = { type: "absurd" } | { type: "wa-sqlite" }; 42 | 43 | function parseQuery(queryString: string) { 44 | const query: Record = {}; 45 | const pairs = ( 46 | queryString[0] === "?" ? queryString.substr(1) : queryString 47 | ).split("&"); 48 | 49 | for (let i = 0; i < pairs.length; i++) { 50 | const pair = pairs[i].split("="); 51 | 52 | query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || ""); 53 | } 54 | return query; 55 | } 56 | 57 | export const backendOptions = { 58 | absurd: { type: "absurd" }, 59 | waMinimal: { 60 | type: "wa-sqlite", 61 | }, 62 | } as const; 63 | 64 | export const AppBenchmark = () => { 65 | const backendName = (parseQuery(useLocation().search || "")["backend"] || 66 | "waMinimal") as keyof typeof backendOptions; 67 | 68 | const config = useMemo(() => { 69 | return buildConfig(backendOptions[backendName || "waMinimal"]); 70 | }, [backendName]); 71 | 72 | return ( 73 | 74 | Loading db...}> 75 | 76 | 77 | 78 | ); 79 | }; 80 | -------------------------------------------------------------------------------- /packages/kikko-doc/docs/backends/web.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | slug: /backends/web 4 | --- 5 | 6 | import Tabs from "@theme/Tabs"; 7 | import TabItem from "@theme/TabItem"; 8 | 9 | # Web 10 | 11 | This backend uses [better-absurd-sql](https://github.com/kikko-land/better-absurd-sql). 12 | 13 | 14 | 15 | 16 | ```bash 17 | yarn add @kikko-land/sql.js @kikko-land/absurd-web-backend 18 | ``` 19 | 20 | 21 | 22 | 23 | ```bash 24 | npm i -S @kikko-land/sql.js @kikko-land/absurd-web-backend 25 | ``` 26 | 27 | 28 | 29 | 30 | Then configure Kikko: 31 | 32 | ```typescript 33 | import { absurdWebBackend } from "@kikko-land/absurd-web-backend"; 34 | // For Vite: 35 | import sqlWasmUrl from "@kikko-land/sql.js/dist/sql-wasm.wasm?url"; 36 | // For CRA: 37 | // import sqlWasmUrl from "@kikko-land/sql.js/dist/sql-wasm.wasm"; 38 | 39 | const config: IInitDbClientConfig = { 40 | dbName: "db-name", 41 | dbBackend: absurdWebBackend({ 42 | wasmUrl: sqlWasmUrl, 43 | }), 44 | plugins: [migrationsPlugin({ migrations: [] }), reactiveQueriesPlugin()], 45 | }; 46 | ``` 47 | 48 | It uses migration plugin. Is is useful when you need to run queries(like table creation) on app start and only once. 49 | 50 | ## Configuration and usage with Vite 51 | 52 | For vite add this to vite config: 53 | 54 | ```typescript 55 | export default defineConfig({ 56 | server: { 57 | headers: { 58 | "Cross-Origin-Embedder-Policy": "require-corp", 59 | "Cross-Origin-Opener-Policy": "same-origin", 60 | }, 61 | }, 62 | }); 63 | ``` 64 | 65 | Also to import wasm use this code: 66 | 67 | ```typescript 68 | import sqlWasmUrl from "@kikko-land/sql.js/dist/sql-wasm.wasm?url"; 69 | ``` 70 | 71 | Code example for react + vite: https://github.com/kikko-land/kikko/tree/main/packages/vite-react-example 72 | 73 | Code example for vue + tauri + vite: [https://github.com/kikko-land/kikko/tree/main/packages/vite-react-example](https://github.com/kikko-land/kikko-tauri-vue) 74 | 75 | ## Configuration and usage with create-react-app 76 | 77 | Create `src/setupProxy.js`: 78 | 79 | ```javascript 80 | module.exports = function (app) { 81 | app.use(function (req, res, next) { 82 | res.setHeader("Cross-Origin-Opener-Policy", "same-origin"); 83 | res.setHeader("Cross-Origin-Embedder-Policy", "require-corp"); 84 | next(); 85 | }); 86 | }; 87 | ``` 88 | 89 | Also to import wasm use this code: 90 | 91 | ```typescript 92 | import sqlWasmUrl from "@kikko-land/sql.js/dist/sql-wasm.wasm"; 93 | ``` 94 | 95 | Code example: https://github.com/kikko-land/kikko-cra-example 96 | -------------------------------------------------------------------------------- /packages/absurd-web-backend/src/absurdWebBackend.ts: -------------------------------------------------------------------------------- 1 | import { initBackend } from "@kikko-land/better-absurd-sql/dist/indexeddb-main-thread"; 2 | import { 3 | getTime, 4 | IDbBackend, 5 | IPrimitiveValue, 6 | IQuery, 7 | ITransactionOpts, 8 | reactiveVar, 9 | } from "@kikko-land/kikko"; 10 | import * as Comlink from "comlink"; 11 | 12 | import type { DbWorker } from "./worker/DB.worker"; 13 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 14 | // @ts-ignore 15 | import RawWorker from "./worker/DB.worker?worker&inline"; 16 | 17 | export const absurdWebBackend = 18 | ({ 19 | wasmUrl, 20 | pageSize, 21 | cacheSize, 22 | }: { 23 | wasmUrl: string | (() => Promise); 24 | 25 | queryTimeout?: number; 26 | pageSize?: number; 27 | cacheSize?: number; 28 | }): IDbBackend => 29 | ({ dbName }: { dbName: string }) => { 30 | // eslint-disable-next-line @typescript-eslint/no-unsafe-call 31 | const rawWorker: Worker = new RawWorker() as Worker; 32 | const isTerminated = reactiveVar(false, { label: "isTerminated" }); 33 | 34 | const dbWorker = Comlink.wrap(rawWorker); 35 | 36 | return { 37 | async initialize() { 38 | if (isTerminated.value) throw new Error("Db backend is terminated"); 39 | 40 | initBackend(rawWorker); 41 | 42 | const url = typeof wasmUrl === "string" ? wasmUrl : await wasmUrl(); 43 | 44 | await dbWorker.initialize( 45 | dbName, 46 | new URL(url, document.baseURI).toString(), 47 | pageSize !== undefined ? pageSize : 32 * 1024, 48 | cacheSize !== undefined ? cacheSize : -5000 49 | ); 50 | }, 51 | async execQueries( 52 | q: 53 | | { type: "usual"; values: IQuery[] } 54 | | { 55 | type: "prepared"; 56 | query: IQuery; 57 | preparedValues: IPrimitiveValue[][]; 58 | }, 59 | transactionOpts?: ITransactionOpts 60 | ) { 61 | const startedAt = getTime(); 62 | const res = await dbWorker.runQueries( 63 | q, 64 | new Date().getTime(), 65 | transactionOpts 66 | ); 67 | const endAt = getTime(); 68 | 69 | return { 70 | result: res.result, 71 | performance: { 72 | ...res.performance, 73 | receiveTime: new Date().getTime() - res.sentAt, 74 | totalTime: endAt - startedAt, 75 | }, 76 | }; 77 | }, 78 | async stop() { 79 | isTerminated.value = true; 80 | 81 | await dbWorker.stop(); 82 | rawWorker.terminate(); 83 | }, 84 | }; 85 | }; 86 | -------------------------------------------------------------------------------- /packages/d1-example/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to Cloudflare Workers! This is your first worker. 3 | * 4 | * - Run `wrangler dev src/index.ts` in your terminal to start a development server 5 | * - Open a browser tab at http://localhost:8787/ to see your worker in action 6 | * - Run `wrangler publish src/index.ts --name my-worker` to publish your worker 7 | * 8 | * Learn more at https://developers.cloudflare.com/workers/ 9 | */ 10 | 11 | import { d1Backend } from "@kikko-land/d1-backend"; 12 | import { initDbClient, makeId, sql } from "@kikko-land/kikko"; 13 | import { 14 | atomicMigrationsPlugin, 15 | IAtomicMigration, 16 | } from "@kikko-land/migrations-plugin"; 17 | 18 | export interface Env { 19 | DB: D1Database; 20 | } 21 | 22 | const createCustomers: IAtomicMigration = { 23 | up: (tr) => { 24 | tr.addQuery( 25 | sql` 26 | CREATE TABLE IF NOT EXISTS Customers (CustomerID INT, CompanyName TEXT, ContactName TEXT, PRIMARY KEY (CustomerID)); 27 | ` 28 | ); 29 | 30 | tr.addQuery( 31 | sql`INSERT INTO Customers (CustomerID, CompanyName, ContactName) VALUES (1, 'Alfreds Futterkiste', 'Maria Anders'),(4, 'Around the Horn', 'Thomas Hardy'),(11, 'Bs Beverages', 'Victoria Ashworth'),(13, 'Bs Beverages', 'Random Name')` 32 | ); 33 | }, 34 | id: 1653668686076, 35 | name: "createCustomers", 36 | }; 37 | 38 | const initDb = (db: D1Database) => 39 | initDbClient({ 40 | dbName: "helloWorld4", 41 | dbBackend: d1Backend({ db }), 42 | plugins: [atomicMigrationsPlugin({ migrations: [createCustomers] })], 43 | }); 44 | 45 | export default { 46 | async fetch(request: Request, env: Env): Promise { 47 | const db = await initDb(env.DB); 48 | const id = makeId(); 49 | 50 | await db.runInAtomicTransaction(async (tr) => { 51 | // For example purpose, you can run async function insied of transaction 52 | await new Promise((resolve) => setTimeout(resolve, 1000, "")); 53 | 54 | // You can also execute query inside of tr(query will be not added to transaction queue) 55 | 56 | const [lastCustomer] = await db.runQuery<{ 57 | CustomerID: string; 58 | CompanyName: string; 59 | ContactName: string; 60 | }>(sql`SELECT * FROM Customers ORDER BY rowid DESC LIMIT 1`); 61 | 62 | tr.addQuery( 63 | // All variables inside ${} will be automatically binded to query 64 | sql`INSERT INTO Customers (CustomerID, CompanyName, ContactName) VALUES (${id}, ${`${lastCustomer.CompanyName}#${id}`}, ${`${lastCustomer.ContactName}#${id}`})` 65 | ); 66 | }); 67 | 68 | return Response.json(await db.runQuery(sql`SELECT * FROM Customers`)); 69 | }, 70 | }; 71 | -------------------------------------------------------------------------------- /packages/reactive-queries-plugin/src/getBroadcastCh.ts: -------------------------------------------------------------------------------- 1 | import { ReactiveVar, reactiveVar } from "@kikko-land/kikko"; 2 | 3 | export type IMessage = { changesInTables: string[] }; 4 | export type IListener = (msg: IMessage) => void; 5 | export interface INotifyChannel { 6 | postMessage(msg: IMessage): Promise; 7 | addEventListener(cb: IListener): void; 8 | removeEventListener(cb: IListener): void; 9 | close(): Promise; 10 | } 11 | 12 | const createMultiTabChannel = async ( 13 | name: string, 14 | webMultiTabSupport: boolean 15 | ): Promise => { 16 | const webChannel = await (async () => { 17 | if (!webMultiTabSupport) return undefined; 18 | 19 | return new (await import("broadcast-channel")).BroadcastChannel(name, { 20 | type: "localstorage", 21 | webWorkerSupport: false, 22 | // idb: { 23 | // onclose: () => { 24 | // // the onclose event is just the IndexedDB closing. 25 | // // you should also close the channel before creating 26 | // // a new one. 27 | // void currentChannel?.close(); 28 | // createChannel(); 29 | // }, 30 | // }, 31 | }); 32 | })(); 33 | 34 | let listeners: IListener[] = []; 35 | 36 | return { 37 | async postMessage(data) { 38 | listeners.forEach((l) => { 39 | l(data); 40 | }); 41 | 42 | if (webChannel) { 43 | await webChannel.postMessage(data); 44 | } 45 | }, 46 | addEventListener(cb) { 47 | listeners.push(cb); 48 | 49 | webChannel?.addEventListener("message", cb); 50 | }, 51 | removeEventListener(cb) { 52 | listeners = listeners.filter((l) => l !== cb); 53 | 54 | webChannel?.removeEventListener("message", cb); 55 | }, 56 | async close() { 57 | listeners = []; 58 | 59 | if (webChannel) { 60 | await webChannel.close(); 61 | } 62 | }, 63 | }; 64 | }; 65 | 66 | export const getBroadcastCh = ( 67 | name: string, 68 | webMultiTabSupport: boolean, 69 | rDbState: ReactiveVar<"running" | "stopping" | "stopped"> 70 | ) => { 71 | const rCh = reactiveVar(undefined, { 72 | label: "notifyChannel", 73 | }); 74 | 75 | let isClosed = false; 76 | let currentChannel: INotifyChannel | undefined; 77 | 78 | const init = async () => { 79 | const ch = await createMultiTabChannel(name, webMultiTabSupport); 80 | 81 | if (isClosed) return; 82 | 83 | rCh.value = ch; 84 | }; 85 | 86 | void init(); 87 | 88 | void (async () => { 89 | await rDbState.waitTill((v) => v === "stopping", { timeout: "infinite" }); 90 | 91 | isClosed = true; 92 | void currentChannel?.close(); 93 | })(); 94 | 95 | return rCh; 96 | }; 97 | -------------------------------------------------------------------------------- /packages/wa-sqlite-backend/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | dist 5 | preload-dist 6 | tmp 7 | out-tsc 8 | 9 | # dependencies 10 | /node_modules 11 | 12 | # IDEs and editors 13 | /.idea 14 | .project 15 | .classpath 16 | .c9/ 17 | *.launch 18 | .settings/ 19 | *.sublime-workspace 20 | 21 | # IDE - VSCode 22 | .vscode/* 23 | !.vscode/settings.json 24 | !.vscode/tasks.json 25 | !.vscode/launch.json 26 | !.vscode/extensions.json 27 | 28 | # misc 29 | /.sass-cache 30 | /connect.lock 31 | /coverage 32 | /libpeerconnection.log 33 | npm-debug.log 34 | yarn-error.log 35 | testem.log 36 | /typings 37 | 38 | # System Files 39 | .DS_Store 40 | Thumbs.db 41 | 42 | # React Native 43 | 44 | ## Xcode 45 | 46 | **/ios/**/build/ 47 | **/ios/**/*.pbxuser 48 | !default.pbxuser 49 | *.mode1v3 50 | !default.mode1v3 51 | *.mode2v3 52 | !default.mode2v3 53 | *.perspectivev3 54 | !default.perspectivev3 55 | xcuserdata 56 | *.xccheckout 57 | *.moved-aside 58 | DerivedData 59 | *.hmap 60 | *.ipa 61 | *.xcuserstate 62 | 63 | ## Android 64 | 65 | **/android/**/build/ 66 | **/android/**/.gradle 67 | **/android/**/local.properties 68 | **/android/**/*.iml 69 | 70 | ## BUCK 71 | 72 | buck-out/ 73 | \.buckd/ 74 | *.keystore 75 | !debug.keystore 76 | 77 | ## fastlane 78 | # 79 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlan to re-generate the 80 | # screenshots whenever they are needed. 81 | # For more information about the recommended setup visit: 82 | # https://docs.fastlane.tools/best-practices/source-control/ 83 | # 84 | */fastlane/report.xml 85 | */fastlane/Preview.html 86 | */fastlane/screenshots 87 | 88 | ## Bundle artifact 89 | *.jsbundle 90 | 91 | ## CocoaPods 92 | **/ios/Pods/ 93 | / 94 | 95 | ## Nested node_modules 96 | 97 | node_modules/ 98 | 99 | # The directory Mix will write compiled artifacts to. 100 | **/_build/ 101 | 102 | # If you run "mix test --cover", coverage assets end up here. 103 | **/cover/ 104 | 105 | # The directory Mix downloads your dependencies sources to. 106 | **/deps/ 107 | 108 | # Where 3rd-party dependencies like ExDoc output generated docs. 109 | **/doc/ 110 | 111 | # Ignore .fetch files in case you like to edit your project deps locally. 112 | **/.fetch 113 | 114 | # If the VM crashes, it generates a dump, let's ignore it too. 115 | **/erl_crash.dump 116 | 117 | # Also ignore archive artifacts (built via "mix archive.build"). 118 | *.ez 119 | 120 | # Ignore package tarball (built via "mix hex.build"). 121 | **/harika-*.tar 122 | 123 | # Since we are building assets from assets/, 124 | # we ignore priv/static. You may want to comment 125 | # this depending on your deployment strategy. 126 | **/priv/static/ 127 | 128 | .DS_Store 129 | coverage 130 | .vim 131 | .vscode 132 | .keys 133 | app.yaml 134 | .firebase 135 | 136 | docker-compose.ymle 137 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | .turbo 4 | 5 | # compiled output 6 | dist 7 | preload-dist 8 | tmp 9 | out-tsc 10 | 11 | # dependencies 12 | /node_modules 13 | 14 | # IDEs and editors 15 | /.idea 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # IDE - VSCode 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | 30 | # misc 31 | /.sass-cache 32 | /connect.lock 33 | /coverage 34 | /libpeerconnection.log 35 | npm-debug.log 36 | yarn-error.log 37 | testem.log 38 | /typings 39 | 40 | # System Files 41 | .DS_Store 42 | Thumbs.db 43 | 44 | # React Native 45 | 46 | ## Xcode 47 | 48 | **/ios/**/build/ 49 | **/ios/**/*.pbxuser 50 | !default.pbxuser 51 | *.mode1v3 52 | !default.mode1v3 53 | *.mode2v3 54 | !default.mode2v3 55 | *.perspectivev3 56 | !default.perspectivev3 57 | xcuserdata 58 | *.xccheckout 59 | *.moved-aside 60 | DerivedData 61 | *.hmap 62 | *.ipa 63 | *.xcuserstate 64 | 65 | ## Android 66 | 67 | **/android/**/build/ 68 | **/android/**/.gradle 69 | **/android/**/local.properties 70 | **/android/**/*.iml 71 | 72 | ## BUCK 73 | 74 | buck-out/ 75 | \.buckd/ 76 | *.keystore 77 | !debug.keystore 78 | 79 | ## fastlane 80 | # 81 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlan to re-generate the 82 | # screenshots whenever they are needed. 83 | # For more information about the recommended setup visit: 84 | # https://docs.fastlane.tools/best-practices/source-control/ 85 | # 86 | */fastlane/report.xml 87 | */fastlane/Preview.html 88 | */fastlane/screenshots 89 | 90 | ## Bundle artifact 91 | *.jsbundle 92 | 93 | ## CocoaPods 94 | **/ios/Pods/ 95 | / 96 | 97 | ## Nested node_modules 98 | 99 | node_modules/ 100 | 101 | # The directory Mix will write compiled artifacts to. 102 | **/_build/ 103 | 104 | # If you run "mix test --cover", coverage assets end up here. 105 | **/cover/ 106 | 107 | # The directory Mix downloads your dependencies sources to. 108 | **/deps/ 109 | 110 | # Where 3rd-party dependencies like ExDoc output generated docs. 111 | **/doc/ 112 | 113 | # Ignore .fetch files in case you like to edit your project deps locally. 114 | **/.fetch 115 | 116 | # If the VM crashes, it generates a dump, let's ignore it too. 117 | **/erl_crash.dump 118 | 119 | # Also ignore archive artifacts (built via "mix archive.build"). 120 | *.ez 121 | 122 | # Ignore package tarball (built via "mix hex.build"). 123 | **/harika-*.tar 124 | 125 | # Since we are building assets from assets/, 126 | # we ignore priv/static. You may want to comment 127 | # this depending on your deployment strategy. 128 | **/priv/static/ 129 | 130 | .DS_Store 131 | coverage 132 | .vim 133 | .vscode 134 | .keys 135 | app.yaml 136 | .firebase 137 | 138 | docker-compose.ymle 139 | 140 | .wrangler 141 | -------------------------------------------------------------------------------- /packages/kikko-doc/docs/reactIntegration/installationAndUsage.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | slug: /react-integration/installation 4 | --- 5 | 6 | import Tabs from "@theme/Tabs"; 7 | import TabItem from "@theme/TabItem"; 8 | 9 | # Installation And Usage 10 | 11 | Install core packages: 12 | 13 | 14 | 15 | 16 | ```bash 17 | yarn add @kikko-land/react 18 | ``` 19 | 20 | 21 | 22 | 23 | ```bash 24 | npm i -S @kikko-land/react 25 | ``` 26 | 27 | 28 | 29 | 30 | You also need to install and configure SQLite backend you need. Please, checkout [backend section](/backends/web) in the doc for more info. 31 | 32 | After wrap the whole app with this components(usage example for vite web): 33 | 34 | ```tsx 35 | import { absurdWebBackend } from "@kikko-land/absurd-web-backend"; 36 | import { DbProvider, EnsureDbLoaded } from "@kikko-land/react"; 37 | import sqlWasmUrl from "@kikko-land/sql.js/dist/sql-wasm.wasm?url"; 38 | 39 | const createNotesTableMigration: IMigration = { 40 | up: async (db) => { 41 | await db.runQuery( 42 | sql`CREATE TABLE notes (id varchar(20) PRIMARY KEY, title TEXT NOT NULL);` 43 | ); 44 | }, 45 | id: 18, 46 | name: "createNotesTable", 47 | }; 48 | 49 | const config: IInitDbClientConfig = { 50 | dbName: "db-name", 51 | dbBackend: absurdWebBackend({ 52 | wasmUrl: sqlWasmUrl, 53 | }), 54 | plugins: [ 55 | migrationsPlugin({ migrations: [createNotesTableMigration] }), 56 | reactiveQueriesPlugin(), 57 | ], 58 | }; 59 | 60 | export const App = () => ( 61 | 62 | Loading db...}> 63 | 64 | 65 | 66 | ); 67 | ``` 68 | 69 | Then use it in your child components: 70 | 71 | ```tsx 72 | import { 73 | useDbQuery, 74 | useFirstRowDbQuery, 75 | useRunDbQuery, 76 | makeId, 77 | runQuery, 78 | sql 79 | } from "@kikko-land/react"; 80 | 81 | type Note = { id: string; title: string }; 82 | const notesTable = sql.table`notes`; 83 | 84 | export const Notes = () => { 85 | const notes = useDbQuery(sql`SELECT * FROM ${notesTable}`); 86 | const notesCount = useFirstRowDbQuery<{ count: number }>( 87 | sql`SELECT COUNT(*) FROM ${notesTable}` 88 | ); 89 | 90 | const addNote = useRunDbQuery((db) => async () => { 91 | const id = makeId(); 92 | 93 | await db.runQuery( 94 | sql`INSERT INTO ${notesTable}(id, title) VALUES(${id}, ${`Note#${id}`})` 95 | ); 96 | }); 97 | 98 | return ( 99 | <> 100 | 101 |
Add note result: {addNote.state.value}
102 |
Query result (total notes count: {notesCount.data?.count})
103 |
{JSON.stringify(notes)}
104 | 105 | ); 106 | }; 107 | ``` 108 | -------------------------------------------------------------------------------- /packages/common-scripts/src/publish.ts: -------------------------------------------------------------------------------- 1 | import { spawn } from "child_process"; 2 | import path from "path"; 3 | import { readFile, writeFile, readdir } from "fs/promises"; 4 | import { resolve } from "path"; 5 | import { cwd } from "process"; 6 | import { PackageJson } from "type-fest"; 7 | import { unlink, rename } from "fs/promises"; 8 | import { existsSync } from "fs"; 9 | 10 | const runCommand = async ( 11 | cwd: string, 12 | command: string, 13 | args: string[], 14 | beforeRun?: () => Promise, 15 | afterRun?: () => Promise 16 | ) => { 17 | console.log( 18 | `\nRunning "${command} ${args.join(" ")}" for ${path.basename(cwd)}:` 19 | ); 20 | if (beforeRun) { 21 | await beforeRun(); 22 | } 23 | 24 | try { 25 | await new Promise((resolve) => { 26 | spawn(command, args, { cwd, stdio: "inherit" }).on("exit", async function( 27 | error 28 | ) { 29 | if (error) { 30 | if (afterRun) { 31 | await afterRun(); 32 | } 33 | 34 | console.log(`Failed to run ${command} at ${cwd}`); 35 | process.exit(1); 36 | } 37 | 38 | resolve(); 39 | }); 40 | }); 41 | } finally { 42 | if (afterRun) { 43 | await afterRun(); 44 | } 45 | } 46 | }; 47 | 48 | const getPackages = async () => { 49 | const exceptPackages = ["vite-react-example", "kikko-doc"]; 50 | const packagesPath = resolve(cwd(), ".."); 51 | 52 | return (await readdir(resolve(packagesPath), { withFileTypes: true })) 53 | .filter((w) => w.isDirectory() && !exceptPackages.includes(w.name)) 54 | .map((w) => ({ 55 | name: `@kikko-land/${w.name}`, 56 | dir: `${packagesPath}/${w.name}`, 57 | })); 58 | }; 59 | 60 | const updateJson = async ( 61 | file: string, 62 | cb: (arg: PackageJson) => PackageJson, 63 | backup = false 64 | ) => { 65 | const content = (await readFile(file)).toString(); 66 | 67 | if (backup) { 68 | await writeFile(file + ".backup", content); 69 | } 70 | 71 | const packageContent = JSON.parse(content); 72 | 73 | await writeFile(file, JSON.stringify(cb(packageContent), undefined, 2)); 74 | }; 75 | 76 | const run = async () => { 77 | const packages = await getPackages(); 78 | 79 | runCommand( 80 | resolve(cwd(), "..", ".."), 81 | "yarn", 82 | ["changeset", "publish"], 83 | async () => { 84 | packages.map(async ({ dir }) => { 85 | await updateJson( 86 | dir + "/package.json", 87 | (json) => { 88 | return { 89 | ...json, 90 | ...json["publishConfig"], 91 | } as PackageJson; 92 | }, 93 | true 94 | ); 95 | }); 96 | }, 97 | async () => { 98 | packages.map(async ({ dir }) => { 99 | if (!existsSync(dir + "/package.json.backup")) return; 100 | await unlink(dir + "/package.json"); 101 | await rename(dir + "/package.json.backup", dir + "/package.json"); 102 | }); 103 | } 104 | ); 105 | }; 106 | 107 | run(); 108 | -------------------------------------------------------------------------------- /packages/kikko-doc/docs/vueIntegration/installationAndUsage.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | slug: /vue-integration/installation 4 | --- 5 | 6 | import Tabs from "@theme/Tabs"; 7 | import TabItem from "@theme/TabItem"; 8 | 9 | # Installation And Usage 10 | 11 | Install core packages: 12 | 13 | 14 | 15 | 16 | ```bash 17 | yarn add @kikko-land/vue 18 | ``` 19 | 20 | 21 | 22 | 23 | ```bash 24 | npm i -S @kikko-land/vue 25 | ``` 26 | 27 | 28 | 29 | 30 | You also need to install and configure SQLite backend you need. Please, checkout [backend section](/backends/web) in the doc for more info. 31 | 32 | After create file `currentDb.ts` that will be storing the db state: 33 | 34 | ```ts 35 | import { Ref, shallowRef } from "vue"; 36 | import { IDbInitState } from "@kikko-land/vue"; 37 | 38 | export const currentDb = shallowRef({ 39 | type: "notInitialized", 40 | }) as Ref; 41 | ``` 42 | 43 | And in the root component initialize the db: 44 | 45 | ```html 46 | 76 | ``` 77 | 78 | And use it: 79 | 80 | ```html 81 | 109 | 110 | 116 | ``` 117 | -------------------------------------------------------------------------------- /packages/kikko/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @kikko-land/core 2 | 3 | ## 0.19.1 4 | 5 | ### Patch Changes 6 | 7 | - 39e9f77: Add srizzle orm support 8 | 9 | ## 0.19.0 10 | 11 | ### Minor Changes 12 | 13 | - 71c1bea: Upgrade boono-sql 14 | 15 | ## 0.18.0 16 | 17 | ### Minor Changes 18 | 19 | - eb496a0: Add Kysely support 20 | 21 | ## 0.17.0 22 | 23 | ### Minor Changes 24 | 25 | - 15a9a4d: Improve performance & error msg 26 | - a44c084: Add wa-sqlite backend 27 | 28 | ## 0.16.0 29 | 30 | ### Minor Changes 31 | 32 | - dc4ac77: Add custom query error 33 | - a0170a6: Introduce new backend API 34 | - bf55118: Improve performance of reactiveVar 35 | 36 | ## 0.15.0 37 | 38 | ### Minor Changes 39 | 40 | - c0ac90e: Use console.debug for queries logs 41 | 42 | ## 0.14.0 43 | 44 | ### Minor Changes 45 | 46 | - 0ac4b28: Use console.info for queries logs 47 | 48 | ## 0.13.0 49 | 50 | ### Minor Changes 51 | 52 | - 085297e: Fix memmory leak 53 | 54 | ## 0.12.0 55 | 56 | ### Minor Changes 57 | 58 | - fc7a4e2: Improve transactions handling 59 | 60 | ## 0.11.0 61 | 62 | ### Minor Changes 63 | 64 | - de4fd98: Increase job timeout time 65 | - d6204b9: Add preparedQueries support 66 | 67 | ## 0.10.0 68 | 69 | ### Minor Changes 70 | 71 | - e331160: Add custom log fns 72 | - 185ca8f: Version bump 73 | 74 | ## 0.9.0 75 | 76 | ### Minor Changes 77 | 78 | - 8ffc4e0: Rename atomicTtransaction -> runInAtomicTransaction 79 | 80 | ## 0.8.0 81 | 82 | ### Minor Changes 83 | 84 | - 8f1d753: Fix reactibity. Make useRunDbQuery in transaction by default 85 | 86 | ### Patch Changes 87 | 88 | - 90f46be: Use fast-equals instead of lodash.isequal 89 | 90 | ## 0.7.0 91 | 92 | ### Minor Changes 93 | 94 | - 9a1e9fc: Add new backend API 95 | 96 | ## 0.6.1 97 | 98 | ### Patch Changes 99 | 100 | - 2705e32: Fix typings in package.json 101 | 102 | ## 0.6.0 103 | 104 | ### Minor Changes 105 | 106 | - 087ab15: Fix types for @kikko-land/kikko 107 | 108 | ## 0.5.0 109 | 110 | ### Minor Changes 111 | 112 | - 056a744: Add new fluent api 113 | 114 | ## 0.4.0 115 | 116 | ### Minor Changes 117 | 118 | - a52a3cb: Upgrade packages 119 | 120 | ### Patch Changes 121 | 122 | - Updated dependencies [a52a3cb] 123 | - @kikko-land/query-builder@0.2.0 124 | - @kikko-land/sql@0.2.0 125 | 126 | ## 0.3.0 127 | 128 | ### Minor Changes 129 | 130 | - dd36c9e: Remove rxjs 131 | 132 | ## 0.2.1 133 | 134 | ### Patch Changes 135 | 136 | - 28c722e: Fix types 137 | 138 | ## 0.2.0 139 | 140 | ### Minor Changes 141 | 142 | - 174767c: Rename kikko to core 143 | 144 | ## 0.1.1 145 | 146 | ### Patch Changes 147 | 148 | - 81605a8: Trong renamed to kikko 149 | - Updated dependencies [81605a8] 150 | - @kikko-land/query-builder@0.1.1 151 | - @kikko-land/sql@0.1.1 152 | 153 | ## 1.3.1 154 | 155 | ### Patch Changes 156 | 157 | - 3c0419b: Releasing with changesets 158 | - Updated dependencies [3c0419b] 159 | - Updated dependencies 160 | - @kikko-land/query-builder@1.3.1 161 | - @kikko-land/sql@1.3.1 162 | 163 | ## 1.3.0 164 | 165 | ### Minor Changes 166 | 167 | - 63fa2da: Changeset package set 168 | 169 | ### Patch Changes 170 | 171 | - Updated dependencies [63fa2da] 172 | - @kikko-land/query-builder@1.3.0 173 | - @kikko-land/sql@1.3.0 174 | -------------------------------------------------------------------------------- /packages/kikko-doc/docs/core/usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | slug: /core/usage 4 | --- 5 | 6 | # Init and run queries 7 | 8 | You can use Kikko without react or any other libs integrations. 9 | 10 | Here is CodeSandbox with examples: 11 | 12 |