create-flow-os 0.0.1-dev.1771785969 → 0.0.1-dev.1771979233
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/package.json +8 -23
- package/src/create/index.ts +31 -0
- package/src/index.ts +14 -0
- package/src/init/index.ts +66 -0
- package/src/init/lib.ts +36 -0
- package/src/init/scaffold.ts +43 -0
- package/LICENSE +0 -97
- package/README.md +0 -26
- package/bin/index.js +0 -1215
- package/config.json +0 -89
- package/lib/utils.ts +0 -91
- package/packages/client/client/root.css +0 -9
- package/packages/client/client/root.tsx +0 -13
- package/packages/client/client/routes/404.tsx +0 -24
- package/packages/client/client/routes/index.tsx +0 -47
- package/packages/server/server/routes/hello.get.ts +0 -3
- package/profiles/client/.dockerignore +0 -12
- package/profiles/client/.oxfmtrc.json +0 -7
- package/profiles/client/.oxlintrc.json +0 -13
- package/profiles/client/.vscode/settings.json +0 -12
- package/profiles/client/Dockerfile +0 -26
- package/profiles/client/README.md +0 -34
- package/profiles/client/bun.lock +0 -335
- package/profiles/client/client/root.css +0 -9
- package/profiles/client/client/root.tsx +0 -13
- package/profiles/client/client/routes/404.tsx +0 -24
- package/profiles/client/client/routes/index.tsx +0 -47
- package/profiles/client/flow.config.ts +0 -3
- package/profiles/client/index.html +0 -5
- package/profiles/client/package.json +0 -29
- package/profiles/client/packages/client/LICENSE +0 -97
- package/profiles/client/packages/client/build/config.ts +0 -166
- package/profiles/client/packages/client/build/vite.ts +0 -54
- package/profiles/client/packages/client/features/attrs.ts +0 -32
- package/profiles/client/packages/client/features/class-flow.ts +0 -116
- package/profiles/client/packages/client/features/index.ts +0 -8
- package/profiles/client/packages/client/features/pseudo-injector.ts +0 -40
- package/profiles/client/packages/client/features/style-flow.ts +0 -106
- package/profiles/client/packages/client/features/style.ts +0 -27
- package/profiles/client/packages/client/features/utils.ts +0 -4
- package/profiles/client/packages/client/features/viewport.ts +0 -20
- package/profiles/client/packages/client/index.ts +0 -6
- package/profiles/client/packages/client/package.json +0 -48
- package/profiles/client/packages/client/runtime/dom.ts +0 -2
- package/profiles/client/packages/client/runtime/jsx-dev-runtime.ts +0 -1
- package/profiles/client/packages/client/runtime/jsx-runtime.ts +0 -1
- package/profiles/client/packages/client/runtime/jsx-types.d.ts +0 -64
- package/profiles/client/packages/client/runtime/jsx.ts +0 -99
- package/profiles/client/packages/client/scripts/build.ts +0 -14
- package/profiles/client/packages/client/scripts/preview.ts +0 -14
- package/profiles/client/packages/client/scripts/start-dev.ts +0 -49
- package/profiles/client/packages/core/LICENSE +0 -97
- package/profiles/client/packages/core/dom.ts +0 -43
- package/profiles/client/packages/core/for.ts +0 -42
- package/profiles/client/packages/core/index.ts +0 -5
- package/profiles/client/packages/core/lifecycle.ts +0 -6
- package/profiles/client/packages/core/package.json +0 -16
- package/profiles/client/packages/core/show-switch.ts +0 -56
- package/profiles/client/packages/core/state.ts +0 -56
- package/profiles/client/packages/router/LICENSE +0 -97
- package/profiles/client/packages/router/index.ts +0 -174
- package/profiles/client/packages/router/package.json +0 -15
- package/profiles/client/packages/style/LICENSE +0 -97
- package/profiles/client/packages/style/breakpoints.ts +0 -20
- package/profiles/client/packages/style/extension/.vscodeignore +0 -5
- package/profiles/client/packages/style/extension/flow-style-colors-0.0.1.vsix +0 -0
- package/profiles/client/packages/style/extension/out/extension.js +0 -130
- package/profiles/client/packages/style/extension/package.json +0 -24
- package/profiles/client/packages/style/extension/src/extension.ts +0 -146
- package/profiles/client/packages/style/extension/tsconfig.json +0 -12
- package/profiles/client/packages/style/index.ts +0 -16
- package/profiles/client/packages/style/package.json +0 -15
- package/profiles/client/packages/style/resolve.ts +0 -84
- package/profiles/client/packages/style/shorthand.ts +0 -62
- package/profiles/client/tsconfig.json +0 -30
- package/profiles/full/.dockerignore +0 -12
- package/profiles/full/.oxfmtrc.json +0 -7
- package/profiles/full/.oxlintrc.json +0 -13
- package/profiles/full/.vscode/settings.json +0 -12
- package/profiles/full/Dockerfile +0 -26
- package/profiles/full/README.md +0 -34
- package/profiles/full/bun.lock +0 -335
- package/profiles/full/client/root.css +0 -9
- package/profiles/full/client/root.tsx +0 -13
- package/profiles/full/client/routes/404.tsx +0 -24
- package/profiles/full/client/routes/index.tsx +0 -47
- package/profiles/full/flow.config.ts +0 -8
- package/profiles/full/index.html +0 -5
- package/profiles/full/package.json +0 -30
- package/profiles/full/packages/client/LICENSE +0 -97
- package/profiles/full/packages/client/build/config.ts +0 -166
- package/profiles/full/packages/client/build/vite.ts +0 -54
- package/profiles/full/packages/client/features/attrs.ts +0 -32
- package/profiles/full/packages/client/features/class-flow.ts +0 -116
- package/profiles/full/packages/client/features/index.ts +0 -8
- package/profiles/full/packages/client/features/pseudo-injector.ts +0 -40
- package/profiles/full/packages/client/features/style-flow.ts +0 -106
- package/profiles/full/packages/client/features/style.ts +0 -27
- package/profiles/full/packages/client/features/utils.ts +0 -4
- package/profiles/full/packages/client/features/viewport.ts +0 -20
- package/profiles/full/packages/client/index.ts +0 -6
- package/profiles/full/packages/client/package.json +0 -48
- package/profiles/full/packages/client/runtime/dom.ts +0 -2
- package/profiles/full/packages/client/runtime/jsx-dev-runtime.ts +0 -1
- package/profiles/full/packages/client/runtime/jsx-runtime.ts +0 -1
- package/profiles/full/packages/client/runtime/jsx-types.d.ts +0 -64
- package/profiles/full/packages/client/runtime/jsx.ts +0 -99
- package/profiles/full/packages/client/scripts/build.ts +0 -14
- package/profiles/full/packages/client/scripts/preview.ts +0 -14
- package/profiles/full/packages/client/scripts/start-dev.ts +0 -49
- package/profiles/full/packages/core/LICENSE +0 -97
- package/profiles/full/packages/core/dom.ts +0 -43
- package/profiles/full/packages/core/for.ts +0 -42
- package/profiles/full/packages/core/index.ts +0 -5
- package/profiles/full/packages/core/lifecycle.ts +0 -6
- package/profiles/full/packages/core/package.json +0 -16
- package/profiles/full/packages/core/show-switch.ts +0 -56
- package/profiles/full/packages/core/state.ts +0 -56
- package/profiles/full/packages/router/LICENSE +0 -97
- package/profiles/full/packages/router/index.ts +0 -174
- package/profiles/full/packages/router/package.json +0 -15
- package/profiles/full/packages/server/LICENSE +0 -97
- package/profiles/full/packages/server/core.ts +0 -140
- package/profiles/full/packages/server/index.ts +0 -24
- package/profiles/full/packages/server/package.json +0 -32
- package/profiles/full/packages/server/plugin.ts +0 -79
- package/profiles/full/packages/server/production.ts +0 -75
- package/profiles/full/packages/server/scripts/start.ts +0 -11
- package/profiles/full/packages/style/LICENSE +0 -97
- package/profiles/full/packages/style/breakpoints.ts +0 -20
- package/profiles/full/packages/style/extension/.vscodeignore +0 -5
- package/profiles/full/packages/style/extension/flow-style-colors-0.0.1.vsix +0 -0
- package/profiles/full/packages/style/extension/out/extension.js +0 -130
- package/profiles/full/packages/style/extension/package.json +0 -24
- package/profiles/full/packages/style/extension/src/extension.ts +0 -146
- package/profiles/full/packages/style/extension/tsconfig.json +0 -12
- package/profiles/full/packages/style/index.ts +0 -16
- package/profiles/full/packages/style/package.json +0 -15
- package/profiles/full/packages/style/resolve.ts +0 -84
- package/profiles/full/packages/style/shorthand.ts +0 -62
- package/profiles/full/server/routes/hello.get.ts +0 -3
- package/profiles/full/tsconfig.json +0 -30
- package/profiles/server/.dockerignore +0 -12
- package/profiles/server/.oxfmtrc.json +0 -7
- package/profiles/server/.oxlintrc.json +0 -13
- package/profiles/server/.vscode/settings.json +0 -12
- package/profiles/server/Dockerfile +0 -26
- package/profiles/server/README.md +0 -34
- package/profiles/server/bun.lock +0 -335
- package/profiles/server/flow.config.ts +0 -6
- package/profiles/server/index.html +0 -5
- package/profiles/server/package.json +0 -27
- package/profiles/server/packages/core/LICENSE +0 -97
- package/profiles/server/packages/core/dom.ts +0 -43
- package/profiles/server/packages/core/for.ts +0 -42
- package/profiles/server/packages/core/index.ts +0 -5
- package/profiles/server/packages/core/lifecycle.ts +0 -6
- package/profiles/server/packages/core/package.json +0 -16
- package/profiles/server/packages/core/show-switch.ts +0 -56
- package/profiles/server/packages/core/state.ts +0 -56
- package/profiles/server/packages/router/LICENSE +0 -97
- package/profiles/server/packages/router/index.ts +0 -174
- package/profiles/server/packages/router/package.json +0 -15
- package/profiles/server/packages/server/LICENSE +0 -97
- package/profiles/server/packages/server/core.ts +0 -140
- package/profiles/server/packages/server/index.ts +0 -24
- package/profiles/server/packages/server/package.json +0 -32
- package/profiles/server/packages/server/plugin.ts +0 -79
- package/profiles/server/packages/server/production.ts +0 -75
- package/profiles/server/packages/server/scripts/start.ts +0 -11
- package/profiles/server/packages/style/LICENSE +0 -97
- package/profiles/server/packages/style/breakpoints.ts +0 -20
- package/profiles/server/packages/style/extension/.vscodeignore +0 -5
- package/profiles/server/packages/style/extension/flow-style-colors-0.0.1.vsix +0 -0
- package/profiles/server/packages/style/extension/out/extension.js +0 -130
- package/profiles/server/packages/style/extension/package.json +0 -24
- package/profiles/server/packages/style/extension/src/extension.ts +0 -146
- package/profiles/server/packages/style/extension/tsconfig.json +0 -12
- package/profiles/server/packages/style/index.ts +0 -16
- package/profiles/server/packages/style/package.json +0 -15
- package/profiles/server/packages/style/resolve.ts +0 -84
- package/profiles/server/packages/style/shorthand.ts +0 -62
- package/profiles/server/server/routes/hello.get.ts +0 -3
- package/profiles/server/tsconfig.json +0 -30
- package/templates/flow.config.client.ts +0 -3
- package/templates/flow.config.server.ts +0 -6
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import os from 'node:os';
|
|
4
|
-
import net from 'node:net';
|
|
5
|
-
import type { Plugin } from 'vite';
|
|
6
|
-
import { createLogger } from 'vite';
|
|
7
|
-
|
|
8
|
-
function isPortFree(port: number): Promise<boolean> {
|
|
9
|
-
return new Promise((resolve) => {
|
|
10
|
-
const s = net.createServer();
|
|
11
|
-
s.once('error', () => resolve(false));
|
|
12
|
-
s.once('listening', () => {
|
|
13
|
-
s.close(() => resolve(true));
|
|
14
|
-
});
|
|
15
|
-
s.listen(port, '127.0.0.1');
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async function findFreePort(from: number, to: number): Promise<number> {
|
|
20
|
-
for (let p = from; p <= to; p++) {
|
|
21
|
-
if (await isPortFree(p)) return p;
|
|
22
|
-
}
|
|
23
|
-
throw new Error(`Nessuna porta libera tra ${from} e ${to}`);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const cyan = (s: string) => `\x1b[36m${s}\x1b[0m`;
|
|
27
|
-
const bold = (s: string) => `\x1b[1m${s}\x1b[0m`;
|
|
28
|
-
const dim = (s: string) => `\x1b[2m${s}\x1b[0m`;
|
|
29
|
-
const stripAnsi = (s: string) => s.replace(/\x1b\[[0-9;]*m/g, '');
|
|
30
|
-
const CONTENT_W = 48;
|
|
31
|
-
const BORDER_W = 52;
|
|
32
|
-
|
|
33
|
-
function getNetworkUrl(port: number): string | null {
|
|
34
|
-
const ifaces = os.networkInterfaces();
|
|
35
|
-
for (const list of Object.values(ifaces ?? {})) {
|
|
36
|
-
if (!list) continue;
|
|
37
|
-
for (const i of list) {
|
|
38
|
-
if (i.family === 'IPv4' && !i.internal) return `http://${i.address}:${port}/`;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/** Monorepo: alias a path assoluti (Rollup in Docker non segue symlink). Fuori monorepo ritorna {}. */
|
|
45
|
-
function resolveAlias(): Record<string, string> {
|
|
46
|
-
const root = path.resolve(process.cwd());
|
|
47
|
-
const packagesDir = path.join(root, 'packages');
|
|
48
|
-
if (!fs.existsSync(packagesDir)) return {};
|
|
49
|
-
const alias: Record<string, string> = {};
|
|
50
|
-
const clientRuntime = path.join(root, 'packages', 'client', 'runtime');
|
|
51
|
-
const jrx = path.join(clientRuntime, 'jsx-runtime.ts');
|
|
52
|
-
if (fs.existsSync(jrx)) {
|
|
53
|
-
alias['@flow.os/client/jsx-runtime'] = jrx;
|
|
54
|
-
alias['@flow.os/client/jsx-dev-runtime'] = path.join(clientRuntime, 'jsx-dev-runtime.ts');
|
|
55
|
-
}
|
|
56
|
-
for (const name of fs.readdirSync(packagesDir)) {
|
|
57
|
-
const dir = path.join(packagesDir, name);
|
|
58
|
-
if (!fs.statSync(dir).isDirectory()) continue;
|
|
59
|
-
const pkgPath = path.join(dir, 'package.json');
|
|
60
|
-
if (!fs.existsSync(pkgPath)) continue;
|
|
61
|
-
const abs = path.resolve(dir);
|
|
62
|
-
try {
|
|
63
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')) as { name?: string };
|
|
64
|
-
if (pkg.name?.startsWith('@flow.os/') || pkg.name === '@flow.os') alias[pkg.name] = abs;
|
|
65
|
-
} catch {}
|
|
66
|
-
alias[`@flow.os/${name}`] = abs;
|
|
67
|
-
}
|
|
68
|
-
return alias;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export type FlowConfigOptions = {
|
|
72
|
-
/** Porta del dev server. Default: 3000 */
|
|
73
|
-
port?: number;
|
|
74
|
-
/** Esporre su rete. Default: true */
|
|
75
|
-
host?: boolean;
|
|
76
|
-
/**
|
|
77
|
-
* Backend in dev: passa flowServer() per usare il server Flow (API da server/routes).
|
|
78
|
-
* Per Go, Rust, Nitro o altro: non passare server e avvia il backend separatamente;
|
|
79
|
-
* opzionalmente aggiungi in plugins un proxy verso la porta del tuo backend.
|
|
80
|
-
*/
|
|
81
|
-
server?: Plugin;
|
|
82
|
-
/** Plugin Vite aggiuntivi. Default: [] */
|
|
83
|
-
plugins?: Plugin[];
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const DEFAULTS = {
|
|
87
|
-
port: 3000,
|
|
88
|
-
host: true,
|
|
89
|
-
server: undefined as Plugin | undefined,
|
|
90
|
-
plugins: [] as Plugin[],
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
function flowServerUrlPlugin(hostEnabled: boolean): Plugin {
|
|
94
|
-
return {
|
|
95
|
-
name: 'flow:server-url',
|
|
96
|
-
configureServer(server) {
|
|
97
|
-
(server as { printUrls?: () => void }).printUrls = () => {};
|
|
98
|
-
server.httpServer?.once('listening', () => {
|
|
99
|
-
const addr = server.httpServer?.address();
|
|
100
|
-
if (!addr || typeof addr !== 'object' || !('port' in addr)) return;
|
|
101
|
-
const port = (addr as { port: number }).port;
|
|
102
|
-
const host = (addr as { address: string }).address;
|
|
103
|
-
const localHost = host === '::' || host === '0.0.0.0' ? 'localhost' : host;
|
|
104
|
-
const localUrl = `http://${localHost}:${port}/`;
|
|
105
|
-
const networkUrl = hostEnabled ? getNetworkUrl(port) : null;
|
|
106
|
-
|
|
107
|
-
const line = (content: string) => {
|
|
108
|
-
const pad = Math.max(0, CONTENT_W - stripAnsi(content).length);
|
|
109
|
-
return dim(' │ ') + content + ' '.repeat(pad) + dim(' │');
|
|
110
|
-
};
|
|
111
|
-
const border = (c: string) => dim(' ' + c + '─'.repeat(BORDER_W) + (c === '╭' ? '╮' : '╯'));
|
|
112
|
-
const out: string[] = [
|
|
113
|
-
'',
|
|
114
|
-
border('╭'),
|
|
115
|
-
line(bold('Flow OS') + dim(' is running')),
|
|
116
|
-
line(cyan('◆') + ' ' + dim('Local: ') + cyan(localUrl)),
|
|
117
|
-
...(networkUrl ? [line(dim('Network: ') + cyan(networkUrl))] : []),
|
|
118
|
-
border('╰'),
|
|
119
|
-
'',
|
|
120
|
-
];
|
|
121
|
-
console.log(out.join('\n'));
|
|
122
|
-
});
|
|
123
|
-
},
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/** Config per flow.config.ts. Client + Vite; server opzionale con server: flowServer(). */
|
|
128
|
-
export default function config(
|
|
129
|
-
options: FlowConfigOptions = {}
|
|
130
|
-
): () => Promise<ReturnType<typeof import('vite').defineConfig>> {
|
|
131
|
-
const { port: optPort = DEFAULTS.port, host = DEFAULTS.host, server = DEFAULTS.server, plugins = DEFAULTS.plugins } = options;
|
|
132
|
-
return async () => {
|
|
133
|
-
let port: number;
|
|
134
|
-
if (process.env.FLOW_DEV_PORT) {
|
|
135
|
-
port = parseInt(process.env.FLOW_DEV_PORT, 10);
|
|
136
|
-
} else {
|
|
137
|
-
port = await findFreePort(3000, 3020);
|
|
138
|
-
}
|
|
139
|
-
const { flow } = await import('./vite.js');
|
|
140
|
-
const allPlugins = [
|
|
141
|
-
flowServerUrlPlugin(host === true),
|
|
142
|
-
...(server ? [server, flow(), ...plugins] : [flow(), ...plugins]),
|
|
143
|
-
];
|
|
144
|
-
const alias = resolveAlias();
|
|
145
|
-
const baseLogger = createLogger('info');
|
|
146
|
-
const customLogger = {
|
|
147
|
-
...baseLogger,
|
|
148
|
-
info: (msg: string, opts?: { clear?: boolean }) => {
|
|
149
|
-
const t = msg.replace(/\s+/g, ' ');
|
|
150
|
-
if (/VITE\s+v?\d|ready\s+in|Local:\s*http|Network:\s*http|press\s+h\s+enter|Port\s+\d+\s+is\s+in\s+use/i.test(t)) return;
|
|
151
|
-
baseLogger.info(msg, opts);
|
|
152
|
-
},
|
|
153
|
-
};
|
|
154
|
-
return {
|
|
155
|
-
resolve: Object.keys(alias).length ? { alias } : {},
|
|
156
|
-
server: { port, host, strictPort: true },
|
|
157
|
-
customLogger,
|
|
158
|
-
build: {
|
|
159
|
-
rollupOptions: {
|
|
160
|
-
external: ['@flow.os/server', /^@flow.os\/server\/.+/],
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
plugins: allPlugins,
|
|
164
|
-
};
|
|
165
|
-
};
|
|
166
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
import { writeFileSync } from 'fs';
|
|
3
|
-
import { resolve } from 'path';
|
|
4
|
-
import type { Plugin } from 'vite';
|
|
5
|
-
|
|
6
|
-
const FLOW_ENTRY_ID = '\0flow-entry';
|
|
7
|
-
const ENTRY_CODE = `import * as root from '/client/root.tsx';
|
|
8
|
-
import { run } from '@flow.os/router';
|
|
9
|
-
const opts = {};
|
|
10
|
-
if (root.fallback != null) opts.fallback = root.fallback;
|
|
11
|
-
if (root.notFound != null) opts.notFound = root.notFound;
|
|
12
|
-
run(root.default, import.meta.glob('/client/routes/**/*.tsx'), Object.keys(opts).length ? opts : undefined);
|
|
13
|
-
`;
|
|
14
|
-
|
|
15
|
-
/** Reset stili browser: niente margin/padding di default, layout full viewport. */
|
|
16
|
-
const FLOW_BASE_STYLE = `<style>html,body{margin:0;padding:0;min-height:100vh}#app{min-height:100vh;box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}</style>`;
|
|
17
|
-
|
|
18
|
-
const HTML = `<!DOCTYPE html>
|
|
19
|
-
<html lang="it">
|
|
20
|
-
<head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Flow</title>${FLOW_BASE_STYLE}</head>
|
|
21
|
-
<body><div id="app"></div><script type="module" src="/entry.tsx"></script></body>
|
|
22
|
-
</html>`;
|
|
23
|
-
|
|
24
|
-
export function flow(): Plugin {
|
|
25
|
-
const cwd = process.cwd();
|
|
26
|
-
return {
|
|
27
|
-
name: 'flow',
|
|
28
|
-
config() {
|
|
29
|
-
return {
|
|
30
|
-
root: resolve(cwd),
|
|
31
|
-
base: '/',
|
|
32
|
-
esbuild: { jsx: 'automatic', jsxImportSource: '@flow.os/client' },
|
|
33
|
-
resolve: { alias: { '~': resolve(cwd, 'client') } },
|
|
34
|
-
build: { target: 'esnext', minify: 'esbuild', sourcemap: true },
|
|
35
|
-
};
|
|
36
|
-
},
|
|
37
|
-
configResolved(_config) {
|
|
38
|
-
writeFileSync(resolve(cwd, 'index.html'), HTML);
|
|
39
|
-
},
|
|
40
|
-
resolveId(id) {
|
|
41
|
-
return id === '/entry.tsx' ? FLOW_ENTRY_ID : null;
|
|
42
|
-
},
|
|
43
|
-
load(id) {
|
|
44
|
-
return id === FLOW_ENTRY_ID ? ENTRY_CODE : null;
|
|
45
|
-
},
|
|
46
|
-
buildEnd(err) {
|
|
47
|
-
if (err) {
|
|
48
|
-
const msg = err.message ?? String(err);
|
|
49
|
-
const stack = err.stack ?? (err as Error).cause?.toString?.();
|
|
50
|
-
console.error('[flow] build error:', msg, stack ?? '');
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { effect } from '@flow.os/core';
|
|
2
|
-
import { isGetter } from './utils.js';
|
|
3
|
-
|
|
4
|
-
/** Props gestite altrove (non passare qui). */
|
|
5
|
-
const SKIP = new Set(['children', 'class', 'className', 'classList', 'classFlow', 'style', 'styleFlow']);
|
|
6
|
-
|
|
7
|
-
export function applyAttrs(el: HTMLElement, rest: Record<string, unknown>): void {
|
|
8
|
-
for (const [k, v] of Object.entries(rest)) {
|
|
9
|
-
if (v == null || SKIP.has(k)) continue;
|
|
10
|
-
if (k.startsWith('on') && typeof v === 'function') {
|
|
11
|
-
el.addEventListener(k.slice(2).toLowerCase(), v as EventListener);
|
|
12
|
-
continue;
|
|
13
|
-
}
|
|
14
|
-
if (isGetter(v)) {
|
|
15
|
-
effect(() => {
|
|
16
|
-
const x = (v as () => unknown)();
|
|
17
|
-
if (typeof x === 'boolean') {
|
|
18
|
-
if (x) el.setAttribute(k, '');
|
|
19
|
-
else el.removeAttribute(k);
|
|
20
|
-
} else {
|
|
21
|
-
el.setAttribute(k, String(x));
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
continue;
|
|
25
|
-
}
|
|
26
|
-
if (typeof v === 'boolean') {
|
|
27
|
-
if (v) el.setAttribute(k, '');
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
if (typeof v === 'string' || typeof v === 'number') el.setAttribute(k, String(v));
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { effect } from '@flow.os/core';
|
|
2
|
-
import { isGetter } from './utils.js';
|
|
3
|
-
|
|
4
|
-
export function toStyleValue(v: unknown): string {
|
|
5
|
-
return typeof v === 'number' ? `${v}px` : String(v ?? '');
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function setStyleProp(el: HTMLElement, key: string, value: string): void {
|
|
9
|
-
if (key.startsWith('--')) el.style.setProperty(key, value);
|
|
10
|
-
else (el.style as unknown as Record<string, string>)[key] = value;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const CLASS_FLOW_MAP: Record<string, string> = {
|
|
14
|
-
text: 'fontSize',
|
|
15
|
-
mb: 'marginBottom',
|
|
16
|
-
mt: 'marginTop',
|
|
17
|
-
ml: 'marginLeft',
|
|
18
|
-
mr: 'marginRight',
|
|
19
|
-
mx: 'marginLeft',
|
|
20
|
-
my: 'marginTop',
|
|
21
|
-
m: 'margin',
|
|
22
|
-
pb: 'paddingBottom',
|
|
23
|
-
pt: 'paddingTop',
|
|
24
|
-
pl: 'paddingLeft',
|
|
25
|
-
pr: 'paddingRight',
|
|
26
|
-
px: 'paddingLeft',
|
|
27
|
-
py: 'paddingTop',
|
|
28
|
-
p: 'padding',
|
|
29
|
-
w: 'width',
|
|
30
|
-
h: 'height',
|
|
31
|
-
minW: 'minWidth',
|
|
32
|
-
minH: 'minHeight',
|
|
33
|
-
maxW: 'maxWidth',
|
|
34
|
-
maxH: 'maxHeight',
|
|
35
|
-
gap: 'gap',
|
|
36
|
-
rounded: 'borderRadius',
|
|
37
|
-
top: 'top',
|
|
38
|
-
left: 'left',
|
|
39
|
-
right: 'right',
|
|
40
|
-
bottom: 'bottom',
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
function resolveClassFlowKey(k: string): string {
|
|
44
|
-
if (k.startsWith('--')) return k;
|
|
45
|
-
return CLASS_FLOW_MAP[k] ?? k;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function isClassFlowReactive(val: unknown): boolean {
|
|
49
|
-
return isGetter(val) || (Array.isArray(val) && val.length === 2 && isGetter(val[0]));
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function resolveClassFlowValue(val: unknown): string {
|
|
53
|
-
if (isGetter(val)) return toStyleValue((val as () => unknown)());
|
|
54
|
-
if (Array.isArray(val) && val.length === 2 && isGetter(val[0]))
|
|
55
|
-
return String((val[0] as () => unknown)()) + String(val[1]);
|
|
56
|
-
return toStyleValue(val);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function applyClassFlowObj(el: HTMLElement, obj: Record<string, unknown>): void {
|
|
60
|
-
for (const [k, val] of Object.entries(obj))
|
|
61
|
-
setStyleProp(el, resolveClassFlowKey(k), resolveClassFlowValue(val));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function applyClassFlow(el: HTMLElement, classFlowVal: unknown): void {
|
|
65
|
-
if (classFlowVal == null) return;
|
|
66
|
-
if (isGetter(classFlowVal)) {
|
|
67
|
-
effect(() => applyClassFlowObj(el, (classFlowVal as () => Record<string, unknown>)()));
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
if (typeof classFlowVal !== 'object' || Array.isArray(classFlowVal) || classFlowVal instanceof Node) return;
|
|
71
|
-
const obj = classFlowVal as Record<string, unknown>;
|
|
72
|
-
const hasReactive = Object.values(obj).some(isClassFlowReactive);
|
|
73
|
-
if (hasReactive) {
|
|
74
|
-
effect(() => {
|
|
75
|
-
for (const [k, val] of Object.entries(obj))
|
|
76
|
-
setStyleProp(el, resolveClassFlowKey(k), resolveClassFlowValue(val));
|
|
77
|
-
});
|
|
78
|
-
} else {
|
|
79
|
-
applyClassFlowObj(el, obj);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function applyClassAndClassList(
|
|
84
|
-
el: HTMLElement,
|
|
85
|
-
classVal: unknown,
|
|
86
|
-
classNameVal: unknown,
|
|
87
|
-
classListVal: unknown
|
|
88
|
-
): void {
|
|
89
|
-
const base = classVal ?? classNameVal;
|
|
90
|
-
if (base == null && (classListVal == null || typeof classListVal !== 'object')) return;
|
|
91
|
-
effect(() => {
|
|
92
|
-
let baseStr = '';
|
|
93
|
-
if (base != null) {
|
|
94
|
-
if (Array.isArray(base)) {
|
|
95
|
-
baseStr = base
|
|
96
|
-
.map((item) => (isGetter(item) ? String((item as () => unknown)()) : String(item)))
|
|
97
|
-
.filter(Boolean)
|
|
98
|
-
.join(' ');
|
|
99
|
-
} else if (isGetter(base)) {
|
|
100
|
-
baseStr = String((base as () => unknown)());
|
|
101
|
-
} else {
|
|
102
|
-
baseStr = String(base);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
const list = classListVal as Record<string, boolean | (() => boolean)> | undefined;
|
|
106
|
-
const truthy: string[] = [];
|
|
107
|
-
if (list && typeof list === 'object' && !(list instanceof Node)) {
|
|
108
|
-
for (const [cls, val] of Object.entries(list)) {
|
|
109
|
-
const v = isGetter(val) ? (val as () => boolean)() : val;
|
|
110
|
-
if (v) truthy.push(cls);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
const full = [baseStr, ...truthy].filter(Boolean).join(' ');
|
|
114
|
-
el.setAttribute('class', full);
|
|
115
|
-
});
|
|
116
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Feature applicate a div, p, button, ecc.
|
|
3
|
-
* Un file per feature; qui si raggruppano e si espongono a jsx.
|
|
4
|
-
*/
|
|
5
|
-
export { applyClassFlow, applyClassAndClassList } from './class-flow.js';
|
|
6
|
-
export { applyStyle } from './style.js';
|
|
7
|
-
export { applyStyleFlow } from './style-flow.js';
|
|
8
|
-
export { applyAttrs } from './attrs.js';
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { styleToCssText } from '@flow.os/style';
|
|
2
|
-
import type { PseudoKey } from '@flow.os/style';
|
|
3
|
-
|
|
4
|
-
const PSEUDO_SELECTOR: Record<PseudoKey, string> = {
|
|
5
|
-
hover: ':hover',
|
|
6
|
-
active: ':active',
|
|
7
|
-
focus: ':focus',
|
|
8
|
-
focusVisible: ':focus-visible',
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
let styleEl: HTMLStyleElement | null = null;
|
|
12
|
-
const cache = new Map<string, string>();
|
|
13
|
-
let id = 0;
|
|
14
|
-
|
|
15
|
-
function ensureStyleEl(): HTMLStyleElement {
|
|
16
|
-
if (styleEl) return styleEl;
|
|
17
|
-
styleEl = document.createElement('style');
|
|
18
|
-
styleEl.setAttribute('data-flow-style', '');
|
|
19
|
-
document.head.appendChild(styleEl);
|
|
20
|
-
return styleEl;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** Restituisce className da aggiungere all'elemento. La regola .sf-{pseudo}-{id}:{pseudo} { ... } è iniettata una sola volta. */
|
|
24
|
-
export function getPseudoClass(
|
|
25
|
-
pseudo: PseudoKey,
|
|
26
|
-
style: Record<string, string>
|
|
27
|
-
): string {
|
|
28
|
-
const cssText = styleToCssText(style);
|
|
29
|
-
if (!cssText) return '';
|
|
30
|
-
const key = `${pseudo}:${cssText}`;
|
|
31
|
-
let className = cache.get(key);
|
|
32
|
-
if (className) return className;
|
|
33
|
-
className = `sf-${pseudo}-${++id}`;
|
|
34
|
-
cache.set(key, className);
|
|
35
|
-
const selector = `.${className}${PSEUDO_SELECTOR[pseudo]}`;
|
|
36
|
-
const rule = `${selector} { ${cssText} }`;
|
|
37
|
-
const el = ensureStyleEl();
|
|
38
|
-
el.appendChild(document.createTextNode(rule));
|
|
39
|
-
return className;
|
|
40
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { effect } from '@flow.os/core';
|
|
2
|
-
import { isGetter } from './utils.js';
|
|
3
|
-
import {
|
|
4
|
-
VIEWPORT_KEYS,
|
|
5
|
-
PSEUDO_KEYS,
|
|
6
|
-
resolveLayer,
|
|
7
|
-
resolvePseudoStyle,
|
|
8
|
-
type PlainLayer,
|
|
9
|
-
type ViewportKey,
|
|
10
|
-
type PseudoKey,
|
|
11
|
-
} from '@flow.os/style';
|
|
12
|
-
import { getViewportBreakpoint } from './viewport.js';
|
|
13
|
-
import { getPseudoClass } from './pseudo-injector.js';
|
|
14
|
-
|
|
15
|
-
const RESERVED = new Set<string>([...VIEWPORT_KEYS, ...PSEUDO_KEYS]);
|
|
16
|
-
|
|
17
|
-
/** Chiama getter e restituisce oggetto plain (una livello, escluse chiavi reserved). */
|
|
18
|
-
function gatherPlain(obj: Record<string, unknown> | null | undefined): PlainLayer {
|
|
19
|
-
const out: PlainLayer = {};
|
|
20
|
-
if (!obj || typeof obj !== 'object' || Array.isArray(obj)) return out;
|
|
21
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
22
|
-
if (RESERVED.has(k)) continue;
|
|
23
|
-
if (v === undefined || v === null) continue;
|
|
24
|
-
if (isGetter(v)) {
|
|
25
|
-
const x = (v as () => unknown)();
|
|
26
|
-
if (typeof x === 'boolean') out[k] = x;
|
|
27
|
-
else if (typeof x === 'number' || typeof x === 'string') out[k] = x;
|
|
28
|
-
else if (Array.isArray(x) && x.length === 2 && isGetter(x[0]))
|
|
29
|
-
out[k] = String((x[0] as () => unknown)()) + String(x[1]);
|
|
30
|
-
else out[k] = String(x);
|
|
31
|
-
} else if (typeof v === 'object' && v !== null && !(v instanceof Node)) {
|
|
32
|
-
if (k === 'base') out['base'] = (v as Record<string, string>)['base'] ?? String(v);
|
|
33
|
-
// nested layer (mob/tab/des/hover/...) già esclusi da RESERVED
|
|
34
|
-
} else {
|
|
35
|
-
out[k] = v as string | number | boolean;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return out;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** Normalizza value in base string + flat object. */
|
|
42
|
-
function normalize(
|
|
43
|
-
value: unknown
|
|
44
|
-
): { base: string; flat: Record<string, unknown> } {
|
|
45
|
-
if (value == null) return { base: '', flat: {} };
|
|
46
|
-
if (typeof value === 'string') return { base: value, flat: {} };
|
|
47
|
-
if (Array.isArray(value)) {
|
|
48
|
-
const base = typeof value[0] === 'string' ? value[0] : '';
|
|
49
|
-
const flat = (value[1] && typeof value[1] === 'object' && !Array.isArray(value[1]))
|
|
50
|
-
? (value[1] as Record<string, unknown>)
|
|
51
|
-
: {};
|
|
52
|
-
return { base, flat };
|
|
53
|
-
}
|
|
54
|
-
if (typeof value === 'object' && !Array.isArray(value) && !(value instanceof Node)) {
|
|
55
|
-
const flat = value as Record<string, unknown>;
|
|
56
|
-
const base = typeof flat['base'] === 'string' ? flat['base'] : '';
|
|
57
|
-
return { base, flat };
|
|
58
|
-
}
|
|
59
|
-
return { base: '', flat: {} };
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function applyStyleFlow(el: HTMLElement, value: unknown): void {
|
|
63
|
-
if (value == null) return;
|
|
64
|
-
const { base, flat } = normalize(value);
|
|
65
|
-
let prevStyleKeys: string[] = [];
|
|
66
|
-
|
|
67
|
-
effect(() => {
|
|
68
|
-
const viewport: ViewportKey = getViewportBreakpoint();
|
|
69
|
-
const plainBase = gatherPlain(flat);
|
|
70
|
-
if (base) plainBase.base = (plainBase.base ? `${plainBase.base} ` : '') + base;
|
|
71
|
-
const viewportLayer = flat[viewport];
|
|
72
|
-
const plainViewport = gatherPlain(
|
|
73
|
-
viewportLayer && typeof viewportLayer === 'object' && !Array.isArray(viewportLayer)
|
|
74
|
-
? (viewportLayer as Record<string, unknown>)
|
|
75
|
-
: {}
|
|
76
|
-
);
|
|
77
|
-
const merged: PlainLayer = { ...plainBase };
|
|
78
|
-
if (plainViewport.base) merged.base = (merged.base ? `${merged.base} ` : '') + plainViewport.base;
|
|
79
|
-
for (const [k, v] of Object.entries(plainViewport)) {
|
|
80
|
-
if (k === 'base') continue;
|
|
81
|
-
(merged as Record<string, unknown>)[k] = v;
|
|
82
|
-
}
|
|
83
|
-
const resolved = resolveLayer(merged);
|
|
84
|
-
|
|
85
|
-
const pseudoClasses: string[] = [];
|
|
86
|
-
for (const pseudo of PSEUDO_KEYS) {
|
|
87
|
-
const rawPseudo = flat[pseudo];
|
|
88
|
-
const plainPseudo = gatherPlain(
|
|
89
|
-
rawPseudo && typeof rawPseudo === 'object' && !Array.isArray(rawPseudo)
|
|
90
|
-
? (rawPseudo as Record<string, unknown>)
|
|
91
|
-
: {}
|
|
92
|
-
);
|
|
93
|
-
const stylePseudo = resolvePseudoStyle(plainPseudo);
|
|
94
|
-
const cls = getPseudoClass(pseudo as PseudoKey, stylePseudo);
|
|
95
|
-
if (cls) pseudoClasses.push(cls);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
el.className = [resolved.class, ...pseudoClasses].filter(Boolean).join(' ');
|
|
99
|
-
for (const k of prevStyleKeys) el.style.removeProperty(k);
|
|
100
|
-
prevStyleKeys = Object.keys(resolved.style);
|
|
101
|
-
for (const [k, v] of Object.entries(resolved.style)) {
|
|
102
|
-
if (k.startsWith('--')) el.style.setProperty(k, v);
|
|
103
|
-
else (el.style as unknown as Record<string, string>)[k] = v;
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { effect } from '@flow.os/core';
|
|
2
|
-
import { isGetter } from './utils.js';
|
|
3
|
-
import { setStyleProp, toStyleValue } from './class-flow.js';
|
|
4
|
-
|
|
5
|
-
export function applyStyle(el: HTMLElement, styleVal: unknown): void {
|
|
6
|
-
if (styleVal == null) return;
|
|
7
|
-
if (isGetter(styleVal)) {
|
|
8
|
-
effect(() => {
|
|
9
|
-
const style = (styleVal as () => Record<string, string> | string)();
|
|
10
|
-
if (typeof style === 'string') {
|
|
11
|
-
el.setAttribute('style', style);
|
|
12
|
-
} else if (style && typeof style === 'object') {
|
|
13
|
-
for (const [sk, sv] of Object.entries(style)) setStyleProp(el, sk, toStyleValue(sv));
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
if (typeof styleVal !== 'object' || styleVal === null || styleVal instanceof Node) return;
|
|
19
|
-
const style = styleVal as Record<string, string | number | (() => string | number)>;
|
|
20
|
-
for (const [sk, sv] of Object.entries(style)) {
|
|
21
|
-
if (isGetter(sv)) {
|
|
22
|
-
effect(() => setStyleProp(el, sk, toStyleValue((sv as () => unknown)())));
|
|
23
|
-
} else {
|
|
24
|
-
setStyleProp(el, sk, toStyleValue(sv));
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { state } from '@flow.os/core';
|
|
2
|
-
import type { ViewportKey } from '@flow.os/style';
|
|
3
|
-
import { getViewportKeyFromWidth } from '@flow.os/style';
|
|
4
|
-
|
|
5
|
-
const [getViewport, setViewport] = state<ViewportKey>('mob');
|
|
6
|
-
let subscribed = false;
|
|
7
|
-
|
|
8
|
-
function subscribe(): void {
|
|
9
|
-
if (subscribed) return;
|
|
10
|
-
subscribed = true;
|
|
11
|
-
const update = () => setViewport(getViewportKeyFromWidth(window.innerWidth));
|
|
12
|
-
update();
|
|
13
|
-
window.addEventListener('resize', update);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/** Breakpoint viewport reattivo (mob/tab/des). Una sola subscription condivisa. */
|
|
17
|
-
export function getViewportBreakpoint(): ViewportKey {
|
|
18
|
-
subscribe();
|
|
19
|
-
return getViewport();
|
|
20
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/// <reference path="./runtime/jsx-types.d.ts" />
|
|
2
|
-
// API pubblica: tutto da qui o da subpath (./config, ./vite, ./jsx-runtime, ./jsx-dev-runtime)
|
|
3
|
-
export { Fragment, jsx, jsxs, jsxDEV } from './runtime/jsx.js';
|
|
4
|
-
export { normalizeChild, setContent } from './runtime/dom.js';
|
|
5
|
-
export { default as config } from './build/config.js';
|
|
6
|
-
export { applyClassFlow, applyClassAndClassList, applyStyle, applyStyleFlow, applyAttrs } from './features/index.js';
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@flow.os/client",
|
|
3
|
-
"version": "0.0.5",
|
|
4
|
-
"license": "PolyForm-Shield-1.0.0",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./index.ts",
|
|
7
|
-
"types": "./index.ts",
|
|
8
|
-
"bin": {
|
|
9
|
-
"flow-os-dev": "./scripts/start-dev.ts",
|
|
10
|
-
"flow-os-build": "./scripts/build.ts",
|
|
11
|
-
"flow-os-preview": "./scripts/preview.ts"
|
|
12
|
-
},
|
|
13
|
-
"dependencies": {
|
|
14
|
-
"@flow.os/core": "workspace:*",
|
|
15
|
-
"@flow.os/router": "workspace:*",
|
|
16
|
-
"@flow.os/style": "workspace:*"
|
|
17
|
-
},
|
|
18
|
-
"peerDependencies": {
|
|
19
|
-
"vite": ">=5.0.0"
|
|
20
|
-
},
|
|
21
|
-
"exports": {
|
|
22
|
-
".": {
|
|
23
|
-
"types": "./index.ts",
|
|
24
|
-
"import": "./index.ts",
|
|
25
|
-
"default": "./index.ts"
|
|
26
|
-
},
|
|
27
|
-
"./config": {
|
|
28
|
-
"types": "./build/config.ts",
|
|
29
|
-
"import": "./build/config.ts",
|
|
30
|
-
"default": "./build/config.ts"
|
|
31
|
-
},
|
|
32
|
-
"./vite": {
|
|
33
|
-
"types": "./build/vite.ts",
|
|
34
|
-
"import": "./build/vite.ts",
|
|
35
|
-
"default": "./build/vite.ts"
|
|
36
|
-
},
|
|
37
|
-
"./jsx-runtime": {
|
|
38
|
-
"types": "./runtime/jsx.ts",
|
|
39
|
-
"import": "./runtime/jsx.ts",
|
|
40
|
-
"default": "./runtime/jsx.ts"
|
|
41
|
-
},
|
|
42
|
-
"./jsx-dev-runtime": {
|
|
43
|
-
"types": "./runtime/jsx.ts",
|
|
44
|
-
"import": "./runtime/jsx.ts",
|
|
45
|
-
"default": "./runtime/jsx.ts"
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './jsx.js';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './jsx.js';
|