@confect/cli 9.0.0-next.9 → 9.0.0

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.
@@ -1,157 +0,0 @@
1
- import { Identifier } from "@confect/core";
2
- import * as Table from "@confect/server/Table";
3
- import * as FileSystem from "@effect/platform/FileSystem";
4
- import * as Path from "@effect/platform/Path";
5
- import { pipe } from "effect/Function";
6
- import * as Array from "effect/Array";
7
- import * as Effect from "effect/Effect";
8
- import * as Order from "effect/Order";
9
- import { fromBundlerError } from "./BuildError";
10
- import * as Bundler from "./Bundler";
11
- import {
12
- DuplicateTableNameError,
13
- InvalidTableDefaultExportError,
14
- InvalidTableFilenameError,
15
- } from "./CodegenError";
16
- import { ConfectDirectory } from "./ConfectDirectory";
17
-
18
- export const TABLES_DIRNAME = "tables";
19
-
20
- /**
21
- * Discovered metadata for a single user-authored table module under
22
- * `confect/tables/`.
23
- *
24
- * - `relativePath` — path from `confect/` to the file (e.g. `tables/notes.ts`).
25
- * - `tableName` — the file basename (e.g. `notes`). This is also the import
26
- * binding used in generated files, and the table name surfaced to Convex.
27
- */
28
- export interface TableModule {
29
- readonly relativePath: string;
30
- readonly tableName: string;
31
- }
32
-
33
- const tableNameFromRelativePath = (relativePath: string) =>
34
- Effect.gen(function* () {
35
- const path = yield* Path.Path;
36
- const { name } = path.parse(relativePath);
37
- return name;
38
- });
39
-
40
- const listTableFiles = Effect.gen(function* () {
41
- const fs = yield* FileSystem.FileSystem;
42
- const path = yield* Path.Path;
43
- const confectDirectory = yield* ConfectDirectory.get;
44
- const tablesDirectory = path.join(confectDirectory, TABLES_DIRNAME);
45
-
46
- if (!(yield* fs.exists(tablesDirectory))) {
47
- return [] as ReadonlyArray<string>;
48
- }
49
-
50
- const allPaths = yield* fs.readDirectory(tablesDirectory, {
51
- recursive: true,
52
- });
53
-
54
- return pipe(
55
- allPaths,
56
- Array.filter((p) => p.endsWith(".ts") && !p.endsWith(".test.ts")),
57
- Array.map((p) => path.join(TABLES_DIRNAME, p)),
58
- );
59
- });
60
-
61
- const byTableName = Order.mapInput(
62
- Order.string,
63
- (tableModule: TableModule) => tableModule.tableName,
64
- );
65
-
66
- /**
67
- * Discover every `confect/tables/**\/*.ts` module by listing the directory.
68
- * Validates that each filename is a legal table identifier — the table name is
69
- * derived from the file basename, so the filename must be a valid JavaScript
70
- * identifier with no leading underscore (Convex reserves `_<name>` for system
71
- * tables).
72
- *
73
- * This step does *not* bundle the table modules. It runs early in the codegen
74
- * pipeline so the `_generated/id.ts` constructor can be emitted *before* any
75
- * user-authored table is bundled (those modules import from `_generated/id.ts`
76
- * for cross-table refs).
77
- *
78
- * A missing `confect/tables/` directory is allowed and produces an empty list.
79
- *
80
- * Fails with {@link InvalidTableFilenameError} if any filename is not a valid
81
- * table identifier, or {@link DuplicateTableNameError} if two files resolve to
82
- * the same table name (the directory is scanned recursively but names are
83
- * derived from the basename alone, so `tables/a/notes.ts` and
84
- * `tables/b/notes.ts` would collide).
85
- */
86
- export const discover = Effect.gen(function* () {
87
- const relativePaths = yield* listTableFiles;
88
-
89
- const tableModules = yield* Effect.forEach(
90
- relativePaths,
91
- (relativePath) =>
92
- Effect.gen(function* () {
93
- const tableName = yield* tableNameFromRelativePath(relativePath);
94
- yield* Effect.try({
95
- try: () => Identifier.validateConfectTableIdentifier(tableName),
96
- catch: (e) =>
97
- new InvalidTableFilenameError({
98
- tablePath: relativePath,
99
- reason: e instanceof Error ? e.message : String(e),
100
- }),
101
- });
102
- return { relativePath, tableName } satisfies TableModule;
103
- }),
104
- { concurrency: "unbounded" },
105
- );
106
-
107
- const sorted = pipe(tableModules, Array.sortBy(byTableName));
108
-
109
- const collisions = Object.entries(
110
- Array.groupBy(sorted, (tableModule) => tableModule.tableName),
111
- )
112
- .filter(([, group]) => group.length > 1)
113
- .map(([tableName, group]) => ({
114
- tableName,
115
- tablePaths: Array.map(group, (tableModule) => tableModule.relativePath),
116
- }));
117
-
118
- if (collisions.length > 0) {
119
- return yield* new DuplicateTableNameError({ collisions });
120
- }
121
-
122
- return sorted;
123
- });
124
-
125
- /**
126
- * Bundle every discovered table module and verify that its default export is
127
- * an {@link Table.UnnamedTable} (the result of `Table.make(...)` before a
128
- * name has been bound). Fails with {@link InvalidTableDefaultExportError} if
129
- * any module's default export is missing or has the wrong shape.
130
- *
131
- * Must run *after* `_generated/id.ts` has been emitted, because user-authored
132
- * table modules typically `import { Id } from "../_generated/id"` for
133
- * cross-table references.
134
- */
135
- export const validate = (tableModules: ReadonlyArray<TableModule>) =>
136
- Effect.gen(function* () {
137
- const path = yield* Path.Path;
138
- const confectDirectory = yield* ConfectDirectory.get;
139
-
140
- yield* Effect.forEach(
141
- tableModules,
142
- ({ relativePath }) =>
143
- Effect.gen(function* () {
144
- const absolutePath = path.resolve(confectDirectory, relativePath);
145
- const { module } = yield* Bundler.bundle(absolutePath).pipe(
146
- Effect.mapError((error) => fromBundlerError(relativePath, error)),
147
- );
148
-
149
- if (!Table.isUnnamedTable(module.default)) {
150
- return yield* new InvalidTableDefaultExportError({
151
- tablePath: relativePath,
152
- });
153
- }
154
- }),
155
- { concurrency: "unbounded" },
156
- );
157
- });
package/src/cliApp.ts DELETED
@@ -1,8 +0,0 @@
1
- import * as Command from "@effect/cli/Command";
2
- import packageJson from "../package.json" with { type: "json" };
3
- import { confect } from "./confect";
4
-
5
- export const cliApp = Command.run(confect, {
6
- name: "Confect",
7
- version: packageJson.version,
8
- });