Compare commits

...

16 Commits

Author SHA1 Message Date
Joel Jeremy Marquez
a910e7b0ef yarn.lock 2026-01-08 10:48:44 -08:00
Joel Jeremy Marquez
15d7befceb Updates 2026-01-08 10:48:28 -08:00
Joel Jeremy Marquez
213db00660 oxfmtrc ignore packages/loot-core/drizzle 2026-01-08 10:48:09 -08:00
Joel Jeremy Marquez
84e0d0ffee Invoke PGLITE_SYNC on SQLite INSERT/UPDATE/DELETE 2026-01-08 10:48:09 -08:00
Joel Jeremy Marquez
72abea19dd Update schema 2026-01-08 10:48:09 -08:00
Joel Jeremy Marquez
20c3f3a26f Update schema 2026-01-08 10:48:09 -08:00
Joel Jeremy Marquez
a4b123486e Migrations update to use "actual" schema 2026-01-08 10:48:09 -08:00
Joel Jeremy Marquez
f1f4aab0c4 Update migration to use builtin PgDialect migrate 2026-01-08 10:47:58 -08:00
Joel Jeremy Marquez
0e759e4370 Update schema and add indeces 2026-01-08 10:47:58 -08:00
Joel Jeremy Marquez
8a88681135 Update drizzle migrations table 2026-01-08 10:47:58 -08:00
Joel Jeremy Marquez
1d216ca83f Update with indeces 2026-01-08 10:47:58 -08:00
Joel Jeremy Marquez
86dcd52a8b Remove pglite filter 2026-01-08 10:47:58 -08:00
Joel Jeremy Marquez
2dc7442466 Drizzle migrations 2026-01-08 10:47:58 -08:00
Joel Jeremy Marquez
ba9256a38b Set parsers and serializers on openDatabase 2026-01-08 10:47:58 -08:00
Joel Jeremy Marquez
3fd9809def Update migrations 2026-01-08 10:47:58 -08:00
Joel Jeremy Marquez
7053fc2f92 PGlite migrations 2026-01-08 10:47:58 -08:00
87 changed files with 48032 additions and 43 deletions

View File

@@ -5,6 +5,7 @@
"arrowParens": "avoid",
"printWidth": 80,
"ignorePatterns": [
"packages/loot-core/drizzle/**/*",
"packages/docs/*" // TOOD: fixme; temporary
]
}

View File

@@ -0,0 +1,16 @@
import { writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { readMigrationFiles } from 'drizzle-orm/migrator';
const lootCoreRootPath = fileURLToPath(new URL('..', import.meta.url));
const migrations = readMigrationFiles({ migrationsFolder: './drizzle/' });
await writeFile(
join(lootCoreRootPath, './drizzle/migrations.json'),
JSON.stringify(migrations),
);
console.log('Migrations compiled!');

View File

@@ -0,0 +1,12 @@
import { defineConfig } from 'drizzle-kit';
// eslint-disable-next-line import/no-default-export
export default defineConfig({
dialect: 'postgresql',
schema: './src/server/db/schema',
casing: 'snake_case',
strict: true,
introspect: {
casing: 'preserve',
},
});

View File

@@ -0,0 +1 @@
CREATE SCHEMA "actual";

View File

@@ -0,0 +1,8 @@
CREATE TABLE "actual"."banks" (
"id" varchar(36) PRIMARY KEY NOT NULL,
"name" text,
"bank_id" text,
"tombstone" boolean DEFAULT false
);
--> statement-breakpoint
CREATE INDEX "banks_bank_id_index" ON "actual"."banks" USING btree ("bank_id") WHERE "actual"."banks"."tombstone" IS FALSE;

View File

@@ -0,0 +1,25 @@
CREATE TABLE "actual"."accounts" (
"id" varchar(36) PRIMARY KEY NOT NULL,
"name" text,
"offbudget" boolean DEFAULT false,
"closed" boolean DEFAULT false,
"sort_order" bigint,
"account_id" text,
"balance_current" bigint,
"balance_available" bigint,
"balance_limit" bigint,
"mask" text,
"official_name" text,
"type" text,
"subtype" text,
"bank" varchar(36),
"account_sync_source" text,
"last_sync" bigint,
"last_reconciled" bigint,
"tombstone" boolean DEFAULT false
);
--> statement-breakpoint
ALTER TABLE "actual"."accounts" ADD CONSTRAINT "accounts_bank_banks_id_fk" FOREIGN KEY ("bank") REFERENCES "actual"."banks"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "accounts_name_index" ON "actual"."accounts" USING btree ("name") WHERE "actual"."accounts"."tombstone" IS FALSE;--> statement-breakpoint
CREATE INDEX "accounts_bank_index" ON "actual"."accounts" USING btree ("bank") WHERE "actual"."accounts"."tombstone" IS FALSE;--> statement-breakpoint
CREATE INDEX "accounts_sort_order_name_index" ON "actual"."accounts" USING btree ("sort_order","name");

View File

@@ -0,0 +1,12 @@
CREATE TABLE "actual"."category_groups" (
"id" varchar(36) PRIMARY KEY NOT NULL,
"name" text,
"is_income" boolean DEFAULT false,
"sort_order" bigint,
"hidden" boolean DEFAULT false,
"tombstone" boolean DEFAULT false
);
--> statement-breakpoint
CREATE INDEX "category_groups_name_index" ON "actual"."category_groups" USING btree ("name") WHERE "actual"."category_groups"."tombstone" IS FALSE;--> statement-breakpoint
CREATE INDEX "category_groups_is_income_sort_order_id_index" ON "actual"."category_groups" USING btree ("is_income","sort_order","id");--> statement-breakpoint
CREATE INDEX "category_groups_sort_order_id_index" ON "actual"."category_groups" USING btree ("sort_order","id");

View File

@@ -0,0 +1,16 @@
CREATE TABLE "actual"."categories" (
"id" varchar(36) PRIMARY KEY NOT NULL,
"name" text,
"is_income" boolean DEFAULT false,
"cat_group" varchar(36),
"sort_order" bigint,
"hidden" boolean DEFAULT false,
"goal_def" jsonb,
"tombstone" boolean DEFAULT false
);
--> statement-breakpoint
ALTER TABLE "actual"."categories" ADD CONSTRAINT "categories_cat_group_category_groups_id_fk" FOREIGN KEY ("cat_group") REFERENCES "actual"."category_groups"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "categories_name_index" ON "actual"."categories" USING btree ("name") WHERE "actual"."categories"."tombstone" IS FALSE;--> statement-breakpoint
CREATE INDEX "categories_cat_group_index" ON "actual"."categories" USING btree ("cat_group") WHERE "actual"."categories"."tombstone" IS FALSE;--> statement-breakpoint
CREATE INDEX "categories_sort_order_id_index" ON "actual"."categories" USING btree ("sort_order","id");--> statement-breakpoint
CREATE INDEX "categories_goal_def_index" ON "actual"."categories" USING btree ("goal_def" NULLS FIRST);

View File

@@ -0,0 +1,8 @@
CREATE TABLE "actual"."category_mapping" (
"id" varchar(36) PRIMARY KEY NOT NULL,
"transfer_id" varchar(36)
);
--> statement-breakpoint
ALTER TABLE "actual"."category_mapping" ADD CONSTRAINT "category_mapping_id_categories_id_fk" FOREIGN KEY ("id") REFERENCES "actual"."categories"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "actual"."category_mapping" ADD CONSTRAINT "category_mapping_transfer_id_categories_id_fk" FOREIGN KEY ("transfer_id") REFERENCES "actual"."categories"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "category_mapping_transfer_id_index" ON "actual"."category_mapping" USING btree ("transfer_id");

View File

@@ -0,0 +1,4 @@
CREATE TABLE "actual"."kvcache" (
"key" text PRIMARY KEY NOT NULL,
"value" text
);

View File

@@ -0,0 +1,4 @@
CREATE TABLE "actual"."kvcache_key" (
"id" smallint PRIMARY KEY NOT NULL,
"key" double precision
);

View File

@@ -0,0 +1,6 @@
CREATE TABLE "actual"."messages_clock" (
"id" integer PRIMARY KEY NOT NULL,
"clock" jsonb
);
--> statement-breakpoint
CREATE INDEX "messages_clock_clock_index" ON "actual"."messages_clock" USING gin ("clock");

View File

@@ -0,0 +1,11 @@
CREATE TABLE "actual"."messages_crdt" (
"id" serial PRIMARY KEY NOT NULL,
"timestamp" text,
"dataset" text,
"row" varchar(36),
"column" text,
"value" "bytea"
);
--> statement-breakpoint
CREATE INDEX "messages_crdt_timestamp_index" ON "actual"."messages_crdt" USING btree ("timestamp");--> statement-breakpoint
CREATE INDEX "messages_crdt_dataset_row_column_timestamp_index" ON "actual"."messages_crdt" USING btree ("dataset","row","column","timestamp");

View File

@@ -0,0 +1,6 @@
CREATE TABLE "actual"."notes" (
"id" varchar(36) PRIMARY KEY NOT NULL,
"note" text
);
--> statement-breakpoint
CREATE INDEX "notes_note_index" ON "actual"."notes" USING gin ("note" gin_trgm_ops);

View File

@@ -0,0 +1,13 @@
CREATE TABLE "actual"."payees" (
"id" varchar(36) PRIMARY KEY NOT NULL,
"name" text,
"transfer_acct" varchar(36),
"favorite" boolean DEFAULT false,
"learn_categories" boolean DEFAULT true,
"tombstone" boolean DEFAULT false,
"category" text
);
--> statement-breakpoint
ALTER TABLE "actual"."payees" ADD CONSTRAINT "payees_transfer_acct_accounts_id_fk" FOREIGN KEY ("transfer_acct") REFERENCES "actual"."accounts"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "payees_name_index" ON "actual"."payees" USING btree ("name") WHERE "actual"."payees"."tombstone" IS FALSE;--> statement-breakpoint
CREATE INDEX "payees_transfer_acct_name_index" ON "actual"."payees" USING btree ("transfer_acct" DESC NULLS FIRST,LOWER("name")) WHERE "actual"."payees"."tombstone" IS FALSE;

View File

@@ -0,0 +1,8 @@
CREATE TABLE "actual"."payee_mapping" (
"id" varchar(36) PRIMARY KEY NOT NULL,
"target_id" varchar(36)
);
--> statement-breakpoint
ALTER TABLE "actual"."payee_mapping" ADD CONSTRAINT "payee_mapping_id_payees_id_fk" FOREIGN KEY ("id") REFERENCES "actual"."payees"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "actual"."payee_mapping" ADD CONSTRAINT "payee_mapping_target_id_payees_id_fk" FOREIGN KEY ("target_id") REFERENCES "actual"."payees"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "payee_mapping_target_id_index" ON "actual"."payee_mapping" USING btree ("target_id");

View File

@@ -0,0 +1,12 @@
CREATE TABLE "actual"."rules" (
"id" varchar(36) PRIMARY KEY NOT NULL,
"stage" text,
"conditions" jsonb,
"actions" jsonb,
"tombstone" boolean DEFAULT false,
"conditions_op" text
);
--> statement-breakpoint
CREATE INDEX "rules_stage_index" ON "actual"."rules" USING btree ("stage") WHERE "actual"."rules"."tombstone" IS FALSE;--> statement-breakpoint
CREATE INDEX "rules_conditions_index" ON "actual"."rules" USING gin ("conditions");--> statement-breakpoint
CREATE INDEX "rules_actions_index" ON "actual"."rules" USING gin ("actions");

View File

@@ -0,0 +1,14 @@
CREATE TABLE "actual"."schedules" (
"id" varchar(36) PRIMARY KEY NOT NULL,
"name" text,
"rule" varchar(36),
"active" boolean DEFAULT false,
"completed" boolean DEFAULT false,
"posts_transaction" boolean DEFAULT false,
"tombstone" boolean DEFAULT false
);
--> statement-breakpoint
ALTER TABLE "actual"."schedules" ADD CONSTRAINT "schedules_rule_rules_id_fk" FOREIGN KEY ("rule") REFERENCES "actual"."rules"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "schedules_name_index" ON "actual"."schedules" USING btree ("name") WHERE "actual"."schedules"."tombstone" IS FALSE;--> statement-breakpoint
CREATE INDEX "schedules_rule_index" ON "actual"."schedules" USING btree ("rule") WHERE "actual"."schedules"."tombstone" IS FALSE;--> statement-breakpoint
CREATE INDEX "schedules_completed_index" ON "actual"."schedules" USING btree ("completed") WHERE "actual"."schedules"."tombstone" IS FALSE;

View File

@@ -0,0 +1,9 @@
CREATE TABLE "actual"."schedules_json_paths" (
"schedule_id" varchar(36) PRIMARY KEY NOT NULL,
"payee" text,
"account" text,
"amount" text,
"date" text
);
--> statement-breakpoint
ALTER TABLE "actual"."schedules_json_paths" ADD CONSTRAINT "schedules_json_paths_schedule_id_schedules_id_fk" FOREIGN KEY ("schedule_id") REFERENCES "actual"."schedules"("id") ON DELETE no action ON UPDATE no action;

View File

@@ -0,0 +1,12 @@
CREATE TABLE "actual"."schedules_next_date" (
"id" varchar(36) PRIMARY KEY NOT NULL,
"schedule_id" varchar(36),
"local_next_date" date,
"local_next_date_ts" bigint,
"base_next_date" date,
"base_next_date_ts" bigint,
"tombstone" boolean DEFAULT false,
CONSTRAINT "schedules_next_date_scheduleId_unique" UNIQUE("schedule_id")
);
--> statement-breakpoint
ALTER TABLE "actual"."schedules_next_date" ADD CONSTRAINT "schedules_next_date_schedule_id_schedules_id_fk" FOREIGN KEY ("schedule_id") REFERENCES "actual"."schedules"("id") ON DELETE no action ON UPDATE no action;

View File

@@ -0,0 +1,36 @@
CREATE TABLE "actual"."transactions" (
"id" varchar(36) PRIMARY KEY NOT NULL,
"is_parent" boolean DEFAULT false,
"is_child" boolean DEFAULT false,
"acct" varchar(36),
"category" varchar(36),
"amount" bigint,
"description" varchar(36),
"notes" text,
"date" date,
"parent_id" varchar(36),
"financial_id" text,
"error" jsonb,
"imported_description" text,
"transferred_id" varchar(36),
"schedule" varchar(36),
"sort_order" bigint,
"starting_balance_flag" boolean DEFAULT false,
"tombstone" boolean DEFAULT false,
"cleared" boolean DEFAULT true,
"reconciled" boolean DEFAULT false,
"raw_synced_data" jsonb,
"pending" boolean,
"location" text,
"type" text
);
--> statement-breakpoint
ALTER TABLE "actual"."transactions" ADD CONSTRAINT "transactions_acct_accounts_id_fk" FOREIGN KEY ("acct") REFERENCES "actual"."accounts"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "actual"."transactions" ADD CONSTRAINT "transactions_category_categories_id_fk" FOREIGN KEY ("category") REFERENCES "actual"."categories"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "actual"."transactions" ADD CONSTRAINT "transactions_parent_id_transactions_id_fk" FOREIGN KEY ("parent_id") REFERENCES "actual"."transactions"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "actual"."transactions" ADD CONSTRAINT "transactions_transferred_id_transactions_id_fk" FOREIGN KEY ("transferred_id") REFERENCES "actual"."transactions"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "actual"."transactions" ADD CONSTRAINT "transactions_schedule_schedules_id_fk" FOREIGN KEY ("schedule") REFERENCES "actual"."schedules"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "transactions_category_date_index" ON "actual"."transactions" USING btree ("category","date") WHERE "actual"."transactions"."tombstone" IS FALSE;--> statement-breakpoint
CREATE INDEX "transactions_acct_index" ON "actual"."transactions" USING btree ("acct") WHERE "actual"."transactions"."tombstone" IS FALSE;--> statement-breakpoint
CREATE INDEX "transactions_parent_id_index" ON "actual"."transactions" USING btree ("parent_id") WHERE "actual"."transactions"."tombstone" IS FALSE;--> statement-breakpoint
CREATE INDEX "transactions_date_starting_balance_flag_sort_order_id_index" ON "actual"."transactions" USING btree ("date" DESC NULLS LAST,"starting_balance_flag","sort_order" DESC NULLS LAST,"id");

View File

@@ -0,0 +1,12 @@
CREATE TABLE "actual"."reflect_budgets" (
"id" text PRIMARY KEY NOT NULL,
"month" date,
"category" varchar(36),
"amount" bigint,
"carryover" boolean DEFAULT false,
"goal" bigint,
"long_goal" bigint
);
--> statement-breakpoint
ALTER TABLE "actual"."reflect_budgets" ADD CONSTRAINT "reflect_budgets_category_categories_id_fk" FOREIGN KEY ("category") REFERENCES "actual"."categories"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "reflect_budgets_month_category_index" ON "actual"."reflect_budgets" USING btree ("month","category");

View File

@@ -0,0 +1,12 @@
CREATE TABLE "actual"."zero_budgets" (
"id" text PRIMARY KEY NOT NULL,
"month" date,
"category" varchar(36),
"amount" bigint,
"carryover" boolean DEFAULT false,
"goal" bigint,
"long_goal" bigint
);
--> statement-breakpoint
ALTER TABLE "actual"."zero_budgets" ADD CONSTRAINT "zero_budgets_category_categories_id_fk" FOREIGN KEY ("category") REFERENCES "actual"."categories"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "zero_budgets_month_category_index" ON "actual"."zero_budgets" USING btree ("month","category");

View File

@@ -0,0 +1,4 @@
CREATE TABLE "actual"."zero_budget_months" (
"id" text PRIMARY KEY NOT NULL,
"buffered" bigint
);

View File

@@ -0,0 +1,10 @@
CREATE TABLE "actual"."transaction_filters" (
"id" varchar(36) PRIMARY KEY NOT NULL,
"name" text,
"conditions" jsonb,
"conditions_op" text,
"tombstone" boolean DEFAULT false
);
--> statement-breakpoint
CREATE INDEX "transaction_filters_name_index" ON "actual"."transaction_filters" USING btree ("name") WHERE "actual"."transaction_filters"."tombstone" IS FALSE;--> statement-breakpoint
CREATE INDEX "transaction_filters_conditions_index" ON "actual"."transaction_filters" USING gin ("conditions") WHERE "actual"."transaction_filters"."tombstone" IS FALSE;

View File

@@ -0,0 +1,4 @@
CREATE TABLE "actual"."preferences" (
"id" text PRIMARY KEY NOT NULL,
"value" text
);

View File

@@ -0,0 +1,28 @@
CREATE TABLE "actual"."custom_reports" (
"id" varchar(36) PRIMARY KEY NOT NULL,
"name" text,
"start_date" date,
"end_date" date,
"date_static" bigint,
"date_range" text,
"mode" text,
"group_by" text,
"balance_type" text,
"show_empty" boolean DEFAULT false,
"show_offbudget" boolean DEFAULT false,
"show_hidden" boolean DEFAULT false,
"show_uncategorized" boolean DEFAULT false,
"selected_categories" text,
"graph_type" text,
"conditions" jsonb,
"conditions_op" text,
"metadata" jsonb,
"interval" text,
"color_scheme" text,
"include_current" boolean DEFAULT false,
"sort_by" text,
"tombstone" boolean DEFAULT false
);
--> statement-breakpoint
CREATE INDEX "custom_reports_name_index" ON "actual"."custom_reports" USING btree ("name") WHERE "actual"."custom_reports"."tombstone" IS FALSE;--> statement-breakpoint
CREATE INDEX "custom_reports_conditions_index" ON "actual"."custom_reports" USING gin ("conditions") WHERE "actual"."custom_reports"."tombstone" IS FALSE;

View File

@@ -0,0 +1,12 @@
CREATE TABLE "actual"."dashboard" (
"id" varchar(36) PRIMARY KEY NOT NULL,
"type" text,
"width" integer,
"height" integer,
"x" integer,
"y" integer,
"meta" jsonb,
"tombstone" boolean DEFAULT false
);
--> statement-breakpoint
CREATE INDEX "dashboard_y_x_index" ON "actual"."dashboard" USING btree ("y" DESC NULLS LAST,"x" DESC NULLS LAST) WHERE "actual"."dashboard"."tombstone" IS FALSE;

View File

@@ -0,0 +1,35 @@
CREATE VIEW "actual"."v_transactions_internal" AS (
SELECT
"actual"."transactions"."id",
"actual"."transactions"."is_parent",
"actual"."transactions"."is_child",
CASE WHEN "actual"."transactions"."is_child" IS FALSE THEN NULL ELSE "actual"."transactions"."parent_id" END AS parent_id,
"actual"."transactions"."acct" AS account,
CASE WHEN "actual"."transactions"."is_parent" IS TRUE THEN NULL ELSE "actual"."category_mapping"."transfer_id" END AS category,
COALESCE("actual"."transactions"."amount", 0) AS amount,
"actual"."payee_mapping"."target_id" AS payee,
"actual"."transactions"."notes",
"actual"."transactions"."date",
"actual"."transactions"."financial_id" AS imported_id,
"actual"."transactions"."error",
"actual"."transactions"."imported_description" AS imported_payee,
"actual"."transactions"."starting_balance_flag",
"actual"."transactions"."transferred_id" AS transfer_id,
"actual"."transactions"."schedule",
"actual"."transactions"."cleared",
"actual"."transactions"."reconciled",
"actual"."transactions"."tombstone",
"actual"."transactions"."sort_order"
FROM
"actual"."transactions"
LEFT JOIN
"actual"."category_mapping"
ON "actual"."transactions"."category" = "actual"."category_mapping"."id"
LEFT JOIN
"actual"."payee_mapping"
ON "actual"."transactions"."description" = "actual"."payee_mapping"."id"
WHERE
"actual"."transactions"."date" IS NOT NULL
AND "actual"."transactions"."acct" IS NOT NULL
AND ("actual"."transactions"."is_child" IS FALSE OR "actual"."transactions"."parent_id" IS NOT NULL)
);

View File

@@ -0,0 +1,13 @@
CREATE VIEW "actual"."v_transactions_internal_alive" AS (
SELECT
"actual"."v_transactions_internal".*
FROM
"actual"."v_transactions_internal"
LEFT JOIN
"actual"."transactions"
ON ("actual"."transactions"."is_child" IS TRUE
AND "actual"."transactions"."id" = "v_transactions_internal"."parent_id")
WHERE
COALESCE("actual"."transactions"."tombstone", FALSE) IS FALSE
AND ("v_transactions_internal"."is_child" IS FALSE OR "actual"."transactions"."tombstone" IS FALSE)
);

View File

@@ -0,0 +1,42 @@
CREATE VIEW "actual"."v_transactions" AS (
SELECT
"v_transactions_internal_alive"."id",
"v_transactions_internal_alive"."is_parent",
"v_transactions_internal_alive"."is_child",
"v_transactions_internal_alive"."parent_id",
"actual"."accounts"."id" AS account,
"actual"."categories"."id" AS category,
"v_transactions_internal_alive"."amount",
"actual"."payees"."id" AS payee,
"v_transactions_internal_alive"."notes",
"v_transactions_internal_alive"."date",
"v_transactions_internal_alive"."imported_id",
"v_transactions_internal_alive"."error",
"v_transactions_internal_alive"."imported_payee",
"v_transactions_internal_alive"."starting_balance_flag",
"v_transactions_internal_alive"."transfer_id",
"v_transactions_internal_alive"."sort_order",
"v_transactions_internal_alive"."cleared",
"v_transactions_internal_alive"."reconciled",
"v_transactions_internal_alive"."tombstone",
"v_transactions_internal_alive"."schedule"
FROM
"actual"."v_transactions_internal_alive"
LEFT JOIN
"actual"."payees"
ON ("actual"."payees"."id" = "v_transactions_internal_alive"."payee"
AND "actual"."payees"."tombstone" IS FALSE)
LEFT JOIN
"actual"."categories"
ON ("actual"."categories"."id" = "v_transactions_internal_alive"."category"
AND "actual"."categories"."tombstone" IS FALSE)
LEFT JOIN
"actual"."accounts"
ON ("actual"."accounts"."id" = "v_transactions_internal_alive"."account"
AND "actual"."accounts"."tombstone" IS FALSE)
ORDER BY
"v_transactions_internal_alive"."date" DESC,
"v_transactions_internal_alive"."starting_balance_flag",
"v_transactions_internal_alive"."sort_order" DESC,
"v_transactions_internal_alive"."id"
);

View File

@@ -0,0 +1 @@
CREATE VIEW "actual"."v_categories" AS (select "id", "name", "is_income", "hidden", "cat_group" as "group", "sort_order", "tombstone" from "actual"."categories");

View File

@@ -0,0 +1 @@
CREATE VIEW "actual"."v_payees" AS (select "actual"."payees"."id", COALESCE("actual"."accounts"."name", "actual"."payees"."name") as "name", "actual"."payees"."transfer_acct", "actual"."payees"."favorite", "actual"."payees"."learn_categories", "actual"."payees"."tombstone" from "actual"."payees" left join "actual"."accounts" on ("actual"."payees"."transfer_acct" = "actual"."accounts"."id" and "actual"."accounts"."tombstone" IS FALSE) where ("actual"."payees"."transfer_acct" is null or "actual"."accounts"."id" is not null));

View File

@@ -0,0 +1,55 @@
CREATE VIEW "actual"."v_schedules" AS (
WITH parsed_rule_conditions AS (
SELECT
"actual"."rules"."id" AS rule_id,
jsonb_extract_path_text(condition, 'value') AS value,
condition ->> 'field' AS field,
condition ->> 'op' AS op
FROM
"actual"."rules"
CROSS JOIN
jsonb_array_elements("actual"."rules"."conditions"::jsonb) AS condition
)
SELECT
"actual"."schedules"."id",
"actual"."schedules"."name",
"actual"."schedules"."rule",
CASE
WHEN "actual"."schedules_next_date"."local_next_date_ts" = "actual"."schedules_next_date"."base_next_date_ts" THEN "actual"."schedules_next_date"."local_next_date"
ELSE "actual"."schedules_next_date"."base_next_date"
END AS next_date,
"actual"."schedules"."completed",
"actual"."schedules"."posts_transaction",
"actual"."schedules"."tombstone",
"actual"."payee_mapping"."target_id" AS _payee,
account_condition.value AS _account,
amount_condition.value AS _amount,
amount_condition.op AS _amount_op,
date_condition.value AS _date,
"actual"."rules"."conditions" AS _conditions,
"actual"."rules"."actions" AS _actions
FROM
"actual"."schedules"
LEFT JOIN
"actual"."schedules_next_date" ON "actual"."schedules_next_date"."schedule_id" = "actual"."schedules"."id"
LEFT JOIN
"actual"."rules" ON "actual"."rules"."id" = "actual"."schedules"."rule"
LEFT JOIN
parsed_rule_conditions payee_condition
ON payee_condition.rule_id = "actual"."rules"."id"
AND payee_condition.field = 'payee'
LEFT JOIN
"actual"."payee_mapping" ON "actual"."payee_mapping"."id" = payee_condition.value
LEFT JOIN
parsed_rule_conditions account_condition
ON account_condition.rule_id = "actual"."rules"."id"
AND account_condition.field = 'account'
LEFT JOIN
parsed_rule_conditions amount_condition
ON amount_condition.rule_id = "actual"."rules"."id"
AND amount_condition.field = 'amount'
LEFT JOIN
parsed_rule_conditions date_condition
ON date_condition.rule_id = "actual"."rules"."id"
AND date_condition.field = 'date'
);

View File

@@ -0,0 +1,20 @@
{
"id": "b4c5ebc2-f16f-45af-921f-879f23c7e333",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
"tables": {},
"enums": {},
"schemas": {
"actual": "actual"
},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -0,0 +1,76 @@
{
"id": "8ce816bc-fae3-4a5d-9476-d6ae4698a825",
"prevId": "b4c5ebc2-f16f-45af-921f-879f23c7e333",
"version": "7",
"dialect": "postgresql",
"tables": {
"actual.banks": {
"name": "banks",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank_id": {
"name": "bank_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"banks_bank_id_index": {
"name": "banks_bank_id_index",
"columns": [
{
"expression": "bank_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"banks\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {
"actual": "actual"
},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -0,0 +1,269 @@
{
"id": "dfd56490-a3a9-4c1a-9808-f915eaa4ab87",
"prevId": "8ce816bc-fae3-4a5d-9476-d6ae4698a825",
"version": "7",
"dialect": "postgresql",
"tables": {
"actual.accounts": {
"name": "accounts",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"offbudget": {
"name": "offbudget",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"closed": {
"name": "closed",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"account_id": {
"name": "account_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"balance_current": {
"name": "balance_current",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_available": {
"name": "balance_available",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_limit": {
"name": "balance_limit",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"mask": {
"name": "mask",
"type": "text",
"primaryKey": false,
"notNull": false
},
"official_name": {
"name": "official_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"subtype": {
"name": "subtype",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank": {
"name": "bank",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"account_sync_source": {
"name": "account_sync_source",
"type": "text",
"primaryKey": false,
"notNull": false
},
"last_sync": {
"name": "last_sync",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"last_reconciled": {
"name": "last_reconciled",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"accounts_name_index": {
"name": "accounts_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_bank_index": {
"name": "accounts_bank_index",
"columns": [
{
"expression": "bank",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_sort_order_name_index": {
"name": "accounts_sort_order_name_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"accounts_bank_banks_id_fk": {
"name": "accounts_bank_banks_id_fk",
"tableFrom": "accounts",
"tableTo": "banks",
"schemaTo": "actual",
"columnsFrom": [
"bank"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.banks": {
"name": "banks",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank_id": {
"name": "bank_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"banks_bank_id_index": {
"name": "banks_bank_id_index",
"columns": [
{
"expression": "bank_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"banks\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {
"actual": "actual"
},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -0,0 +1,386 @@
{
"id": "f06bb796-f73e-45f5-80f7-d1926f88a481",
"prevId": "dfd56490-a3a9-4c1a-9808-f915eaa4ab87",
"version": "7",
"dialect": "postgresql",
"tables": {
"actual.accounts": {
"name": "accounts",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"offbudget": {
"name": "offbudget",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"closed": {
"name": "closed",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"account_id": {
"name": "account_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"balance_current": {
"name": "balance_current",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_available": {
"name": "balance_available",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_limit": {
"name": "balance_limit",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"mask": {
"name": "mask",
"type": "text",
"primaryKey": false,
"notNull": false
},
"official_name": {
"name": "official_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"subtype": {
"name": "subtype",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank": {
"name": "bank",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"account_sync_source": {
"name": "account_sync_source",
"type": "text",
"primaryKey": false,
"notNull": false
},
"last_sync": {
"name": "last_sync",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"last_reconciled": {
"name": "last_reconciled",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"accounts_name_index": {
"name": "accounts_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_bank_index": {
"name": "accounts_bank_index",
"columns": [
{
"expression": "bank",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_sort_order_name_index": {
"name": "accounts_sort_order_name_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"accounts_bank_banks_id_fk": {
"name": "accounts_bank_banks_id_fk",
"tableFrom": "accounts",
"tableTo": "banks",
"schemaTo": "actual",
"columnsFrom": [
"bank"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.banks": {
"name": "banks",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank_id": {
"name": "bank_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"banks_bank_id_index": {
"name": "banks_bank_id_index",
"columns": [
{
"expression": "bank_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"banks\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_groups": {
"name": "category_groups",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"category_groups_name_index": {
"name": "category_groups_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"category_groups\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_is_income_sort_order_id_index": {
"name": "category_groups_is_income_sort_order_id_index",
"columns": [
{
"expression": "is_income",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_sort_order_id_index": {
"name": "category_groups_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {
"actual": "actual"
},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -0,0 +1,534 @@
{
"id": "7756822c-2419-47e7-8053-e6aaf841c5d0",
"prevId": "f06bb796-f73e-45f5-80f7-d1926f88a481",
"version": "7",
"dialect": "postgresql",
"tables": {
"actual.accounts": {
"name": "accounts",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"offbudget": {
"name": "offbudget",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"closed": {
"name": "closed",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"account_id": {
"name": "account_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"balance_current": {
"name": "balance_current",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_available": {
"name": "balance_available",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_limit": {
"name": "balance_limit",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"mask": {
"name": "mask",
"type": "text",
"primaryKey": false,
"notNull": false
},
"official_name": {
"name": "official_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"subtype": {
"name": "subtype",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank": {
"name": "bank",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"account_sync_source": {
"name": "account_sync_source",
"type": "text",
"primaryKey": false,
"notNull": false
},
"last_sync": {
"name": "last_sync",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"last_reconciled": {
"name": "last_reconciled",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"accounts_name_index": {
"name": "accounts_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_bank_index": {
"name": "accounts_bank_index",
"columns": [
{
"expression": "bank",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_sort_order_name_index": {
"name": "accounts_sort_order_name_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"accounts_bank_banks_id_fk": {
"name": "accounts_bank_banks_id_fk",
"tableFrom": "accounts",
"tableTo": "banks",
"schemaTo": "actual",
"columnsFrom": [
"bank"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.banks": {
"name": "banks",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank_id": {
"name": "bank_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"banks_bank_id_index": {
"name": "banks_bank_id_index",
"columns": [
{
"expression": "bank_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"banks\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.categories": {
"name": "categories",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"cat_group": {
"name": "cat_group",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"goal_def": {
"name": "goal_def",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"categories_name_index": {
"name": "categories_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_cat_group_index": {
"name": "categories_cat_group_index",
"columns": [
{
"expression": "cat_group",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_sort_order_id_index": {
"name": "categories_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_goal_def_index": {
"name": "categories_goal_def_index",
"columns": [
{
"expression": "goal_def",
"isExpression": false,
"asc": true,
"nulls": "first"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"categories_cat_group_category_groups_id_fk": {
"name": "categories_cat_group_category_groups_id_fk",
"tableFrom": "categories",
"tableTo": "category_groups",
"schemaTo": "actual",
"columnsFrom": [
"cat_group"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_groups": {
"name": "category_groups",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"category_groups_name_index": {
"name": "category_groups_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"category_groups\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_is_income_sort_order_id_index": {
"name": "category_groups_is_income_sort_order_id_index",
"columns": [
{
"expression": "is_income",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_sort_order_id_index": {
"name": "category_groups_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {
"actual": "actual"
},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -0,0 +1,604 @@
{
"id": "d1032c6e-7dc2-4543-b33d-d402aadfa5c0",
"prevId": "7756822c-2419-47e7-8053-e6aaf841c5d0",
"version": "7",
"dialect": "postgresql",
"tables": {
"actual.accounts": {
"name": "accounts",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"offbudget": {
"name": "offbudget",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"closed": {
"name": "closed",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"account_id": {
"name": "account_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"balance_current": {
"name": "balance_current",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_available": {
"name": "balance_available",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_limit": {
"name": "balance_limit",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"mask": {
"name": "mask",
"type": "text",
"primaryKey": false,
"notNull": false
},
"official_name": {
"name": "official_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"subtype": {
"name": "subtype",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank": {
"name": "bank",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"account_sync_source": {
"name": "account_sync_source",
"type": "text",
"primaryKey": false,
"notNull": false
},
"last_sync": {
"name": "last_sync",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"last_reconciled": {
"name": "last_reconciled",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"accounts_name_index": {
"name": "accounts_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_bank_index": {
"name": "accounts_bank_index",
"columns": [
{
"expression": "bank",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_sort_order_name_index": {
"name": "accounts_sort_order_name_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"accounts_bank_banks_id_fk": {
"name": "accounts_bank_banks_id_fk",
"tableFrom": "accounts",
"tableTo": "banks",
"schemaTo": "actual",
"columnsFrom": [
"bank"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.banks": {
"name": "banks",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank_id": {
"name": "bank_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"banks_bank_id_index": {
"name": "banks_bank_id_index",
"columns": [
{
"expression": "bank_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"banks\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.categories": {
"name": "categories",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"cat_group": {
"name": "cat_group",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"goal_def": {
"name": "goal_def",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"categories_name_index": {
"name": "categories_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_cat_group_index": {
"name": "categories_cat_group_index",
"columns": [
{
"expression": "cat_group",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_sort_order_id_index": {
"name": "categories_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_goal_def_index": {
"name": "categories_goal_def_index",
"columns": [
{
"expression": "goal_def",
"isExpression": false,
"asc": true,
"nulls": "first"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"categories_cat_group_category_groups_id_fk": {
"name": "categories_cat_group_category_groups_id_fk",
"tableFrom": "categories",
"tableTo": "category_groups",
"schemaTo": "actual",
"columnsFrom": [
"cat_group"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_groups": {
"name": "category_groups",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"category_groups_name_index": {
"name": "category_groups_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"category_groups\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_is_income_sort_order_id_index": {
"name": "category_groups_is_income_sort_order_id_index",
"columns": [
{
"expression": "is_income",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_sort_order_id_index": {
"name": "category_groups_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_mapping": {
"name": "category_mapping",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"transfer_id": {
"name": "transfer_id",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"category_mapping_transfer_id_index": {
"name": "category_mapping_transfer_id_index",
"columns": [
{
"expression": "transfer_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"category_mapping_id_categories_id_fk": {
"name": "category_mapping_id_categories_id_fk",
"tableFrom": "category_mapping",
"tableTo": "categories",
"schemaTo": "actual",
"columnsFrom": [
"id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"category_mapping_transfer_id_categories_id_fk": {
"name": "category_mapping_transfer_id_categories_id_fk",
"tableFrom": "category_mapping",
"tableTo": "categories",
"schemaTo": "actual",
"columnsFrom": [
"transfer_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {
"actual": "actual"
},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -0,0 +1,629 @@
{
"id": "b992c78c-07f8-49c0-b884-2cd84826bc5e",
"prevId": "d1032c6e-7dc2-4543-b33d-d402aadfa5c0",
"version": "7",
"dialect": "postgresql",
"tables": {
"actual.accounts": {
"name": "accounts",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"offbudget": {
"name": "offbudget",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"closed": {
"name": "closed",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"account_id": {
"name": "account_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"balance_current": {
"name": "balance_current",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_available": {
"name": "balance_available",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_limit": {
"name": "balance_limit",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"mask": {
"name": "mask",
"type": "text",
"primaryKey": false,
"notNull": false
},
"official_name": {
"name": "official_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"subtype": {
"name": "subtype",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank": {
"name": "bank",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"account_sync_source": {
"name": "account_sync_source",
"type": "text",
"primaryKey": false,
"notNull": false
},
"last_sync": {
"name": "last_sync",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"last_reconciled": {
"name": "last_reconciled",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"accounts_name_index": {
"name": "accounts_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_bank_index": {
"name": "accounts_bank_index",
"columns": [
{
"expression": "bank",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_sort_order_name_index": {
"name": "accounts_sort_order_name_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"accounts_bank_banks_id_fk": {
"name": "accounts_bank_banks_id_fk",
"tableFrom": "accounts",
"tableTo": "banks",
"schemaTo": "actual",
"columnsFrom": [
"bank"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.banks": {
"name": "banks",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank_id": {
"name": "bank_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"banks_bank_id_index": {
"name": "banks_bank_id_index",
"columns": [
{
"expression": "bank_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"banks\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.categories": {
"name": "categories",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"cat_group": {
"name": "cat_group",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"goal_def": {
"name": "goal_def",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"categories_name_index": {
"name": "categories_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_cat_group_index": {
"name": "categories_cat_group_index",
"columns": [
{
"expression": "cat_group",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_sort_order_id_index": {
"name": "categories_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_goal_def_index": {
"name": "categories_goal_def_index",
"columns": [
{
"expression": "goal_def",
"isExpression": false,
"asc": true,
"nulls": "first"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"categories_cat_group_category_groups_id_fk": {
"name": "categories_cat_group_category_groups_id_fk",
"tableFrom": "categories",
"tableTo": "category_groups",
"schemaTo": "actual",
"columnsFrom": [
"cat_group"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_groups": {
"name": "category_groups",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"category_groups_name_index": {
"name": "category_groups_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"category_groups\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_is_income_sort_order_id_index": {
"name": "category_groups_is_income_sort_order_id_index",
"columns": [
{
"expression": "is_income",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_sort_order_id_index": {
"name": "category_groups_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_mapping": {
"name": "category_mapping",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"transfer_id": {
"name": "transfer_id",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"category_mapping_transfer_id_index": {
"name": "category_mapping_transfer_id_index",
"columns": [
{
"expression": "transfer_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"category_mapping_id_categories_id_fk": {
"name": "category_mapping_id_categories_id_fk",
"tableFrom": "category_mapping",
"tableTo": "categories",
"schemaTo": "actual",
"columnsFrom": [
"id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"category_mapping_transfer_id_categories_id_fk": {
"name": "category_mapping_transfer_id_categories_id_fk",
"tableFrom": "category_mapping",
"tableTo": "categories",
"schemaTo": "actual",
"columnsFrom": [
"transfer_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.kvcache": {
"name": "kvcache",
"schema": "actual",
"columns": {
"key": {
"name": "key",
"type": "text",
"primaryKey": true,
"notNull": true
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {
"actual": "actual"
},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -0,0 +1,654 @@
{
"id": "fa5286ef-f600-4d3b-9b22-9499d204f746",
"prevId": "b992c78c-07f8-49c0-b884-2cd84826bc5e",
"version": "7",
"dialect": "postgresql",
"tables": {
"actual.accounts": {
"name": "accounts",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"offbudget": {
"name": "offbudget",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"closed": {
"name": "closed",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"account_id": {
"name": "account_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"balance_current": {
"name": "balance_current",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_available": {
"name": "balance_available",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_limit": {
"name": "balance_limit",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"mask": {
"name": "mask",
"type": "text",
"primaryKey": false,
"notNull": false
},
"official_name": {
"name": "official_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"subtype": {
"name": "subtype",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank": {
"name": "bank",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"account_sync_source": {
"name": "account_sync_source",
"type": "text",
"primaryKey": false,
"notNull": false
},
"last_sync": {
"name": "last_sync",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"last_reconciled": {
"name": "last_reconciled",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"accounts_name_index": {
"name": "accounts_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_bank_index": {
"name": "accounts_bank_index",
"columns": [
{
"expression": "bank",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_sort_order_name_index": {
"name": "accounts_sort_order_name_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"accounts_bank_banks_id_fk": {
"name": "accounts_bank_banks_id_fk",
"tableFrom": "accounts",
"tableTo": "banks",
"schemaTo": "actual",
"columnsFrom": [
"bank"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.banks": {
"name": "banks",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank_id": {
"name": "bank_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"banks_bank_id_index": {
"name": "banks_bank_id_index",
"columns": [
{
"expression": "bank_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"banks\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.categories": {
"name": "categories",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"cat_group": {
"name": "cat_group",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"goal_def": {
"name": "goal_def",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"categories_name_index": {
"name": "categories_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_cat_group_index": {
"name": "categories_cat_group_index",
"columns": [
{
"expression": "cat_group",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_sort_order_id_index": {
"name": "categories_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_goal_def_index": {
"name": "categories_goal_def_index",
"columns": [
{
"expression": "goal_def",
"isExpression": false,
"asc": true,
"nulls": "first"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"categories_cat_group_category_groups_id_fk": {
"name": "categories_cat_group_category_groups_id_fk",
"tableFrom": "categories",
"tableTo": "category_groups",
"schemaTo": "actual",
"columnsFrom": [
"cat_group"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_groups": {
"name": "category_groups",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"category_groups_name_index": {
"name": "category_groups_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"category_groups\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_is_income_sort_order_id_index": {
"name": "category_groups_is_income_sort_order_id_index",
"columns": [
{
"expression": "is_income",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_sort_order_id_index": {
"name": "category_groups_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_mapping": {
"name": "category_mapping",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"transfer_id": {
"name": "transfer_id",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"category_mapping_transfer_id_index": {
"name": "category_mapping_transfer_id_index",
"columns": [
{
"expression": "transfer_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"category_mapping_id_categories_id_fk": {
"name": "category_mapping_id_categories_id_fk",
"tableFrom": "category_mapping",
"tableTo": "categories",
"schemaTo": "actual",
"columnsFrom": [
"id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"category_mapping_transfer_id_categories_id_fk": {
"name": "category_mapping_transfer_id_categories_id_fk",
"tableFrom": "category_mapping",
"tableTo": "categories",
"schemaTo": "actual",
"columnsFrom": [
"transfer_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.kvcache_key": {
"name": "kvcache_key",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "smallint",
"primaryKey": true,
"notNull": true
},
"key": {
"name": "key",
"type": "double precision",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.kvcache": {
"name": "kvcache",
"schema": "actual",
"columns": {
"key": {
"name": "key",
"type": "text",
"primaryKey": true,
"notNull": true
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {
"actual": "actual"
},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -0,0 +1,695 @@
{
"id": "0497ea54-59b8-4380-a96c-25e7821d1f7e",
"prevId": "fa5286ef-f600-4d3b-9b22-9499d204f746",
"version": "7",
"dialect": "postgresql",
"tables": {
"actual.accounts": {
"name": "accounts",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"offbudget": {
"name": "offbudget",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"closed": {
"name": "closed",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"account_id": {
"name": "account_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"balance_current": {
"name": "balance_current",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_available": {
"name": "balance_available",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_limit": {
"name": "balance_limit",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"mask": {
"name": "mask",
"type": "text",
"primaryKey": false,
"notNull": false
},
"official_name": {
"name": "official_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"subtype": {
"name": "subtype",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank": {
"name": "bank",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"account_sync_source": {
"name": "account_sync_source",
"type": "text",
"primaryKey": false,
"notNull": false
},
"last_sync": {
"name": "last_sync",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"last_reconciled": {
"name": "last_reconciled",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"accounts_name_index": {
"name": "accounts_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_bank_index": {
"name": "accounts_bank_index",
"columns": [
{
"expression": "bank",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_sort_order_name_index": {
"name": "accounts_sort_order_name_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"accounts_bank_banks_id_fk": {
"name": "accounts_bank_banks_id_fk",
"tableFrom": "accounts",
"tableTo": "banks",
"schemaTo": "actual",
"columnsFrom": [
"bank"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.banks": {
"name": "banks",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank_id": {
"name": "bank_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"banks_bank_id_index": {
"name": "banks_bank_id_index",
"columns": [
{
"expression": "bank_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"banks\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.categories": {
"name": "categories",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"cat_group": {
"name": "cat_group",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"goal_def": {
"name": "goal_def",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"categories_name_index": {
"name": "categories_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_cat_group_index": {
"name": "categories_cat_group_index",
"columns": [
{
"expression": "cat_group",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_sort_order_id_index": {
"name": "categories_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_goal_def_index": {
"name": "categories_goal_def_index",
"columns": [
{
"expression": "goal_def",
"isExpression": false,
"asc": true,
"nulls": "first"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"categories_cat_group_category_groups_id_fk": {
"name": "categories_cat_group_category_groups_id_fk",
"tableFrom": "categories",
"tableTo": "category_groups",
"schemaTo": "actual",
"columnsFrom": [
"cat_group"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_groups": {
"name": "category_groups",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"category_groups_name_index": {
"name": "category_groups_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"category_groups\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_is_income_sort_order_id_index": {
"name": "category_groups_is_income_sort_order_id_index",
"columns": [
{
"expression": "is_income",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_sort_order_id_index": {
"name": "category_groups_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_mapping": {
"name": "category_mapping",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"transfer_id": {
"name": "transfer_id",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"category_mapping_transfer_id_index": {
"name": "category_mapping_transfer_id_index",
"columns": [
{
"expression": "transfer_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"category_mapping_id_categories_id_fk": {
"name": "category_mapping_id_categories_id_fk",
"tableFrom": "category_mapping",
"tableTo": "categories",
"schemaTo": "actual",
"columnsFrom": [
"id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"category_mapping_transfer_id_categories_id_fk": {
"name": "category_mapping_transfer_id_categories_id_fk",
"tableFrom": "category_mapping",
"tableTo": "categories",
"schemaTo": "actual",
"columnsFrom": [
"transfer_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.kvcache_key": {
"name": "kvcache_key",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "smallint",
"primaryKey": true,
"notNull": true
},
"key": {
"name": "key",
"type": "double precision",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.kvcache": {
"name": "kvcache",
"schema": "actual",
"columns": {
"key": {
"name": "key",
"type": "text",
"primaryKey": true,
"notNull": true
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.messages_clock": {
"name": "messages_clock",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true
},
"clock": {
"name": "clock",
"type": "jsonb",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"messages_clock_clock_index": {
"name": "messages_clock_clock_index",
"columns": [
{
"expression": "clock",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "gin",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {
"actual": "actual"
},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -0,0 +1,793 @@
{
"id": "0560d98f-6e67-47b9-804a-272f0ee08415",
"prevId": "0497ea54-59b8-4380-a96c-25e7821d1f7e",
"version": "7",
"dialect": "postgresql",
"tables": {
"actual.accounts": {
"name": "accounts",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"offbudget": {
"name": "offbudget",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"closed": {
"name": "closed",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"account_id": {
"name": "account_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"balance_current": {
"name": "balance_current",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_available": {
"name": "balance_available",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_limit": {
"name": "balance_limit",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"mask": {
"name": "mask",
"type": "text",
"primaryKey": false,
"notNull": false
},
"official_name": {
"name": "official_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"subtype": {
"name": "subtype",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank": {
"name": "bank",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"account_sync_source": {
"name": "account_sync_source",
"type": "text",
"primaryKey": false,
"notNull": false
},
"last_sync": {
"name": "last_sync",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"last_reconciled": {
"name": "last_reconciled",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"accounts_name_index": {
"name": "accounts_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_bank_index": {
"name": "accounts_bank_index",
"columns": [
{
"expression": "bank",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_sort_order_name_index": {
"name": "accounts_sort_order_name_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"accounts_bank_banks_id_fk": {
"name": "accounts_bank_banks_id_fk",
"tableFrom": "accounts",
"tableTo": "banks",
"schemaTo": "actual",
"columnsFrom": [
"bank"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.banks": {
"name": "banks",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank_id": {
"name": "bank_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"banks_bank_id_index": {
"name": "banks_bank_id_index",
"columns": [
{
"expression": "bank_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"banks\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.categories": {
"name": "categories",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"cat_group": {
"name": "cat_group",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"goal_def": {
"name": "goal_def",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"categories_name_index": {
"name": "categories_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_cat_group_index": {
"name": "categories_cat_group_index",
"columns": [
{
"expression": "cat_group",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_sort_order_id_index": {
"name": "categories_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_goal_def_index": {
"name": "categories_goal_def_index",
"columns": [
{
"expression": "goal_def",
"isExpression": false,
"asc": true,
"nulls": "first"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"categories_cat_group_category_groups_id_fk": {
"name": "categories_cat_group_category_groups_id_fk",
"tableFrom": "categories",
"tableTo": "category_groups",
"schemaTo": "actual",
"columnsFrom": [
"cat_group"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_groups": {
"name": "category_groups",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"category_groups_name_index": {
"name": "category_groups_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"category_groups\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_is_income_sort_order_id_index": {
"name": "category_groups_is_income_sort_order_id_index",
"columns": [
{
"expression": "is_income",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_sort_order_id_index": {
"name": "category_groups_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_mapping": {
"name": "category_mapping",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"transfer_id": {
"name": "transfer_id",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"category_mapping_transfer_id_index": {
"name": "category_mapping_transfer_id_index",
"columns": [
{
"expression": "transfer_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"category_mapping_id_categories_id_fk": {
"name": "category_mapping_id_categories_id_fk",
"tableFrom": "category_mapping",
"tableTo": "categories",
"schemaTo": "actual",
"columnsFrom": [
"id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"category_mapping_transfer_id_categories_id_fk": {
"name": "category_mapping_transfer_id_categories_id_fk",
"tableFrom": "category_mapping",
"tableTo": "categories",
"schemaTo": "actual",
"columnsFrom": [
"transfer_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.kvcache_key": {
"name": "kvcache_key",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "smallint",
"primaryKey": true,
"notNull": true
},
"key": {
"name": "key",
"type": "double precision",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.kvcache": {
"name": "kvcache",
"schema": "actual",
"columns": {
"key": {
"name": "key",
"type": "text",
"primaryKey": true,
"notNull": true
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.messages_clock": {
"name": "messages_clock",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true
},
"clock": {
"name": "clock",
"type": "jsonb",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"messages_clock_clock_index": {
"name": "messages_clock_clock_index",
"columns": [
{
"expression": "clock",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "gin",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.messages_crdt": {
"name": "messages_crdt",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"timestamp": {
"name": "timestamp",
"type": "text",
"primaryKey": false,
"notNull": false
},
"dataset": {
"name": "dataset",
"type": "text",
"primaryKey": false,
"notNull": false
},
"row": {
"name": "row",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"column": {
"name": "column",
"type": "text",
"primaryKey": false,
"notNull": false
},
"value": {
"name": "value",
"type": "bytea",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"messages_crdt_timestamp_index": {
"name": "messages_crdt_timestamp_index",
"columns": [
{
"expression": "timestamp",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"messages_crdt_dataset_row_column_timestamp_index": {
"name": "messages_crdt_dataset_row_column_timestamp_index",
"columns": [
{
"expression": "dataset",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "row",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "column",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "timestamp",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {
"actual": "actual"
},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -0,0 +1,835 @@
{
"id": "ff8b49fe-aa92-43a2-bd14-12510e4a4b75",
"prevId": "0560d98f-6e67-47b9-804a-272f0ee08415",
"version": "7",
"dialect": "postgresql",
"tables": {
"actual.accounts": {
"name": "accounts",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"offbudget": {
"name": "offbudget",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"closed": {
"name": "closed",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"account_id": {
"name": "account_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"balance_current": {
"name": "balance_current",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_available": {
"name": "balance_available",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_limit": {
"name": "balance_limit",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"mask": {
"name": "mask",
"type": "text",
"primaryKey": false,
"notNull": false
},
"official_name": {
"name": "official_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"subtype": {
"name": "subtype",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank": {
"name": "bank",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"account_sync_source": {
"name": "account_sync_source",
"type": "text",
"primaryKey": false,
"notNull": false
},
"last_sync": {
"name": "last_sync",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"last_reconciled": {
"name": "last_reconciled",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"accounts_name_index": {
"name": "accounts_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_bank_index": {
"name": "accounts_bank_index",
"columns": [
{
"expression": "bank",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_sort_order_name_index": {
"name": "accounts_sort_order_name_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"accounts_bank_banks_id_fk": {
"name": "accounts_bank_banks_id_fk",
"tableFrom": "accounts",
"tableTo": "banks",
"schemaTo": "actual",
"columnsFrom": [
"bank"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.banks": {
"name": "banks",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank_id": {
"name": "bank_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"banks_bank_id_index": {
"name": "banks_bank_id_index",
"columns": [
{
"expression": "bank_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"banks\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.categories": {
"name": "categories",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"cat_group": {
"name": "cat_group",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"goal_def": {
"name": "goal_def",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"categories_name_index": {
"name": "categories_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_cat_group_index": {
"name": "categories_cat_group_index",
"columns": [
{
"expression": "cat_group",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_sort_order_id_index": {
"name": "categories_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_goal_def_index": {
"name": "categories_goal_def_index",
"columns": [
{
"expression": "goal_def",
"isExpression": false,
"asc": true,
"nulls": "first"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"categories_cat_group_category_groups_id_fk": {
"name": "categories_cat_group_category_groups_id_fk",
"tableFrom": "categories",
"tableTo": "category_groups",
"schemaTo": "actual",
"columnsFrom": [
"cat_group"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_groups": {
"name": "category_groups",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"category_groups_name_index": {
"name": "category_groups_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"category_groups\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_is_income_sort_order_id_index": {
"name": "category_groups_is_income_sort_order_id_index",
"columns": [
{
"expression": "is_income",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_sort_order_id_index": {
"name": "category_groups_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_mapping": {
"name": "category_mapping",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"transfer_id": {
"name": "transfer_id",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"category_mapping_transfer_id_index": {
"name": "category_mapping_transfer_id_index",
"columns": [
{
"expression": "transfer_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"category_mapping_id_categories_id_fk": {
"name": "category_mapping_id_categories_id_fk",
"tableFrom": "category_mapping",
"tableTo": "categories",
"schemaTo": "actual",
"columnsFrom": [
"id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"category_mapping_transfer_id_categories_id_fk": {
"name": "category_mapping_transfer_id_categories_id_fk",
"tableFrom": "category_mapping",
"tableTo": "categories",
"schemaTo": "actual",
"columnsFrom": [
"transfer_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.kvcache_key": {
"name": "kvcache_key",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "smallint",
"primaryKey": true,
"notNull": true
},
"key": {
"name": "key",
"type": "double precision",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.kvcache": {
"name": "kvcache",
"schema": "actual",
"columns": {
"key": {
"name": "key",
"type": "text",
"primaryKey": true,
"notNull": true
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.messages_clock": {
"name": "messages_clock",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true
},
"clock": {
"name": "clock",
"type": "jsonb",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"messages_clock_clock_index": {
"name": "messages_clock_clock_index",
"columns": [
{
"expression": "clock",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "gin",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.messages_crdt": {
"name": "messages_crdt",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"timestamp": {
"name": "timestamp",
"type": "text",
"primaryKey": false,
"notNull": false
},
"dataset": {
"name": "dataset",
"type": "text",
"primaryKey": false,
"notNull": false
},
"row": {
"name": "row",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"column": {
"name": "column",
"type": "text",
"primaryKey": false,
"notNull": false
},
"value": {
"name": "value",
"type": "bytea",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"messages_crdt_timestamp_index": {
"name": "messages_crdt_timestamp_index",
"columns": [
{
"expression": "timestamp",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"messages_crdt_dataset_row_column_timestamp_index": {
"name": "messages_crdt_dataset_row_column_timestamp_index",
"columns": [
{
"expression": "dataset",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "row",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "column",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "timestamp",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.notes": {
"name": "notes",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"note": {
"name": "note",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"notes_note_index": {
"name": "notes_note_index",
"columns": [
{
"expression": "note",
"isExpression": false,
"asc": true,
"nulls": "last",
"opclass": "gin_trgm_ops"
}
],
"isUnique": false,
"concurrently": false,
"method": "gin",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {
"actual": "actual"
},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -0,0 +1,947 @@
{
"id": "02802e2f-3cce-492b-b874-68f274366be9",
"prevId": "ff8b49fe-aa92-43a2-bd14-12510e4a4b75",
"version": "7",
"dialect": "postgresql",
"tables": {
"actual.accounts": {
"name": "accounts",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"offbudget": {
"name": "offbudget",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"closed": {
"name": "closed",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"account_id": {
"name": "account_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"balance_current": {
"name": "balance_current",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_available": {
"name": "balance_available",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"balance_limit": {
"name": "balance_limit",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"mask": {
"name": "mask",
"type": "text",
"primaryKey": false,
"notNull": false
},
"official_name": {
"name": "official_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"subtype": {
"name": "subtype",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank": {
"name": "bank",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"account_sync_source": {
"name": "account_sync_source",
"type": "text",
"primaryKey": false,
"notNull": false
},
"last_sync": {
"name": "last_sync",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"last_reconciled": {
"name": "last_reconciled",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"accounts_name_index": {
"name": "accounts_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_bank_index": {
"name": "accounts_bank_index",
"columns": [
{
"expression": "bank",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"accounts\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"accounts_sort_order_name_index": {
"name": "accounts_sort_order_name_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"accounts_bank_banks_id_fk": {
"name": "accounts_bank_banks_id_fk",
"tableFrom": "accounts",
"tableTo": "banks",
"schemaTo": "actual",
"columnsFrom": [
"bank"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.banks": {
"name": "banks",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"bank_id": {
"name": "bank_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"banks_bank_id_index": {
"name": "banks_bank_id_index",
"columns": [
{
"expression": "bank_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"banks\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.categories": {
"name": "categories",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"cat_group": {
"name": "cat_group",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"goal_def": {
"name": "goal_def",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"categories_name_index": {
"name": "categories_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_cat_group_index": {
"name": "categories_cat_group_index",
"columns": [
{
"expression": "cat_group",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"categories\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_sort_order_id_index": {
"name": "categories_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"categories_goal_def_index": {
"name": "categories_goal_def_index",
"columns": [
{
"expression": "goal_def",
"isExpression": false,
"asc": true,
"nulls": "first"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"categories_cat_group_category_groups_id_fk": {
"name": "categories_cat_group_category_groups_id_fk",
"tableFrom": "categories",
"tableTo": "category_groups",
"schemaTo": "actual",
"columnsFrom": [
"cat_group"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_groups": {
"name": "category_groups",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_income": {
"name": "is_income",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"hidden": {
"name": "hidden",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
}
},
"indexes": {
"category_groups_name_index": {
"name": "category_groups_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"category_groups\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_is_income_sort_order_id_index": {
"name": "category_groups_is_income_sort_order_id_index",
"columns": [
{
"expression": "is_income",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"category_groups_sort_order_id_index": {
"name": "category_groups_sort_order_id_index",
"columns": [
{
"expression": "sort_order",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.category_mapping": {
"name": "category_mapping",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"transfer_id": {
"name": "transfer_id",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"category_mapping_transfer_id_index": {
"name": "category_mapping_transfer_id_index",
"columns": [
{
"expression": "transfer_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"category_mapping_id_categories_id_fk": {
"name": "category_mapping_id_categories_id_fk",
"tableFrom": "category_mapping",
"tableTo": "categories",
"schemaTo": "actual",
"columnsFrom": [
"id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"category_mapping_transfer_id_categories_id_fk": {
"name": "category_mapping_transfer_id_categories_id_fk",
"tableFrom": "category_mapping",
"tableTo": "categories",
"schemaTo": "actual",
"columnsFrom": [
"transfer_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.kvcache_key": {
"name": "kvcache_key",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "smallint",
"primaryKey": true,
"notNull": true
},
"key": {
"name": "key",
"type": "double precision",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.kvcache": {
"name": "kvcache",
"schema": "actual",
"columns": {
"key": {
"name": "key",
"type": "text",
"primaryKey": true,
"notNull": true
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.messages_clock": {
"name": "messages_clock",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true
},
"clock": {
"name": "clock",
"type": "jsonb",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"messages_clock_clock_index": {
"name": "messages_clock_clock_index",
"columns": [
{
"expression": "clock",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "gin",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.messages_crdt": {
"name": "messages_crdt",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"timestamp": {
"name": "timestamp",
"type": "text",
"primaryKey": false,
"notNull": false
},
"dataset": {
"name": "dataset",
"type": "text",
"primaryKey": false,
"notNull": false
},
"row": {
"name": "row",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"column": {
"name": "column",
"type": "text",
"primaryKey": false,
"notNull": false
},
"value": {
"name": "value",
"type": "bytea",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"messages_crdt_timestamp_index": {
"name": "messages_crdt_timestamp_index",
"columns": [
{
"expression": "timestamp",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"messages_crdt_dataset_row_column_timestamp_index": {
"name": "messages_crdt_dataset_row_column_timestamp_index",
"columns": [
{
"expression": "dataset",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "row",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "column",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "timestamp",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.notes": {
"name": "notes",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"note": {
"name": "note",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"notes_note_index": {
"name": "notes_note_index",
"columns": [
{
"expression": "note",
"isExpression": false,
"asc": true,
"nulls": "last",
"opclass": "gin_trgm_ops"
}
],
"isUnique": false,
"concurrently": false,
"method": "gin",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"actual.payees": {
"name": "payees",
"schema": "actual",
"columns": {
"id": {
"name": "id",
"type": "varchar(36)",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"transfer_acct": {
"name": "transfer_acct",
"type": "varchar(36)",
"primaryKey": false,
"notNull": false
},
"favorite": {
"name": "favorite",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"learn_categories": {
"name": "learn_categories",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": true
},
"tombstone": {
"name": "tombstone",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"category": {
"name": "category",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"payees_name_index": {
"name": "payees_name_index",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"payees\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
},
"payees_transfer_acct_name_index": {
"name": "payees_transfer_acct_name_index",
"columns": [
{
"expression": "transfer_acct",
"isExpression": false,
"asc": false,
"nulls": "first"
},
{
"expression": "LOWER(\"name\")",
"asc": true,
"isExpression": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"actual\".\"payees\".\"tombstone\" IS FALSE",
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"payees_transfer_acct_accounts_id_fk": {
"name": "payees_transfer_acct_accounts_id_fk",
"tableFrom": "payees",
"tableTo": "accounts",
"schemaTo": "actual",
"columnsFrom": [
"transfer_acct"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {
"actual": "actual"
},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,223 @@
{
"version": "7",
"dialect": "postgresql",
"entries": [
{
"idx": 0,
"version": "7",
"when": 1746804001125,
"tag": "0000_actual",
"breakpoints": true
},
{
"idx": 1,
"version": "7",
"when": 1746804080933,
"tag": "0001_banks",
"breakpoints": true
},
{
"idx": 2,
"version": "7",
"when": 1746804090229,
"tag": "0002_accounts",
"breakpoints": true
},
{
"idx": 3,
"version": "7",
"when": 1746804097946,
"tag": "0003_category_groups",
"breakpoints": true
},
{
"idx": 4,
"version": "7",
"when": 1746804110341,
"tag": "0004_categories",
"breakpoints": true
},
{
"idx": 5,
"version": "7",
"when": 1746804128843,
"tag": "0005_category_mapping",
"breakpoints": true
},
{
"idx": 6,
"version": "7",
"when": 1746804137174,
"tag": "0006_kvcache",
"breakpoints": true
},
{
"idx": 7,
"version": "7",
"when": 1746804144286,
"tag": "0007_kvcache_key",
"breakpoints": true
},
{
"idx": 8,
"version": "7",
"when": 1746804157965,
"tag": "0008_messages_clock",
"breakpoints": true
},
{
"idx": 9,
"version": "7",
"when": 1746804168475,
"tag": "0009_messages_crdt",
"breakpoints": true
},
{
"idx": 10,
"version": "7",
"when": 1746804176918,
"tag": "0010_notes",
"breakpoints": true
},
{
"idx": 11,
"version": "7",
"when": 1746804184977,
"tag": "0011_payees",
"breakpoints": true
},
{
"idx": 12,
"version": "7",
"when": 1746804197035,
"tag": "0012_payee_mapping",
"breakpoints": true
},
{
"idx": 13,
"version": "7",
"when": 1746804206655,
"tag": "0013_rules",
"breakpoints": true
},
{
"idx": 14,
"version": "7",
"when": 1746804214941,
"tag": "0014_schedules",
"breakpoints": true
},
{
"idx": 15,
"version": "7",
"when": 1746804226176,
"tag": "0015_schedules_json_paths",
"breakpoints": true
},
{
"idx": 16,
"version": "7",
"when": 1746804234405,
"tag": "0016_schedules_next_date",
"breakpoints": true
},
{
"idx": 17,
"version": "7",
"when": 1746804250495,
"tag": "0017_transactions",
"breakpoints": true
},
{
"idx": 18,
"version": "7",
"when": 1746804262438,
"tag": "0018_reflect_budgets",
"breakpoints": true
},
{
"idx": 19,
"version": "7",
"when": 1746804272345,
"tag": "0019_zero_budgets",
"breakpoints": true
},
{
"idx": 20,
"version": "7",
"when": 1746804370208,
"tag": "0020_zero_budget_months",
"breakpoints": true
},
{
"idx": 21,
"version": "7",
"when": 1746804378691,
"tag": "0021_transaction_filters",
"breakpoints": true
},
{
"idx": 22,
"version": "7",
"when": 1746804388851,
"tag": "0022_preferences",
"breakpoints": true
},
{
"idx": 23,
"version": "7",
"when": 1746804397783,
"tag": "0023_custom_reports",
"breakpoints": true
},
{
"idx": 24,
"version": "7",
"when": 1746804406335,
"tag": "0024_dashboard",
"breakpoints": true
},
{
"idx": 25,
"version": "7",
"when": 1746804423286,
"tag": "0025_v_transactions_internal",
"breakpoints": true
},
{
"idx": 26,
"version": "7",
"when": 1746804433194,
"tag": "0026_v_transactions_internal_alive",
"breakpoints": true
},
{
"idx": 27,
"version": "7",
"when": 1746804442376,
"tag": "0027_v_transactions",
"breakpoints": true
},
{
"idx": 28,
"version": "7",
"when": 1746804450701,
"tag": "0028_v_categories",
"breakpoints": true
},
{
"idx": 29,
"version": "7",
"when": 1746804461121,
"tag": "0029_v_payees",
"breakpoints": true
},
{
"idx": 30,
"version": "7",
"when": 1746804470099,
"tag": "0030_v_schedules",
"breakpoints": true
}
]
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,555 @@
BEGIN TRANSACTION;
-- banks table
CREATE TRIGGER banks_after_insert_pglite_sync
AFTER INSERT ON banks
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('banks', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER banks_after_update_pglite_sync
AFTER UPDATE ON banks
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('banks', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER banks_after_delete_pglite_sync
AFTER DELETE ON banks
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('banks', 'DELETE', 'id', OLD.id);
END;
-- accounts table
CREATE TRIGGER accounts_after_insert_pglite_sync
AFTER INSERT ON accounts
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('accounts', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER accounts_after_update_pglite_sync
AFTER UPDATE ON accounts
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('accounts', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER accounts_after_delete_pglite_sync
AFTER DELETE ON accounts
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('accounts', 'DELETE', 'id', OLD.id);
END;
-- category_groups table
CREATE TRIGGER category_groups_after_insert_pglite_sync
AFTER INSERT ON category_groups
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('category_groups', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER category_groups_after_update_pglite_sync
AFTER UPDATE ON category_groups
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('category_groups', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER category_groups_after_delete_pglite_sync
AFTER DELETE ON category_groups
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('category_groups', 'DELETE', 'id', OLD.id);
END;
-- categories table
CREATE TRIGGER categories_after_insert_pglite_sync
AFTER INSERT ON categories
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('categories', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER categories_after_update_pglite_sync
AFTER UPDATE ON categories
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('categories', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER categories_after_delete_pglite_sync
AFTER DELETE ON categories
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('categories', 'DELETE', 'id', OLD.id);
END;
-- category_mapping table
CREATE TRIGGER category_mapping_after_insert_pglite_sync
AFTER INSERT ON category_mapping
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('category_mapping', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER category_mapping_after_update_pglite_sync
AFTER UPDATE ON category_mapping
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('category_mapping', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER category_mapping_after_delete_pglite_sync
AFTER DELETE ON category_mapping
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('category_mapping', 'DELETE', 'id', OLD.id);
END;
-- kvcache table
CREATE TRIGGER kvcache_after_insert_pglite_sync
AFTER INSERT ON kvcache
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('kvcache', 'INSERT', 'key', NEW.key);
END;
CREATE TRIGGER kvcache_after_update_pglite_sync
AFTER UPDATE ON kvcache
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('kvcache', 'UPDATE', 'key', NEW.key);
END;
CREATE TRIGGER kvcache_after_delete_pglite_sync
AFTER DELETE ON kvcache
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('kvcache', 'DELETE', 'key', OLD.key);
END;
-- kvcache_key table
CREATE TRIGGER kvcache_key_after_insert_pglite_sync
AFTER INSERT ON kvcache_key
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('kvcache_key', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER kvcache_key_after_update_pglite_sync
AFTER UPDATE ON kvcache_key
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('kvcache_key', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER kvcache_key_after_delete_pglite_sync
AFTER DELETE ON kvcache_key
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('kvcache_key', 'DELETE', 'id', OLD.id);
END;
-- messages_clock table
CREATE TRIGGER messages_clock_after_insert_pglite_sync
AFTER INSERT ON messages_clock
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('messages_clock', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER messages_clock_after_update_pglite_sync
AFTER UPDATE ON messages_clock
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('messages_clock', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER messages_clock_after_delete_pglite_sync
AFTER DELETE ON messages_clock
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('messages_clock', 'DELETE', 'id', OLD.id);
END;
-- messages_crdt table
CREATE TRIGGER messages_crdt_after_insert_pglite_sync
AFTER INSERT ON messages_crdt
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('messages_crdt', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER messages_crdt_after_update_pglite_sync
AFTER UPDATE ON messages_crdt
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('messages_crdt', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER messages_crdt_after_delete_pglite_sync
AFTER DELETE ON messages_crdt
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('messages_crdt', 'DELETE', 'id', OLD.id);
END;
-- notes table
CREATE TRIGGER notes_after_insert_pglite_sync
AFTER INSERT ON notes
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('notes', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER notes_after_update_pglite_sync
AFTER UPDATE ON notes
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('notes', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER notes_after_delete_pglite_sync
AFTER DELETE ON notes
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('notes', 'DELETE', 'id', OLD.id);
END;
-- payees table
CREATE TRIGGER payees_after_insert_pglite_sync
AFTER INSERT ON payees
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('payees', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER payees_after_update_pglite_sync
AFTER UPDATE ON payees
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('payees', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER payees_after_delete_pglite_sync
AFTER DELETE ON payees
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('payees', 'DELETE', 'id', OLD.id);
END;
-- payee_mapping table
CREATE TRIGGER payee_mapping_after_insert_pglite_sync
AFTER INSERT ON payee_mapping
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('payee_mapping', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER payee_mapping_after_update_pglite_sync
AFTER UPDATE ON payee_mapping
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('payee_mapping', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER payee_mapping_after_delete_pglite_sync
AFTER DELETE ON payee_mapping
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('payee_mapping', 'DELETE', 'id', OLD.id);
END;
-- rules table
CREATE TRIGGER rules_after_insert_pglite_sync
AFTER INSERT ON rules
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('rules', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER rules_after_update_pglite_sync
AFTER UPDATE ON rules
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('rules', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER rules_after_delete_pglite_sync
AFTER DELETE ON rules
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('rules', 'DELETE', 'id', OLD.id);
END;
-- schedules table
CREATE TRIGGER schedules_after_insert_pglite_sync
AFTER INSERT ON schedules
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('schedules', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER schedules_after_update_pglite_sync
AFTER UPDATE ON schedules
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('schedules', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER schedules_after_delete_pglite_sync
AFTER DELETE ON schedules
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('schedules', 'DELETE', 'id', OLD.id);
END;
-- schedules_json_paths table
CREATE TRIGGER schedules_json_paths_after_insert_pglite_sync
AFTER INSERT ON schedules_json_paths
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('schedules_json_paths', 'INSERT', 'schedule_id', NEW.schedule_id);
END;
CREATE TRIGGER schedules_json_paths_after_update_pglite_sync
AFTER UPDATE ON schedules_json_paths
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('schedules_json_paths', 'UPDATE', 'schedule_id', NEW.schedule_id);
END;
CREATE TRIGGER schedules_json_paths_after_delete_pglite_sync
AFTER DELETE ON schedules_json_paths
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('schedules_json_paths', 'DELETE', 'schedule_id', OLD.schedule_id);
END;
-- schedules_next_date table
CREATE TRIGGER schedules_next_date_after_insert_pglite_sync
AFTER INSERT ON schedules_next_date
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('schedules_next_date', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER schedules_next_date_after_update_pglite_sync
AFTER UPDATE ON schedules_next_date
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('schedules_next_date', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER schedules_next_date_after_delete_pglite_sync
AFTER DELETE ON schedules_next_date
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('schedules_next_date', 'DELETE', 'id', OLD.id);
END;
-- transactions table
CREATE TRIGGER transactions_after_insert_pglite_sync
AFTER INSERT ON transactions
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('transactions', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER transactions_after_update_pglite_sync
AFTER UPDATE ON transactions
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('transactions', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER transactions_after_delete_pglite_sync
AFTER DELETE ON transactions
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('transactions', 'DELETE', 'id', OLD.id);
END;
-- reflect_budgets table
CREATE TRIGGER reflect_budgets_after_insert_pglite_sync
AFTER INSERT ON reflect_budgets
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('reflect_budgets', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER reflect_budgets_after_update_pglite_sync
AFTER UPDATE ON reflect_budgets
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('reflect_budgets', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER reflect_budgets_after_delete_pglite_sync
AFTER DELETE ON reflect_budgets
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('reflect_budgets', 'DELETE', 'id', OLD.id);
END;
-- zero_budgets table
CREATE TRIGGER zero_budgets_after_insert_pglite_sync
AFTER INSERT ON zero_budgets
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('zero_budgets', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER zero_budgets_after_update_pglite_sync
AFTER UPDATE ON zero_budgets
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('zero_budgets', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER zero_budgets_after_delete_pglite_sync
AFTER DELETE ON zero_budgets
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('zero_budgets', 'DELETE', 'id', OLD.id);
END;
-- zero_budget_months table
CREATE TRIGGER zero_budget_months_after_insert_pglite_sync
AFTER INSERT ON zero_budget_months
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('zero_budget_months', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER zero_budget_months_after_update_pglite_sync
AFTER UPDATE ON zero_budget_months
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('zero_budget_months', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER zero_budget_months_after_delete_pglite_sync
AFTER DELETE ON zero_budget_months
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('zero_budget_months', 'DELETE', 'id', OLD.id);
END;
-- transaction_filters table
CREATE TRIGGER transaction_filters_after_insert_pglite_sync
AFTER INSERT ON transaction_filters
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('transaction_filters', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER transaction_filters_after_update_pglite_sync
AFTER UPDATE ON transaction_filters
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('transaction_filters', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER transaction_filters_after_delete_pglite_sync
AFTER DELETE ON transaction_filters
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('transaction_filters', 'DELETE', 'id', OLD.id);
END;
-- preferences table
CREATE TRIGGER preferences_after_insert_pglite_sync
AFTER INSERT ON preferences
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('preferences', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER preferences_after_update_pglite_sync
AFTER UPDATE ON preferences
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('preferences', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER preferences_after_delete_pglite_sync
AFTER DELETE ON preferences
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('preferences', 'DELETE', 'id', OLD.id);
END;
-- custom_reports table
CREATE TRIGGER custom_reports_after_insert_pglite_sync
AFTER INSERT ON custom_reports
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('custom_reports', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER custom_reports_after_update_pglite_sync
AFTER UPDATE ON custom_reports
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('custom_reports', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER custom_reports_after_delete_pglite_sync
AFTER DELETE ON custom_reports
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('custom_reports', 'DELETE', 'id', OLD.id);
END;
-- dashboard table
CREATE TRIGGER dashboard_after_insert_pglite_sync
AFTER INSERT ON dashboard
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('dashboard', 'INSERT', 'id', NEW.id);
END;
CREATE TRIGGER dashboard_after_update_pglite_sync
AFTER UPDATE ON dashboard
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('dashboard', 'UPDATE', 'id', NEW.id);
END;
CREATE TRIGGER dashboard_after_delete_pglite_sync
AFTER DELETE ON dashboard
FOR EACH ROW
BEGIN
SELECT PGLITE_SYNC('dashboard', 'DELETE', 'id', OLD.id);
END;
COMMIT;

View File

@@ -60,9 +60,11 @@
"generate:i18n": "i18next",
"test": "npm-run-all -cp 'test:*'",
"test:node": "ENV=node vitest --run",
"test:web": "ENV=web vitest --run -c vitest.web.config.ts"
"test:web": "ENV=web vitest --run -c vitest.web.config.ts",
"generate:db-migrations": "drizzle-kit generate --config=drizzle.config.ts $@ && node ./bin/compile-drizzle-migrations.mjs"
},
"dependencies": {
"@electric-sql/pglite": "^0.3.14",
"@jlongster/sql.js": "^1.6.7",
"@reduxjs/toolkit": "^2.10.1",
"@rschedule/core": "^1.5.0",
@@ -75,6 +77,7 @@
"csv-stringify": "^6.6.0",
"date-fns": "^4.1.0",
"deep-equal": "^2.2.3",
"drizzle-orm": "^0.45.1",
"handlebars": "^4.7.8",
"lru-cache": "^11.2.2",
"md5": "^2.3.0",
@@ -99,6 +102,7 @@
"browserify-zlib": "^0.2.0",
"buffer": "^6.0.3",
"cross-env": "^10.1.0",
"drizzle-kit": "^0.31.8",
"fake-indexeddb": "^6.2.5",
"fast-check": "4.3.0",
"i18next": "^25.6.2",

View File

@@ -0,0 +1,7 @@
import { PGlite } from '@electric-sql/pglite';
import { drizzle } from 'drizzle-orm/pglite';
export type PgliteDatabase = ReturnType<typeof drizzle>;
export async function openDatabase(id?: string): Promise<PgliteDatabase>;
export async function exportDatabase(db: PGlite): Promise<Uint8Array>;

View File

@@ -0,0 +1,152 @@
import { PGlite, PGliteOptions, types } from '@electric-sql/pglite';
import { pg_trgm } from '@electric-sql/pglite/contrib/pg_trgm';
import { live } from '@electric-sql/pglite/live';
import { drizzle } from 'drizzle-orm/pglite';
import drizzleConfig from '../../../../drizzle.config';
import * as schema from '../../../server/db/schema';
import * as prefs from '../../../server/prefs';
import { PgliteDatabase } from '.';
let db: PgliteDatabase = null;
const serializers: PGliteOptions['serializers'] = {
[types.BOOL]: value => {
switch (value) {
case null:
case 0:
return 'FALSE';
case 1:
return 'TRUE';
default:
return value;
}
},
};
const parsers: PGliteOptions['parsers'] = {
[types.BOOL]: value => {
switch (value) {
case null:
case 'f':
return 0;
case 't':
return 1;
default:
return value;
}
},
};
const extensions: PGliteOptions['extensions'] = {
live,
pg_trgm,
};
export async function openDatabase(id?: string): Promise<PgliteDatabase> {
// if (dataDir) {
// const indexedDb = idb.openDatabase();
// return await PGlite.create({
// loadDataDir: new Blob([file]),
// relaxedDurability: true,
// });
// }
// if (id && !id.startsWith('idb://')) {
// throw new Error('Only idb:// dataDir is supported.');
// }
const dataDir = ensureDataDir(id);
if (db) {
if (db.$client.dataDir === dataDir) {
return db;
} else {
db.$client.close();
db = null;
}
}
const client = await PGlite.create(dataDir, {
relaxedDurability: true,
extensions,
// Maintain compatibility with the sqlite schema for now.
serializers,
parsers,
});
db = drizzle({
client,
logger: true,
schema,
casing: drizzleConfig.casing,
});
// Enable extensions as needed.
await db.execute('CREATE EXTENSION IF NOT EXISTS pg_trgm');
/* eslint-disable rulesdir/typography */
const results = await db.execute(
`SELECT table_name, column_name, data_type
FROM information_schema.columns
WHERE table_schema = 'actual'
ORDER BY table_name, ordinal_position;
`,
);
/* eslint-enable rulesdir/typography */
console.log('PGlite columns:', JSON.stringify(results));
return db;
}
export async function exportDatabase(db: PGlite): Promise<Uint8Array> {
const dump = await db.dumpDataDir();
if (dump instanceof File) {
return await fileToUint8Array(dump);
}
return await blobToUint8Array(dump);
}
function fileToUint8Array(file: File): Promise<Uint8Array> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const arrayBuffer = reader.result; // The ArrayBuffer of the file
const uint8Array =
typeof arrayBuffer === 'string'
? new TextEncoder().encode(arrayBuffer)
: new Uint8Array(arrayBuffer);
resolve(uint8Array);
};
reader.onerror = reject; // Handle any error in reading the file
reader.readAsArrayBuffer(file); // Reads the file as an array buffer
});
}
function blobToUint8Array(blob: Blob): Promise<Uint8Array> {
return new Promise((resolve, reject) => {
blob
.arrayBuffer()
.then(arrayBuffer => {
const uint8Array = new Uint8Array(arrayBuffer);
resolve(uint8Array);
})
.catch(reject);
});
}
function ensureDataDir(id?: string) {
if (!id) {
const currentPrefs = prefs.getPrefs();
if (!currentPrefs || !currentPrefs.id) {
throw new Error('No id provided and there is no budget file currently open.');
}
id = currentPrefs.id;
}
return `idb://${id}`;
}

View File

@@ -6,6 +6,7 @@ import { removeFile, readFile } from '../fs';
import { logger } from '../log';
import { normalise } from './normalise';
import { pgliteSync } from './pgliteSync';
import { unicodeLike } from './unicodeLike';
function verifyParamTypes(sql, arr) {
@@ -113,6 +114,8 @@ export function openDatabase(pathOrBuffer: string | Buffer) {
db.function('UNICODE_LIKE', { deterministic: true }, unicodeLike);
db.function('REGEXP', { deterministic: true }, regexp);
db.function('NORMALISE', { deterministic: true }, normalise);
// @ts-expect-error @types/better-sqlite3 does not support setting strict 3rd argument
db.function('SYNC_PGLITE', { deterministic: true }, pgliteSync);
return db;
}

View File

@@ -4,6 +4,7 @@ import initSqlJS, { type Database } from '@jlongster/sql.js';
import { logger } from '../log';
import { normalise } from './normalise';
import { pgliteSync } from './pgliteSync';
import { unicodeLike } from './unicodeLike';
import type { SqlJsModule } from '.';
@@ -205,6 +206,7 @@ export async function openDatabase(pathOrBuffer?: string | Buffer) {
db.create_function('UNICODE_LIKE', unicodeLike);
db.create_function('REGEXP', regexp);
db.create_function('NORMALISE', normalise);
db.create_function('PGLITE_SYNC', pgliteSync);
return db;
}

View File

@@ -0,0 +1,6 @@
export function pgliteSync(
table: string,
operation: 'INSERT' | 'UPDATE' | 'DELETE',
primaryKeyColumn: string,
primaryKeyValue: string,
): 1 | 0;

View File

@@ -0,0 +1,145 @@
import { sql } from 'drizzle-orm';
import * as db from '../../../server/db';
import { actualSchema } from '../../../server/db/schema';
import * as dbUtil from '../../../server/db/util';
import * as pglite from '../pglite';
import * as sqlite from '.';
// These have been renamed in the PGlite schema so that
// they match the rest of the schema which is snake_case.
const RENAMED_COLUMNS = new Map([
['targetId', 'target_id'],
['transferId', 'transfer_id'],
['isParent', 'is_parent'],
['isChild', 'is_child'],
]);
export function pgliteSync(
table: string,
operation: 'INSERT' | 'UPDATE' | 'DELETE',
primaryKeyColumn: string,
primaryKeyValue: string,
) {
// Default to id.
primaryKeyColumn = primaryKeyColumn || 'id';
console.log(
'pgliteSync',
table,
operation,
primaryKeyColumn,
primaryKeyValue,
);
switch (operation) {
case 'INSERT':
case 'UPDATE':
insertOrUpdateRow(table, primaryKeyColumn, primaryKeyValue);
break;
case 'DELETE':
deleteRow(table, primaryKeyColumn, primaryKeyValue);
break;
default:
return 0;
}
return 1;
}
async function insertOrUpdateRow(
table: string,
primaryKeyColumn: string,
primaryKeyValue: string,
): Promise<void> {
const pgliteDb = await pglite.openDatabase();
// Get from sqlite.
const sqliteDb = db.getDatabase();
const [row] = await sqlite.runQuery<Record<string, unknown>>(
sqliteDb,
`SELECT * FROM ${table} WHERE ${primaryKeyColumn} = ?`,
[primaryKeyValue],
true,
);
if (!row) {
console.warn(
`${table} row not found in sqlite with ${primaryKeyColumn}: ${primaryKeyValue}`,
);
return;
}
console.log(`${table} row from sqlite:`, JSON.stringify(row));
const columnNames = Object.keys(row).map(column => {
const renamedColumn = RENAMED_COLUMNS.get(column);
return renamedColumn ? renamedColumn : column;
});
const columns = sql.join(
columnNames.map(column => sql.identifier(column)),
sql`,`,
);
const values = sql.join(
Object.values(row).map(value => sql`${value}`),
sql`,`,
);
const updateValues = sql.join(
columnNames
// No need to update the id column.
.filter(column => column !== primaryKeyColumn)
.map(
column => sql`${sql.identifier(column)} = ${dbUtil.excluded(column)}`,
),
sql`,`,
);
try {
await pgliteDb.execute(sql`
INSERT INTO ${actualSchema}.${sql.identifier(table)} (${columns}) VALUES (${values})
ON CONFLICT (${sql.identifier(primaryKeyColumn)}) DO UPDATE SET ${updateValues}
`);
const { rows } = await pgliteDb.execute(sql`
SELECT * FROM ${actualSchema}.${sql.identifier(table)}
WHERE ${sql.identifier(primaryKeyColumn)} = ${primaryKeyValue}
`);
console.log(
`${table} row inserted/updated in PGlite:`,
JSON.stringify(rows[0]),
);
} catch (err) {
console.error(
`Error inserting/updating ${table} row in PGlite with ${primaryKeyColumn}: ${primaryKeyValue}`,
err,
);
}
}
async function deleteRow(
table: string,
primaryKeyColumn: string,
primaryKeyValue: string,
): Promise<void> {
console.log(`Deleting row with ${primaryKeyColumn}:`, primaryKeyValue);
const pgliteDb = await pglite.openDatabase();
try {
await pgliteDb.execute(sql`
DELETE FROM ${actualSchema}.${sql.identifier(table)}
WHERE ${sql.identifier(primaryKeyColumn)} = ${primaryKeyValue}
`);
console.log(
`${table} row deleted from PGlite with ${primaryKeyColumn}:`,
primaryKeyValue,
);
} catch (err) {
console.error(
`Error deleting ${table} row in PGlite with ${primaryKeyColumn}: ${primaryKeyValue}`,
err,
);
}
}

View File

@@ -0,0 +1,151 @@
import { sql } from 'drizzle-orm';
import * as db from '../../../server/db';
import { actualSchema } from '../../../server/db/schema';
import * as dbUtil from '../../../server/db/util';
import * as pglite from '../pglite';
import * as sqlite from '.';
import { logger } from '../log';
// These have been renamed in the PGlite schema so that
// they match the rest of the schema which is snake_case.
const RENAMED_COLUMNS = new Map([
['targetId', 'target_id'],
['transferId', 'transfer_id'],
['isParent', 'is_parent'],
['isChild', 'is_child'],
]);
export function pgliteSync(
table: string,
operation: 'INSERT' | 'UPDATE' | 'DELETE',
primaryKeyColumn: string,
primaryKeyValue: string,
) {
// Default to id.
primaryKeyColumn = primaryKeyColumn || 'id';
console.log(
'pgliteSync',
table,
operation,
primaryKeyColumn,
primaryKeyValue,
);
switch (operation) {
case 'INSERT':
case 'UPDATE':
insertOrUpdateRow(table, primaryKeyColumn, primaryKeyValue);
break;
case 'DELETE':
deleteRow(table, primaryKeyColumn, primaryKeyValue);
break;
default:
return 0;
}
return 1;
}
async function insertOrUpdateRow(
table: string,
primaryKeyColumn: string,
primaryKeyValue: string,
): Promise<void> {
const pgliteDb = await pglite.openDatabase();
// Get from sqlite.
const sqliteDb = db.getDatabase();
if (!sqliteDb) {
logger.warn('No sqlite database found for pglite sync');
return;
}
const [row] = await sqlite.runQuery<Record<string, unknown>>(
sqliteDb,
`SELECT * FROM ${table} WHERE ${primaryKeyColumn} = ?`,
[primaryKeyValue],
true,
);
if (!row) {
console.warn(
`${table} row not found in sqlite with ${primaryKeyColumn}: ${primaryKeyValue}`,
);
return;
}
console.log(`${table} row from sqlite:`, JSON.stringify(row));
const columnNames = Object.keys(row).map(column => {
const renamedColumn = RENAMED_COLUMNS.get(column);
return renamedColumn ? renamedColumn : column;
});
const columns = sql.join(
columnNames.map(column => sql.identifier(column)),
sql`,`,
);
const values = sql.join(
Object.values(row).map(value => sql`${value}`),
sql`,`,
);
const updateValues = sql.join(
columnNames
// No need to update the id column.
.filter(column => column !== primaryKeyColumn)
.map(
column => sql`${sql.identifier(column)} = ${dbUtil.excluded(column)}`,
),
sql`,`,
);
try {
await pgliteDb.execute(sql`
INSERT INTO ${actualSchema}.${sql.identifier(table)} (${columns}) VALUES (${values})
ON CONFLICT (${sql.identifier(primaryKeyColumn)}) DO UPDATE SET ${updateValues}
`);
const { rows } = await pgliteDb.execute(sql`
SELECT * FROM ${actualSchema}.${sql.identifier(table)}
WHERE ${sql.identifier(primaryKeyColumn)} = ${primaryKeyValue}
`);
console.log(
`${table} row inserted/updated in PGlite:`,
JSON.stringify(rows[0]),
);
} catch (err) {
console.error(
`Error inserting/updating ${table} row in PGlite with ${primaryKeyColumn}: ${primaryKeyValue}`,
err,
);
}
}
async function deleteRow(
table: string,
primaryKeyColumn: string,
primaryKeyValue: string,
): Promise<void> {
console.log(`Deleting row with ${primaryKeyColumn}:`, primaryKeyValue);
const pgliteDb = await pglite.openDatabase();
try {
await pgliteDb.execute(sql`
DELETE FROM ${actualSchema}.${sql.identifier(table)}
WHERE ${sql.identifier(primaryKeyColumn)} = ${primaryKeyValue}
`);
console.log(
`${table} row deleted from PGlite with ${primaryKeyColumn}:`,
primaryKeyValue,
);
} catch (err) {
console.error(
`Error deleting ${table} row in PGlite with ${primaryKeyColumn}: ${primaryKeyValue}`,
err,
);
}
}

View File

@@ -0,0 +1,699 @@
import { Clock, deserializeClock, serializeClock } from '@actual-app/crdt';
import { and, eq, isNotNull, isNull, or, sql } from 'drizzle-orm';
import {
AnyPgColumn,
bigint,
boolean,
customType,
date,
index,
integer,
jsonb,
pgSchema,
QueryBuilder,
serial,
text,
varchar,
doublePrecision,
smallint,
} from 'drizzle-orm/pg-core';
import drizzleConfig from '../../../../drizzle.config';
import { Template } from '../../budget/types/templates';
import { isFalse, lower } from '../util';
const bytea = customType<{
// data: Buffer;
data: Uint8Array;
default: false;
}>({
dataType() {
return 'bytea';
},
});
export const actualSchema = pgSchema('actual');
export const banksTable = actualSchema.table(
'banks',
{
id: varchar({ length: 36 }).primaryKey(),
name: text(),
bankId: text(),
tombstone: boolean().default(false),
},
table => [index().on(table.bankId).where(isFalse(table.tombstone))],
);
export const accountsTable = actualSchema.table(
'accounts',
{
id: varchar({ length: 36 }).primaryKey(),
name: text(),
offbudget: boolean().default(false),
closed: boolean().default(false),
sortOrder: bigint({ mode: 'number' }),
// This is UUID but with some prefix.
accountId: text(),
balanceCurrent: bigint({ mode: 'number' }),
balanceAvailable: bigint({ mode: 'number' }),
balanceLimit: bigint({ mode: 'number' }),
mask: text(),
officialName: text(),
type: text(),
subtype: text(),
bank: varchar({ length: 36 }).references(() => banksTable.id),
accountSyncSource: text({
enum: ['simpleFin', 'goCardless', 'pluggyai'],
}),
// These are texts in sqlite but bigint in pglite
lastSync: bigint({ mode: 'number' }),
lastReconciled: bigint({ mode: 'number' }),
tombstone: boolean().default(false),
},
table => [
index().on(table.name).where(isFalse(table.tombstone)),
index().on(table.bank).where(isFalse(table.tombstone)),
// Sorting indeces
index().on(table.sortOrder, table.name),
],
);
export const categoryGroupsTable = actualSchema.table(
'category_groups',
{
id: varchar({ length: 36 }).primaryKey(),
name: text(),
isIncome: boolean().default(false),
sortOrder: bigint({ mode: 'number' }),
hidden: boolean().default(false),
tombstone: boolean().default(false),
},
table => [
index().on(table.name).where(isFalse(table.tombstone)),
// Sorting indeces
index().on(table.isIncome, table.sortOrder, table.id),
index().on(table.sortOrder, table.id),
],
);
export const categoriesTable = actualSchema.table(
'categories',
{
id: varchar({ length: 36 }).primaryKey(),
name: text(),
isIncome: boolean().default(false),
catGroup: varchar({ length: 36 }).references(() => categoryGroupsTable.id),
sortOrder: bigint({ mode: 'number' }),
hidden: boolean().default(false),
goalDef: jsonb().$type<Template[]>(),
tombstone: boolean().default(false),
},
table => [
index().on(table.name).where(isFalse(table.tombstone)),
index().on(table.catGroup).where(isFalse(table.tombstone)),
// Sorting indeces
index().on(table.sortOrder, table.id),
index().on(table.goalDef.nullsFirst()),
],
);
export const categoryMappingTable = actualSchema.table(
'category_mapping',
{
id: varchar({ length: 36 })
.primaryKey()
.references(() => categoriesTable.id),
// This column is camelCase in sqlite. Let's use snake_case in pglite for consistency.
transferId: varchar({ length: 36 }).references(() => categoriesTable.id),
},
table => [index().on(table.transferId)],
);
export const kvCacheTable = actualSchema.table('kvcache', {
key: text().primaryKey(),
value: text(),
});
export const kvCacheKeyTable = actualSchema.table(
'kvcache_key',
{
id: smallint().primaryKey(),
key: doublePrecision(),
},
);
const clockJsonb = customType<{ data: Clock; driverData: string }>({
dataType() {
return 'jsonb';
},
toDriver(clock: Clock): string {
return serializeClock(clock);
},
fromDriver(clock: string): Clock {
return deserializeClock(clock);
},
});
export const messagesClockTable = actualSchema.table(
'messages_clock',
{
id: integer().primaryKey(),
clock: clockJsonb(),
},
table => [index().using('gin', table.clock)],
);
export const messagesCrdtTable = actualSchema.table(
'messages_crdt',
{
id: serial().primaryKey(),
timestamp: text(),
dataset: text(),
row: varchar({ length: 36 }),
column: text(),
value: bytea(),
},
table => [
index().on(table.timestamp),
index().on(table.dataset, table.row, table.column, table.timestamp),
],
);
export const notesTable = actualSchema.table(
'notes',
{
id: varchar({ length: 36 }).primaryKey(),
note: text(),
},
table => [index().using('gin', table.note.op('gin_trgm_ops'))],
);
export const payeesTable = actualSchema.table(
'payees',
{
id: varchar({ length: 36 }).primaryKey(),
name: text(),
transferAcct: varchar({ length: 36 }).references(() => accountsTable.id),
favorite: boolean().default(false),
learnCategories: boolean().default(true),
tombstone: boolean().default(false),
// Unused in codebase. Can this be removed?
category: text(),
},
table => [
index().on(table.name).where(isFalse(table.tombstone)),
// Sorting indeces
index('payees_transfer_acct_name_index')
.on(table.transferAcct.nullsFirst().desc(), lower(table.name))
.where(isFalse(table.tombstone)),
],
);
export const payeeMappingTable = actualSchema.table(
'payee_mapping',
{
id: varchar({ length: 36 })
.primaryKey()
.references(() => payeesTable.id),
// This column is camelCase in sqlite. Let's use snake_case in pglite for consistency.
targetId: varchar({ length: 36 }).references(() => payeesTable.id),
},
table => [index().on(table.targetId)],
);
export const rulesTable = actualSchema.table(
'rules',
{
id: varchar({ length: 36 }).primaryKey(),
stage: text({ enum: ['pre', 'post'] }),
conditions: jsonb(),
actions: jsonb(),
tombstone: boolean().default(false),
conditionsOp: text({ enum: ['and', 'or'] }),
},
table => [
index().on(table.stage).where(isFalse(table.tombstone)),
index().using('gin', table.conditions),
index().using('gin', table.actions),
],
);
export const schedulesTable = actualSchema.table(
'schedules',
{
id: varchar({ length: 36 }).primaryKey(),
name: text(),
rule: varchar({ length: 36 }).references(() => rulesTable.id),
active: boolean().default(false),
completed: boolean().default(false),
postsTransaction: boolean().default(false),
tombstone: boolean().default(false),
},
table => [
index().on(table.name).where(isFalse(table.tombstone)),
index().on(table.rule).where(isFalse(table.tombstone)),
index().on(table.completed).where(isFalse(table.tombstone)),
],
);
/**
* This may no longer be needed since postgresql natively
* supports querying jsonb columns.
*/
export const schedulesJsonPathTable = actualSchema.table(
'schedules_json_paths',
{
scheduleId: varchar({ length: 36 })
.primaryKey()
.references(() => schedulesTable.id),
payee: text(),
account: text(),
amount: text(),
date: text(),
},
);
export const schedulesNextDateTable = actualSchema.table(
'schedules_next_date',
{
id: varchar({ length: 36 }).primaryKey(),
scheduleId: varchar({ length: 36 })
.unique()
.references(() => schedulesTable.id),
localNextDate: date({ mode: 'string' }),
localNextDateTs: bigint({ mode: 'number' }),
baseNextDate: date({ mode: 'string' }),
baseNextDateTs: bigint({ mode: 'number' }),
tombstone: boolean().default(false),
},
);
export const transactionsTable = actualSchema.table(
'transactions',
{
id: varchar({ length: 36 }).primaryKey(),
// This column is camelCase in sqlite. Let's use snake_case in pglite for consistency.
isParent: boolean().default(false),
// This column is camelCase in sqlite. Let's use snake_case in pglite for consistency.
isChild: boolean().default(false),
acct: varchar({ length: 36 }).references(() => accountsTable.id),
category: varchar({ length: 36 }).references(() => categoriesTable.id),
amount: bigint({ mode: 'number' }),
description: varchar({ length: 36 }),
notes: text(),
date: date({ mode: 'string' }),
// Need to add AnyPgColumn when self-referencing
// https://orm.drizzle.team/docs/indexes-constraints#foreign-key
parentId: varchar({ length: 36 }).references(
(): AnyPgColumn => transactionsTable.id,
),
financialId: text(),
error: jsonb(),
importedDescription: text(),
// Need to add AnyPgColumn when self-referencing
// https://orm.drizzle.team/docs/indexes-constraints#foreign-key
transferredId: varchar({ length: 36 }).references(
(): AnyPgColumn => transactionsTable.id,
),
schedule: varchar({ length: 36 }).references(() => schedulesTable.id),
sortOrder: bigint({ mode: 'number' }),
startingBalanceFlag: boolean().default(false),
tombstone: boolean().default(false),
cleared: boolean().default(true),
reconciled: boolean().default(false),
rawSyncedData: jsonb(),
// Unused in codebase. Can this be removed?
pending: boolean(),
location: text(),
type: text(),
},
table => [
index().on(table.category, table.date).where(isFalse(table.tombstone)),
index().on(table.acct).where(isFalse(table.tombstone)),
index().on(table.parentId).where(isFalse(table.tombstone)),
// Sorting indeces
index().on(
table.date.desc(),
table.startingBalanceFlag,
table.sortOrder.desc(),
table.id,
),
],
);
export const reflectBudgetsTable = actualSchema.table(
'reflect_budgets',
{
id: text().primaryKey(),
month: date({ mode: 'string' }),
category: varchar({ length: 36 }).references(() => categoriesTable.id),
amount: bigint({ mode: 'number' }),
carryover: boolean().default(false),
goal: bigint({ mode: 'number' }),
longGoal: bigint({ mode: 'number' }),
},
table => [index().on(table.month, table.category)],
);
export const zeroBudgetsTable = actualSchema.table(
'zero_budgets',
{
id: text().primaryKey(),
month: date({ mode: 'string' }),
category: varchar({ length: 36 }).references(() => categoriesTable.id),
amount: bigint({ mode: 'number' }),
carryover: boolean().default(false),
goal: bigint({ mode: 'number' }),
longGoal: bigint({ mode: 'number' }),
},
table => [index().on(table.month, table.category)],
);
export const zeroBudgetMonthsTable = actualSchema.table('zero_budget_months', {
id: text().primaryKey(),
buffered: bigint({ mode: 'number' }),
});
export const transactionFiltersTable = actualSchema.table(
'transaction_filters',
{
id: varchar({ length: 36 }).primaryKey(),
name: text(),
// Consider indexing in the future.
conditions: jsonb(),
conditionsOp: text({ enum: ['and', 'or'] }),
tombstone: boolean().default(false),
},
table => [
index().on(table.name).where(isFalse(table.tombstone)),
index().using('gin', table.conditions).where(isFalse(table.tombstone)),
],
);
export const preferencesTable = actualSchema.table('preferences', {
id: text().primaryKey(),
value: text(),
});
export const customReportsTable = actualSchema.table(
'custom_reports',
{
id: varchar({ length: 36 }).primaryKey(),
name: text(),
startDate: date({ mode: 'string' }),
endDate: date({ mode: 'string' }),
dateStatic: bigint({ mode: 'number' }),
dateRange: text(),
mode: text(),
groupBy: text(),
balanceType: text(),
showEmpty: boolean().default(false),
showOffbudget: boolean().default(false),
showHidden: boolean().default(false),
showUncategorized: boolean().default(false),
selectedCategories: text(),
graphType: text(),
// Consider indexing in the future.
conditions: jsonb(),
conditionsOp: text({ enum: ['and', 'or'] }),
metadata: jsonb(),
interval: text(),
colorScheme: text(),
includeCurrent: boolean().default(false),
sortBy: text(),
tombstone: boolean().default(false),
},
table => [
index().on(table.name).where(isFalse(table.tombstone)),
index().using('gin', table.conditions).where(isFalse(table.tombstone)),
],
);
export const dashboardTable = actualSchema.table(
'dashboard',
{
id: varchar({ length: 36 }).primaryKey(),
type: text(),
width: integer(),
height: integer(),
x: integer(),
y: integer(),
meta: jsonb().$type<Record<string, unknown>>(),
tombstone: boolean().default(false),
},
table => [
// Sorting indeces
index().on(table.y.desc(), table.x.desc()).where(isFalse(table.tombstone)),
],
);
const transactionsInternalViewColumns = {
id: varchar({ length: 36 }),
isParent: boolean(),
isChild: boolean(),
parentId: varchar({ length: 36 }),
account: varchar({ length: 36 }),
category: varchar({ length: 36 }),
amount: bigint({ mode: 'number' }),
payee: varchar({ length: 36 }),
notes: text(),
date: date({ mode: 'string' }),
importedId: text(),
error: jsonb(),
importedPayee: text(),
startingBalanceFlag: boolean(),
transferId: varchar({ length: 36 }),
schedule: varchar({ length: 36 }),
cleared: boolean(),
reconciled: boolean(),
tombstone: boolean(),
sortOrder: bigint({ mode: 'number' }),
};
export const transactionsInternalView = actualSchema
.view('v_transactions_internal', transactionsInternalViewColumns)
.as(
sql`
SELECT
${transactionsTable.id},
${transactionsTable.isParent},
${transactionsTable.isChild},
CASE WHEN ${transactionsTable.isChild} IS FALSE THEN NULL ELSE ${transactionsTable.parentId} END AS parent_id,
${transactionsTable.acct} AS account,
CASE WHEN ${transactionsTable.isParent} IS TRUE THEN NULL ELSE ${categoryMappingTable.transferId} END AS category,
COALESCE(${transactionsTable.amount}, 0) AS amount,
${payeeMappingTable.targetId} AS payee,
${transactionsTable.notes},
${transactionsTable.date},
${transactionsTable.financialId} AS imported_id,
${transactionsTable.error},
${transactionsTable.importedDescription} AS imported_payee,
${transactionsTable.startingBalanceFlag},
${transactionsTable.transferredId} AS transfer_id,
${transactionsTable.schedule},
${transactionsTable.cleared},
${transactionsTable.reconciled},
${transactionsTable.tombstone},
${transactionsTable.sortOrder}
FROM
${transactionsTable}
LEFT JOIN
${categoryMappingTable}
ON ${transactionsTable.category} = ${categoryMappingTable.id}
LEFT JOIN
${payeeMappingTable}
ON ${transactionsTable.description} = ${payeeMappingTable.id}
WHERE
${transactionsTable.date} IS NOT NULL
AND ${transactionsTable.acct} IS NOT NULL
AND (${transactionsTable.isChild} IS FALSE OR ${transactionsTable.parentId} IS NOT NULL)
`,
);
export const transactionsInternalViewAlive = actualSchema
.view('v_transactions_internal_alive', transactionsInternalViewColumns)
.as(
sql`
SELECT
${transactionsInternalView}.*
FROM
${transactionsInternalView}
LEFT JOIN
${transactionsTable}
ON (${transactionsTable.isChild} IS TRUE
AND ${transactionsTable.id} = ${transactionsInternalView.parentId})
WHERE
COALESCE(${transactionsTable.tombstone}, FALSE) IS FALSE
AND (${transactionsInternalView.isChild} IS FALSE OR ${transactionsTable.tombstone} IS FALSE)
`,
);
export const transactionsView = actualSchema
.view('v_transactions', transactionsInternalViewColumns)
.as(
sql`
SELECT
${transactionsInternalViewAlive.id},
${transactionsInternalViewAlive.isParent},
${transactionsInternalViewAlive.isChild},
${transactionsInternalViewAlive.parentId},
${accountsTable.id} AS account,
${categoriesTable.id} AS category,
${transactionsInternalViewAlive.amount},
${payeesTable.id} AS payee,
${transactionsInternalViewAlive.notes},
${transactionsInternalViewAlive.date},
${transactionsInternalViewAlive.importedId},
${transactionsInternalViewAlive.error},
${transactionsInternalViewAlive.importedPayee},
${transactionsInternalViewAlive.startingBalanceFlag},
${transactionsInternalViewAlive.transferId},
${transactionsInternalViewAlive.sortOrder},
${transactionsInternalViewAlive.cleared},
${transactionsInternalViewAlive.reconciled},
${transactionsInternalViewAlive.tombstone},
${transactionsInternalViewAlive.schedule}
FROM
${transactionsInternalViewAlive}
LEFT JOIN
${payeesTable}
ON (${payeesTable.id} = ${transactionsInternalViewAlive.payee}
AND ${payeesTable.tombstone} IS FALSE)
LEFT JOIN
${categoriesTable}
ON (${categoriesTable.id} = ${transactionsInternalViewAlive.category}
AND ${categoriesTable.tombstone} IS FALSE)
LEFT JOIN
${accountsTable}
ON (${accountsTable.id} = ${transactionsInternalViewAlive.account}
AND ${accountsTable.tombstone} IS FALSE)
ORDER BY
${transactionsInternalViewAlive.date} DESC,
${transactionsInternalViewAlive.startingBalanceFlag},
${transactionsInternalViewAlive.sortOrder} DESC,
${transactionsInternalViewAlive.id}
`,
);
// https://github.com/drizzle-team/drizzle-orm/issues/3332
const snakeCaseQueryBuilder = new QueryBuilder({
casing: drizzleConfig.casing,
});
export const categoriesView = actualSchema.view('v_categories').as(
snakeCaseQueryBuilder
.select({
id: categoriesTable.id,
name: categoriesTable.name,
isIncome: categoriesTable.isIncome,
hidden: categoriesTable.hidden,
group: sql`${categoriesTable.catGroup}`.as('group'),
sortOrder: categoriesTable.sortOrder,
tombstone: categoriesTable.tombstone,
})
.from(categoriesTable),
);
export const payeesView = actualSchema.view('v_payees').as(
snakeCaseQueryBuilder
.select({
id: payeesTable.id,
name: sql`COALESCE(${accountsTable.name}, ${payeesTable.name})`.as(
'name',
),
transferAcct: payeesTable.transferAcct,
favorite: payeesTable.favorite,
learnCategories: payeesTable.learnCategories,
tombstone: payeesTable.tombstone,
})
.from(payeesTable)
.leftJoin(
accountsTable,
and(
eq(payeesTable.transferAcct, accountsTable.id),
isFalse(accountsTable.tombstone),
),
)
// We never want to show transfer payees that are pointing to deleted accounts.
// Either this is not a transfer payee, if the account exists
.where(or(isNull(payeesTable.transferAcct), isNotNull(accountsTable.id))),
);
export const schedulesView = actualSchema
.view('v_schedules', {
id: varchar({ length: 36 }),
name: text(),
rule: varchar({ length: 36 }),
nextDate: date({ mode: 'string' }),
completed: boolean(),
postsTransaction: boolean(),
active: boolean(),
tombstone: boolean(),
_payee: varchar({ length: 36 }),
_account: varchar({ length: 36 }),
_amount: text(),
_amountOp: text(),
_date: jsonb(),
_conditions: jsonb(),
_actions: jsonb(),
})
.as(
/* eslint-disable rulesdir/typography */
sql`
WITH parsed_rule_conditions AS (
SELECT
${rulesTable.id} AS rule_id,
jsonb_extract_path_text(condition, 'value') AS value,
condition ->> 'field' AS field,
condition ->> 'op' AS op
FROM
${rulesTable}
CROSS JOIN
jsonb_array_elements(${rulesTable.conditions}::jsonb) AS condition
)
SELECT
${schedulesTable.id},
${schedulesTable.name},
${schedulesTable.rule},
CASE
WHEN ${schedulesNextDateTable.localNextDateTs} = ${schedulesNextDateTable.baseNextDateTs} THEN ${schedulesNextDateTable.localNextDate}
ELSE ${schedulesNextDateTable.baseNextDate}
END AS next_date,
${schedulesTable.completed},
${schedulesTable.postsTransaction},
${schedulesTable.tombstone},
${payeeMappingTable.targetId} AS _payee,
account_condition.value AS _account,
amount_condition.value AS _amount,
amount_condition.op AS _amount_op,
date_condition.value AS _date,
${rulesTable.conditions} AS _conditions,
${rulesTable.actions} AS _actions
FROM
${schedulesTable}
LEFT JOIN
${schedulesNextDateTable} ON ${schedulesNextDateTable.scheduleId} = ${schedulesTable.id}
LEFT JOIN
${rulesTable} ON ${rulesTable.id} = ${schedulesTable.rule}
LEFT JOIN
parsed_rule_conditions payee_condition
ON payee_condition.rule_id = ${rulesTable.id}
AND payee_condition.field = 'payee'
LEFT JOIN
${payeeMappingTable} ON ${payeeMappingTable.id} = payee_condition.value
LEFT JOIN
parsed_rule_conditions account_condition
ON account_condition.rule_id = ${rulesTable.id}
AND account_condition.field = 'account'
LEFT JOIN
parsed_rule_conditions amount_condition
ON amount_condition.rule_id = ${rulesTable.id}
AND amount_condition.field = 'amount'
LEFT JOIN
parsed_rule_conditions date_condition
ON date_condition.rule_id = ${rulesTable.id}
AND date_condition.field = 'date'
`,
/* eslint-enable rulesdir/typography */
);

View File

@@ -136,6 +136,7 @@ export type DbScheduleNextDate = {
local_next_date_ts: number;
base_next_date: number;
base_next_date_ts: number;
tombstone: 1 | 0;
};
// This is unused in the codebase.
@@ -179,7 +180,7 @@ export type DbReflectBudget = {
month: number;
category: string;
amount: number;
carryover: number;
carryover: 1 | 0;
goal: number;
long_goal: number;
};
@@ -194,7 +195,7 @@ export type DbZeroBudget = {
month: number;
category: string;
amount: number;
carryover: number;
carryover: 1 | 0;
goal: number;
long_goal: number;
};
@@ -300,6 +301,8 @@ export type DbViewPayee = {
id: DbPayee['id'];
name: DbAccount['name'] | DbPayee['name'];
transfer_acct: DbPayee['transfer_acct'];
favorite: DbPayee['favorite'];
learn_categories: DbPayee['learn_categories'];
tombstone: DbPayee['tombstone'];
};

View File

@@ -1,3 +1,5 @@
import { Column, sql } from 'drizzle-orm';
// @ts-strict-ignore
export async function incrFetch(
runQuery,
@@ -34,3 +36,27 @@ export function whereIn(ids: string[], field: string) {
const filter = `${field} IN (` + ids2.map(id => `'${id}'`).join(',') + ')';
return filter;
}
// Drizzle ORM expressions
export function isTrue(column: Column | string) {
return sql`${columnOrIdentifier(column)} IS TRUE`;
}
export function isFalse(column: Column | string) {
return sql`${columnOrIdentifier(column)} IS FALSE`;
}
export function excluded(column: Column | string) {
return sql`excluded.${columnOrIdentifier(column)}`;
}
export function lower(column: Column | string) {
return sql`LOWER(${columnOrIdentifier(column)})`;
}
function columnOrIdentifier(column: Column | string) {
if (typeof column === 'string') {
return sql.identifier(column);
}
return column;
}

View File

@@ -2,11 +2,14 @@
import './polyfills';
import * as injectAPI from '@actual-app/api/injected';
import * as CRDT from '@actual-app/crdt';
import { v4 as uuidv4 } from 'uuid';
import * as asyncStorage from '../platform/server/asyncStorage';
import * as connection from '../platform/server/connection';
import * as fs from '../platform/server/fs';
import { logger, setVerboseMode } from '../platform/server/log';
import * as pglite from '../platform/server/pglite';
import * as sqlite from '../platform/server/sqlite';
import { q } from '../shared/query';
import { amountToInteger, integerToAmount } from '../shared/util';

View File

@@ -79,9 +79,9 @@ withMigrationsDir(argv.m || getMigrationsDir(), async () => {
case 'migrate':
const applied = await migrate(getDatabase());
if (applied.length === 0) {
logger.log('No pending migrations');
console.log('No pending migrations');
} else {
logger.log('Applied migrations:\n' + applied.join('\n'));
console.log('Applied migrations:\n' + applied.join('\n'));
}
break;
case 'list':

View File

@@ -2,14 +2,18 @@
// We have to bundle in JS migrations manually to avoid having to `eval`
// them which doesn't play well with CSP. There isn't great, and eventually
// we can remove this migration.
import { type Database } from '@jlongster/sql.js';
import { Database } from '@jlongster/sql.js';
import { PgDialect, PgSession } from 'drizzle-orm/pg-core';
import drizzleMigrations from '../../../drizzle/migrations.json';
import drizzleConfig from '../../../drizzle.config';
import m1632571489012 from '../../../migrations/1632571489012_remove_cache';
import m1722717601000 from '../../../migrations/1722717601000_reports_move_selected_categories';
import m1722804019000 from '../../../migrations/1722804019000_create_dashboard_table';
import m1723665565000 from '../../../migrations/1723665565000_prefs';
import * as fs from '../../platform/server/fs';
import { logger } from '../../platform/server/log';
import * as pglite from '../../platform/server/pglite';
import * as sqlite from '../../platform/server/sqlite';
import * as prefs from '../prefs';
@@ -97,7 +101,7 @@ export function getPending(appliedIds: number[], all: string[]): string[] {
});
}
async function applyJavaScript(db, id) {
async function applyJavaScript(db: Database, id) {
const dbInterface = {
runQuery: (query, params, fetchAll) =>
sqlite.runQuery(db, query, params, fetchAll),
@@ -116,7 +120,7 @@ async function applyJavaScript(db, id) {
});
}
async function applySql(db, sql) {
async function applySql(db: Database, sql: string) {
try {
await sqlite.execQuery(db, sql);
} catch (e) {
@@ -174,3 +178,17 @@ export async function migrate(db: Database): Promise<string[]> {
return pending;
}
export async function migratePGlite(db: pglite.PgliteDatabase) {
console.log('🚀 Starting pglite migration...');
const dialect = new PgDialect({
casing: drizzleConfig.casing,
});
await dialect.migrate(drizzleMigrations, db._.session as PgSession, {
migrationsFolder: '../../../drizzle',
});
console.log('🎉 Completed pglite migration.');
}

View File

@@ -0,0 +1,120 @@
-- __migrations__ definition
CREATE TABLE __migrations__ (
id BIGINT PRIMARY KEY NOT NULL
);
-- accounts definition
CREATE TABLE accounts (
id VARCHAR(36) PRIMARY KEY,
account_id VARCHAR(36),
name TEXT,
balance_current BIGINT,
balance_available BIGINT,
balance_limit BIGINT,
mask TEXT,
official_name TEXT,
type TEXT,
subtype TEXT,
bank TEXT,
offbudget BOOLEAN DEFAULT FALSE,
closed BOOLEAN DEFAULT FALSE,
tombstone BOOLEAN DEFAULT FALSE
);
-- banks definition
CREATE TABLE banks (
id VARCHAR(36) PRIMARY KEY,
bank_id TEXT,
name TEXT,
tombstone BOOLEAN DEFAULT FALSE
);
-- categories definition
CREATE TABLE categories (
id VARCHAR(36) PRIMARY KEY,
name TEXT,
is_income BOOLEAN DEFAULT FALSE,
cat_group VARCHAR(36),
sort_order BIGINT,
tombstone BOOLEAN DEFAULT FALSE
);
-- category_groups definition
CREATE TABLE category_groups (
id VARCHAR(36) PRIMARY KEY,
name TEXT UNIQUE,
is_income BOOLEAN DEFAULT FALSE,
sort_order BIGINT,
tombstone BOOLEAN DEFAULT FALSE
);
-- category_mapping definition
CREATE TABLE category_mapping (
id VARCHAR(36) PRIMARY KEY,
transferId VARCHAR(36)
);
-- created_budgets definition
CREATE TABLE created_budgets (
month TEXT PRIMARY KEY
);
-- db_version definition
CREATE TABLE db_version (
version TEXT PRIMARY KEY
);
-- messages_clock definition
CREATE TABLE messages_clock (
id BIGINT PRIMARY KEY,
clock TEXT
);
-- messages_crdt definition
CREATE TABLE messages_crdt (
id BIGINT PRIMARY KEY,
timestamp BIGINT NOT NULL UNIQUE,
dataset TEXT NOT NULL,
row TEXT NOT NULL,
"column" TEXT NOT NULL,
value BYTEA NOT NULL
);
-- spreadsheet_cells definition
CREATE TABLE spreadsheet_cells (
name TEXT PRIMARY KEY,
expr TEXT,
cachedValue TEXT
);
-- transactions definition
CREATE TABLE transactions (
id VARCHAR(36) PRIMARY KEY,
isParent BOOLEAN DEFAULT FALSE,
isChild BOOLEAN DEFAULT FALSE,
acct VARCHAR(36),
category VARCHAR(36),
amount BIGINT,
description TEXT,
notes TEXT,
date DATE, -- INTEGER in sqlite
financial_id TEXT,
type TEXT,
location TEXT,
error TEXT,
imported_description TEXT,
starting_balance_flag BOOLEAN DEFAULT FALSE,
transferred_id VARCHAR(36),
sort_order BIGINT, -- Using BIGINT to support large sort numbers
tombstone BOOLEAN DEFAULT FALSE
);
-- pending_transactions definition
CREATE TABLE pending_transactions (
id VARCHAR(36) PRIMARY KEY,
acct VARCHAR(36),
amount BIGINT,
description TEXT,
date DATE, -- INTEGER in sqlite
FOREIGN KEY(acct) REFERENCES accounts(id)
);

View File

@@ -1,6 +1,8 @@
// @ts-strict-ignore
import md5 from 'md5';
import * as pglite from '../platform/server/pglite';
import { schema, schemaConfig, makeViews } from './aql';
import * as db from './db';
import * as migrations from './migrate/migrations';
@@ -9,6 +11,7 @@ import * as migrations from './migrate/migrations';
async function runMigrations() {
await migrations.migrate(db.getDatabase());
await migrations.migratePGlite(await pglite.openDatabase());
}
async function updateViews() {

View File

@@ -104,6 +104,7 @@ export default defineConfig(({ mode }) => {
visualizer({ template: 'raw-data', filename: `${outDir}/stats.json` }),
],
optimizeDeps: {
exclude: ['@electric-sql/pglite'],
include: [
'buffer',
'process',

1273
yarn.lock

File diff suppressed because it is too large Load Diff