rimecms 0.30.1 → 0.30.3
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 +1 -1
- package/dist/adapter-sqlite/generate-schema/column.server.js +1 -4
- package/dist/adapter-sqlite/generate-schema/write.server.js +1 -3
- package/dist/core/config/auth/better-auth-hooks.server.js +6 -3
- package/dist/core/dev/cli/build/index.d.ts +1 -0
- package/dist/core/dev/cli/build/index.js +10 -5
- package/dist/core/dev/cli/build/templates.d.ts +1 -1
- package/dist/core/dev/cli/build/templates.js +10 -7
- package/dist/core/dev/cli/index.js +1 -0
- package/dist/core/dev/cli/init/index.server.js +3 -3
- package/dist/core/dev/cli/init/templates.js +8 -1
- package/dist/core/dev/cli/util/package-manager.server.js +27 -26
- package/dist/core/dev/constants.d.ts +11 -2
- package/dist/core/dev/constants.js +11 -0
- package/dist/core/dev/generate/runtime/index.server.d.ts +24 -0
- package/dist/core/dev/generate/runtime/index.server.js +93 -0
- package/dist/core/dev/generate/types/index.server.js +42 -18
- package/dist/core/dev/vite/index.server.js +38 -17
- package/dist/core/fields/builders/boolean-builder.d.ts +1 -2
- package/dist/core/fields/builders/field-builder.d.ts +11 -6
- package/dist/core/fields/builders/field-builder.js +12 -5
- package/dist/core/fields/builders/form-field-builder.d.ts +11 -14
- package/dist/core/fields/builders/form-field-builder.js +17 -15
- package/dist/core/fields/util.js +1 -1
- package/dist/core/operations/blocks/extract.server.js +1 -1
- package/dist/core/operations/hooks/before-read/process-document-fields.server.js +3 -3
- package/dist/core/operations/hooks/before-upsert/set-default-values.server.js +3 -3
- package/dist/core/operations/hooks/before-upsert/validate-fields.server.js +7 -7
- package/dist/core/operations/shared/fallback-data-from-original.js +1 -1
- package/dist/core/operations/tree/extract.server.js +1 -1
- package/dist/core/plugins/api-init/index.server.js +2 -2
- package/dist/fields/blocks/index.d.ts +1 -1
- package/dist/fields/blocks/index.js +5 -2
- package/dist/fields/checkbox/index.d.ts +1 -1
- package/dist/fields/checkbox/index.js +3 -2
- package/dist/fields/combobox/index.d.ts +1 -1
- package/dist/fields/combobox/index.js +4 -2
- package/dist/fields/date/index.d.ts +2 -2
- package/dist/fields/date/index.js +7 -5
- package/dist/fields/email/index.d.ts +3 -3
- package/dist/fields/email/index.js +9 -8
- package/dist/fields/group/component/Group.svelte +1 -1
- package/dist/fields/group/index.d.ts +1 -1
- package/dist/fields/group/index.js +4 -2
- package/dist/fields/link/index.d.ts +1 -1
- package/dist/fields/link/index.js +9 -5
- package/dist/fields/link/module.server.d.ts +2 -0
- package/dist/fields/link/{runtime.server.js → module.server.js} +0 -8
- package/dist/fields/number/index.d.ts +1 -1
- package/dist/fields/number/index.js +3 -2
- package/dist/fields/radio/index.d.ts +1 -1
- package/dist/fields/radio/index.js +4 -2
- package/dist/fields/relation/index.d.ts +2 -6
- package/dist/fields/relation/index.js +5 -9
- package/dist/fields/relation/{runtime.d.ts → module.d.ts} +2 -2
- package/dist/fields/relation/module.js +4 -0
- package/dist/fields/relation/module.server.d.ts +5 -0
- package/dist/fields/relation/{runtime.server.js → module.server.js} +3 -6
- package/dist/fields/rich-text/index.d.ts +1 -1
- package/dist/fields/rich-text/index.js +3 -2
- package/dist/fields/select/index.d.ts +1 -1
- package/dist/fields/select/index.js +4 -1
- package/dist/fields/slug/index.d.ts +1 -1
- package/dist/fields/slug/index.js +3 -2
- package/dist/fields/tabs/index.d.ts +1 -1
- package/dist/fields/tabs/index.js +10 -2
- package/dist/fields/text/index.d.ts +1 -1
- package/dist/fields/text/index.js +3 -2
- package/dist/fields/textarea/index.d.ts +1 -1
- package/dist/fields/textarea/index.js +3 -2
- package/dist/fields/time/index.d.ts +1 -1
- package/dist/fields/time/index.js +3 -2
- package/dist/fields/toggle/index.d.ts +1 -1
- package/dist/fields/toggle/index.js +3 -3
- package/dist/fields/tree/index.d.ts +1 -1
- package/dist/fields/tree/index.js +4 -2
- package/dist/panel/components/fields/RenderFields.svelte +1 -1
- package/dist/panel/context/collection.svelte.js +5 -3
- package/dist/panel/context/documentForm.svelte.js +47 -28
- package/dist/panel/context/form.svelte.js +3 -3
- package/dist/util/doc.js +1 -1
- package/package.json +1 -8
- package/dist/fields/blocks/index.server.d.ts +0 -3
- package/dist/fields/blocks/index.server.js +0 -5
- package/dist/fields/checkbox/index.server.d.ts +0 -3
- package/dist/fields/checkbox/index.server.js +0 -3
- package/dist/fields/combobox/index.server.d.ts +0 -3
- package/dist/fields/combobox/index.server.js +0 -4
- package/dist/fields/date/index.server.d.ts +0 -3
- package/dist/fields/date/index.server.js +0 -3
- package/dist/fields/email/index.server.d.ts +0 -4
- package/dist/fields/email/index.server.js +0 -3
- package/dist/fields/group/index.server.d.ts +0 -2
- package/dist/fields/group/index.server.js +0 -12
- package/dist/fields/index.server.d.ts +0 -14
- package/dist/fields/index.server.js +0 -65
- package/dist/fields/link/runtime.server.d.ts +0 -5
- package/dist/fields/number/index.server.d.ts +0 -3
- package/dist/fields/number/index.server.js +0 -3
- package/dist/fields/radio/index.server.d.ts +0 -3
- package/dist/fields/radio/index.server.js +0 -4
- package/dist/fields/relation/runtime.js +0 -4
- package/dist/fields/relation/runtime.server.d.ts +0 -8
- package/dist/fields/rich-text/index.server.d.ts +0 -3
- package/dist/fields/rich-text/index.server.js +0 -3
- package/dist/fields/select/index.server.d.ts +0 -3
- package/dist/fields/select/index.server.js +0 -4
- package/dist/fields/slug/index.server.d.ts +0 -3
- package/dist/fields/slug/index.server.js +0 -3
- package/dist/fields/tabs/index.server.d.ts +0 -3
- package/dist/fields/tabs/index.server.js +0 -18
- package/dist/fields/text/index.server.d.ts +0 -3
- package/dist/fields/text/index.server.js +0 -3
- package/dist/fields/textarea/index.server.d.ts +0 -3
- package/dist/fields/textarea/index.server.js +0 -3
- package/dist/fields/time/index.server.d.ts +0 -3
- package/dist/fields/time/index.server.js +0 -3
- package/dist/fields/toggle/index.server.d.ts +0 -3
- package/dist/fields/toggle/index.server.js +0 -3
- package/dist/fields/tree/index.server.d.ts +0 -3
- package/dist/fields/tree/index.server.js +0 -4
- /package/dist/fields/link/{runtime.d.ts → module.d.ts} +0 -0
- /package/dist/fields/link/{runtime.js → module.js} +0 -0
package/README.md
CHANGED
|
@@ -245,7 +245,7 @@ npx rime build
|
|
|
245
245
|
npx rime build -d # to copy the database directory
|
|
246
246
|
```
|
|
247
247
|
|
|
248
|
-
It's doing bascically `vite build` under the hood and create the
|
|
248
|
+
It's doing bascically `vite build` under the hood and create the server file inside an app directory, plus giving some info on how to run it.
|
|
249
249
|
|
|
250
250
|
## ROADMAP
|
|
251
251
|
|
|
@@ -66,10 +66,7 @@ export function toSchemaColumn(field, parentPath) {
|
|
|
66
66
|
// reading it off the generic FormField base needs a narrow cast, same as
|
|
67
67
|
// each field's own toSchema did today by typing against its concrete field.
|
|
68
68
|
const { unique, required } = field.get;
|
|
69
|
-
|
|
70
|
-
// on the FormFieldBuilder base (see the comment there) — narrow cast here.
|
|
71
|
-
const dataType = field.dataType;
|
|
72
|
-
const columnExpr = COLUMN_EXPR[dataType](snake);
|
|
69
|
+
const columnExpr = COLUMN_EXPR[field.dataType](snake);
|
|
73
70
|
const referencesStr = field._references ? templateReferences(field._references) : '';
|
|
74
71
|
const defaultValue = RESOLVE_DEFAULT[field.type]?.(field);
|
|
75
72
|
const suffix = templateUniqueRequired({ unique, required }, defaultValue);
|
|
@@ -31,19 +31,17 @@ const write = (schema) => {
|
|
|
31
31
|
};
|
|
32
32
|
const command = commandMap[pm];
|
|
33
33
|
logger.info('[✓] Schema: generated at src/lib/server/schema.ts');
|
|
34
|
-
console.log('============================================================');
|
|
35
34
|
console.log(`\n ⚡︎ ${command} drizzle-kit generate \n`);
|
|
36
35
|
const generateResult = spawnSync(command, ['drizzle-kit', 'generate'], { stdio: 'inherit' });
|
|
37
36
|
if (generateResult.error || generateResult.status !== 0) {
|
|
38
37
|
throw new Error('drizzle-kit generate failed');
|
|
39
38
|
}
|
|
40
|
-
console.log('\n============================================================');
|
|
41
39
|
console.log(`\n ⚡︎ ${command} drizzle-kit migrate \n`);
|
|
42
40
|
const migrateResult = spawnSync(command, ['drizzle-kit', 'migrate'], { stdio: 'inherit' });
|
|
43
41
|
if (migrateResult.error || migrateResult.status !== 0) {
|
|
44
42
|
throw new Error('drizzle-kit migrate failed');
|
|
45
43
|
}
|
|
46
|
-
console.log('\n
|
|
44
|
+
console.log('\n');
|
|
47
45
|
// Only mark the schema as in sync once generate + migrate both actually
|
|
48
46
|
// succeeded — otherwise a future run with an unchanged schema string would
|
|
49
47
|
// skip re-running drizzle-kit and the DB would stay silently out of sync.
|
|
@@ -74,7 +74,7 @@ const handleUserCreation = async (ctx) => {
|
|
|
74
74
|
/**
|
|
75
75
|
* Create the collection document
|
|
76
76
|
*/
|
|
77
|
-
const [error] = await trycatch(() => event.locals.rime
|
|
77
|
+
const [error, userData] = await trycatch(() => event.locals.rime
|
|
78
78
|
.collection(ctx.body.type)
|
|
79
79
|
.system(event.locals.isInit)
|
|
80
80
|
.create({
|
|
@@ -89,7 +89,7 @@ const handleUserCreation = async (ctx) => {
|
|
|
89
89
|
}
|
|
90
90
|
}));
|
|
91
91
|
// If error clean up session/account/user created
|
|
92
|
-
//
|
|
92
|
+
// note: would be cleaner to do it with the admin plugin, not possible at the moment
|
|
93
93
|
if (error) {
|
|
94
94
|
console.log(error);
|
|
95
95
|
logger.error(error.message);
|
|
@@ -105,6 +105,8 @@ const handleUserCreation = async (ctx) => {
|
|
|
105
105
|
await rime.adapter.db.delete(authUsersTable).where(eq(authUsersTable.id, user.id));
|
|
106
106
|
throw new APIError('BAD_REQUEST');
|
|
107
107
|
}
|
|
108
|
+
// Return rime user data
|
|
109
|
+
return userData;
|
|
108
110
|
};
|
|
109
111
|
/****************************************************/
|
|
110
112
|
/* Before Hooks
|
|
@@ -131,6 +133,7 @@ export const betterAuthAfterHook = createAuthMiddleware(async (ctx) => {
|
|
|
131
133
|
}
|
|
132
134
|
// Handle sign-up
|
|
133
135
|
if (ctx.path.startsWith('/sign-up')) {
|
|
134
|
-
|
|
136
|
+
await handleUserCreation(ctx);
|
|
137
|
+
return await getUserAttributes(ctx);
|
|
135
138
|
}
|
|
136
139
|
});
|
|
@@ -4,15 +4,15 @@ import chalk from 'chalk';
|
|
|
4
4
|
import { spawnSync } from 'child_process';
|
|
5
5
|
import { copyFileSync, cpSync, existsSync, mkdirSync, renameSync, rmSync, writeFileSync } from 'fs';
|
|
6
6
|
import { getInvokingPackageManager } from '../util/package-manager.server.js';
|
|
7
|
-
import { envProduction,
|
|
7
|
+
import { envProduction, nodeServer } from './templates.js';
|
|
8
8
|
const installCommands = {
|
|
9
9
|
pnpm: {
|
|
10
|
-
addDeps: 'pnpm install
|
|
10
|
+
addDeps: 'pnpm install sharp serve-static',
|
|
11
11
|
prodInstall: 'pnpm install --prod',
|
|
12
12
|
runEnv: 'pnpm rime env'
|
|
13
13
|
},
|
|
14
14
|
npm: {
|
|
15
|
-
addDeps: 'npm install
|
|
15
|
+
addDeps: 'npm install sharp serve-static',
|
|
16
16
|
prodInstall: 'npm install --omit=dev',
|
|
17
17
|
runEnv: 'npx rime env'
|
|
18
18
|
}
|
|
@@ -38,9 +38,14 @@ export const build = (args) => {
|
|
|
38
38
|
cpSync('./db', './app/db', { recursive: true });
|
|
39
39
|
logger.info('[✓] database copied');
|
|
40
40
|
}
|
|
41
|
+
// Copy static folder if flag is set
|
|
42
|
+
if (args.withStatic) {
|
|
43
|
+
cpSync('./static', './app/static', { recursive: true });
|
|
44
|
+
logger.info('[✓] static directory copied');
|
|
45
|
+
}
|
|
41
46
|
// Create main entry server file
|
|
42
|
-
writeFileSync('./app/index.js',
|
|
43
|
-
logger.info('[✓]
|
|
47
|
+
writeFileSync('./app/index.js', nodeServer);
|
|
48
|
+
logger.info('[✓] server created at app/index.js');
|
|
44
49
|
// Create .env file if flag is set
|
|
45
50
|
const envContent = envProduction();
|
|
46
51
|
if (args.withEnv) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const envProduction: () => string;
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const nodeServer = "import { createServer } from 'node:http';\nimport serveStatic from 'serve-static';\nimport { handler } from './build/handler.js';\n\nconst serve = serveStatic('./static');\n\nconst port = process.env.PORT || 3000;\nconst host = process.env.HOST || '127.0.0.1';\nconst protocol = process.env.ORIGIN?.startsWith('https') ? 'https' : 'http';\n\ncreateServer((req, res) => {\n\tserve(req, res, () => handler(req, res, () => {\n\t\tres.statusCode = 404;\n\t\tres.end();\n\t}));\n}).listen(port, host, () => {\n\tconsole.log(`server running on ${protocol}://${host}:${port}`);\n});\n";
|
|
@@ -22,7 +22,7 @@ HOST=localhost
|
|
|
22
22
|
# MISC
|
|
23
23
|
BODY_SIZE_LIMIT=10485760 # 10(MB) * 1024 * 1024 = 10485760 bytes
|
|
24
24
|
`;
|
|
25
|
-
export const
|
|
25
|
+
export const nodeServer = `import { createServer } from 'node:http';
|
|
26
26
|
import serveStatic from 'serve-static';
|
|
27
27
|
import { handler } from './build/handler.js';
|
|
28
28
|
|
|
@@ -30,11 +30,14 @@ const serve = serveStatic('./static');
|
|
|
30
30
|
|
|
31
31
|
const port = process.env.PORT || 3000;
|
|
32
32
|
const host = process.env.HOST || '127.0.0.1';
|
|
33
|
+
const protocol = process.env.ORIGIN?.startsWith('https') ? 'https' : 'http';
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
createServer((req, res) => {
|
|
36
|
+
serve(req, res, () => handler(req, res, () => {
|
|
37
|
+
res.statusCode = 404;
|
|
38
|
+
res.end();
|
|
39
|
+
}));
|
|
40
|
+
}).listen(port, host, () => {
|
|
41
|
+
console.log(\`server running on \${protocol}://\${host}:\${port}\`);
|
|
42
|
+
});
|
|
40
43
|
`;
|
|
@@ -18,6 +18,7 @@ program
|
|
|
18
18
|
.command('build')
|
|
19
19
|
.option('-d, --with-database', 'Include database', false)
|
|
20
20
|
.option('-e, --with-env', 'Create the /app/.env file from the production template', false)
|
|
21
|
+
.option('-s, --with-static', 'Copy the current static directory', false)
|
|
21
22
|
.action(async (args) => {
|
|
22
23
|
const build = await import('./build/index.js').then((m) => m.build);
|
|
23
24
|
build(args);
|
|
@@ -3,7 +3,7 @@ import { randomId } from '../../../../util/random.js';
|
|
|
3
3
|
import { isValidSlug, slugify } from '../../../../util/string.js';
|
|
4
4
|
import { generate as generateCode } from '@babel/generator';
|
|
5
5
|
import * as t from '@babel/types';
|
|
6
|
-
import { babelParse } from 'ast-kit';
|
|
6
|
+
import { babelParse, getLang } from 'ast-kit';
|
|
7
7
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
8
8
|
import { cp, mkdir } from 'fs/promises';
|
|
9
9
|
import fs from 'node:fs';
|
|
@@ -60,7 +60,7 @@ export const init = async ({ force, name: incomingName, skipInstall }) => {
|
|
|
60
60
|
mkdirSync(configDirPath);
|
|
61
61
|
}
|
|
62
62
|
writeFileSync(configPath, templates.defaultConfig(name.toString()));
|
|
63
|
-
logger.info(
|
|
63
|
+
logger.info(`[✓] Config created at ${configDirPath}/rime.config.ts`);
|
|
64
64
|
}
|
|
65
65
|
else {
|
|
66
66
|
logger.info('[✓] Config already exists (skip)');
|
|
@@ -113,7 +113,7 @@ export const init = async ({ force, name: incomingName, skipInstall }) => {
|
|
|
113
113
|
}
|
|
114
114
|
let content = fs.readFileSync(configPath, 'utf-8');
|
|
115
115
|
content = content.replace("from '@sveltejs/adapter-auto'", "from '@sveltejs/adapter-node'");
|
|
116
|
-
const program = babelParse(content, configPath);
|
|
116
|
+
const program = babelParse(content, getLang(configPath));
|
|
117
117
|
const programBody = program.body;
|
|
118
118
|
const configObject = findSvelteConfigObject(programBody);
|
|
119
119
|
if (!configObject) {
|
|
@@ -24,9 +24,16 @@ const Pages = Collection.create('pages', {
|
|
|
24
24
|
fields: [text('title').isTitle()]
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
+
const Medias = Collection.create('medias', {
|
|
28
|
+
upload: true,
|
|
29
|
+
fields: [
|
|
30
|
+
text('alt').required(),
|
|
31
|
+
]
|
|
32
|
+
});
|
|
33
|
+
|
|
27
34
|
export default rime({
|
|
28
35
|
$adapter: adapterSqlite('${name}.sqlite'),
|
|
29
|
-
collections: [Pages]
|
|
36
|
+
collections: [Pages, Medias]
|
|
30
37
|
});
|
|
31
38
|
`;
|
|
32
39
|
export const drizzleConfig = (name) => `
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { logger } from '../../../logger/index.server.js';
|
|
2
2
|
import { execSync } from 'child_process';
|
|
3
|
-
import { existsSync
|
|
3
|
+
import { existsSync } from 'fs';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
const packageManagersMap = {
|
|
6
6
|
yarn: 'yarn.lock',
|
|
@@ -14,17 +14,17 @@ const packageManagerConfigs = {
|
|
|
14
14
|
command: 'echo "yarn is not supported, please use pnpm or npm" && exit 1'
|
|
15
15
|
},
|
|
16
16
|
pnpm: {
|
|
17
|
-
command: 'pnpm add -D drizzle-kit && pnpm add -D @sveltejs/adapter-node && pnpm add drizzle-orm @lucide/svelte sharp',
|
|
18
|
-
preInstall:
|
|
17
|
+
command: 'pnpm add -D drizzle-kit && pnpm add -D @sveltejs/adapter-node && pnpm add drizzle-orm @libsql/client @lucide/svelte sharp',
|
|
18
|
+
preInstall: configurePnpm,
|
|
19
19
|
postInstall: () => {
|
|
20
20
|
execSync('pnpm rebuild');
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
bun: {
|
|
24
|
-
command: 'bun add -D drizzle-kit && bun add -D @sveltejs/adapter-node && bun add drizzle-orm @lucide/svelte sharp'
|
|
24
|
+
command: 'bun add -D drizzle-kit && bun add -D @sveltejs/adapter-node && bun add drizzle-orm @libsql/client @lucide/svelte sharp'
|
|
25
25
|
},
|
|
26
26
|
npm: {
|
|
27
|
-
command: 'npm install -D drizzle-kit && npm install -D @sveltejs/adapter-node && npm install drizzle-orm @lucide/svelte sharp'
|
|
27
|
+
command: 'npm install -D drizzle-kit && npm install -D @sveltejs/adapter-node && npm install drizzle-orm @libsql/client @lucide/svelte sharp'
|
|
28
28
|
},
|
|
29
29
|
deno: {
|
|
30
30
|
command: 'echo "deno is not supported, please use pnpm or npm" && exit 1'
|
|
@@ -55,7 +55,7 @@ export function getInvokingPackageManager() {
|
|
|
55
55
|
return 'npm';
|
|
56
56
|
}
|
|
57
57
|
export function installDependencies() {
|
|
58
|
-
const pm =
|
|
58
|
+
const pm = getInvokingPackageManager();
|
|
59
59
|
if (pm === 'deno' || pm === 'yarn') {
|
|
60
60
|
throw new Error('Unsupported package manager ' + pm);
|
|
61
61
|
}
|
|
@@ -68,28 +68,29 @@ export function installDependencies() {
|
|
|
68
68
|
// Post installation hooks
|
|
69
69
|
config.postInstall?.();
|
|
70
70
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
/**
|
|
72
|
+
* pnpm 11 no longer reads the "pnpm" field in package.json (onlyBuiltDependencies
|
|
73
|
+
* included) - every pnpm-specific setting moved to pnpm-workspace.yaml, and
|
|
74
|
+
* onlyBuiltDependencies itself was replaced by allowBuilds (a name -> boolean map).
|
|
75
|
+
* `pnpm config set --location=project` writes there directly (creating the file if
|
|
76
|
+
* it doesn't exist yet, even for a non-monorepo single package).
|
|
77
|
+
*
|
|
78
|
+
* strictDepBuilds is also now on by default: any dependency (however deep) with a
|
|
79
|
+
* build script that isn't in allowBuilds hard-fails the whole install with
|
|
80
|
+
* ERR_PNPM_IGNORED_BUILDS instead of just skipping that one script. allowBuilds only
|
|
81
|
+
* covers esbuild/sharp; the rest of this command's tree (drizzle-kit, adapter-node,
|
|
82
|
+
* ...) will always have *something* pnpm hasn't seen before, and pinning every one of
|
|
83
|
+
* them here would just break again on their next update - so strict-dep-builds is
|
|
84
|
+
* turned off the same way.
|
|
85
|
+
*/
|
|
86
|
+
function configurePnpm() {
|
|
87
|
+
const allowBuilds = JSON.stringify({ esbuild: false, sharp: true, 'better-sqlite3': false });
|
|
77
88
|
try {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
packageJson.pnpm = {};
|
|
82
|
-
}
|
|
83
|
-
// Update onlyBuiltDependencies
|
|
84
|
-
const existingBuiltDeps = packageJson.pnpm.onlyBuiltDependencies || [];
|
|
85
|
-
const newBuiltDeps = ['esbuild', 'sharp'];
|
|
86
|
-
// Merge and deduplicate
|
|
87
|
-
const mergedBuiltDeps = [...new Set([...existingBuiltDeps, ...newBuiltDeps])];
|
|
88
|
-
packageJson.pnpm.onlyBuiltDependencies = mergedBuiltDeps;
|
|
89
|
-
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, '\t'), 'utf-8');
|
|
90
|
-
logger.info('[✓] Updated package.json with pnpm configuration');
|
|
89
|
+
execSync(`pnpm config set --location=project --json allowBuilds '${allowBuilds}'`);
|
|
90
|
+
execSync('pnpm config set --location=project strict-dep-builds false');
|
|
91
|
+
logger.info('[✓] Configured pnpm-workspace.yaml: allowBuilds (sharp) and strict-dep-builds (false)');
|
|
91
92
|
}
|
|
92
93
|
catch (error) {
|
|
93
|
-
logger.error('Failed to
|
|
94
|
+
logger.error('Failed to configure pnpm:', error);
|
|
94
95
|
}
|
|
95
96
|
}
|
|
@@ -1,2 +1,11 @@
|
|
|
1
|
-
export const OUTPUT_DIR
|
|
2
|
-
export const INPUT_DIR
|
|
1
|
+
export declare const OUTPUT_DIR = "+rime.generated";
|
|
2
|
+
export declare const INPUT_DIR = "+rime";
|
|
3
|
+
/**
|
|
4
|
+
* True when `metaUrl` (pass the caller's own `import.meta.url` — this can't be one shared
|
|
5
|
+
* value, it depends on which file is asking) is running from inside an installed `rimecms`
|
|
6
|
+
* package (node_modules/rimecms/...), false when running from rime's own repo. Deliberately
|
|
7
|
+
* filesystem-based rather than an env var: a shell dotenv plugin auto-loading this repo's own
|
|
8
|
+
* .env (which used to set IS_RIME_REPO=true) into every child process — including an unrelated
|
|
9
|
+
* consumer app's dev server — made that value unreliable; this can't leak the same way.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isInstalledDependency(metaUrl: string): boolean;
|
|
@@ -1,2 +1,13 @@
|
|
|
1
1
|
export const OUTPUT_DIR = '+rime.generated';
|
|
2
2
|
export const INPUT_DIR = '+rime';
|
|
3
|
+
/**
|
|
4
|
+
* True when `metaUrl` (pass the caller's own `import.meta.url` — this can't be one shared
|
|
5
|
+
* value, it depends on which file is asking) is running from inside an installed `rimecms`
|
|
6
|
+
* package (node_modules/rimecms/...), false when running from rime's own repo. Deliberately
|
|
7
|
+
* filesystem-based rather than an env var: a shell dotenv plugin auto-loading this repo's own
|
|
8
|
+
* .env (which used to set IS_RIME_REPO=true) into every child process — including an unrelated
|
|
9
|
+
* consumer app's dev server — made that value unreliable; this can't leak the same way.
|
|
10
|
+
*/
|
|
11
|
+
export function isInstalledDependency(metaUrl) {
|
|
12
|
+
return metaUrl.includes('/node_modules/rimecms/');
|
|
13
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type RuntimeRegistryEntry = {
|
|
2
|
+
client: string;
|
|
3
|
+
server: string;
|
|
4
|
+
};
|
|
5
|
+
export type RuntimeRegistry = Map<string, RuntimeRegistryEntry>;
|
|
6
|
+
/**
|
|
7
|
+
* Builds the `$rime/<name>` → { browser file, server file } lookup table.
|
|
8
|
+
*
|
|
9
|
+
* @example rime's own field, installed as a dependency in some app
|
|
10
|
+
* // /my-app/node_modules/rimecms/dist/fields/relation/module.ts + module.server.ts
|
|
11
|
+
* // → registry.get('fields/relation') → { client: '.../module.ts', server: '.../module.server.ts' }
|
|
12
|
+
* // → import { x } from '$rime/fields/relation' // resolves
|
|
13
|
+
*
|
|
14
|
+
* @example that same app's own custom field
|
|
15
|
+
* // /my-app/src/lib/fields/geocode/module.ts + module.server.ts
|
|
16
|
+
* // → registry.get('fields/geocode') → { client: '.../module.ts', server: '.../module.server.ts' }
|
|
17
|
+
* // → import { x } from '$rime/fields/geocode' // resolves, same mechanism, zero extra setup
|
|
18
|
+
*
|
|
19
|
+
* @example nothing on disk for that name
|
|
20
|
+
* // no folder anywhere has both typo/module.ts and typo/module.server.ts
|
|
21
|
+
* // → registry.get('typo') → undefined
|
|
22
|
+
* // → import { x } from '$rime/typo' // fails: "cannot resolve module"
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildRuntimeRegistry(): RuntimeRegistry;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { isInstalledDependency, OUTPUT_DIR } from '../../constants.js';
|
|
5
|
+
/**
|
|
6
|
+
* Walks up from `startDir` to the nearest ancestor containing a `package.json`, then returns
|
|
7
|
+
* its `dist/` — self-correcting regardless of how deeply nested this file is (unlike counting
|
|
8
|
+
* a fixed number of `..` segments, which would silently point at the wrong directory, not
|
|
9
|
+
* error, the moment this file's own location changes).
|
|
10
|
+
*/
|
|
11
|
+
function findDistRoot(startDir) {
|
|
12
|
+
let dir = startDir;
|
|
13
|
+
while (!fs.existsSync(path.join(dir, 'package.json'))) {
|
|
14
|
+
const parent = path.dirname(dir);
|
|
15
|
+
if (parent === dir) {
|
|
16
|
+
throw new Error(`$rime: could not locate rimecms's package root above ${startDir}`);
|
|
17
|
+
}
|
|
18
|
+
dir = parent;
|
|
19
|
+
}
|
|
20
|
+
return path.join(dir, 'dist');
|
|
21
|
+
}
|
|
22
|
+
/** `module.ts` when scanning TS source, `module.js` when scanning a built `dist/`. */
|
|
23
|
+
function findModuleFile(dir, baseName) {
|
|
24
|
+
for (const ext of ['.ts', '.js']) {
|
|
25
|
+
const candidate = path.join(dir, `${baseName}${ext}`);
|
|
26
|
+
if (fs.existsSync(candidate))
|
|
27
|
+
return candidate;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Recursively finds every `module`/`module.server` pair under `root`, registered under the
|
|
33
|
+
* containing folder's path relative to `root` — `$rime/<key>` mirrors the real path, e.g.
|
|
34
|
+
* `fields/relation/module.ts` under a `lib`-rooted scan registers as `fields/relation`.
|
|
35
|
+
*
|
|
36
|
+
* Both files are required to register a `$rime/<key>` entry: this pair only exists for a field
|
|
37
|
+
* whose hook needs different server/client behavior (relation, link) — a field with nothing to
|
|
38
|
+
* split just overrides `generateType()` on its builder directly and never needs either file.
|
|
39
|
+
* `+rime.generated/` is skipped since it's sanitize's own output, unrelated to this.
|
|
40
|
+
*/
|
|
41
|
+
function scanModulePairs(root) {
|
|
42
|
+
const registry = new Map();
|
|
43
|
+
if (!fs.existsSync(root))
|
|
44
|
+
return registry;
|
|
45
|
+
const walk = (dir) => {
|
|
46
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
47
|
+
if (!entry.isDirectory() || entry.name === OUTPUT_DIR)
|
|
48
|
+
continue;
|
|
49
|
+
const fullPath = path.join(dir, entry.name);
|
|
50
|
+
const client = findModuleFile(fullPath, 'module');
|
|
51
|
+
const server = findModuleFile(fullPath, 'module.server');
|
|
52
|
+
if (client && server) {
|
|
53
|
+
const key = path.relative(root, fullPath).split(path.sep).join('/');
|
|
54
|
+
registry.set(key, { client, server });
|
|
55
|
+
}
|
|
56
|
+
walk(fullPath);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
walk(root);
|
|
60
|
+
return registry;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Builds the `$rime/<name>` → { browser file, server file } lookup table.
|
|
64
|
+
*
|
|
65
|
+
* @example rime's own field, installed as a dependency in some app
|
|
66
|
+
* // /my-app/node_modules/rimecms/dist/fields/relation/module.ts + module.server.ts
|
|
67
|
+
* // → registry.get('fields/relation') → { client: '.../module.ts', server: '.../module.server.ts' }
|
|
68
|
+
* // → import { x } from '$rime/fields/relation' // resolves
|
|
69
|
+
*
|
|
70
|
+
* @example that same app's own custom field
|
|
71
|
+
* // /my-app/src/lib/fields/geocode/module.ts + module.server.ts
|
|
72
|
+
* // → registry.get('fields/geocode') → { client: '.../module.ts', server: '.../module.server.ts' }
|
|
73
|
+
* // → import { x } from '$rime/fields/geocode' // resolves, same mechanism, zero extra setup
|
|
74
|
+
*
|
|
75
|
+
* @example nothing on disk for that name
|
|
76
|
+
* // no folder anywhere has both typo/module.ts and typo/module.server.ts
|
|
77
|
+
* // → registry.get('typo') → undefined
|
|
78
|
+
* // → import { x } from '$rime/typo' // fails: "cannot resolve module"
|
|
79
|
+
*/
|
|
80
|
+
export function buildRuntimeRegistry() {
|
|
81
|
+
const registry = new Map();
|
|
82
|
+
if (isInstalledDependency(import.meta.url)) {
|
|
83
|
+
const nativeLibDir = findDistRoot(path.dirname(fileURLToPath(import.meta.url)));
|
|
84
|
+
for (const [key, entry] of scanModulePairs(nativeLibDir)) {
|
|
85
|
+
registry.set(key, entry);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const consumerLibDir = path.resolve(process.cwd(), 'src/lib');
|
|
89
|
+
for (const [key, entry] of scanModulePairs(consumerLibDir)) {
|
|
90
|
+
registry.set(key, entry);
|
|
91
|
+
}
|
|
92
|
+
return registry;
|
|
93
|
+
}
|
|
@@ -6,15 +6,15 @@ import { logger } from '../../../logger/index.server.js';
|
|
|
6
6
|
import { withVersionsSuffix } from '../../../naming.js';
|
|
7
7
|
import { BlocksBuilder } from '../../../../fields/blocks/index.js';
|
|
8
8
|
import { GroupFieldBuilder } from '../../../../fields/group/index.js';
|
|
9
|
-
import { getFieldPrivateModule } from '../../../../fields/index.server.js';
|
|
10
9
|
import { TabsBuilder } from '../../../../fields/tabs/index.js';
|
|
11
10
|
import { TreeBuilder } from '../../../../fields/tree/index.js';
|
|
12
11
|
import { trycatchSync } from '../../../../util/function.js';
|
|
13
12
|
import { capitalize, toPascalCase } from '../../../../util/string.js';
|
|
14
13
|
import fs from 'node:fs';
|
|
15
14
|
import path from 'node:path';
|
|
16
|
-
import { OUTPUT_DIR } from '../../constants.js';
|
|
17
|
-
|
|
15
|
+
import { isInstalledDependency, OUTPUT_DIR } from '../../constants.js';
|
|
16
|
+
import { buildRuntimeRegistry } from '../runtime/index.server.js';
|
|
17
|
+
const IS_RIME_REPO = !isInstalledDependency(import.meta.url);
|
|
18
18
|
// Relation type
|
|
19
19
|
const relationValueType = `
|
|
20
20
|
export type RelationValue<T> =
|
|
@@ -110,13 +110,47 @@ const templateRegister = (config) => {
|
|
|
110
110
|
};
|
|
111
111
|
const templateDeclareVirtualModule = () => [
|
|
112
112
|
`declare module '$rime/config' {`,
|
|
113
|
-
...(
|
|
113
|
+
...(IS_RIME_REPO ? ['\t// eslint-disable-next-line no-restricted-imports'] : []),
|
|
114
114
|
`\texport * from '${PACKAGE_NAME}/config/server';`,
|
|
115
115
|
`}`,
|
|
116
116
|
`declare module '$rime/schema' {`,
|
|
117
117
|
`\texport * from '$lib/+rime.generated/schema.server.js';`,
|
|
118
|
-
`}
|
|
118
|
+
`}`,
|
|
119
|
+
...templateDeclareFieldModules()
|
|
119
120
|
].join('\n');
|
|
121
|
+
/**
|
|
122
|
+
* One `declare module '$rime/<name>'` per registered field module.ts + module.server.ts pair
|
|
123
|
+
* (rime-native and consumer-local alike — see buildRuntimeRegistry), sourced from the
|
|
124
|
+
* `.server.ts` side (the real, server-only implementation of the shared hook; the client
|
|
125
|
+
* module.ts only has the no-op). Unrelated to type generation itself — that goes through
|
|
126
|
+
* `field.use.generateType()` on the builder instance directly, not through this registry.
|
|
127
|
+
* Runtime resolution (the Vite plugin's `load()`) is unaffected either way — it still picks
|
|
128
|
+
* the real client-vs-server module dynamically based on build context.
|
|
129
|
+
*/
|
|
130
|
+
const templateDeclareFieldModules = () => {
|
|
131
|
+
const registry = buildRuntimeRegistry();
|
|
132
|
+
return Array.from(registry.entries()).map(([name, entry]) => {
|
|
133
|
+
const modulePath = toModuleSpecifier(entry.server);
|
|
134
|
+
return `declare module '$rime/${name}' {\n\texport * from '${modulePath}';\n}`;
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* `$lib/...` when the file is inside this app's own src/lib (true for a consumer's own custom
|
|
139
|
+
* field, and for rime's own fields when developing rime itself, since they live inside src/lib
|
|
140
|
+
* in that case too) — matches the `$rime/schema` declaration above, and stays readable/portable
|
|
141
|
+
* instead of an absolute path. Falls back to an absolute path only when there's genuinely no
|
|
142
|
+
* alias for it: rime's own fields when installed as a real dependency, living in
|
|
143
|
+
* node_modules/rimecms/dist/, outside this app's src/lib entirely.
|
|
144
|
+
*/
|
|
145
|
+
function toModuleSpecifier(serverPath) {
|
|
146
|
+
const libRoot = path.resolve(process.cwd(), 'src/lib');
|
|
147
|
+
const jsPath = serverPath.replace(/\.ts$/, '.js');
|
|
148
|
+
const relative = path.relative(libRoot, jsPath);
|
|
149
|
+
if (!relative.startsWith('..')) {
|
|
150
|
+
return `$lib/${relative.split(path.sep).join('/')}`;
|
|
151
|
+
}
|
|
152
|
+
return jsPath;
|
|
153
|
+
}
|
|
120
154
|
/**
|
|
121
155
|
* Generates type definitions for image sizes
|
|
122
156
|
* @returns A string containing the type definition for image sizes
|
|
@@ -155,17 +189,7 @@ export async function generateTypesString(config) {
|
|
|
155
189
|
* @returns An array of string containing fields type definitions
|
|
156
190
|
*/
|
|
157
191
|
const buildFieldsTypes = async (fields) => {
|
|
158
|
-
|
|
159
|
-
for (const field of fields) {
|
|
160
|
-
if (field instanceof FormFieldBuilder || field instanceof TabsBuilder) {
|
|
161
|
-
const fieldServerMethods = await getFieldPrivateModule(field);
|
|
162
|
-
if (fieldServerMethods) {
|
|
163
|
-
const result = await Promise.resolve(fieldServerMethods.toType(field));
|
|
164
|
-
strFields.push(result);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return strFields;
|
|
192
|
+
return fields.map((field) => field.use.generateType()).filter(Boolean);
|
|
169
193
|
};
|
|
170
194
|
const buildblocksTypes = async (fields) => {
|
|
171
195
|
for (const field of fields) {
|
|
@@ -314,10 +338,10 @@ export async function generateTypesString(config) {
|
|
|
314
338
|
}
|
|
315
339
|
}`;
|
|
316
340
|
const content = [
|
|
317
|
-
...(
|
|
341
|
+
...(IS_RIME_REPO ? ['// eslint-disable-next-line no-restricted-imports'] : []),
|
|
318
342
|
`import '${PACKAGE_NAME}';`,
|
|
319
343
|
`import type { Session } from 'better-auth';`,
|
|
320
|
-
...(
|
|
344
|
+
...(IS_RIME_REPO ? ['// eslint-disable-next-line no-restricted-imports'] : []),
|
|
321
345
|
typeImports,
|
|
322
346
|
'',
|
|
323
347
|
relationValueType,
|