proteum 2.0.0-1 → 2.1.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.
- package/AGENTS.md +13 -1
- package/README.md +375 -0
- package/agents/framework/AGENTS.md +917 -0
- package/agents/project/AGENTS.md +138 -0
- package/agents/{codex → project}/CODING_STYLE.md +3 -2
- package/agents/project/client/AGENTS.md +108 -0
- package/agents/{codex → project}/client/pages/AGENTS.md +8 -8
- package/agents/{codex → project}/server/routes/AGENTS.md +2 -1
- package/agents/project/server/services/AGENTS.md +170 -0
- package/agents/{codex → project}/tests/AGENTS.md +1 -0
- package/cli/app/config.ts +3 -2
- package/cli/app/index.ts +6 -66
- package/cli/bin.js +7 -2
- package/cli/commands/build.ts +94 -27
- package/cli/commands/check.ts +15 -1
- package/cli/commands/dev.ts +288 -132
- package/cli/commands/doctor.ts +108 -0
- package/cli/commands/explain.ts +226 -0
- package/cli/commands/init.ts +76 -70
- package/cli/commands/lint.ts +18 -1
- package/cli/commands/refresh.ts +16 -6
- package/cli/commands/typecheck.ts +14 -1
- package/cli/compiler/artifacts/controllers.ts +150 -0
- package/cli/compiler/artifacts/discovery.ts +132 -0
- package/cli/compiler/artifacts/manifest.ts +267 -0
- package/cli/compiler/artifacts/routing.ts +315 -0
- package/cli/compiler/artifacts/services.ts +480 -0
- package/cli/compiler/artifacts/shared.ts +12 -0
- package/cli/compiler/client/identite.ts +2 -1
- package/cli/compiler/client/index.ts +13 -3
- package/cli/compiler/common/controllers.ts +23 -28
- package/cli/compiler/common/files/style.ts +3 -4
- package/cli/compiler/common/generatedRouteModules.ts +333 -19
- package/cli/compiler/common/proteumManifest.ts +133 -0
- package/cli/compiler/index.ts +33 -896
- package/cli/compiler/server/index.ts +21 -4
- package/cli/context.ts +71 -0
- package/cli/index.ts +39 -181
- package/cli/presentation/commands.ts +208 -0
- package/cli/presentation/compileReporter.ts +65 -0
- package/cli/presentation/devSession.ts +70 -0
- package/cli/presentation/help.ts +193 -0
- package/cli/presentation/ink.ts +69 -0
- package/cli/presentation/layout.ts +83 -0
- package/cli/runtime/argv.ts +49 -0
- package/cli/runtime/command.ts +25 -0
- package/cli/runtime/commands.ts +221 -0
- package/cli/runtime/importEsm.ts +7 -0
- package/cli/runtime/verbose.ts +15 -0
- package/cli/utils/agents.ts +5 -4
- package/cli/utils/keyboard.ts +12 -6
- package/client/app/index.ts +0 -6
- package/client/services/router/index.tsx +1 -1
- package/client/services/router/response/index.tsx +2 -2
- package/common/dev/serverHotReload.ts +12 -0
- package/common/router/index.ts +3 -2
- package/common/router/layouts.ts +1 -1
- package/common/router/pageSetup.ts +1 -0
- package/package.json +10 -8
- package/prettier/router-registration-plugin.cjs +52 -0
- package/prettier.config.cjs +1 -0
- package/scripts/cleanup-generated-controllers.ts +2 -2
- package/scripts/fix-reference-app-typing.ts +2 -2
- package/scripts/format-router-registrations.ts +119 -0
- package/scripts/migrate-explicit-controllers-and-request.ts +423 -0
- package/scripts/refactor-server-controllers.ts +19 -18
- package/scripts/refactor-server-runtime-aliases.ts +1 -1
- package/server/app/commands.ts +309 -25
- package/server/app/container/config.ts +1 -1
- package/server/app/container/index.ts +2 -2
- package/server/app/controller/index.ts +13 -4
- package/server/app/index.ts +53 -37
- package/server/app/service/container.ts +26 -28
- package/server/app/service/index.ts +10 -20
- package/server/app.tsconfig.json +9 -2
- package/server/index.ts +32 -1
- package/server/services/auth/index.ts +234 -15
- package/server/services/auth/router/index.ts +39 -7
- package/server/services/auth/router/request.ts +40 -8
- package/server/services/disks/index.ts +1 -1
- package/server/services/prisma/Facet.ts +2 -2
- package/server/services/prisma/index.ts +22 -5
- package/server/services/prisma/mariadb.ts +47 -0
- package/server/services/router/http/index.ts +9 -1
- package/server/services/router/index.ts +10 -4
- package/server/services/router/response/index.ts +26 -6
- package/types/auth-check-rules.test.ts +51 -0
- package/types/controller-request-context.test.ts +55 -0
- package/types/service-config.test.ts +39 -0
- package/agents/codex/AGENTS.md +0 -95
- package/agents/codex/client/AGENTS.md +0 -102
- package/agents/codex/server/services/AGENTS.md +0 -137
- package/server/services/models.7z +0 -0
- /package/agents/{codex → project}/agents.md.zip +0 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { Builtins, Cli, Option } from 'clipanion';
|
|
2
|
+
|
|
3
|
+
import type { TArgsObject } from '../context';
|
|
4
|
+
import { applyLegacyBooleanArgs, assertNoLegacyArgs } from './argv';
|
|
5
|
+
import { buildUsage, ProteumCommand, runCommandModule } from './command';
|
|
6
|
+
|
|
7
|
+
class InitCommand extends ProteumCommand {
|
|
8
|
+
public static paths = [['init']];
|
|
9
|
+
|
|
10
|
+
public static usage = buildUsage('init');
|
|
11
|
+
|
|
12
|
+
public legacyArgs = Option.Rest();
|
|
13
|
+
|
|
14
|
+
public async execute() {
|
|
15
|
+
assertNoLegacyArgs('init', this.legacyArgs);
|
|
16
|
+
this.setCliArgs();
|
|
17
|
+
await runCommandModule(() => import('../commands/init'));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class DevCommand extends ProteumCommand {
|
|
22
|
+
public static paths = [['dev']];
|
|
23
|
+
|
|
24
|
+
public static usage = buildUsage('dev');
|
|
25
|
+
|
|
26
|
+
public port = Option.String('--port', { description: 'Override the router port.' });
|
|
27
|
+
public cache = Option.Boolean('--cache', true, { description: 'Enable filesystem caching.' });
|
|
28
|
+
public legacyArgs = Option.Rest();
|
|
29
|
+
|
|
30
|
+
public async execute() {
|
|
31
|
+
assertNoLegacyArgs('dev', this.legacyArgs);
|
|
32
|
+
this.setCliArgs({ port: this.port ?? '', cache: this.cache });
|
|
33
|
+
await runCommandModule(() => import('../commands/dev'));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
class RefreshCommand extends ProteumCommand {
|
|
38
|
+
public static paths = [['refresh']];
|
|
39
|
+
|
|
40
|
+
public static usage = buildUsage('refresh');
|
|
41
|
+
|
|
42
|
+
public legacyArgs = Option.Rest();
|
|
43
|
+
|
|
44
|
+
public async execute() {
|
|
45
|
+
assertNoLegacyArgs('refresh', this.legacyArgs);
|
|
46
|
+
this.setCliArgs();
|
|
47
|
+
await runCommandModule(() => import('../commands/refresh'));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
class BuildCommand extends ProteumCommand {
|
|
52
|
+
public static paths = [['build']];
|
|
53
|
+
|
|
54
|
+
public static usage = buildUsage('build');
|
|
55
|
+
|
|
56
|
+
public port = Option.String('--port', { description: 'Override the router port.' });
|
|
57
|
+
public prod = Option.Boolean('--prod', false, { description: 'Build in production mode.' });
|
|
58
|
+
public cache = Option.Boolean('--cache', false, { description: 'Enable filesystem caching during the build.' });
|
|
59
|
+
public analyze = Option.Boolean('--analyze', false, { description: 'Emit the client bundle analysis report.' });
|
|
60
|
+
public strict = Option.Boolean('--strict', false, {
|
|
61
|
+
description: 'Refresh generated typings and fail the build if TypeScript reports any error.',
|
|
62
|
+
});
|
|
63
|
+
public legacyArgs = Option.Rest();
|
|
64
|
+
|
|
65
|
+
public async execute() {
|
|
66
|
+
const args = {
|
|
67
|
+
port: this.port ?? '',
|
|
68
|
+
dev: false,
|
|
69
|
+
prod: this.prod,
|
|
70
|
+
cache: this.cache,
|
|
71
|
+
analyze: this.analyze,
|
|
72
|
+
strict: this.strict,
|
|
73
|
+
} satisfies TArgsObject;
|
|
74
|
+
|
|
75
|
+
applyLegacyBooleanArgs('build', this.legacyArgs, ['prod', 'cache', 'analyze', 'strict'], args);
|
|
76
|
+
this.setCliArgs(args);
|
|
77
|
+
await runCommandModule(() => import('../commands/build'));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
class TypecheckCommand extends ProteumCommand {
|
|
82
|
+
public static paths = [['typecheck']];
|
|
83
|
+
|
|
84
|
+
public static usage = buildUsage('typecheck');
|
|
85
|
+
|
|
86
|
+
public legacyArgs = Option.Rest();
|
|
87
|
+
|
|
88
|
+
public async execute() {
|
|
89
|
+
assertNoLegacyArgs('typecheck', this.legacyArgs);
|
|
90
|
+
this.setCliArgs();
|
|
91
|
+
await runCommandModule(() => import('../commands/typecheck'));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
class LintCommand extends ProteumCommand {
|
|
96
|
+
public static paths = [['lint']];
|
|
97
|
+
|
|
98
|
+
public static usage = buildUsage('lint');
|
|
99
|
+
|
|
100
|
+
public fix = Option.Boolean('--fix', false, { description: 'Apply fixable lint changes.' });
|
|
101
|
+
public legacyArgs = Option.Rest();
|
|
102
|
+
|
|
103
|
+
public async execute() {
|
|
104
|
+
const args = { fix: this.fix } satisfies TArgsObject;
|
|
105
|
+
|
|
106
|
+
applyLegacyBooleanArgs('lint', this.legacyArgs, ['fix'], args);
|
|
107
|
+
this.setCliArgs(args);
|
|
108
|
+
await runCommandModule(() => import('../commands/lint'));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
class CheckCommand extends ProteumCommand {
|
|
113
|
+
public static paths = [['check']];
|
|
114
|
+
|
|
115
|
+
public static usage = buildUsage('check');
|
|
116
|
+
|
|
117
|
+
public legacyArgs = Option.Rest();
|
|
118
|
+
|
|
119
|
+
public async execute() {
|
|
120
|
+
assertNoLegacyArgs('check', this.legacyArgs);
|
|
121
|
+
this.setCliArgs();
|
|
122
|
+
await runCommandModule(() => import('../commands/check'));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
class DoctorCommand extends ProteumCommand {
|
|
127
|
+
public static paths = [['doctor']];
|
|
128
|
+
|
|
129
|
+
public static usage = buildUsage('doctor');
|
|
130
|
+
|
|
131
|
+
public json = Option.Boolean('--json', false, { description: 'Print JSON output.' });
|
|
132
|
+
public strict = Option.Boolean('--strict', false, { description: 'Exit with failure if any diagnostics exist.' });
|
|
133
|
+
public legacyArgs = Option.Rest();
|
|
134
|
+
|
|
135
|
+
public async execute() {
|
|
136
|
+
const args = { json: this.json, strict: this.strict } satisfies TArgsObject;
|
|
137
|
+
|
|
138
|
+
applyLegacyBooleanArgs('doctor', this.legacyArgs, ['json', 'strict'], args);
|
|
139
|
+
this.setCliArgs(args);
|
|
140
|
+
await runCommandModule(() => import('../commands/doctor'));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
class ExplainCommand extends ProteumCommand {
|
|
145
|
+
public static paths = [['explain']];
|
|
146
|
+
|
|
147
|
+
public static usage = buildUsage('explain');
|
|
148
|
+
|
|
149
|
+
public json = Option.Boolean('--json', false, { description: 'Print JSON output.' });
|
|
150
|
+
public all = Option.Boolean('--all', false, { description: 'Include every explain section.' });
|
|
151
|
+
public app = Option.Boolean('--app', false, { description: 'Include the app section.' });
|
|
152
|
+
public conventions = Option.Boolean('--conventions', false, { description: 'Include the conventions section.' });
|
|
153
|
+
public env = Option.Boolean('--env', false, { description: 'Include the env section.' });
|
|
154
|
+
public services = Option.Boolean('--services', false, { description: 'Include the services section.' });
|
|
155
|
+
public controllers = Option.Boolean('--controllers', false, { description: 'Include the controllers section.' });
|
|
156
|
+
public routes = Option.Boolean('--routes', false, { description: 'Include the routes section.' });
|
|
157
|
+
public layouts = Option.Boolean('--layouts', false, { description: 'Include the layouts section.' });
|
|
158
|
+
public diagnostics = Option.Boolean('--diagnostics', false, {
|
|
159
|
+
description: 'Include the diagnostics section.',
|
|
160
|
+
});
|
|
161
|
+
public legacyArgs = Option.Rest();
|
|
162
|
+
|
|
163
|
+
public async execute() {
|
|
164
|
+
const args = {
|
|
165
|
+
json: this.json,
|
|
166
|
+
all: this.all,
|
|
167
|
+
app: this.app,
|
|
168
|
+
conventions: this.conventions,
|
|
169
|
+
env: this.env,
|
|
170
|
+
services: this.services,
|
|
171
|
+
controllers: this.controllers,
|
|
172
|
+
routes: this.routes,
|
|
173
|
+
layouts: this.layouts,
|
|
174
|
+
diagnostics: this.diagnostics,
|
|
175
|
+
} satisfies TArgsObject;
|
|
176
|
+
|
|
177
|
+
applyLegacyBooleanArgs(
|
|
178
|
+
'explain',
|
|
179
|
+
this.legacyArgs,
|
|
180
|
+
['json', 'all', 'app', 'conventions', 'env', 'services', 'controllers', 'routes', 'layouts', 'diagnostics'],
|
|
181
|
+
args,
|
|
182
|
+
);
|
|
183
|
+
this.setCliArgs(args);
|
|
184
|
+
await runCommandModule(() => import('../commands/explain'));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export const registeredCommands = {
|
|
189
|
+
init: InitCommand,
|
|
190
|
+
dev: DevCommand,
|
|
191
|
+
refresh: RefreshCommand,
|
|
192
|
+
build: BuildCommand,
|
|
193
|
+
typecheck: TypecheckCommand,
|
|
194
|
+
lint: LintCommand,
|
|
195
|
+
check: CheckCommand,
|
|
196
|
+
doctor: DoctorCommand,
|
|
197
|
+
explain: ExplainCommand,
|
|
198
|
+
} as const;
|
|
199
|
+
|
|
200
|
+
export const createCli = (version: string) => {
|
|
201
|
+
const clipanion = new Cli({
|
|
202
|
+
binaryLabel: 'Proteum',
|
|
203
|
+
binaryName: 'proteum',
|
|
204
|
+
binaryVersion: version,
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
clipanion.register(Builtins.HelpCommand);
|
|
208
|
+
clipanion.register(Builtins.VersionCommand);
|
|
209
|
+
clipanion.register(Builtins.DefinitionsCommand);
|
|
210
|
+
clipanion.register(InitCommand);
|
|
211
|
+
clipanion.register(DevCommand);
|
|
212
|
+
clipanion.register(RefreshCommand);
|
|
213
|
+
clipanion.register(BuildCommand);
|
|
214
|
+
clipanion.register(TypecheckCommand);
|
|
215
|
+
clipanion.register(LintCommand);
|
|
216
|
+
clipanion.register(CheckCommand);
|
|
217
|
+
clipanion.register(DoctorCommand);
|
|
218
|
+
clipanion.register(ExplainCommand);
|
|
219
|
+
|
|
220
|
+
return clipanion;
|
|
221
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// The CLI still boots through ts-node in CommonJS mode, but Ink ships as ESM-only.
|
|
2
|
+
// Use Node's native dynamic import so presentation code can depend on Ink safely.
|
|
3
|
+
const nativeDynamicImport = new Function('specifier', 'return import(specifier)') as <T = unknown>(
|
|
4
|
+
specifier: string,
|
|
5
|
+
) => Promise<T>;
|
|
6
|
+
|
|
7
|
+
export const importEsm = <T = unknown>(specifier: string) => nativeDynamicImport(specifier) as Promise<T>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import cli from '../context';
|
|
2
|
+
|
|
3
|
+
export const isVerbose = () => cli.verbose === true;
|
|
4
|
+
|
|
5
|
+
export const logVerbose = (...args: unknown[]) => {
|
|
6
|
+
if (!isVerbose()) return;
|
|
7
|
+
|
|
8
|
+
console.info(...args);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const logVerboseWarn = (...args: unknown[]) => {
|
|
12
|
+
if (!isVerbose()) return;
|
|
13
|
+
|
|
14
|
+
console.warn(...args);
|
|
15
|
+
};
|
package/cli/utils/agents.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// Npm
|
|
6
6
|
import fs from 'fs-extra';
|
|
7
7
|
import path from 'path';
|
|
8
|
+
import { logVerbose } from '../runtime/verbose';
|
|
8
9
|
|
|
9
10
|
/*----------------------------------
|
|
10
11
|
- TYPES
|
|
@@ -19,7 +20,7 @@ type TAgentLinkDefinition = { projectPath: string; sourcePath: string; ensurePar
|
|
|
19
20
|
----------------------------------*/
|
|
20
21
|
|
|
21
22
|
// Project-local AGENTS entrypoints mapped to their framework-owned source files.
|
|
22
|
-
const
|
|
23
|
+
const projectAgentLinkDefinitions: TAgentLinkDefinition[] = [
|
|
23
24
|
{ projectPath: 'AGENTS.md', sourcePath: 'AGENTS.md' },
|
|
24
25
|
{ projectPath: 'CODING_STYLE.md', sourcePath: 'CODING_STYLE.md' },
|
|
25
26
|
{ projectPath: path.join('client', 'AGENTS.md'), sourcePath: path.join('client', 'AGENTS.md') },
|
|
@@ -37,8 +38,8 @@ const codexAgentLinkDefinitions: TAgentLinkDefinition[] = [
|
|
|
37
38
|
----------------------------------*/
|
|
38
39
|
|
|
39
40
|
export function ensureProjectAgentSymlinks({ appRoot, coreRoot }: TEnsureProjectAgentSymlinksArgs) {
|
|
40
|
-
const agentSourceRoot = path.join(coreRoot, 'agents', '
|
|
41
|
-
const agentLinks =
|
|
41
|
+
const agentSourceRoot = path.join(coreRoot, 'agents', 'project');
|
|
42
|
+
const agentLinks = projectAgentLinkDefinitions.map((linkDefinition) => ({
|
|
42
43
|
...linkDefinition,
|
|
43
44
|
sourcePath: path.join(agentSourceRoot, linkDefinition.sourcePath),
|
|
44
45
|
}));
|
|
@@ -86,7 +87,7 @@ function ensureSymlinks(appRoot: string, linkDefinitions: TAgentLinkDefinition[]
|
|
|
86
87
|
const symlinkTarget = path.relative(projectParentDir, sourceFilepath);
|
|
87
88
|
fs.symlinkSync(symlinkTarget, projectFilepath);
|
|
88
89
|
|
|
89
|
-
|
|
90
|
+
logVerbose(`${logPrefix} Created ${path.relative(appRoot, projectFilepath) || '.'} -> ${symlinkTarget}`);
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
93
|
|
package/cli/utils/keyboard.ts
CHANGED
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
// npm
|
|
6
6
|
import readline, { Key } from 'readline';
|
|
7
|
+
import { logVerbose } from '../runtime/verbose';
|
|
7
8
|
|
|
8
9
|
/*----------------------------------
|
|
9
10
|
- TYPES
|
|
10
11
|
----------------------------------*/
|
|
11
12
|
|
|
12
|
-
type TKeyboardCommand = { remove?: boolean; run: (str: string, chunk: string, key: Key) => void };
|
|
13
|
+
type TKeyboardCommand = { remove?: boolean; run: (str: string, chunk: string, key: Key) => void | Promise<void> };
|
|
13
14
|
|
|
14
15
|
/*----------------------------------
|
|
15
16
|
- METHODS
|
|
@@ -34,14 +35,19 @@ class KeyboardCommands {
|
|
|
34
35
|
if (key.meta) str = 'meta+' + str;
|
|
35
36
|
|
|
36
37
|
const kCommand = this.commands[str] || this.commands.fallback;
|
|
37
|
-
if (kCommand) {
|
|
38
|
-
kCommand.run(str, chunk, key);
|
|
39
38
|
|
|
40
|
-
|
|
39
|
+
try {
|
|
40
|
+
if (kCommand) {
|
|
41
|
+
await kCommand.run(str, chunk, key);
|
|
42
|
+
|
|
43
|
+
if (kCommand.remove) delete this.commands[str];
|
|
44
|
+
}
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error(error);
|
|
41
47
|
}
|
|
42
48
|
|
|
43
|
-
if (str === 'ctrl+c') {
|
|
44
|
-
|
|
49
|
+
if (str === 'ctrl+c' && !kCommand) {
|
|
50
|
+
logVerbose(`Exiting ...`);
|
|
45
51
|
process.exit(0);
|
|
46
52
|
}
|
|
47
53
|
});
|
package/client/app/index.ts
CHANGED
|
@@ -56,7 +56,6 @@ export default abstract class Application {
|
|
|
56
56
|
public constructor() {}
|
|
57
57
|
|
|
58
58
|
public registerService(service: AnyService) {
|
|
59
|
-
console.log(`[app] Register service`, service.constructor?.name);
|
|
60
59
|
this.servicesList.push(service);
|
|
61
60
|
}
|
|
62
61
|
|
|
@@ -69,14 +68,9 @@ export default abstract class Application {
|
|
|
69
68
|
public abstract boot(): void;
|
|
70
69
|
|
|
71
70
|
public startServices() {
|
|
72
|
-
console.log(`[app] Starting ${this.servicesList.length} services.`);
|
|
73
|
-
|
|
74
71
|
for (const service of this.servicesList) {
|
|
75
|
-
console.log(`[app] Start service`, service);
|
|
76
72
|
service.start();
|
|
77
73
|
}
|
|
78
|
-
|
|
79
|
-
console.log(`[app] All ${this.servicesList.length} services were started.`);
|
|
80
74
|
}
|
|
81
75
|
|
|
82
76
|
public bindErrorHandlers() {
|
|
@@ -44,7 +44,7 @@ import ClientPage from './response/page';
|
|
|
44
44
|
type AppPropsContext = Parameters<typeof App>[0]['context'];
|
|
45
45
|
|
|
46
46
|
// Routes (import __register)
|
|
47
|
-
import appRoutes from '
|
|
47
|
+
import appRoutes from '@generated/client/routes';
|
|
48
48
|
|
|
49
49
|
/*----------------------------------
|
|
50
50
|
- CONFIG
|
|
@@ -15,8 +15,8 @@ import type ClientResponse from '@client/services/router/response';
|
|
|
15
15
|
import ClientRequest from '@client/services/router/request';
|
|
16
16
|
import ClientPage from '@client/services/router/response/page';
|
|
17
17
|
import { history } from '@client/services/router/request/history';
|
|
18
|
-
import createControllers from '
|
|
19
|
-
import type { TControllers } from '
|
|
18
|
+
import createControllers from '@generated/common/controllers';
|
|
19
|
+
import type { TControllers } from '@generated/common/controllers';
|
|
20
20
|
|
|
21
21
|
/*----------------------------------
|
|
22
22
|
- TYPES
|
|
@@ -2,6 +2,7 @@ export const serverHotReloadMessageType = {
|
|
|
2
2
|
request: 'proteum:router-reload',
|
|
3
3
|
succeeded: 'proteum:router-reload-succeeded',
|
|
4
4
|
failed: 'proteum:router-reload-failed',
|
|
5
|
+
ready: 'proteum:server-ready',
|
|
5
6
|
} as const;
|
|
6
7
|
|
|
7
8
|
export type TServerHotReloadRequest = { type: typeof serverHotReloadMessageType.request; changedFiles: string[] };
|
|
@@ -12,6 +13,11 @@ export type TServerHotReloadResult = {
|
|
|
12
13
|
error?: string;
|
|
13
14
|
};
|
|
14
15
|
|
|
16
|
+
export type TServerReadyMessage = {
|
|
17
|
+
type: typeof serverHotReloadMessageType.ready;
|
|
18
|
+
publicUrl: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
15
21
|
export const isServerHotReloadRequest = (value: unknown): value is TServerHotReloadRequest =>
|
|
16
22
|
typeof value === 'object' &&
|
|
17
23
|
value !== null &&
|
|
@@ -24,3 +30,9 @@ export const isServerHotReloadResult = (value: unknown): value is TServerHotRelo
|
|
|
24
30
|
((value as TServerHotReloadResult).type === serverHotReloadMessageType.succeeded ||
|
|
25
31
|
(value as TServerHotReloadResult).type === serverHotReloadMessageType.failed) &&
|
|
26
32
|
Array.isArray((value as TServerHotReloadResult).changedFiles);
|
|
33
|
+
|
|
34
|
+
export const isServerReadyMessage = (value: unknown): value is TServerReadyMessage =>
|
|
35
|
+
typeof value === 'object' &&
|
|
36
|
+
value !== null &&
|
|
37
|
+
(value as TServerReadyMessage).type === serverHotReloadMessageType.ready &&
|
|
38
|
+
typeof (value as TServerReadyMessage).publicUrl === 'string';
|
package/common/router/index.ts
CHANGED
|
@@ -13,7 +13,7 @@ import type { TAnyRouter, TRouterContext as ServerRouterContext, TRouteHttpMetho
|
|
|
13
13
|
|
|
14
14
|
import type RouterRequest from './request';
|
|
15
15
|
|
|
16
|
-
import type {
|
|
16
|
+
import type { TAuthCheckInput, TAuthTrackingContext } from '@server/services/auth';
|
|
17
17
|
|
|
18
18
|
import type { TAppArrowFunction } from '@common/app';
|
|
19
19
|
|
|
@@ -86,7 +86,8 @@ export type TRouteOptions = {
|
|
|
86
86
|
domain?: string;
|
|
87
87
|
accept?: string;
|
|
88
88
|
raw?: boolean; // true to return raw data
|
|
89
|
-
auth?:
|
|
89
|
+
auth?: TAuthCheckInput;
|
|
90
|
+
authTracking?: TAuthTrackingContext;
|
|
90
91
|
redirectLogged?: string; // Redirect to this route if auth: false and user is logged
|
|
91
92
|
|
|
92
93
|
// Rendering
|
package/common/router/layouts.ts
CHANGED
|
@@ -11,7 +11,7 @@ import type { TDataProvider, TPageRenderContext } from './response/page';
|
|
|
11
11
|
|
|
12
12
|
// App
|
|
13
13
|
import internalLayout from '@client/pages/_layout';
|
|
14
|
-
import generatedLayouts, { layoutOrder } from '
|
|
14
|
+
import generatedLayouts, { layoutOrder } from '@generated/client/layouts';
|
|
15
15
|
|
|
16
16
|
/*----------------------------------
|
|
17
17
|
- CONST
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "proteum",
|
|
3
|
-
"description": "
|
|
4
|
-
"version": "2.
|
|
3
|
+
"description": "LLM-first Opinionated Typescript Framework for web applications.",
|
|
4
|
+
"version": "2.1.0",
|
|
5
5
|
"author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
|
|
6
6
|
"repository": "git://github.com/gaetanlegac/proteum.git",
|
|
7
7
|
"license": "MIT",
|
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
"proteum": "cli/bin.js"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@
|
|
19
|
+
"@inkjs/ui": "^2.0.0",
|
|
20
|
+
"@prisma/adapter-mariadb": "7.2.0",
|
|
21
|
+
"@prisma/client": "7.2.0",
|
|
20
22
|
"@rspack/core": "^1.7.9",
|
|
21
23
|
"@tailwindcss/postcss": "^4.1.17",
|
|
22
24
|
"accepts": "^1.3.7",
|
|
@@ -25,12 +27,14 @@
|
|
|
25
27
|
"aws-sdk": "^2.1415.0",
|
|
26
28
|
"bowser": "^2.11.0",
|
|
27
29
|
"cli-highlight": "^2.1.11",
|
|
30
|
+
"clipanion": "^4.0.0-rc.4",
|
|
28
31
|
"compression": "^1.7.4",
|
|
29
32
|
"cookie-parser": "^1.4.5",
|
|
30
33
|
"cors": "^2.8.5",
|
|
31
34
|
"cron-parser": "^4.0.0",
|
|
32
35
|
"css-loader": "^6.2.0",
|
|
33
36
|
"dayjs": "^1.11.5",
|
|
37
|
+
"dotenv": "^17.2.3",
|
|
34
38
|
"escape-regexp": "^0.0.1",
|
|
35
39
|
"eslint": "^9.39.4",
|
|
36
40
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
@@ -47,6 +51,7 @@
|
|
|
47
51
|
"history": "^5.0.1",
|
|
48
52
|
"hpp": "^0.2.3",
|
|
49
53
|
"human-interval": "^2.0.1",
|
|
54
|
+
"ink": "^6.8.0",
|
|
50
55
|
"intl": "^1.2.5",
|
|
51
56
|
"iso-639-1": "^2.1.9",
|
|
52
57
|
"jsonwebtoken": "^8.5.1",
|
|
@@ -72,7 +77,6 @@
|
|
|
72
77
|
"slugify": "^1.6.6",
|
|
73
78
|
"source-map-support": "^0.5.21",
|
|
74
79
|
"stopword": "^3.1.1",
|
|
75
|
-
"style-loader": "^4.0.0",
|
|
76
80
|
"tailwindcss": "^4.1.17",
|
|
77
81
|
"ts-alias": "^0.0.7",
|
|
78
82
|
"ts-node": "^10.9.1",
|
|
@@ -81,12 +85,11 @@
|
|
|
81
85
|
"typescript-eslint": "^8.57.1",
|
|
82
86
|
"uuid": "^8.3.2",
|
|
83
87
|
"validator": "^13.7.0",
|
|
88
|
+
"webpack-bundle-analyzer": "^5.2.0",
|
|
84
89
|
"yaml": "^1.10.2",
|
|
85
|
-
"yargs-parser": "^21.1.1",
|
|
86
90
|
"youch": "^3.3.3",
|
|
87
91
|
"youch-terminal": "^2.2.3",
|
|
88
|
-
"zod": "^4.1.5"
|
|
89
|
-
"webpack-bundle-analyzer": "^5.2.0"
|
|
92
|
+
"zod": "^4.1.5"
|
|
90
93
|
},
|
|
91
94
|
"devDependencies": {
|
|
92
95
|
"@types/cookie": "^0.4.1",
|
|
@@ -102,7 +105,6 @@
|
|
|
102
105
|
"@types/prompts": "^2.0.14",
|
|
103
106
|
"@types/sharp": "^0.31.1",
|
|
104
107
|
"@types/universal-analytics": "^0.4.5",
|
|
105
|
-
"@types/yargs-parser": "^21.0.0",
|
|
106
108
|
"schema-dts": "^1.1.2"
|
|
107
109
|
}
|
|
108
110
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { createRequire } = require('module');
|
|
3
|
+
|
|
4
|
+
const requireFromWorkspace = createRequire(path.join(process.cwd(), 'package.json'));
|
|
5
|
+
|
|
6
|
+
const estreePlugin = (() => {
|
|
7
|
+
try {
|
|
8
|
+
return requireFromWorkspace('prettier/plugins/estree');
|
|
9
|
+
} catch {
|
|
10
|
+
return require('prettier/plugins/estree');
|
|
11
|
+
}
|
|
12
|
+
})();
|
|
13
|
+
|
|
14
|
+
const basePrinter = estreePlugin.printers.estree;
|
|
15
|
+
const ROUTER_REGISTRATION_METHODS = new Set(['page', 'error']);
|
|
16
|
+
|
|
17
|
+
const isRouterRegistrationCall = (node) =>
|
|
18
|
+
node?.type === 'CallExpression' &&
|
|
19
|
+
node.callee?.type === 'MemberExpression' &&
|
|
20
|
+
node.callee.object?.type === 'Identifier' &&
|
|
21
|
+
node.callee.object.name === 'Router' &&
|
|
22
|
+
node.callee.property?.type === 'Identifier' &&
|
|
23
|
+
ROUTER_REGISTRATION_METHODS.has(node.callee.property.name);
|
|
24
|
+
|
|
25
|
+
const printRouterRegistrationCall = (path, print) => {
|
|
26
|
+
const node = path.getValue();
|
|
27
|
+
const parts = [path.call(print, 'callee'), '('];
|
|
28
|
+
|
|
29
|
+
for (const [index] of node.arguments.entries()) {
|
|
30
|
+
if (index > 0) parts.push(', ');
|
|
31
|
+
parts.push(path.call(print, 'arguments', index));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
parts.push(')');
|
|
35
|
+
|
|
36
|
+
return parts;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
module.exports = {
|
|
40
|
+
printers: {
|
|
41
|
+
estree: {
|
|
42
|
+
...basePrinter,
|
|
43
|
+
print(path, options, print) {
|
|
44
|
+
const node = path.getValue();
|
|
45
|
+
|
|
46
|
+
if (isRouterRegistrationCall(node)) return printRouterRegistrationCall(path, print);
|
|
47
|
+
|
|
48
|
+
return basePrinter.print(path, options, print);
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
};
|
package/prettier.config.cjs
CHANGED
|
@@ -14,7 +14,7 @@ const findControllerFiles = (dir: string): string[] => {
|
|
|
14
14
|
continue;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
if (dirent.isFile() && dirent.name.endsWith('.
|
|
17
|
+
if (dirent.isFile() && /\.(tsx?|jsx?)$/.test(dirent.name) && !dirent.name.endsWith('.d.ts')) files.push(filepath);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
return files;
|
|
@@ -25,7 +25,7 @@ if (!repoRoots.length)
|
|
|
25
25
|
throw new Error('Usage: ts-node scripts/cleanup-generated-controllers.ts <repo-root> [repo-root...]');
|
|
26
26
|
|
|
27
27
|
for (const repoRoot of repoRoots) {
|
|
28
|
-
const controllerFiles = findControllerFiles(path.join(repoRoot, 'server', '
|
|
28
|
+
const controllerFiles = findControllerFiles(path.join(repoRoot, 'server', 'controllers'));
|
|
29
29
|
let updated = 0;
|
|
30
30
|
|
|
31
31
|
for (const controllerFile of controllerFiles) {
|
|
@@ -196,11 +196,11 @@ const patchCentralFiles = () => {
|
|
|
196
196
|
),
|
|
197
197
|
);
|
|
198
198
|
|
|
199
|
-
applyLiteralReplacement(path.join(UNIQUE_ROOT, 'server/
|
|
199
|
+
applyLiteralReplacement(path.join(UNIQUE_ROOT, 'server/controllers/Domains/search.ts'), (source) =>
|
|
200
200
|
source.includes(' public async GetLandingSeoCachedSearches() {')
|
|
201
201
|
? source
|
|
202
202
|
: assertReplace(
|
|
203
|
-
path.join(UNIQUE_ROOT, 'server/
|
|
203
|
+
path.join(UNIQUE_ROOT, 'server/controllers/Domains/search.ts'),
|
|
204
204
|
source,
|
|
205
205
|
` public async GetLandingSeoCachedSearch() {
|
|
206
206
|
const { Domains } = this.services;
|