@proseql/cli 0.2.4

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.
Files changed (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +333 -0
  3. package/dist/commands/collections.d.ts +53 -0
  4. package/dist/commands/collections.d.ts.map +1 -0
  5. package/dist/commands/collections.js +145 -0
  6. package/dist/commands/collections.js.map +1 -0
  7. package/dist/commands/convert.d.ts +72 -0
  8. package/dist/commands/convert.d.ts.map +1 -0
  9. package/dist/commands/convert.js +340 -0
  10. package/dist/commands/convert.js.map +1 -0
  11. package/dist/commands/create.d.ts +48 -0
  12. package/dist/commands/create.d.ts.map +1 -0
  13. package/dist/commands/create.js +141 -0
  14. package/dist/commands/create.js.map +1 -0
  15. package/dist/commands/delete.d.ts +51 -0
  16. package/dist/commands/delete.d.ts.map +1 -0
  17. package/dist/commands/delete.js +122 -0
  18. package/dist/commands/delete.js.map +1 -0
  19. package/dist/commands/describe.d.ts +74 -0
  20. package/dist/commands/describe.d.ts.map +1 -0
  21. package/dist/commands/describe.js +206 -0
  22. package/dist/commands/describe.js.map +1 -0
  23. package/dist/commands/init.d.ts +37 -0
  24. package/dist/commands/init.d.ts.map +1 -0
  25. package/dist/commands/init.js +340 -0
  26. package/dist/commands/init.js.map +1 -0
  27. package/dist/commands/migrate.d.ts +65 -0
  28. package/dist/commands/migrate.d.ts.map +1 -0
  29. package/dist/commands/migrate.js +483 -0
  30. package/dist/commands/migrate.js.map +1 -0
  31. package/dist/commands/query.d.ts +56 -0
  32. package/dist/commands/query.d.ts.map +1 -0
  33. package/dist/commands/query.js +159 -0
  34. package/dist/commands/query.js.map +1 -0
  35. package/dist/commands/stats.d.ts +55 -0
  36. package/dist/commands/stats.d.ts.map +1 -0
  37. package/dist/commands/stats.js +188 -0
  38. package/dist/commands/stats.js.map +1 -0
  39. package/dist/commands/update.d.ts +50 -0
  40. package/dist/commands/update.d.ts.map +1 -0
  41. package/dist/commands/update.js +121 -0
  42. package/dist/commands/update.js.map +1 -0
  43. package/dist/config/discovery.d.ts +37 -0
  44. package/dist/config/discovery.d.ts.map +1 -0
  45. package/dist/config/discovery.js +171 -0
  46. package/dist/config/discovery.js.map +1 -0
  47. package/dist/config/loader.d.ts +49 -0
  48. package/dist/config/loader.d.ts.map +1 -0
  49. package/dist/config/loader.js +195 -0
  50. package/dist/config/loader.js.map +1 -0
  51. package/dist/index.d.ts +8 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +7 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/main.d.ts +66 -0
  56. package/dist/main.d.ts.map +1 -0
  57. package/dist/main.js +621 -0
  58. package/dist/main.js.map +1 -0
  59. package/dist/output/csv.d.ts +14 -0
  60. package/dist/output/csv.d.ts.map +1 -0
  61. package/dist/output/csv.js +54 -0
  62. package/dist/output/csv.js.map +1 -0
  63. package/dist/output/formatter.d.ts +18 -0
  64. package/dist/output/formatter.d.ts.map +1 -0
  65. package/dist/output/formatter.js +29 -0
  66. package/dist/output/formatter.js.map +1 -0
  67. package/dist/output/json.d.ts +13 -0
  68. package/dist/output/json.d.ts.map +1 -0
  69. package/dist/output/json.js +15 -0
  70. package/dist/output/json.js.map +1 -0
  71. package/dist/output/table.d.ts +18 -0
  72. package/dist/output/table.d.ts.map +1 -0
  73. package/dist/output/table.js +115 -0
  74. package/dist/output/table.js.map +1 -0
  75. package/dist/output/yaml.d.ts +13 -0
  76. package/dist/output/yaml.d.ts.map +1 -0
  77. package/dist/output/yaml.js +16 -0
  78. package/dist/output/yaml.js.map +1 -0
  79. package/dist/parsers/filter-parser.d.ts +65 -0
  80. package/dist/parsers/filter-parser.d.ts.map +1 -0
  81. package/dist/parsers/filter-parser.js +198 -0
  82. package/dist/parsers/filter-parser.js.map +1 -0
  83. package/dist/parsers/set-parser.d.ts +55 -0
  84. package/dist/parsers/set-parser.d.ts.map +1 -0
  85. package/dist/parsers/set-parser.js +198 -0
  86. package/dist/parsers/set-parser.js.map +1 -0
  87. package/dist/prompt.d.ts +58 -0
  88. package/dist/prompt.d.ts.map +1 -0
  89. package/dist/prompt.js +121 -0
  90. package/dist/prompt.js.map +1 -0
  91. package/package.json +59 -0
@@ -0,0 +1,159 @@
1
+ /**
2
+ * ProseQL CLI - Query Command
3
+ *
4
+ * Boots the database from config, resolves collection by name, and executes
5
+ * queries with parsed where, select, sort, and limit options.
6
+ */
7
+ import * as path from "node:path";
8
+ import { createPersistentEffectDatabase, jsonCodec, makeSerializerLayer, NodeStorageLayer, tomlCodec, yamlCodec, } from "@proseql/node";
9
+ import { Chunk, Effect, Layer, Stream } from "effect";
10
+ import { parseFilters, } from "../parsers/filter-parser.js";
11
+ /**
12
+ * Parse the select string into a field array.
13
+ * Comma-separated list of field names, e.g., "id,title,author"
14
+ */
15
+ function parseSelect(select) {
16
+ return select
17
+ .split(",")
18
+ .map((field) => field.trim())
19
+ .filter((field) => field.length > 0);
20
+ }
21
+ /**
22
+ * Parse the sort string into a sort config object.
23
+ * Format: "field:direction" where direction is "asc" or "desc"
24
+ * Examples: "year:desc", "title:asc"
25
+ */
26
+ function parseSort(sort) {
27
+ const parts = sort.split(":");
28
+ if (parts.length !== 2) {
29
+ return undefined;
30
+ }
31
+ const [field, direction] = parts;
32
+ const trimmedField = field.trim();
33
+ const trimmedDirection = direction.trim().toLowerCase();
34
+ if (!trimmedField) {
35
+ return undefined;
36
+ }
37
+ if (trimmedDirection !== "asc" && trimmedDirection !== "desc") {
38
+ return undefined;
39
+ }
40
+ return { [trimmedField]: trimmedDirection };
41
+ }
42
+ /**
43
+ * Resolve relative file paths in the config to absolute paths
44
+ * based on the config file's directory.
45
+ */
46
+ function resolveConfigPaths(config, configPath) {
47
+ const configDir = path.dirname(configPath);
48
+ const resolved = {};
49
+ for (const [collectionName, collectionConfig] of Object.entries(config)) {
50
+ if (collectionConfig.file && !path.isAbsolute(collectionConfig.file)) {
51
+ resolved[collectionName] = {
52
+ ...collectionConfig,
53
+ file: path.resolve(configDir, collectionConfig.file),
54
+ };
55
+ }
56
+ else {
57
+ resolved[collectionName] = collectionConfig;
58
+ }
59
+ }
60
+ return resolved;
61
+ }
62
+ /**
63
+ * Execute the query command.
64
+ *
65
+ * Boots the database from the config, resolves the collection by name,
66
+ * and executes a query with the provided options.
67
+ *
68
+ * @param options - Query command options
69
+ * @returns Result with queried data or error message
70
+ */
71
+ export function runQuery(options) {
72
+ return Effect.gen(function* () {
73
+ const { collection, config, configPath, where, select, sort, limit } = options;
74
+ // Check if collection exists in config
75
+ if (!(collection in config)) {
76
+ const availableCollections = Object.keys(config).join(", ");
77
+ return {
78
+ success: false,
79
+ message: `Collection '${collection}' not found in config. Available collections: ${availableCollections || "(none)"}`,
80
+ };
81
+ }
82
+ // Parse filter expressions from --where flags
83
+ const whereClause = where && where.length > 0 ? yield* parseFilters(where) : undefined;
84
+ // Parse select fields
85
+ const selectFields = select ? parseSelect(select) : undefined;
86
+ // Parse sort
87
+ const sortConfig = sort ? parseSort(sort) : undefined;
88
+ if (sort && !sortConfig) {
89
+ return {
90
+ success: false,
91
+ message: `Invalid sort format: '${sort}'. Expected format: 'field:asc' or 'field:desc'`,
92
+ };
93
+ }
94
+ // Resolve relative file paths in the config
95
+ const resolvedConfig = resolveConfigPaths(config, configPath);
96
+ // Build the persistence layer for database operations
97
+ const PersistenceLayer = Layer.merge(NodeStorageLayer, makeSerializerLayer([jsonCodec(), yamlCodec(), tomlCodec()]));
98
+ // Boot the database and execute the query
99
+ const program = Effect.gen(function* () {
100
+ const db = yield* createPersistentEffectDatabase(resolvedConfig, {});
101
+ // Get the collection (type assertion needed since we check collection existence above)
102
+ const coll = db[collection];
103
+ // Execute the query
104
+ const queryOptions = {};
105
+ if (whereClause && Object.keys(whereClause).length > 0) {
106
+ queryOptions.where = whereClause;
107
+ }
108
+ if (selectFields && selectFields.length > 0) {
109
+ queryOptions.select = selectFields;
110
+ }
111
+ if (sortConfig) {
112
+ queryOptions.sort = sortConfig;
113
+ }
114
+ if (limit !== undefined && limit > 0) {
115
+ queryOptions.limit = limit;
116
+ }
117
+ // Execute the query and collect results
118
+ const stream = coll.query(Object.keys(queryOptions).length > 0 ? queryOptions : undefined);
119
+ // Collect the stream into an array
120
+ const chunk = yield* Stream.runCollect(stream);
121
+ const results = Chunk.toReadonlyArray(chunk);
122
+ return results;
123
+ });
124
+ // Run the program with the persistence layer
125
+ const result = yield* program.pipe(Effect.provide(PersistenceLayer), Effect.scoped, Effect.catchAll((error) => {
126
+ const message = error instanceof Error ? error.message : String(error);
127
+ return Effect.succeed({
128
+ success: false,
129
+ message: `Query failed: ${message}`,
130
+ });
131
+ }));
132
+ // Check if we got an error result
133
+ if ("success" in result && result.success === false) {
134
+ return result;
135
+ }
136
+ // We got data
137
+ const data = result;
138
+ return {
139
+ success: true,
140
+ data,
141
+ count: data.length,
142
+ };
143
+ });
144
+ }
145
+ /**
146
+ * Handle the query command from CLI main.ts.
147
+ * This is the entry point called by the command dispatcher.
148
+ *
149
+ * @param options - Query command options
150
+ * @returns Promise that resolves to the query results or rejects on error
151
+ */
152
+ export async function handleQuery(options) {
153
+ const result = await Effect.runPromise(runQuery(options).pipe(Effect.catchTag("FilterParseError", (error) => Effect.succeed({
154
+ success: false,
155
+ message: error.message,
156
+ }))));
157
+ return result;
158
+ }
159
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/commands/query.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EACN,8BAA8B,EAE9B,SAAS,EACT,mBAAmB,EACnB,gBAAgB,EAChB,SAAS,EACT,SAAS,GACT,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACtD,OAAO,EAEN,YAAY,GACZ,MAAM,6BAA6B,CAAC;AAgCrC;;;GAGG;AACH,SAAS,WAAW,CAAC,MAAc;IAClC,OAAO,MAAM;SACX,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACvC,CAAC;AAED;;;;GAIG;AACH,SAAS,SAAS,CAAC,IAAY;IAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC;IACjC,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAClC,MAAM,gBAAgB,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAExD,IAAI,CAAC,YAAY,EAAE,CAAC;QACnB,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,IAAI,gBAAgB,KAAK,KAAK,IAAI,gBAAgB,KAAK,MAAM,EAAE,CAAC;QAC/D,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,OAAO,EAAE,CAAC,YAAY,CAAC,EAAE,gBAAgB,EAAE,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,SAAS,kBAAkB,CAC1B,MAAsB,EACtB,UAAkB;IAElB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAA4C,EAAE,CAAC;IAE7D,KAAK,MAAM,CAAC,cAAc,EAAE,gBAAgB,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACzE,IAAI,gBAAgB,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;YACtE,QAAQ,CAAC,cAAc,CAAC,GAAG;gBAC1B,GAAG,gBAAgB;gBACnB,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,gBAAgB,CAAC,IAAI,CAAC;aACpD,CAAC;QACH,CAAC;aAAM,CAAC;YACP,QAAQ,CAAC,cAAc,CAAC,GAAG,gBAAgB,CAAC;QAC7C,CAAC;IACF,CAAC;IAED,OAAO,QAA0B,CAAC;AACnC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CACvB,OAAqB;IAErB,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC1B,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GACnE,OAAO,CAAC;QAET,uCAAuC;QACvC,IAAI,CAAC,CAAC,UAAU,IAAI,MAAM,CAAC,EAAE,CAAC;YAC7B,MAAM,oBAAoB,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5D,OAAO;gBACN,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,eAAe,UAAU,iDAAiD,oBAAoB,IAAI,QAAQ,EAAE;aACrH,CAAC;QACH,CAAC;QAED,8CAA8C;QAC9C,MAAM,WAAW,GAChB,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAEpE,sBAAsB;QACtB,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE9D,aAAa;QACb,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAEtD,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACzB,OAAO;gBACN,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,yBAAyB,IAAI,iDAAiD;aACvF,CAAC;QACH,CAAC;QAED,4CAA4C;QAC5C,MAAM,cAAc,GAAG,kBAAkB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAE9D,sDAAsD;QACtD,MAAM,gBAAgB,GAAG,KAAK,CAAC,KAAK,CACnC,gBAAgB,EAChB,mBAAmB,CAAC,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,CAC5D,CAAC;QAEF,0CAA0C;QAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACnC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,8BAA8B,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;YAErE,uFAAuF;YACvF,MAAM,IAAI,GAAG,EAAE,CAAC,UAA6B,CAS5C,CAAC;YAEF,oBAAoB;YACpB,MAAM,YAAY,GAKd,EAAE,CAAC;YAEP,IAAI,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxD,YAAY,CAAC,KAAK,GAAG,WAAW,CAAC;YAClC,CAAC;YACD,IAAI,YAAY,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7C,YAAY,CAAC,MAAM,GAAG,YAAY,CAAC;YACpC,CAAC;YACD,IAAI,UAAU,EAAE,CAAC;gBAChB,YAAY,CAAC,IAAI,GAAG,UAAU,CAAC;YAChC,CAAC;YACD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACtC,YAAY,CAAC,KAAK,GAAG,KAAK,CAAC;YAC5B,CAAC;YAED,wCAAwC;YACxC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CACxB,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAC/D,CAAC;YAEF,mCAAmC;YACnC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,eAAe,CAAC,KAAK,CAE1C,CAAC;YAEF,OAAO,OAAO,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,6CAA6C;QAC7C,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,CACjC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAChC,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE;YACzB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO,MAAM,CAAC,OAAO,CAAC;gBACrB,OAAO,EAAE,KAAc;gBACvB,OAAO,EAAE,iBAAiB,OAAO,EAAE;aACnC,CAAC,CAAC;QACJ,CAAC,CAAC,CACF,CAAC;QAEF,kCAAkC;QAClC,IAAI,SAAS,IAAI,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YACrD,OAAO,MAAqB,CAAC;QAC9B,CAAC;QAED,cAAc;QACd,MAAM,IAAI,GAAG,MAAgD,CAAC;QAC9D,OAAO;YACN,OAAO,EAAE,IAAI;YACb,IAAI;YACJ,KAAK,EAAE,IAAI,CAAC,MAAM;SAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAqB;IACtD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CACrC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CACrB,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,KAAK,EAAE,EAAE,CAC7C,MAAM,CAAC,OAAO,CAAC;QACd,OAAO,EAAE,KAAc;QACvB,OAAO,EAAE,KAAK,CAAC,OAAO;KACtB,CAAC,CACF,CACD,CACD,CAAC;IAEF,OAAO,MAAM,CAAC;AACf,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * ProseQL CLI - Stats Command
3
+ *
4
+ * Boots the database from config, reports per-collection entity count,
5
+ * file size on disk, and serialization format.
6
+ */
7
+ import { type DatabaseConfig } from "@proseql/node";
8
+ import { Effect } from "effect";
9
+ /**
10
+ * Options for the stats command.
11
+ */
12
+ export interface StatsOptions {
13
+ /** The database configuration */
14
+ readonly config: DatabaseConfig;
15
+ /** The path to the config file (used for resolving relative file paths) */
16
+ readonly configPath: string;
17
+ }
18
+ /**
19
+ * Statistics for a single collection.
20
+ */
21
+ export interface CollectionStats {
22
+ readonly name: string;
23
+ readonly count: number;
24
+ readonly file: string;
25
+ readonly format: string;
26
+ readonly size: string;
27
+ readonly sizeBytes: number;
28
+ }
29
+ /**
30
+ * Result of the stats command.
31
+ */
32
+ export interface StatsResult {
33
+ readonly success: boolean;
34
+ readonly message?: string;
35
+ readonly data?: ReadonlyArray<CollectionStats>;
36
+ }
37
+ /**
38
+ * Execute the stats command.
39
+ *
40
+ * Boots the database from the config, and reports statistics for all collections
41
+ * including entity counts, file sizes, and serialization formats.
42
+ *
43
+ * @param options - Stats command options
44
+ * @returns Result with collection statistics or error message
45
+ */
46
+ export declare function runStats(options: StatsOptions): Effect.Effect<StatsResult>;
47
+ /**
48
+ * Handle the stats command from CLI main.ts.
49
+ * This is the entry point called by the command dispatcher.
50
+ *
51
+ * @param options - Stats command options
52
+ * @returns Promise that resolves to the stats result or rejects on error
53
+ */
54
+ export declare function handleStats(options: StatsOptions): Promise<StatsResult>;
55
+ //# sourceMappingURL=stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/commands/stats.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAEN,KAAK,cAAc,EAMnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAS,MAAM,EAAiB,MAAM,QAAQ,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,iCAAiC;IACjC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,2EAA2E;IAC3E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;CAC/C;AAsGD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAgG1E;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAG7E"}
@@ -0,0 +1,188 @@
1
+ /**
2
+ * ProseQL CLI - Stats Command
3
+ *
4
+ * Boots the database from config, reports per-collection entity count,
5
+ * file size on disk, and serialization format.
6
+ */
7
+ import * as fs from "node:fs";
8
+ import * as path from "node:path";
9
+ import { createPersistentEffectDatabase, jsonCodec, makeSerializerLayer, NodeStorageLayer, tomlCodec, yamlCodec, } from "@proseql/node";
10
+ import { Chunk, Effect, Layer, Stream } from "effect";
11
+ /**
12
+ * Resolve relative file paths in the config to absolute paths
13
+ * based on the config file's directory.
14
+ */
15
+ function resolveConfigPaths(config, configPath) {
16
+ const configDir = path.dirname(configPath);
17
+ const resolved = {};
18
+ for (const [collectionName, collectionConfig] of Object.entries(config)) {
19
+ if (collectionConfig.file && !path.isAbsolute(collectionConfig.file)) {
20
+ resolved[collectionName] = {
21
+ ...collectionConfig,
22
+ file: path.resolve(configDir, collectionConfig.file),
23
+ };
24
+ }
25
+ else {
26
+ resolved[collectionName] = collectionConfig;
27
+ }
28
+ }
29
+ return resolved;
30
+ }
31
+ /**
32
+ * Determine the serialization format from a file path.
33
+ * Returns the format based on the file extension.
34
+ */
35
+ function getFormatFromFile(filePath) {
36
+ if (!filePath) {
37
+ return "(in-memory)";
38
+ }
39
+ const ext = path.extname(filePath).toLowerCase();
40
+ switch (ext) {
41
+ case ".json":
42
+ return "json";
43
+ case ".jsonl":
44
+ return "jsonl";
45
+ case ".yaml":
46
+ case ".yml":
47
+ return "yaml";
48
+ case ".toml":
49
+ return "toml";
50
+ case ".json5":
51
+ return "json5";
52
+ case ".jsonc":
53
+ return "jsonc";
54
+ case ".hjson":
55
+ return "hjson";
56
+ case ".toon":
57
+ return "toon";
58
+ default:
59
+ return ext ? ext.slice(1) : "unknown";
60
+ }
61
+ }
62
+ /**
63
+ * Get the file size on disk.
64
+ * Returns the size in bytes, or 0 if the file doesn't exist or path is undefined.
65
+ */
66
+ function getFileSize(filePath) {
67
+ if (!filePath) {
68
+ return 0;
69
+ }
70
+ try {
71
+ const stat = fs.statSync(filePath);
72
+ return stat.size;
73
+ }
74
+ catch {
75
+ // File doesn't exist or can't be read
76
+ return 0;
77
+ }
78
+ }
79
+ /**
80
+ * Format bytes into a human-readable string.
81
+ */
82
+ function formatBytes(bytes) {
83
+ if (bytes === 0) {
84
+ return "(in-memory)";
85
+ }
86
+ const units = ["B", "KB", "MB", "GB"];
87
+ let unitIndex = 0;
88
+ let size = bytes;
89
+ while (size >= 1024 && unitIndex < units.length - 1) {
90
+ size /= 1024;
91
+ unitIndex++;
92
+ }
93
+ // Use fixed precision for KB and above, no decimals for bytes
94
+ if (unitIndex === 0) {
95
+ return `${size} ${units[unitIndex]}`;
96
+ }
97
+ return `${size.toFixed(2)} ${units[unitIndex]}`;
98
+ }
99
+ /**
100
+ * Execute the stats command.
101
+ *
102
+ * Boots the database from the config, and reports statistics for all collections
103
+ * including entity counts, file sizes, and serialization formats.
104
+ *
105
+ * @param options - Stats command options
106
+ * @returns Result with collection statistics or error message
107
+ */
108
+ export function runStats(options) {
109
+ return Effect.gen(function* () {
110
+ const { config, configPath } = options;
111
+ const collectionNames = Object.keys(config);
112
+ if (collectionNames.length === 0) {
113
+ return {
114
+ success: true,
115
+ data: [],
116
+ message: "No collections configured",
117
+ };
118
+ }
119
+ // Resolve relative file paths in the config
120
+ const resolvedConfig = resolveConfigPaths(config, configPath);
121
+ // Build the persistence layer for database operations
122
+ const PersistenceLayer = Layer.merge(NodeStorageLayer, makeSerializerLayer([jsonCodec(), yamlCodec(), tomlCodec()]));
123
+ // Boot the database and gather collection stats
124
+ const program = Effect.gen(function* () {
125
+ const db = yield* createPersistentEffectDatabase(resolvedConfig, {});
126
+ const results = [];
127
+ for (const name of collectionNames) {
128
+ const collectionConfig = resolvedConfig[name];
129
+ const filePath = collectionConfig?.file;
130
+ // Get the collection (type assertion needed since we verify existence via config)
131
+ const coll = db[name];
132
+ // Count entities by querying all and collecting
133
+ const stream = coll.query();
134
+ const chunk = yield* Stream.runCollect(stream);
135
+ const count = Chunk.size(chunk);
136
+ // Get format from file extension
137
+ const format = getFormatFromFile(filePath);
138
+ // Get file size on disk
139
+ const sizeBytes = getFileSize(filePath);
140
+ const size = formatBytes(sizeBytes);
141
+ // Get relative file path for display (relative to config dir)
142
+ const configDir = path.dirname(configPath);
143
+ const displayPath = filePath
144
+ ? path.relative(configDir, filePath) || filePath
145
+ : "(in-memory)";
146
+ results.push({
147
+ name,
148
+ count,
149
+ file: displayPath,
150
+ format,
151
+ size,
152
+ sizeBytes,
153
+ });
154
+ }
155
+ return results;
156
+ });
157
+ // Run the program with the persistence layer
158
+ const result = yield* program.pipe(Effect.provide(PersistenceLayer), Effect.scoped, Effect.catchAll((error) => {
159
+ const message = error instanceof Error ? error.message : String(error);
160
+ return Effect.succeed({
161
+ success: false,
162
+ message: `Failed to get collection stats: ${message}`,
163
+ });
164
+ }));
165
+ // Check if we got an error result
166
+ if ("success" in result && result.success === false) {
167
+ return result;
168
+ }
169
+ // We got data
170
+ const data = result;
171
+ return {
172
+ success: true,
173
+ data,
174
+ };
175
+ });
176
+ }
177
+ /**
178
+ * Handle the stats command from CLI main.ts.
179
+ * This is the entry point called by the command dispatcher.
180
+ *
181
+ * @param options - Stats command options
182
+ * @returns Promise that resolves to the stats result or rejects on error
183
+ */
184
+ export async function handleStats(options) {
185
+ const result = await Effect.runPromise(runStats(options));
186
+ return result;
187
+ }
188
+ //# sourceMappingURL=stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/commands/stats.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * ProseQL CLI - Update Command
3
+ *
4
+ * Updates an existing entity in a collection. Parses --set flag using set-parser,
5
+ * calls update on the collection, and prints the updated entity.
6
+ */
7
+ import { type DatabaseConfig } from "@proseql/node";
8
+ import { Effect } from "effect";
9
+ /**
10
+ * Options for the update command.
11
+ */
12
+ export interface UpdateOptions {
13
+ /** Name of the collection containing the entity */
14
+ readonly collection: string;
15
+ /** ID of the entity to update */
16
+ readonly id: string;
17
+ /** The database configuration */
18
+ readonly config: DatabaseConfig;
19
+ /** The path to the config file (used for resolving relative file paths) */
20
+ readonly configPath: string;
21
+ /** Assignment string for --set flag (e.g., "year=2025,title=New Title") */
22
+ readonly set: string;
23
+ }
24
+ /**
25
+ * Result of the update command.
26
+ */
27
+ export interface UpdateResult {
28
+ readonly success: boolean;
29
+ readonly message?: string;
30
+ readonly data?: Record<string, unknown>;
31
+ }
32
+ /**
33
+ * Execute the update command.
34
+ *
35
+ * Boots the database from the config, parses the --set assignments,
36
+ * and updates the entity in the specified collection.
37
+ *
38
+ * @param options - Update command options
39
+ * @returns Effect that resolves to the update result
40
+ */
41
+ export declare function runUpdate(options: UpdateOptions): Effect.Effect<UpdateResult, never>;
42
+ /**
43
+ * Handle the update command from CLI main.ts.
44
+ * This is the entry point called by the command dispatcher.
45
+ *
46
+ * @param options - Update command options
47
+ * @returns Promise that resolves to the update result
48
+ */
49
+ export declare function handleUpdate(options: UpdateOptions): Promise<UpdateResult>;
50
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAEN,KAAK,cAAc,EAMnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAS,MAAM,QAAQ,CAAC;AAGvC;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,mDAAmD;IACnD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,iCAAiC;IACjC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,2EAA2E;IAC3E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC;AA2BD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CACxB,OAAO,EAAE,aAAa,GACpB,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,KAAK,CAAC,CAgGpC;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CACjC,OAAO,EAAE,aAAa,GACpB,OAAO,CAAC,YAAY,CAAC,CAEvB"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * ProseQL CLI - Update Command
3
+ *
4
+ * Updates an existing entity in a collection. Parses --set flag using set-parser,
5
+ * calls update on the collection, and prints the updated entity.
6
+ */
7
+ import * as path from "node:path";
8
+ import { createPersistentEffectDatabase, jsonCodec, makeSerializerLayer, NodeStorageLayer, tomlCodec, yamlCodec, } from "@proseql/node";
9
+ import { Effect, Layer } from "effect";
10
+ import { parseSets } from "../parsers/set-parser.js";
11
+ /**
12
+ * Resolve relative file paths in the config to absolute paths
13
+ * based on the config file's directory.
14
+ */
15
+ function resolveConfigPaths(config, configPath) {
16
+ const configDir = path.dirname(configPath);
17
+ const resolved = {};
18
+ for (const [collectionName, collectionConfig] of Object.entries(config)) {
19
+ if (collectionConfig.file && !path.isAbsolute(collectionConfig.file)) {
20
+ resolved[collectionName] = {
21
+ ...collectionConfig,
22
+ file: path.resolve(configDir, collectionConfig.file),
23
+ };
24
+ }
25
+ else {
26
+ resolved[collectionName] = collectionConfig;
27
+ }
28
+ }
29
+ return resolved;
30
+ }
31
+ /**
32
+ * Execute the update command.
33
+ *
34
+ * Boots the database from the config, parses the --set assignments,
35
+ * and updates the entity in the specified collection.
36
+ *
37
+ * @param options - Update command options
38
+ * @returns Effect that resolves to the update result
39
+ */
40
+ export function runUpdate(options) {
41
+ return Effect.gen(function* () {
42
+ const { collection, id, config, configPath, set } = options;
43
+ // Check if collection exists in config
44
+ if (!(collection in config)) {
45
+ const availableCollections = Object.keys(config).join(", ");
46
+ return {
47
+ success: false,
48
+ message: `Collection '${collection}' not found in config. Available collections: ${availableCollections || "(none)"}`,
49
+ };
50
+ }
51
+ // Parse the --set assignments
52
+ const parseResult = yield* parseSets(set).pipe(Effect.catchTag("SetParseError", (error) => Effect.succeed({
53
+ success: false,
54
+ message: error.message,
55
+ })));
56
+ // Check if parsing failed
57
+ if ("success" in parseResult && parseResult.success === false) {
58
+ return parseResult;
59
+ }
60
+ const updateData = parseResult;
61
+ // Resolve relative file paths in the config
62
+ const resolvedConfig = resolveConfigPaths(config, configPath);
63
+ // Build the persistence layer for database operations
64
+ const PersistenceLayer = Layer.merge(NodeStorageLayer, makeSerializerLayer([jsonCodec(), yamlCodec(), tomlCodec()]));
65
+ // Boot the database and execute the update
66
+ const program = Effect.gen(function* () {
67
+ const db = yield* createPersistentEffectDatabase(resolvedConfig, {});
68
+ // Get the collection (type assertion needed since we check collection existence above)
69
+ const coll = db[collection];
70
+ // Execute the update operation
71
+ const updated = yield* coll.update(id, updateData);
72
+ return updated;
73
+ });
74
+ // Run the program with the persistence layer
75
+ const result = yield* program.pipe(Effect.provide(PersistenceLayer), Effect.scoped, Effect.catchAll((error) => {
76
+ // Extract error message based on error type
77
+ let message;
78
+ if (error && typeof error === "object") {
79
+ const errorObj = error;
80
+ if ("_tag" in errorObj && typeof errorObj.message === "string") {
81
+ // Tagged error with message field
82
+ message = errorObj.message;
83
+ }
84
+ else if (error instanceof Error) {
85
+ message = error.message;
86
+ }
87
+ else {
88
+ message = String(error);
89
+ }
90
+ }
91
+ else {
92
+ message = String(error);
93
+ }
94
+ return Effect.succeed({
95
+ success: false,
96
+ message: `Update failed: ${message}`,
97
+ });
98
+ }));
99
+ // Check if we got an error result
100
+ if ("success" in result && result.success === false) {
101
+ return result;
102
+ }
103
+ // We got the updated entity
104
+ const entity = result;
105
+ return {
106
+ success: true,
107
+ data: entity,
108
+ };
109
+ });
110
+ }
111
+ /**
112
+ * Handle the update command from CLI main.ts.
113
+ * This is the entry point called by the command dispatcher.
114
+ *
115
+ * @param options - Update command options
116
+ * @returns Promise that resolves to the update result
117
+ */
118
+ export async function handleUpdate(options) {
119
+ return Effect.runPromise(runUpdate(options));
120
+ }
121
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { Effect } from "effect";
2
+ declare const ConfigNotFoundError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
3
+ readonly _tag: "ConfigNotFoundError";
4
+ } & Readonly<A>;
5
+ /**
6
+ * Error thrown when no config file can be found.
7
+ */
8
+ export declare class ConfigNotFoundError extends ConfigNotFoundError_base<{
9
+ readonly searchedPaths: readonly string[];
10
+ readonly message: string;
11
+ }> {
12
+ }
13
+ /**
14
+ * Discover a proseql config file.
15
+ *
16
+ * If `overridePath` is provided, it is validated and returned directly.
17
+ * Otherwise, the function walks from `cwd` upward, checking for:
18
+ * - `proseql.config.ts`
19
+ * - `proseql.config.js`
20
+ * - `proseql.config.json`
21
+ *
22
+ * Returns the absolute path to the config file.
23
+ * Fails with ConfigNotFoundError if no config file is found.
24
+ *
25
+ * @param cwd - The directory to start searching from
26
+ * @param overridePath - Optional explicit path to a config file
27
+ */
28
+ export declare function discoverConfig(cwd: string, overridePath?: string): Effect.Effect<string, ConfigNotFoundError>;
29
+ /**
30
+ * Synchronous version of discoverConfig for use in contexts
31
+ * where Effect is not available.
32
+ *
33
+ * @throws Error if no config file is found
34
+ */
35
+ export declare function discoverConfigSync(cwd: string, overridePath?: string): string;
36
+ export {};
37
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/config/discovery.ts"],"names":[],"mappings":"AAEA,OAAO,EAAQ,MAAM,EAAE,MAAM,QAAQ,CAAC;;;;AAMtC;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,yBAEvC;IACD,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB,CAAC;CAAG;AA0EL;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC7B,GAAG,EAAE,MAAM,EACX,YAAY,CAAC,EAAE,MAAM,GACnB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAyD5C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAkC7E"}