@kitledger/core 0.0.7 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,7 @@ import * as v from "valibot";
3
3
  import { InferOutput } from "valibot";
4
4
  import { KitledgerDb } from "./db.js";
5
5
  import { FilterOperationParameters, GetOperationResult } from "./db.js";
6
+ import { Ledger } from "./ledgers.js";
6
7
  import { accounts } from "./schema.js";
7
8
  import { ValidationFailure, ValidationSuccess } from "./validation.js";
8
9
  export declare enum BalanceType {
@@ -29,7 +30,7 @@ export type AccountCreateData = InferOutput<typeof AccountCreateSchema>;
29
30
  * @param params
30
31
  * @returns
31
32
  */
32
- export declare function filterAccounts(db: KitledgerDb, params: FilterOperationParameters): Promise<GetOperationResult<Account>>;
33
+ export declare function filterAccounts(db: KitledgerDb, ledgers: Ledger[], params: FilterOperationParameters): Promise<GetOperationResult<Account>>;
33
34
  /**
34
35
  * Finds the parent account by ID or ref_id or alt_id.
35
36
  * Returns the ID of the parent account if found, otherwise returns null.
@@ -40,5 +41,5 @@ export declare function findParentAccount(db: KitledgerDb, parentId: string, led
40
41
  * @param ledgerId
41
42
  * @returns
42
43
  */
43
- export declare function findLedgerId(db: KitledgerDb, ledgerId: string): Promise<string | null>;
44
- export declare function createAccount(db: KitledgerDb, data: AccountCreateData): Promise<ValidationSuccess<Account> | ValidationFailure<AccountCreateData>>;
44
+ export declare function findLedgerId(ledgers: Ledger[], ledgerId: string): Promise<string | null>;
45
+ export declare function createAccount(db: KitledgerDb, ledgers: Ledger[], data: AccountCreateData): Promise<ValidationSuccess<Account> | ValidationFailure<AccountCreateData>>;
package/dist/accounts.js CHANGED
@@ -2,7 +2,7 @@ import { and, eq, or, sql } from "drizzle-orm";
2
2
  import { v7 } from "uuid";
3
3
  import * as v from "valibot";
4
4
  import { ANY, defaultLimit, defaultOffset, maxLimit, parseBooleanFilterValue, } from "./db.js";
5
- import { accounts, ledgers } from "./schema.js";
5
+ import { accounts } from "./schema.js";
6
6
  import { parseValibotIssues, } from "./validation.js";
7
7
  export var BalanceType;
8
8
  (function (BalanceType) {
@@ -26,7 +26,7 @@ export const AccountCreateSchema = v.object({
26
26
  * @param params
27
27
  * @returns
28
28
  */
29
- export async function filterAccounts(db, params) {
29
+ export async function filterAccounts(db, ledgers, params) {
30
30
  const { limit = defaultLimit, offset = defaultOffset, ...filters } = params;
31
31
  const filterConditions = [];
32
32
  let ledgerId = null;
@@ -47,7 +47,7 @@ export async function filterAccounts(db, params) {
47
47
  filterConditions.push(sql `${accounts.name} ILIKE ${"%" + String(value) + "%"}`);
48
48
  }
49
49
  if (key === accounts.ledger_id.name && String(value).length > 0) {
50
- ledgerId = await findLedgerId(db, String(value));
50
+ ledgerId = await findLedgerId(ledgers, String(value));
51
51
  if (ledgerId) {
52
52
  filterConditions.push(eq(accounts.ledger_id, ledgerId));
53
53
  }
@@ -106,12 +106,9 @@ export async function findParentAccount(db, parentId, ledgerId) {
106
106
  * @param ledgerId
107
107
  * @returns
108
108
  */
109
- export async function findLedgerId(db, ledgerId) {
110
- const ledger = await db.query.ledgers.findFirst({
111
- where: and(or(eq(sql `${ledgers.id}::text`, ledgerId), eq(ledgers.ref_id, ledgerId), eq(ledgers.alt_id, ledgerId)), eq(ledgers.active, true)),
112
- columns: { id: true },
113
- });
114
- return ledger ? ledger.id : null;
109
+ export async function findLedgerId(ledgers, ledgerId) {
110
+ const ledger = ledgers.find((l) => l.refId === ledgerId);
111
+ return ledger ? ledger.refId : null;
115
112
  }
116
113
  // ACTIONS
117
114
  async function refIdAlreadyExists(db, refId) {
@@ -131,7 +128,7 @@ async function altIdAlreadyExists(db, altId) {
131
128
  });
132
129
  return results.length > 0;
133
130
  }
134
- async function validateAccountCreate(db, data) {
131
+ async function validateAccountCreate(db, ledgers, data) {
135
132
  const result = v.safeParse(AccountCreateSchema, data);
136
133
  let success = result.success;
137
134
  if (!result.success) {
@@ -141,7 +138,7 @@ async function validateAccountCreate(db, data) {
141
138
  const [refIdError, altIdError, ledgerId] = await Promise.all([
142
139
  refIdAlreadyExists(db, result.output.ref_id),
143
140
  altIdAlreadyExists(db, result.output.alt_id ?? null),
144
- findLedgerId(db, result.output.ledger_id),
141
+ findLedgerId(ledgers, result.output.ledger_id),
145
142
  ]);
146
143
  if (refIdError) {
147
144
  success = false;
@@ -187,8 +184,8 @@ async function validateAccountCreate(db, data) {
187
184
  }
188
185
  return { success, data: result.output, errors: errors };
189
186
  }
190
- export async function createAccount(db, data) {
191
- const validation = await validateAccountCreate(db, data);
187
+ export async function createAccount(db, ledgers, data) {
188
+ const validation = await validateAccountCreate(db, ledgers, data);
192
189
  if (!validation.success || !validation.data) {
193
190
  return {
194
191
  success: false,
package/dist/art.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Returns an ASCII representation of the logo for display in the console.
3
+ *
4
+ * @returns A string representation of the ASCII logo.
5
+ */
6
+ export declare function getAsciiLogo(): string;
package/dist/art.js ADDED
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Returns an ASCII representation of the logo for display in the console.
3
+ *
4
+ * @returns A string representation of the ASCII logo.
5
+ */
6
+ export function getAsciiLogo() {
7
+ return `.................................................................
8
+ .................................................................
9
+ .................................................................
10
+ .................................................................
11
+ .................................................................
12
+ .................................................................
13
+ .................................................................
14
+ .................................................................
15
+ ............################.......################-.............
16
+ ............#++++++++++###.......###++++++++++###................
17
+ ............#++++++++###.......###++++++++++###..................
18
+ ............#++++++###.......###++++++++++###....................
19
+ ............#++++###.......###++++++++++###......................
20
+ ............#++###.......###++++++++++###........................
21
+ ............####.......###++++++++++###..........................
22
+ ............##.......###++++++++++###............................
23
+ ...................###++++++++++###..............................
24
+ .................###++++++++++###................................
25
+ ...............###++++++++++###..................................
26
+ .............###++++++++++###....................................
27
+ ............##++++++++++###........####..........................
28
+ ............#+++++++++###........###++###........................
29
+ ............#++++++++##........###++++++###......................
30
+ ............#++++++++#.......###++++++++++###....................
31
+ ............#++++++++###.......###++++++++++###..................
32
+ ............#++++++++++###.......###++++++++++###................
33
+ ............################.......################..............
34
+ .................................................................
35
+ .................................................................
36
+ .................................................................
37
+ .................................................................
38
+ .................................................................
39
+ .................................................................
40
+ .................................................................
41
+ .................................................................`;
42
+ }
package/dist/db.d.ts CHANGED
@@ -2,6 +2,13 @@ import { PostgresJsDatabase } from "drizzle-orm/postgres-js";
2
2
  import postgres from "postgres";
3
3
  import * as v from "valibot";
4
4
  import * as schema from "./schema.js";
5
+ /**
6
+ * Options for configuring the Kitledger database connection.
7
+ *
8
+ * @remarks
9
+ * Includes parameters for connection URL, SSL, connection pool size,
10
+ * migrations table and schema, and auto-migration setting.
11
+ */
5
12
  export type KitledgerDbOptions = {
6
13
  url: string;
7
14
  ssl?: boolean;
@@ -10,10 +17,26 @@ export type KitledgerDbOptions = {
10
17
  migrationsSchema?: string;
11
18
  autoMigrate?: boolean;
12
19
  };
20
+ /**
21
+ * Database instance type for Kitledger, extending PostgresJsDatabase with the defined schema.
22
+ *
23
+ * @remarks
24
+ * Includes a reference to the underlying Postgres client.
25
+ */
13
26
  export type KitledgerDb = PostgresJsDatabase<typeof schema> & {
14
27
  $client: postgres.Sql<{}>;
15
28
  };
16
29
  export declare function runMigrations(db: KitledgerDb, migrationsTable: string, migrationsSchema: string): Promise<void>;
30
+ /**
31
+ * Initializes the Kitledger database with the provided options.
32
+ *
33
+ * @remarks
34
+ * Sets up the database connection, applies migrations automatically if enabled,
35
+ * and returns the initialized database instance.
36
+ *
37
+ * @param options - Configuration options for the database connection.
38
+ * @returns A promise that resolves to the initialized Kitledger database instance.
39
+ */
17
40
  export declare function initializeDatabase(options: KitledgerDbOptions): Promise<KitledgerDb>;
18
41
  /**
19
42
  * Supported operation types for get operations.
@@ -43,13 +66,22 @@ export type GetOperationResult<T> = {
43
66
  message: string;
44
67
  }[];
45
68
  };
69
+ /**
70
+ * Type definition for a single row in a query result.
71
+ */
46
72
  export type QueryResultRow = v.InferInput<typeof QueryResultRowSchema>;
73
+ /**
74
+ * Schema definition for a single row in a query result.
75
+ */
47
76
  export declare const QueryResultRowSchema: v.RecordSchema<v.StringSchema<undefined>, v.UnionSchema<[v.StringSchema<undefined>, v.NumberSchema<undefined>, v.BooleanSchema<undefined>, v.DateSchema<undefined>, v.NullSchema<undefined>, v.RecordSchema<v.StringSchema<undefined>, v.UnionSchema<[v.StringSchema<undefined>, v.NumberSchema<undefined>, v.BooleanSchema<undefined>, v.DateSchema<undefined>, v.NullSchema<undefined>], undefined>, undefined>], undefined>, undefined>;
77
+ /**
78
+ * Schema definition for an array of query result rows.
79
+ */
48
80
  export declare const QueryResultSchema: v.ArraySchema<v.RecordSchema<v.StringSchema<undefined>, v.UnionSchema<[v.StringSchema<undefined>, v.NumberSchema<undefined>, v.BooleanSchema<undefined>, v.DateSchema<undefined>, v.NullSchema<undefined>, v.RecordSchema<v.StringSchema<undefined>, v.UnionSchema<[v.StringSchema<undefined>, v.NumberSchema<undefined>, v.BooleanSchema<undefined>, v.DateSchema<undefined>, v.NullSchema<undefined>], undefined>, undefined>], undefined>, undefined>, undefined>;
49
81
  /**
50
82
  * Utility function to parse boolean filter values from strings or booleans to be used in queries and filters.
51
- * @param value
52
- * @returns
83
+ * @param value The value to parse, which can be a string or a boolean.
84
+ * @returns The parsed boolean value, or null if the input is not a valid boolean string.
53
85
  */
54
86
  export declare function parseBooleanFilterValue(value: string | boolean): boolean | null;
55
87
  /**
package/dist/db.js CHANGED
@@ -2,19 +2,37 @@ import { drizzle } from "drizzle-orm/postgres-js";
2
2
  import { migrate } from "drizzle-orm/postgres-js/migrator";
3
3
  import { dirname, resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
+ import postgres from "postgres";
5
6
  import * as v from "valibot";
6
7
  import * as schema from "./schema.js";
7
8
  const __filename = fileURLToPath(import.meta.url);
8
9
  const __dirname = dirname(__filename);
10
+ /*
11
+ * Runs database migrations using the specified migrations table and schema.
12
+ *
13
+ * @param db - The Kitledger database instance.
14
+ * @param migrationsTable - The name of the migrations table.
15
+ * @param migrationsSchema - The schema where the migrations table is located.
16
+ * @returns A promise that resolves when migrations are complete.
17
+ */
9
18
  export async function runMigrations(db, migrationsTable, migrationsSchema) {
10
19
  const migrationsPath = resolve(__dirname, "../dist/migrations");
11
- console.log("***Using migrations path:", migrationsPath);
12
20
  await migrate(db, {
13
21
  migrationsFolder: migrationsPath,
14
22
  migrationsTable: migrationsTable,
15
23
  migrationsSchema: migrationsSchema,
16
24
  });
17
25
  }
26
+ /**
27
+ * Initializes the Kitledger database with the provided options.
28
+ *
29
+ * @remarks
30
+ * Sets up the database connection, applies migrations automatically if enabled,
31
+ * and returns the initialized database instance.
32
+ *
33
+ * @param options - Configuration options for the database connection.
34
+ * @returns A promise that resolves to the initialized Kitledger database instance.
35
+ */
18
36
  export async function initializeDatabase(options) {
19
37
  const dbConfig = {
20
38
  url: options.url,
@@ -22,8 +40,20 @@ export async function initializeDatabase(options) {
22
40
  max: options.max ? options.max : 10,
23
41
  autoMigrate: options.autoMigrate ?? true,
24
42
  };
43
+ const queryClient = postgres(dbConfig.url, {
44
+ ssl: dbConfig.ssl,
45
+ max: dbConfig.max,
46
+ onnotice: (msg) => {
47
+ /**
48
+ * Ignore notices about skipping already applied migrations
49
+ */
50
+ if (!msg.message.includes("skipping")) {
51
+ console.log("Kitledger Postgres notice:", msg);
52
+ }
53
+ },
54
+ });
25
55
  const db = drizzle({
26
- connection: dbConfig,
56
+ client: queryClient,
27
57
  schema: schema,
28
58
  });
29
59
  const migrationsTable = options.migrationsTable || "schema_history";
@@ -45,6 +75,9 @@ export var GetOperationType;
45
75
  GetOperationType["SEARCH"] = "search";
46
76
  GetOperationType["QUERY"] = "query";
47
77
  })(GetOperationType || (GetOperationType = {}));
78
+ /**
79
+ * Schema definition for a single row in a query result.
80
+ */
48
81
  export const QueryResultRowSchema = v.record(v.string(), v.union([
49
82
  v.string(),
50
83
  v.number(),
@@ -53,11 +86,14 @@ export const QueryResultRowSchema = v.record(v.string(), v.union([
53
86
  v.null(),
54
87
  v.record(v.string(), v.union([v.string(), v.number(), v.boolean(), v.date(), v.null()])),
55
88
  ]));
89
+ /**
90
+ * Schema definition for an array of query result rows.
91
+ */
56
92
  export const QueryResultSchema = v.array(QueryResultRowSchema);
57
93
  /**
58
94
  * Utility function to parse boolean filter values from strings or booleans to be used in queries and filters.
59
- * @param value
60
- * @returns
95
+ * @param value The value to parse, which can be a string or a boolean.
96
+ * @returns The parsed boolean value, or null if the input is not a valid boolean string.
61
97
  */
62
98
  export function parseBooleanFilterValue(value) {
63
99
  if (typeof value === "boolean") {
@@ -1,19 +1,45 @@
1
1
  import type { Field } from "./fields.js";
2
+ /**
3
+ * Enumeration for the status of an entity model.
4
+ */
2
5
  export declare enum EntityModelStatus {
3
6
  ACTIVE = 0,
4
7
  INACTIVE = 1
5
8
  }
9
+ /**
10
+ * Infers the meta type of an entity based on its fields.
11
+ *
12
+ * @param TFields - An array of Field definitions.
13
+ * @returns A mapped type where each field's refId is the key and its value type is the value.
14
+ */
6
15
  export type InferEntityMetaType<TFields extends readonly Field[]> = {
7
- [K in TFields[number] as K["ref_id"]]: K["__primitive_type"];
16
+ [K in TFields[number] as K["refId"]]: K["__valueType"];
8
17
  };
18
+ /**
19
+ * Type definition for an entity in the system.
20
+ *
21
+ * @param TData - The type of the data contained within the entity.
22
+ * @returns An object representing the entity with its metadata and data.
23
+ */
9
24
  export type Entity<TData = Record<string, any>> = {
10
25
  id: string;
11
- model_ref_id: string;
12
- created_at: Date;
13
- updated_at: Date;
26
+ modelRefId: string;
27
+ createdAt: Date;
28
+ updatedAt: Date;
14
29
  data: TData;
15
30
  };
31
+ /**
32
+ * Type definition for a hook function that operates on an entity.
33
+ *
34
+ * @param TData - The type of the data contained within the entity.
35
+ * @returns A promise that resolves to the modified entity.
36
+ */
16
37
  export type EntityHook<TData> = (entity: Entity<TData>) => Promise<Entity<TData>>;
38
+ /**
39
+ * Type definition for the hooks associated with an entity.
40
+ * @param TData - The type of the data contained within the entity.
41
+ * @returns An object containing arrays of hook functions for various entity lifecycle events.
42
+ */
17
43
  export type EntityHooks<TData = Record<string, any>> = {
18
44
  creating?: EntityHook<TData>[];
19
45
  updating?: EntityHook<TData>[];
@@ -22,20 +48,43 @@ export type EntityHooks<TData = Record<string, any>> = {
22
48
  updated?: EntityHook<TData>[];
23
49
  deleted?: EntityHook<TData>[];
24
50
  };
51
+ /**
52
+ * Type definition for an entity model in the system.
53
+ *
54
+ * @returns An object representing the entity model with its metadata, fields, and hooks.
55
+ */
25
56
  export type EntityModel = {
26
- ref_id: string;
27
- alt_id?: string;
57
+ refId: string;
58
+ altId?: string;
28
59
  name: string;
29
60
  status: EntityModelStatus;
30
61
  fields?: Field[];
31
62
  hooks?: EntityHooks<any>;
32
63
  };
64
+ /**
65
+ * Options for defining an entity model.
66
+ *
67
+ * @param TFields - An array of Field definitions.
68
+ * @returns An object containing the options for the entity model.
69
+ */
33
70
  export type EntityModelOptions<TFields extends readonly Field[]> = {
34
- ref_id: string;
35
- alt_id?: string;
71
+ refId: string;
72
+ altId?: string;
36
73
  name: string;
37
74
  status?: EntityModelStatus;
38
75
  fields?: TFields;
39
76
  hooks?: EntityHooks<InferEntityMetaType<TFields>>;
40
77
  };
41
- export declare function defineEntityModel<const TFields extends readonly Field[]>(options: EntityModelOptions<TFields>): EntityModel;
78
+ /**
79
+ * Defines an entity model with the provided options.
80
+ *
81
+ * @remarks
82
+ * This function helps in creating a strongly typed entity model by inferring
83
+ * the types of the fields provided.
84
+ *
85
+ * @param options The options for defining the entity model.
86
+ * @returns A strongly typed entity model.
87
+ */
88
+ export declare function defineEntityModel<const TFields extends readonly Field[]>(options: EntityModelOptions<TFields>): EntityModel & {
89
+ fields: TFields;
90
+ };
package/dist/entities.js CHANGED
@@ -1,14 +1,26 @@
1
+ /**
2
+ * Enumeration for the status of an entity model.
3
+ */
1
4
  export var EntityModelStatus;
2
5
  (function (EntityModelStatus) {
3
6
  EntityModelStatus[EntityModelStatus["ACTIVE"] = 0] = "ACTIVE";
4
7
  EntityModelStatus[EntityModelStatus["INACTIVE"] = 1] = "INACTIVE";
5
8
  })(EntityModelStatus || (EntityModelStatus = {}));
9
+ /**
10
+ * Defines an entity model with the provided options.
11
+ *
12
+ * @remarks
13
+ * This function helps in creating a strongly typed entity model by inferring
14
+ * the types of the fields provided.
15
+ *
16
+ * @param options The options for defining the entity model.
17
+ * @returns A strongly typed entity model.
18
+ */
6
19
  export function defineEntityModel(options) {
7
- const entityModel = {
20
+ return {
8
21
  ...options,
9
22
  status: options.status ?? EntityModelStatus.ACTIVE,
10
23
  fields: options.fields,
11
24
  hooks: options.hooks,
12
25
  };
13
- return entityModel;
14
26
  }
@@ -1,6 +1,5 @@
1
1
  import { Account } from "./accounts.js";
2
2
  import { ApiToken, Permission, PermissionAssignment, Role, SystemPermission, User, UserRole } from "./auth.js";
3
- import { Ledger } from "./ledgers.js";
4
3
  /**
5
4
  * A generic factory function to create an array of items.
6
5
  * @param factory A function that creates a single item.
@@ -37,9 +36,6 @@ export declare class UserFactory extends BaseFactory<User> {
37
36
  export declare class UserRoleFactory extends BaseFactory<UserRole> {
38
37
  constructor();
39
38
  }
40
- export declare class LedgerFactory extends BaseFactory<Ledger> {
41
- constructor();
42
- }
43
39
  export declare class AccountFactory extends BaseFactory<Account> {
44
40
  constructor();
45
41
  }
package/dist/factories.js CHANGED
@@ -115,26 +115,11 @@ const makeUserRole = () => ({
115
115
  created_at: faker.date.past(),
116
116
  updated_at: faker.date.recent(),
117
117
  });
118
- export class LedgerFactory extends BaseFactory {
119
- constructor() {
120
- super(makeLedger);
121
- }
122
- }
123
118
  export class AccountFactory extends BaseFactory {
124
119
  constructor() {
125
120
  super(makeAccount);
126
121
  }
127
122
  }
128
- const makeLedger = () => ({
129
- id: v7(),
130
- ref_id: v7(),
131
- alt_id: v7(),
132
- name: faker.company.name(),
133
- description: faker.company.catchPhrase(),
134
- active: true,
135
- created_at: faker.date.past(),
136
- updated_at: faker.date.recent(),
137
- });
138
123
  const makeAccount = () => ({
139
124
  id: v7(),
140
125
  ref_id: v7(),