ignotum 0.0.0 → 0.0.2
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.
- package/README.md +161 -0
- package/dist/cli/bin.d.mts +1 -0
- package/dist/cli/bin.mjs +1696 -0
- package/dist/cli/bin.mjs.map +1 -0
- package/dist/runtime/api-BXXIZc_Q.js +119 -0
- package/dist/runtime/api-BXXIZc_Q.js.map +1 -0
- package/dist/runtime/api-Cpx57mk3.d.ts +47 -0
- package/dist/runtime/client/jsx-dev-runtime.d.ts +2 -0
- package/dist/runtime/client/jsx-dev-runtime.js +2 -0
- package/dist/runtime/client/jsx-runtime.d.ts +2 -0
- package/dist/runtime/client/jsx-runtime.js +2 -0
- package/dist/runtime/client.d.ts +29 -0
- package/dist/runtime/client.js +364 -0
- package/dist/runtime/client.js.map +1 -0
- package/dist/runtime/index-BgWROoyk.d.ts +249 -0
- package/dist/runtime/internal/api.d.ts +2 -0
- package/dist/runtime/internal/api.js +2 -0
- package/dist/runtime/internal/server.d.ts +6 -0
- package/dist/runtime/internal/server.js +7 -0
- package/dist/runtime/internal/server.js.map +1 -0
- package/dist/runtime/internal/types.d.ts +2 -0
- package/dist/runtime/internal/types.js +2 -0
- package/dist/runtime/result-B2W-z2wG.js +136 -0
- package/dist/runtime/result-B2W-z2wG.js.map +1 -0
- package/dist/runtime/result-C1ZdsM6Y.d.ts +106 -0
- package/dist/runtime/schema-CNEVLF7D.js +116 -0
- package/dist/runtime/schema-CNEVLF7D.js.map +1 -0
- package/dist/runtime/server.d.ts +9 -0
- package/dist/runtime/server.js +9 -0
- package/dist/runtime/server.js.map +1 -0
- package/package.json +81 -2
- package/src/cli/agent-files.ts +35 -0
- package/src/cli/bin.ts +5 -0
- package/src/cli/client-plugin.ts +66 -0
- package/src/cli/codegen.ts +203 -0
- package/src/cli/command.ts +155 -0
- package/src/cli/dev.ts +206 -0
- package/src/cli/new-project.ts +377 -0
- package/src/cli/package-manager.ts +55 -0
- package/src/client/errors.ts +83 -0
- package/src/client/hooks.ts +141 -0
- package/src/client/index.ts +90 -0
- package/src/client/jsx-dev-runtime.ts +2 -0
- package/src/client/jsx-runtime.ts +2 -0
- package/src/client/query.ts +17 -0
- package/src/client/sync.ts +487 -0
- package/src/dev-runtime/database.ts +374 -0
- package/src/dev-runtime/dev-database.ts +199 -0
- package/src/dev-runtime/functions.ts +293 -0
- package/src/dev-runtime/id.ts +11 -0
- package/src/dev-runtime/sync.ts +473 -0
- package/src/internal/api.ts +141 -0
- package/src/internal/http-paths.ts +5 -0
- package/src/internal/server.ts +3 -0
- package/src/internal/types.ts +2 -0
- package/src/raw.d.ts +4 -0
- package/src/server/index.ts +8 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { NodeRuntime, NodeServices } from "@effect/platform-node";
|
|
2
|
+
import { Effect, Path, Schema, Terminal } from "effect";
|
|
3
|
+
import { Argument, CliError, Command, Flag } from "effect/unstable/cli";
|
|
4
|
+
|
|
5
|
+
import packageJson from "../../package.json" with { type: "json" };
|
|
6
|
+
import { generate } from "./codegen.js";
|
|
7
|
+
import { resetDevDatabase } from "../dev-runtime/dev-database.js";
|
|
8
|
+
import { dev as runDev } from "./dev.js";
|
|
9
|
+
import { createProject } from "./new-project.js";
|
|
10
|
+
import { installDependencies } from "./package-manager.js";
|
|
11
|
+
|
|
12
|
+
const DevPort = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 65_535 }));
|
|
13
|
+
|
|
14
|
+
const codegen = Command.make(
|
|
15
|
+
"codegen",
|
|
16
|
+
{},
|
|
17
|
+
Effect.fn("codegen")(function* () {
|
|
18
|
+
const path = yield* Path.Path;
|
|
19
|
+
const terminal = yield* Terminal.Terminal;
|
|
20
|
+
const result = yield* generate(path.resolve(".")).pipe(
|
|
21
|
+
Effect.mapError((error) =>
|
|
22
|
+
CliError.UserError.make({ cause: error, userMessage: error.message }),
|
|
23
|
+
),
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
yield* terminal.display(
|
|
27
|
+
`Generated ${result.written.length} file${result.written.length === 1 ? "" : "s"}; ${result.unchanged.length} unchanged.\n`,
|
|
28
|
+
);
|
|
29
|
+
}),
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const resetDevDatabaseCommand = Command.make(
|
|
33
|
+
"reset",
|
|
34
|
+
{},
|
|
35
|
+
Effect.fn("dev db reset")(function* () {
|
|
36
|
+
const path = yield* Path.Path;
|
|
37
|
+
const terminal = yield* Terminal.Terminal;
|
|
38
|
+
const result = yield* resetDevDatabase(path.resolve(".")).pipe(
|
|
39
|
+
Effect.mapError((error) =>
|
|
40
|
+
CliError.UserError.make({ cause: error, userMessage: error.message }),
|
|
41
|
+
),
|
|
42
|
+
);
|
|
43
|
+
const message =
|
|
44
|
+
result.removed === 0
|
|
45
|
+
? `Development database is already empty: ${result.databasePath}\n`
|
|
46
|
+
: `Reset development database: ${result.databasePath}\n`;
|
|
47
|
+
yield* terminal.display(message);
|
|
48
|
+
}),
|
|
49
|
+
).pipe(Command.withDescription("Delete the local SQLite development database."));
|
|
50
|
+
|
|
51
|
+
const devDatabase = Command.make("db").pipe(
|
|
52
|
+
Command.withDescription("Manage the local development database."),
|
|
53
|
+
Command.withSubcommands([resetDevDatabaseCommand]),
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const dev = Command.make(
|
|
57
|
+
"dev",
|
|
58
|
+
{
|
|
59
|
+
host: Flag.string("host").pipe(Flag.withDefault("127.0.0.1")),
|
|
60
|
+
open: Flag.boolean("open").pipe(Flag.withDefault(false)),
|
|
61
|
+
port: Flag.integer("port").pipe(Flag.withSchema(DevPort), Flag.withDefault(3210)),
|
|
62
|
+
},
|
|
63
|
+
Effect.fn("dev")(function* ({ host, open, port }) {
|
|
64
|
+
const path = yield* Path.Path;
|
|
65
|
+
|
|
66
|
+
return yield* runDev({
|
|
67
|
+
host,
|
|
68
|
+
open,
|
|
69
|
+
port,
|
|
70
|
+
projectDirectory: path.resolve("."),
|
|
71
|
+
}).pipe(
|
|
72
|
+
Effect.mapError((error) =>
|
|
73
|
+
CliError.UserError.make({ cause: error, userMessage: error.message }),
|
|
74
|
+
),
|
|
75
|
+
);
|
|
76
|
+
}),
|
|
77
|
+
).pipe(
|
|
78
|
+
Command.withDescription("Run the local Ignotum development server."),
|
|
79
|
+
Command.withSubcommands([devDatabase]),
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const install = Command.make(
|
|
83
|
+
"install",
|
|
84
|
+
{},
|
|
85
|
+
Effect.fn("install")(function* () {
|
|
86
|
+
const path = yield* Path.Path;
|
|
87
|
+
const terminal = yield* Terminal.Terminal;
|
|
88
|
+
const packageManager = yield* installDependencies(path.resolve(".")).pipe(
|
|
89
|
+
Effect.mapError((error) =>
|
|
90
|
+
CliError.UserError.make({ cause: error, userMessage: error.message }),
|
|
91
|
+
),
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
yield* terminal.display(`Installed dependencies with ${packageManager}.\n`);
|
|
95
|
+
}),
|
|
96
|
+
).pipe(Command.withDescription("Install dependencies with pnpm, or npm when pnpm is unavailable."));
|
|
97
|
+
|
|
98
|
+
const newProject = Command.make(
|
|
99
|
+
"new",
|
|
100
|
+
{
|
|
101
|
+
directory: Argument.string("directory").pipe(
|
|
102
|
+
Argument.withDescription('Directory to create. Use "." for the current directory.'),
|
|
103
|
+
),
|
|
104
|
+
git: Flag.boolean("git").pipe(
|
|
105
|
+
Flag.withDescription("Initialize a Git repository. Use --no-git to skip it."),
|
|
106
|
+
Flag.withDefault(true),
|
|
107
|
+
),
|
|
108
|
+
install: Flag.boolean("install").pipe(
|
|
109
|
+
Flag.withDescription("Install dependencies. Use --no-install to skip it."),
|
|
110
|
+
Flag.withDefault(true),
|
|
111
|
+
),
|
|
112
|
+
},
|
|
113
|
+
Effect.fn("new")(function* ({ directory, git, install }) {
|
|
114
|
+
const path = yield* Path.Path;
|
|
115
|
+
const terminal = yield* Terminal.Terminal;
|
|
116
|
+
const currentDirectory = path.resolve(".");
|
|
117
|
+
const result = yield* createProject({ currentDirectory, directory, git, install }).pipe(
|
|
118
|
+
Effect.mapError((error) =>
|
|
119
|
+
CliError.UserError.make({ cause: error, userMessage: error.message }),
|
|
120
|
+
),
|
|
121
|
+
);
|
|
122
|
+
const changeDirectory = result.directory === currentDirectory ? "" : ` cd ${directory}\n`;
|
|
123
|
+
|
|
124
|
+
const installCommand = result.packageManager === null ? " npx ignotum install\n" : "";
|
|
125
|
+
|
|
126
|
+
yield* terminal.display(
|
|
127
|
+
`Created ${result.projectName} in ${result.directory}.\n\nNext steps:\n${changeDirectory}${installCommand} npx ignotum dev\n`,
|
|
128
|
+
);
|
|
129
|
+
}),
|
|
130
|
+
).pipe(
|
|
131
|
+
Command.withDescription("Create a new Ignotum app in an empty directory."),
|
|
132
|
+
Command.withExamples([
|
|
133
|
+
{
|
|
134
|
+
command: "ignotum new my-app",
|
|
135
|
+
description: "Create an app in a new directory.",
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
command: "ignotum new . --no-git --no-install",
|
|
139
|
+
description: "Create an app in the current directory without Git or dependency installation.",
|
|
140
|
+
},
|
|
141
|
+
]),
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const ignotum = Command.make("ignotum").pipe(
|
|
145
|
+
Command.withSubcommands([newProject, install, codegen, dev]),
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
export const main = (): void => {
|
|
149
|
+
ignotum.pipe(
|
|
150
|
+
Command.run({ version: packageJson.version }),
|
|
151
|
+
// @effect-diagnostics-next-line strictEffectProvide:off
|
|
152
|
+
Effect.provide(NodeServices.layer),
|
|
153
|
+
NodeRuntime.runMain,
|
|
154
|
+
);
|
|
155
|
+
};
|
package/src/cli/dev.ts
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
|
|
4
|
+
import prefresh from "@prefresh/vite";
|
|
5
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
6
|
+
import { Effect, FileSystem, Path, Schema } from "effect";
|
|
7
|
+
import { createServer, defaultClientConditions, normalizePath } from "vite";
|
|
8
|
+
import type { Alias, ViteDevServer } from "vite";
|
|
9
|
+
|
|
10
|
+
import { generate } from "./codegen.js";
|
|
11
|
+
import { ignotumClientPlugin } from "./client-plugin.js";
|
|
12
|
+
import { acquireDevDatabaseLock, devDatabasePath } from "../dev-runtime/dev-database.js";
|
|
13
|
+
import { ignotumSyncPlugin } from "../dev-runtime/sync.js";
|
|
14
|
+
|
|
15
|
+
const requiredClientFiles = ["App.tsx", "styles.css"] as const;
|
|
16
|
+
const preactSpecifiers = [
|
|
17
|
+
"preact/jsx-dev-runtime",
|
|
18
|
+
"preact/jsx-runtime",
|
|
19
|
+
"preact/devtools",
|
|
20
|
+
"preact/debug",
|
|
21
|
+
"preact/hooks",
|
|
22
|
+
"preact",
|
|
23
|
+
] as const;
|
|
24
|
+
const prefreshSpecifiers = ["@prefresh/core", "@prefresh/utils"] as const;
|
|
25
|
+
|
|
26
|
+
export class ClientFileNotFound extends Schema.TaggedError<ClientFileNotFound>()(
|
|
27
|
+
"ClientFileNotFound",
|
|
28
|
+
{
|
|
29
|
+
message: Schema.String,
|
|
30
|
+
path: Schema.String,
|
|
31
|
+
},
|
|
32
|
+
) {}
|
|
33
|
+
|
|
34
|
+
export class ClientRuntimeResolutionFailed extends Schema.TaggedError<ClientRuntimeResolutionFailed>()(
|
|
35
|
+
"ClientRuntimeResolutionFailed",
|
|
36
|
+
{
|
|
37
|
+
cause: Schema.Defect(),
|
|
38
|
+
message: Schema.String,
|
|
39
|
+
},
|
|
40
|
+
) {}
|
|
41
|
+
|
|
42
|
+
export class ViteStartupFailed extends Schema.TaggedError<ViteStartupFailed>()(
|
|
43
|
+
"ViteStartupFailed",
|
|
44
|
+
{
|
|
45
|
+
cause: Schema.Defect(),
|
|
46
|
+
message: Schema.String,
|
|
47
|
+
},
|
|
48
|
+
) {}
|
|
49
|
+
|
|
50
|
+
export interface DevOptions {
|
|
51
|
+
readonly host: string;
|
|
52
|
+
readonly open: boolean;
|
|
53
|
+
readonly port: number;
|
|
54
|
+
readonly projectDirectory: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const validateClientFiles = Effect.fn("Dev.validateClientFiles")(function* (
|
|
58
|
+
projectDirectory: string,
|
|
59
|
+
) {
|
|
60
|
+
const fileSystem = yield* FileSystem.FileSystem;
|
|
61
|
+
const path = yield* Path.Path;
|
|
62
|
+
const clientDirectory = path.join(projectDirectory, "client");
|
|
63
|
+
|
|
64
|
+
yield* Effect.forEach(
|
|
65
|
+
requiredClientFiles,
|
|
66
|
+
Effect.fn("Dev.validateClientFile")(function* (fileName) {
|
|
67
|
+
const filePath = path.join(clientDirectory, fileName);
|
|
68
|
+
const exists = yield* fileSystem.exists(filePath);
|
|
69
|
+
|
|
70
|
+
if (!exists) {
|
|
71
|
+
return yield* ClientFileNotFound.make({
|
|
72
|
+
message: `Required client file not found: ${filePath}`,
|
|
73
|
+
path: filePath,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}),
|
|
77
|
+
{ discard: true },
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const resolveClientAliases = Effect.fn("Dev.resolveClientAliases")(function* () {
|
|
82
|
+
return yield* Effect.try({
|
|
83
|
+
try: (): Array<Alias> => {
|
|
84
|
+
const prefreshRequire = createRequire(import.meta.resolve("@prefresh/vite"));
|
|
85
|
+
|
|
86
|
+
return [
|
|
87
|
+
{
|
|
88
|
+
find: /^tailwindcss$/,
|
|
89
|
+
replacement: normalizePath(fileURLToPath(import.meta.resolve("tailwindcss/index.css"))),
|
|
90
|
+
},
|
|
91
|
+
...preactSpecifiers.map((specifier) => ({
|
|
92
|
+
find: specifier,
|
|
93
|
+
replacement: normalizePath(fileURLToPath(import.meta.resolve(specifier))),
|
|
94
|
+
})),
|
|
95
|
+
...prefreshSpecifiers.map((specifier) => ({
|
|
96
|
+
find: specifier,
|
|
97
|
+
replacement: normalizePath(prefreshRequire.resolve(specifier)),
|
|
98
|
+
})),
|
|
99
|
+
];
|
|
100
|
+
},
|
|
101
|
+
catch: (cause) =>
|
|
102
|
+
ClientRuntimeResolutionFailed.make({
|
|
103
|
+
cause,
|
|
104
|
+
message: "Ignotum could not resolve its client runtime.",
|
|
105
|
+
}),
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const acquireViteServer = Effect.fn("Dev.acquireViteServer")(function* (options: DevOptions) {
|
|
110
|
+
const fileSystem = yield* FileSystem.FileSystem;
|
|
111
|
+
const path = yield* Path.Path;
|
|
112
|
+
const aliases = yield* resolveClientAliases();
|
|
113
|
+
const clientDirectory = path.join(options.projectDirectory, "client");
|
|
114
|
+
const databasePath = yield* devDatabasePath(options.projectDirectory);
|
|
115
|
+
const stateDirectory = path.dirname(databasePath);
|
|
116
|
+
const sourceClientEntry = fileURLToPath(new URL("../../src/client/index.ts", import.meta.url));
|
|
117
|
+
const sourceContractsEntry = fileURLToPath(
|
|
118
|
+
new URL("../../../contracts/src/schema/index.ts", import.meta.url),
|
|
119
|
+
);
|
|
120
|
+
const hasSourceClient = yield* fileSystem.exists(sourceClientEntry);
|
|
121
|
+
const hasSourceContracts = yield* fileSystem.exists(sourceContractsEntry);
|
|
122
|
+
const hasWorkspaceSourceExports = hasSourceClient && hasSourceContracts;
|
|
123
|
+
|
|
124
|
+
yield* fileSystem.makeDirectory(stateDirectory, { recursive: true });
|
|
125
|
+
|
|
126
|
+
return yield* Effect.acquireRelease(
|
|
127
|
+
Effect.tryPromise({
|
|
128
|
+
try: () =>
|
|
129
|
+
prefresh().then((prefreshPlugin) =>
|
|
130
|
+
createServer({
|
|
131
|
+
appType: "spa",
|
|
132
|
+
configFile: false,
|
|
133
|
+
mode: "development",
|
|
134
|
+
root: clientDirectory,
|
|
135
|
+
plugins: [
|
|
136
|
+
ignotumSyncPlugin(options.projectDirectory, databasePath),
|
|
137
|
+
ignotumClientPlugin(),
|
|
138
|
+
prefreshPlugin,
|
|
139
|
+
tailwindcss(),
|
|
140
|
+
],
|
|
141
|
+
oxc: {
|
|
142
|
+
jsx: {
|
|
143
|
+
importSource: "ignotum/client",
|
|
144
|
+
runtime: "automatic",
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
resolve: {
|
|
148
|
+
alias: aliases,
|
|
149
|
+
conditions: [
|
|
150
|
+
...(hasWorkspaceSourceExports ? ["@ignotum/source"] : []),
|
|
151
|
+
...defaultClientConditions,
|
|
152
|
+
],
|
|
153
|
+
dedupe: ["preact"],
|
|
154
|
+
tsconfigPaths: true,
|
|
155
|
+
},
|
|
156
|
+
server: {
|
|
157
|
+
forwardConsole: {
|
|
158
|
+
logLevels: ["warn", "error"],
|
|
159
|
+
unhandledErrors: true,
|
|
160
|
+
},
|
|
161
|
+
host: options.host,
|
|
162
|
+
open: options.open,
|
|
163
|
+
port: options.port,
|
|
164
|
+
strictPort: true,
|
|
165
|
+
},
|
|
166
|
+
}),
|
|
167
|
+
),
|
|
168
|
+
catch: (cause) =>
|
|
169
|
+
ViteStartupFailed.make({
|
|
170
|
+
cause,
|
|
171
|
+
message: "Ignotum could not create the Vite development server.",
|
|
172
|
+
}),
|
|
173
|
+
}),
|
|
174
|
+
(server) => Effect.promise(() => server.close()),
|
|
175
|
+
);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const listen = Effect.fn("Dev.listen")(function* (server: ViteDevServer) {
|
|
179
|
+
yield* Effect.tryPromise({
|
|
180
|
+
try: () => server.listen(),
|
|
181
|
+
catch: (cause) =>
|
|
182
|
+
ViteStartupFailed.make({
|
|
183
|
+
cause,
|
|
184
|
+
message: "Ignotum could not start the Vite development server.",
|
|
185
|
+
}),
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
export const dev = Effect.fn("Dev.run")(function* (options: DevOptions) {
|
|
190
|
+
yield* validateClientFiles(options.projectDirectory);
|
|
191
|
+
yield* generate(options.projectDirectory);
|
|
192
|
+
|
|
193
|
+
return yield* Effect.scoped(
|
|
194
|
+
Effect.gen(function* () {
|
|
195
|
+
yield* acquireDevDatabaseLock(options.projectDirectory);
|
|
196
|
+
const server = yield* acquireViteServer(options);
|
|
197
|
+
|
|
198
|
+
yield* listen(server);
|
|
199
|
+
yield* Effect.sync(() => {
|
|
200
|
+
server.printUrls();
|
|
201
|
+
server.bindCLIShortcuts({ print: true });
|
|
202
|
+
});
|
|
203
|
+
return yield* Effect.never;
|
|
204
|
+
}),
|
|
205
|
+
);
|
|
206
|
+
});
|