create-flowdular 0.2.1 → 0.2.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 +2 -0
- package/dist/bin.js +29 -10
- package/package.json +1 -1
- package/template/default/flowdular.json +12 -1
- package/template/default/modules/example/package.json +1 -1
- package/template/default/modules/example/src/client/NotesView.tsrx +27 -23
- package/template/default/package.json +1 -1
- package/template/default/platform/index.html +157 -2
- package/template/default/platform/package.json +1 -1
- package/template/default/platform/src/generated/modules.client.ts +17 -1
- package/template/default/platform/src/generated/modules.server.ts +59 -0
package/README.md
CHANGED
|
@@ -26,6 +26,8 @@ pnpm dev
|
|
|
26
26
|
|
|
27
27
|
Open [localhost:4310](http://localhost:4310). `setup` opens an interactive wizard for a local demo, PostgreSQL settings or a configuration check. It asks before resetting the local demo database.
|
|
28
28
|
|
|
29
|
+
The starter enables all nine platform modules: system, authentication, users, profile, agents, automations, workflows, their integration, and sandbox access. Local demo setup grants their declared permissions to demo owners. The example module stays available as a starting point; business modules from Official Modules are optional downloads.
|
|
30
|
+
|
|
29
31
|
`npm create` launches the generator. The generated application uses **pnpm workspaces**. If pnpm is unavailable during installation, the generator invokes its pinned version through `npm exec`.
|
|
30
32
|
|
|
31
33
|
You can also launch the generator directly:
|
package/dist/bin.js
CHANGED
|
@@ -244,6 +244,7 @@ function installDependencies(packageManager, directory) {
|
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
// src/report.ts
|
|
247
|
+
import { styleText } from "node:util";
|
|
247
248
|
var DEV_URL = "http://localhost:4310";
|
|
248
249
|
function runScript(packageManager, script, ...arguments_) {
|
|
249
250
|
if (arguments_.length === 0) {
|
|
@@ -260,14 +261,26 @@ function nextSteps(input) {
|
|
|
260
261
|
runScript(input.packageManager, "dev")
|
|
261
262
|
];
|
|
262
263
|
}
|
|
263
|
-
function renderNextSteps(input) {
|
|
264
|
+
function renderNextSteps(input, color = false) {
|
|
265
|
+
const paint = (text, format) => color ? styleText(format, text, { validateStream: false }) : text;
|
|
266
|
+
const labels = [
|
|
267
|
+
"Open your project",
|
|
268
|
+
...input.installed ? [] : ["Install dependencies"],
|
|
269
|
+
"Choose local demo or PostgreSQL",
|
|
270
|
+
"Start your app"
|
|
271
|
+
];
|
|
264
272
|
return [
|
|
265
273
|
"",
|
|
266
|
-
"
|
|
267
|
-
"",
|
|
268
|
-
...nextSteps(input).map((step) => ` ${step}`),
|
|
274
|
+
` ${paint("FLOWDULAR", "bold")} ${paint("Project created", "green")}`,
|
|
269
275
|
"",
|
|
270
|
-
|
|
276
|
+
...nextSteps(input).flatMap((step, index) => [
|
|
277
|
+
` ${paint(`${index + 1}.`, "cyan")} ${labels[index]}`,
|
|
278
|
+
` ${paint(step, "bold")}`,
|
|
279
|
+
""
|
|
280
|
+
]),
|
|
281
|
+
` ${paint("Local URL", "dim")} ${paint(DEV_URL, "cyan")}`,
|
|
282
|
+
` ${paint("Demo login", "dim")} admin@example.com`,
|
|
283
|
+
` ${paint("Demo account is created only with local demo setup.", "dim")}`,
|
|
271
284
|
""
|
|
272
285
|
].join("\n");
|
|
273
286
|
}
|
|
@@ -436,6 +449,9 @@ async function scaffold(request) {
|
|
|
436
449
|
|
|
437
450
|
// src/index.ts
|
|
438
451
|
var processIo = {
|
|
452
|
+
color: Boolean(
|
|
453
|
+
process.stdout.isTTY && process.stdout.hasColors?.() && !("NO_COLOR" in process.env) && !process.env.CI
|
|
454
|
+
),
|
|
439
455
|
cwd: process.cwd(),
|
|
440
456
|
out: (text) => process.stdout.write(text),
|
|
441
457
|
err: (text) => process.stderr.write(text)
|
|
@@ -508,11 +524,14 @@ async function run(argv, io = processIo) {
|
|
|
508
524
|
}
|
|
509
525
|
const here = relative2(io.cwd, result.directory);
|
|
510
526
|
io.out(
|
|
511
|
-
renderNextSteps(
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
527
|
+
renderNextSteps(
|
|
528
|
+
{
|
|
529
|
+
directory: here.length > 0 ? here : ".",
|
|
530
|
+
packageManager,
|
|
531
|
+
installed
|
|
532
|
+
},
|
|
533
|
+
io.color
|
|
534
|
+
)
|
|
516
535
|
);
|
|
517
536
|
return 0;
|
|
518
537
|
}
|
package/package.json
CHANGED
|
@@ -8,7 +8,18 @@
|
|
|
8
8
|
},
|
|
9
9
|
"modules": {
|
|
10
10
|
"roots": ["modules"],
|
|
11
|
-
"enabled": [
|
|
11
|
+
"enabled": [
|
|
12
|
+
"system.core",
|
|
13
|
+
"auth.core",
|
|
14
|
+
"agents.core",
|
|
15
|
+
"automations.core",
|
|
16
|
+
"workflows.core",
|
|
17
|
+
"automations-workflows.integration",
|
|
18
|
+
"example.core",
|
|
19
|
+
"profile.core",
|
|
20
|
+
"sandbox.core",
|
|
21
|
+
"users.core"
|
|
22
|
+
]
|
|
12
23
|
},
|
|
13
24
|
"locales": ["en", "pl"],
|
|
14
25
|
"agent": {
|
|
@@ -195,30 +195,34 @@ export function NotesView(props: NotesViewProps) @{
|
|
|
195
195
|
onSubmit={submit}
|
|
196
196
|
>
|
|
197
197
|
<div class="ui-drawer__body">
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
<
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
198
|
+
<div class="ui-form">
|
|
199
|
+
@if (error) {
|
|
200
|
+
<Alert>{error}</Alert>
|
|
201
|
+
}
|
|
202
|
+
<FormField label={t('example.field.title')} required>
|
|
203
|
+
<input
|
|
204
|
+
class="ui-input"
|
|
205
|
+
id="title"
|
|
206
|
+
name="title"
|
|
207
|
+
required
|
|
208
|
+
maxLength={120}
|
|
209
|
+
/>
|
|
210
|
+
</FormField>
|
|
211
|
+
<FormField
|
|
212
|
+
label={t('example.field.body')}
|
|
206
213
|
required
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
maxLength={4000}
|
|
220
|
-
></textarea>
|
|
221
|
-
</FormField>
|
|
214
|
+
help={t('example.field.body.help')}
|
|
215
|
+
>
|
|
216
|
+
<textarea
|
|
217
|
+
class="ui-textarea"
|
|
218
|
+
id="body"
|
|
219
|
+
name="body"
|
|
220
|
+
required
|
|
221
|
+
rows={6}
|
|
222
|
+
maxLength={4000}
|
|
223
|
+
></textarea>
|
|
224
|
+
</FormField>
|
|
225
|
+
</div>
|
|
222
226
|
</div>
|
|
223
227
|
<div class="ui-drawer__foot">
|
|
224
228
|
<Button type="button" onClick={closeForm}>{t(
|
|
@@ -1,13 +1,168 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
2
|
+
<html lang="en" class="flowdular-booting">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<meta name="theme-color" content="#141B2E" />
|
|
7
7
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
8
|
+
<style id="flowdular-critical-splash">
|
|
9
|
+
html,
|
|
10
|
+
body,
|
|
11
|
+
#root {
|
|
12
|
+
min-height: 100%;
|
|
13
|
+
margin: 0;
|
|
14
|
+
background: #0c1222;
|
|
15
|
+
}
|
|
16
|
+
.flowdular-splash {
|
|
17
|
+
position: fixed;
|
|
18
|
+
inset: 0;
|
|
19
|
+
z-index: 2147483647;
|
|
20
|
+
display: grid;
|
|
21
|
+
place-items: center;
|
|
22
|
+
background: #0c1222;
|
|
23
|
+
color: #f4f6fa;
|
|
24
|
+
transition: opacity 180ms ease;
|
|
25
|
+
}
|
|
26
|
+
.flowdular-splash__content {
|
|
27
|
+
display: grid;
|
|
28
|
+
justify-items: center;
|
|
29
|
+
gap: 16px;
|
|
30
|
+
font:
|
|
31
|
+
600 13px/1.2 ui-sans-serif,
|
|
32
|
+
system-ui,
|
|
33
|
+
sans-serif;
|
|
34
|
+
letter-spacing: 0.14em;
|
|
35
|
+
text-transform: uppercase;
|
|
36
|
+
}
|
|
37
|
+
.flowdular-splash__stage {
|
|
38
|
+
min-width: 190px;
|
|
39
|
+
font-size: 10px;
|
|
40
|
+
font-weight: 500;
|
|
41
|
+
color: #8794ab;
|
|
42
|
+
letter-spacing: 0.08em;
|
|
43
|
+
text-align: center;
|
|
44
|
+
text-transform: none;
|
|
45
|
+
}
|
|
46
|
+
.flowdular-splash__mark {
|
|
47
|
+
display: block;
|
|
48
|
+
width: 44px;
|
|
49
|
+
height: 44px;
|
|
50
|
+
animation: flowdular-pulse 1.4s ease-in-out infinite alternate;
|
|
51
|
+
}
|
|
52
|
+
.flowdular-splash--leaving {
|
|
53
|
+
opacity: 0;
|
|
54
|
+
pointer-events: none;
|
|
55
|
+
}
|
|
56
|
+
@keyframes flowdular-pulse {
|
|
57
|
+
to {
|
|
58
|
+
opacity: 0.45;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
@media (prefers-reduced-motion: reduce) {
|
|
62
|
+
.flowdular-splash__mark {
|
|
63
|
+
animation: none;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
</style>
|
|
8
67
|
<!--ssr-head-->
|
|
9
68
|
</head>
|
|
10
|
-
<body>
|
|
69
|
+
<body aria-busy="true">
|
|
70
|
+
<div
|
|
71
|
+
id="flowdular-splash"
|
|
72
|
+
class="flowdular-splash"
|
|
73
|
+
role="status"
|
|
74
|
+
aria-live="polite"
|
|
75
|
+
>
|
|
76
|
+
<div class="flowdular-splash__content">
|
|
77
|
+
<svg
|
|
78
|
+
class="flowdular-splash__mark"
|
|
79
|
+
viewBox="0 0 24 24"
|
|
80
|
+
aria-hidden="true"
|
|
81
|
+
>
|
|
82
|
+
<g fill="#ffffff">
|
|
83
|
+
<circle cx="7.9" cy="3.4" r="1.7" />
|
|
84
|
+
<rect x="6.2" y="3.4" width="3.4" height="1.6" />
|
|
85
|
+
<rect x="6.2" y="10.8" width="3.4" height="9.8" />
|
|
86
|
+
<circle cx="7.9" cy="20.6" r="1.7" />
|
|
87
|
+
<circle cx="16.1" cy="3.4" r="1.7" />
|
|
88
|
+
<rect x="14.4" y="3.4" width="3.4" height="9.8" />
|
|
89
|
+
<rect x="14.4" y="19" width="3.4" height="1.6" />
|
|
90
|
+
<circle cx="16.1" cy="20.6" r="1.7" />
|
|
91
|
+
</g>
|
|
92
|
+
<g fill="#e08a45">
|
|
93
|
+
<circle cx="3.4" cy="7.9" r="1.7" />
|
|
94
|
+
<rect x="3.4" y="6.2" width="9.8" height="3.4" />
|
|
95
|
+
<rect x="19" y="6.2" width="1.6" height="3.4" />
|
|
96
|
+
<circle cx="20.6" cy="7.9" r="1.7" />
|
|
97
|
+
<circle cx="3.4" cy="16.1" r="1.7" />
|
|
98
|
+
<rect x="3.4" y="14.4" width="1.6" height="3.4" />
|
|
99
|
+
<rect x="10.8" y="14.4" width="9.8" height="3.4" />
|
|
100
|
+
<circle cx="20.6" cy="16.1" r="1.7" />
|
|
101
|
+
</g>
|
|
102
|
+
</svg>
|
|
103
|
+
<span>Flowdular</span>
|
|
104
|
+
<small id="flowdular-splash-stage" class="flowdular-splash__stage"
|
|
105
|
+
>Starting workspace</small
|
|
106
|
+
>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
11
109
|
<div id="root"><!--ssr-body--></div>
|
|
110
|
+
<script nonce="__FLOWDULAR_CSP_NONCE__">
|
|
111
|
+
(() => {
|
|
112
|
+
if (document.getElementById('flowdular-web-data')) {
|
|
113
|
+
document.getElementById('flowdular-splash')?.remove();
|
|
114
|
+
document.documentElement.classList.remove('flowdular-booting');
|
|
115
|
+
document.body.removeAttribute('aria-busy');
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const startedAt = performance.now();
|
|
119
|
+
const stages = [
|
|
120
|
+
'Securing session',
|
|
121
|
+
'Selecting workspace',
|
|
122
|
+
'Loading modules',
|
|
123
|
+
'Preparing workspace',
|
|
124
|
+
];
|
|
125
|
+
let stageIndex = 0;
|
|
126
|
+
let ready = false;
|
|
127
|
+
let stageTimer;
|
|
128
|
+
const stage = document.getElementById('flowdular-splash-stage');
|
|
129
|
+
const advance = () => {
|
|
130
|
+
if (!stage || ready) return;
|
|
131
|
+
stage.textContent = stages[Math.min(stageIndex, stages.length - 1)];
|
|
132
|
+
stageIndex += 1;
|
|
133
|
+
};
|
|
134
|
+
const finish = () => {
|
|
135
|
+
if (ready) return;
|
|
136
|
+
ready = true;
|
|
137
|
+
clearInterval(stageTimer);
|
|
138
|
+
const splash = document.getElementById('flowdular-splash');
|
|
139
|
+
if (!splash) return;
|
|
140
|
+
const leave = () => {
|
|
141
|
+
splash.classList.add('flowdular-splash--leaving');
|
|
142
|
+
document.documentElement.classList.remove('flowdular-booting');
|
|
143
|
+
document.body.setAttribute('aria-busy', 'false');
|
|
144
|
+
setTimeout(() => splash.remove(), 200);
|
|
145
|
+
};
|
|
146
|
+
const remaining = Math.max(0, 850 - (performance.now() - startedAt));
|
|
147
|
+
setTimeout(leave, remaining);
|
|
148
|
+
};
|
|
149
|
+
window.addEventListener('DOMContentLoaded', () => {
|
|
150
|
+
advance();
|
|
151
|
+
stageTimer = setInterval(advance, 320);
|
|
152
|
+
/* The server-rendered page is already visible underneath; hydration
|
|
153
|
+
in development can take seconds, so the splash never blocks longer
|
|
154
|
+
than this. */
|
|
155
|
+
setTimeout(finish, 2500);
|
|
156
|
+
});
|
|
157
|
+
window.addEventListener('flowdular:ready', finish, { once: true });
|
|
158
|
+
})();
|
|
159
|
+
</script>
|
|
160
|
+
<noscript
|
|
161
|
+
><style>
|
|
162
|
+
.flowdular-splash {
|
|
163
|
+
display: none;
|
|
164
|
+
}
|
|
165
|
+
</style></noscript
|
|
166
|
+
>
|
|
12
167
|
</body>
|
|
13
168
|
</html>
|
|
@@ -7,10 +7,26 @@ import type {
|
|
|
7
7
|
} from '@flowdular/sdk/client';
|
|
8
8
|
import { createClientContribution as system_core } from '@flowdular/sdk/modules/system/client';
|
|
9
9
|
import { createClientContribution as auth_core } from '@flowdular/sdk/modules/auth/client';
|
|
10
|
+
import { createClientContribution as agents_core } from '@flowdular/sdk/modules/agents/client';
|
|
11
|
+
import { createClientContribution as automations_core } from '@flowdular/sdk/modules/automations/client';
|
|
12
|
+
import { createClientContribution as workflows_core } from '@flowdular/sdk/modules/workflows/client';
|
|
10
13
|
import { createClientContribution as example_core } from '@app/module-example/client';
|
|
14
|
+
import { createClientContribution as profile_core } from '@flowdular/sdk/modules/profile/client';
|
|
15
|
+
import { createClientContribution as sandbox_core } from '@flowdular/sdk/modules/sandbox/client';
|
|
16
|
+
import { createClientContribution as users_core } from '@flowdular/sdk/modules/users/client';
|
|
11
17
|
|
|
12
18
|
export function createModuleClientContributions(
|
|
13
19
|
context: ModuleClientContext,
|
|
14
20
|
): readonly ModuleClientContribution[] {
|
|
15
|
-
return [
|
|
21
|
+
return [
|
|
22
|
+
system_core(context),
|
|
23
|
+
auth_core(context),
|
|
24
|
+
agents_core(context),
|
|
25
|
+
automations_core(context),
|
|
26
|
+
workflows_core(context),
|
|
27
|
+
example_core(context),
|
|
28
|
+
profile_core(context),
|
|
29
|
+
sandbox_core(context),
|
|
30
|
+
users_core(context),
|
|
31
|
+
];
|
|
16
32
|
}
|
|
@@ -6,7 +6,14 @@ import type {
|
|
|
6
6
|
} from '@flowdular/sdk/modules/auth/server';
|
|
7
7
|
import type { WebMount } from '@flowdular/sdk/server';
|
|
8
8
|
import { createServerComposition as system_core } from '@flowdular/sdk/modules/system/platform';
|
|
9
|
+
import { createServerComposition as agents_core } from '@flowdular/sdk/modules/agents/platform';
|
|
10
|
+
import { createServerComposition as automations_core } from '@flowdular/sdk/modules/automations/platform';
|
|
11
|
+
import { createServerComposition as workflows_core } from '@flowdular/sdk/modules/workflows/platform';
|
|
12
|
+
import { createServerComposition as automations_workflows_integration } from '@flowdular/sdk/modules/automations-workflows-integration/platform';
|
|
9
13
|
import { createServerComposition as example_core } from '@app/module-example/platform';
|
|
14
|
+
import { createServerComposition as profile_core } from '@flowdular/sdk/modules/profile/platform';
|
|
15
|
+
import { createServerComposition as sandbox_core } from '@flowdular/sdk/modules/sandbox/platform';
|
|
16
|
+
import { createServerComposition as users_core } from '@flowdular/sdk/modules/users/platform';
|
|
10
17
|
|
|
11
18
|
export function composeModuleServer(
|
|
12
19
|
context: PlatformServerContext,
|
|
@@ -19,6 +26,37 @@ export function composeModuleServer(
|
|
|
19
26
|
}),
|
|
20
27
|
moduleId: 'system.core',
|
|
21
28
|
},
|
|
29
|
+
{
|
|
30
|
+
...agents_core({
|
|
31
|
+
...context,
|
|
32
|
+
agentDefinitions: context.agentDefinitions.forModule('agents.core'),
|
|
33
|
+
}),
|
|
34
|
+
moduleId: 'agents.core',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
...automations_core({
|
|
38
|
+
...context,
|
|
39
|
+
agentDefinitions:
|
|
40
|
+
context.agentDefinitions.forModule('automations.core'),
|
|
41
|
+
}),
|
|
42
|
+
moduleId: 'automations.core',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
...workflows_core({
|
|
46
|
+
...context,
|
|
47
|
+
agentDefinitions: context.agentDefinitions.forModule('workflows.core'),
|
|
48
|
+
}),
|
|
49
|
+
moduleId: 'workflows.core',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
...automations_workflows_integration({
|
|
53
|
+
...context,
|
|
54
|
+
agentDefinitions: context.agentDefinitions.forModule(
|
|
55
|
+
'automations-workflows.integration',
|
|
56
|
+
),
|
|
57
|
+
}),
|
|
58
|
+
moduleId: 'automations-workflows.integration',
|
|
59
|
+
},
|
|
22
60
|
{
|
|
23
61
|
...example_core({
|
|
24
62
|
...context,
|
|
@@ -26,6 +64,27 @@ export function composeModuleServer(
|
|
|
26
64
|
}),
|
|
27
65
|
moduleId: 'example.core',
|
|
28
66
|
},
|
|
67
|
+
{
|
|
68
|
+
...profile_core({
|
|
69
|
+
...context,
|
|
70
|
+
agentDefinitions: context.agentDefinitions.forModule('profile.core'),
|
|
71
|
+
}),
|
|
72
|
+
moduleId: 'profile.core',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
...sandbox_core({
|
|
76
|
+
...context,
|
|
77
|
+
agentDefinitions: context.agentDefinitions.forModule('sandbox.core'),
|
|
78
|
+
}),
|
|
79
|
+
moduleId: 'sandbox.core',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
...users_core({
|
|
83
|
+
...context,
|
|
84
|
+
agentDefinitions: context.agentDefinitions.forModule('users.core'),
|
|
85
|
+
}),
|
|
86
|
+
moduleId: 'users.core',
|
|
87
|
+
},
|
|
29
88
|
];
|
|
30
89
|
}
|
|
31
90
|
|