create-flowdular 0.1.0 → 0.2.1

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 CHANGED
@@ -1,51 +1,91 @@
1
+ [![Flowdular: Build your business platform](https://cdn.jsdelivr.net/npm/create-flowdular@latest/assets/flowdular-banner.png)](https://flowdular.com)
2
+
1
3
  # create-flowdular
2
4
 
3
- Scaffold a Flowdular application.
5
+ [![npm version](https://img.shields.io/npm/v/create-flowdular?color=f59e0b)](https://www.npmjs.com/package/create-flowdular)
6
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D22.22.2-339933?logo=nodedotjs&logoColor=white)](https://nodejs.org/)
7
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://github.com/Flowdular/flowdular/blob/main/LICENSE)
8
+
9
+ Create a Flowdular application with the platform, an example module and local development configuration. Start with embedded PostgreSQL, then extend the application with your own business modules.
10
+
11
+ ## Quick start
4
12
 
5
- ```bash
13
+ Use Node.js **22.22.2 or newer**:
14
+
15
+ ```sh
6
16
  npm create flowdular@latest my-app
17
+ cd my-app
18
+ ```
19
+
20
+ For this new local application, initialize demo authentication and start the development server:
21
+
22
+ ```sh
23
+ pnpm flowdular setup
24
+ pnpm dev
7
25
  ```
8
26
 
9
- `pnpm create flowdular my-app` and `yarn create flowdular my-app` resolve to the
10
- same package. `npx create-flowdular@latest my-app` runs it directly.
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.
11
28
 
12
- It creates the directory, copies the template (the platform plus one example
13
- module), rewrites the package name, generates this app's secret keys into
14
- `.env`, installs the pnpm workspace dependencies, and
15
- makes the first commit.
29
+ `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`.
16
30
 
17
- ## Options
31
+ You can also launch the generator directly:
18
32
 
19
- | Option | Default | Effect |
20
- | ----------------------- | --------- | ------------------------------------------- |
21
- | `-t, --template <name>` | `default` | Template to copy |
22
- | `--pm <manager>` | `pnpm` | Use `pnpm` for this template |
23
- | `--no-install` | installs | Skip dependency installation |
24
- | `--no-git` | commits | Skip repository initialization |
25
- | `-f, --force` | refuses | Scaffold into a directory that is not empty |
26
- | `-h, --help` | | Show usage |
27
- | `-v, --version` | | Show the version |
33
+ ```sh
34
+ npx create-flowdular@latest my-app
35
+ ```
28
36
 
29
- ## What it generates
37
+ ## What you get
30
38
 
31
- Local development runs on embedded PostgreSQL, so a new app needs no database
32
- server and no connection string. The generated `.env` sets
33
- `FD_DATABASE_ADAPTER=pglite` and one fresh base64 encoded 32 byte key per
34
- secret: `FD_AGENT_CREDENTIAL_KEY`, `FD_AGENT_RUN_GRANT_KEY`,
35
- `FD_WORKFLOWS_PAYLOAD_KEY`, `FD_WORKFLOWS_CURSOR_KEY` and `FD_AUTH_MFA_KEY`. The
36
- keys differ on every run and never leave the machine.
39
+ | Included | Purpose |
40
+ | ----------------- | ---------------------------------------------------------- |
41
+ | `platform/` | Application shell and generated module composition |
42
+ | `modules/` | An example module and space for your business modules |
43
+ | `flowdular.json` | Workspace and module configuration |
44
+ | `.env` | Local database selection and freshly generated secret keys |
45
+ | Workspace scripts | Development server, type checking, tests and validation |
37
46
 
38
- The scaffolder makes no network call of its own; the only one is the package
39
- manager install, which `--no-install` skips. It collects nothing.
47
+ The generator installs dependencies and initializes Git by default. Local development uses PGlite, an embedded PostgreSQL implementation, so the default setup needs no external database server.
40
48
 
41
- ## After it finishes
49
+ ## Options
42
50
 
43
- ```bash
51
+ Pass generator flags after `--` when using `npm create`:
52
+
53
+ ```sh
54
+ npm create flowdular@latest my-app -- --no-install --no-git
44
55
  cd my-app
45
- pnpm flowdular setup quick --apply --confirm reset-local-auth
46
- pnpm dev
56
+ pnpm install
47
57
  ```
48
58
 
49
- Then open <http://localhost:4310>.
59
+ | Option | Behavior |
60
+ | ----------------------- | ------------------------------------------------------------- |
61
+ | `-t, --template <name>` | Select a template; defaults to `default` |
62
+ | `--pm pnpm` | Select the package manager supported by this template |
63
+ | `--no-install` | Generate files without installing dependencies |
64
+ | `--no-git` | Skip Git initialization and the initial commit |
65
+ | `-f, --force` | Allow a nonempty target directory; inspect its contents first |
66
+ | `-h, --help` | Show usage |
67
+ | `-v, --version` | Show the generator version |
68
+
69
+ ## Configuration and secrets
70
+
71
+ Each run generates separate random 32-byte keys for agent credentials, agent grants, workflow payloads, workflow cursors and authentication MFA. They are written to the new application's `.env`. Keep that file private and provide deployment secrets through your hosting environment.
72
+
73
+ The default adapter is `FD_DATABASE_ADAPTER=pglite`. For a hosted PostgreSQL deployment, follow the [database adapter guide](https://github.com/Flowdular/flowdular/blob/main/docs/database-adapters.md) and [configuration reference](https://github.com/Flowdular/flowdular/blob/main/docs/configuration.md).
74
+
75
+ ## Next steps
76
+
77
+ ```sh
78
+ pnpm flowdular doctor
79
+ pnpm verify
80
+ pnpm flowdular help
81
+ ```
82
+
83
+ Read the [module guide](https://github.com/Flowdular/flowdular/blob/main/docs/modules.md) to extend the application. Business modules from [Official Modules](https://github.com/Flowdular/official-modules) are installed as source through the CLI.
84
+
85
+ ## Packages and support
86
+
87
+ - [@flowdular/sdk](https://www.npmjs.com/package/@flowdular/sdk): shared platform APIs, UI and core modules.
88
+ - [flowdular](https://www.npmjs.com/package/flowdular): workspace CLI.
89
+ - [Documentation](https://github.com/Flowdular/flowdular/tree/main/docs) · [Source and issues](https://github.com/Flowdular/flowdular) · [Website](https://flowdular.com)
50
90
 
51
- `npm create` launches the generator; the generated application uses pnpm workspaces. If pnpm is missing, the generator runs the pinned pnpm version through `npm exec`. The only Flowdular dependencies published to npm are `@flowdular/sdk`, `flowdular` and `create-flowdular`. UI is available through `@flowdular/sdk/ui` and `@flowdular/sdk/ui/styles`.
91
+ Licensed under MIT. Repository documentation and source require repository access while the repositories are private.
Binary file
package/dist/bin.js CHANGED
@@ -256,15 +256,7 @@ function nextSteps(input) {
256
256
  return [
257
257
  `cd ${input.directory}`,
258
258
  ...input.installed ? [] : [`${input.packageManager} install`],
259
- runScript(
260
- input.packageManager,
261
- "flowdular",
262
- "setup",
263
- "quick",
264
- "--apply",
265
- "--confirm",
266
- "reset-local-auth"
267
- ),
259
+ runScript(input.packageManager, "flowdular", "setup"),
268
260
  runScript(input.packageManager, "dev")
269
261
  ];
270
262
  }
@@ -275,7 +267,7 @@ function renderNextSteps(input) {
275
267
  "",
276
268
  ...nextSteps(input).map((step) => ` ${step}`),
277
269
  "",
278
- `Then open ${DEV_URL} and sign in as admin@example.com.`,
270
+ `Then open ${DEV_URL} and follow the setup choice. Local demo uses admin@example.com.`,
279
271
  ""
280
272
  ].join("\n");
281
273
  }
@@ -313,20 +305,23 @@ var SECRET_KEYS = [
313
305
  function generateSecrets() {
314
306
  const secrets = {};
315
307
  for (const key of SECRET_KEYS)
316
- secrets[key] = randomBytes(32).toString("base64");
308
+ secrets[key] = randomBytes(32).toString(
309
+ key === "FD_AUTH_MFA_KEY" ? "base64url" : "base64"
310
+ );
317
311
  return secrets;
318
312
  }
319
313
  function renderEnvironmentFile(secrets) {
320
314
  return [
321
315
  "# Local configuration for this Flowdular app. Never commit it.",
322
- "# Regenerate any key with: openssl rand -base64 32",
316
+ "# Regenerate service keys with: openssl rand -base64 32",
317
+ "# For FD_AUTH_MFA_KEY use: openssl rand -hex 32",
323
318
  "",
324
319
  "# Local development runs on embedded PostgreSQL, so there is no server to",
325
320
  "# install and no connection string to configure. A deployment sets",
326
321
  "# FD_DATABASE_ADAPTER=postgresql and the FD_DATABASE_* URLs instead.",
327
322
  "FD_DATABASE_ADAPTER=pglite",
328
323
  "",
329
- "# Base64 encoded 32 byte keys, generated once for this app.",
324
+ "# 32 byte keys, generated once for this app; MFA uses base64url.",
330
325
  ...SECRET_KEYS.map((key) => `${key}=${secrets[key]}`),
331
326
  ""
332
327
  ].join("\n");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-flowdular",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "description": "Scaffold a Flowdular application: the platform, one example module and the secrets a fresh install needs.",
6
6
  "license": "MIT",
@@ -24,7 +24,8 @@
24
24
  "files": [
25
25
  "dist",
26
26
  "template",
27
- "README.md"
27
+ "README.md",
28
+ "assets"
28
29
  ],
29
30
  "engines": {
30
31
  "node": ">=22.22.2"
@@ -7,7 +7,7 @@ example module, and nothing else you have to configure.
7
7
 
8
8
  ```bash
9
9
  pnpm install
10
- pnpm flowdular setup quick --apply --confirm reset-local-auth
10
+ pnpm flowdular setup
11
11
  pnpm dev
12
12
  ```
13
13
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "./node_modules/@flowdular/contracts/schemas/project.schema.json",
2
+ "$schema": "./platform/node_modules/@flowdular/sdk/packages/contracts/schemas/project.schema.json",
3
3
  "schemaVersion": 1,
4
4
  "architectureVersion": "0.2.0",
5
5
  "specs": {
@@ -10,5 +10,10 @@
10
10
  "roots": ["modules"],
11
11
  "enabled": ["system.core", "auth.core", "example.core"]
12
12
  },
13
- "locales": ["en", "pl"]
13
+ "locales": ["en", "pl"],
14
+ "agent": {
15
+ "policy": "platform/node_modules/@flowdular/sdk/.ai/policies/capabilities.yaml",
16
+ "modelRouting": "platform/node_modules/@flowdular/sdk/.ai/policies/model-routing.yaml",
17
+ "blueprints": "platform/node_modules/@flowdular/sdk/.ai/blueprints"
18
+ }
14
19
  }
@@ -16,12 +16,12 @@
16
16
  "dependencies": {
17
17
  "octane": "0.1.51",
18
18
  "segment-state": "0.2.0",
19
- "@flowdular/sdk": "0.1.0"
19
+ "@flowdular/sdk": "0.2.1"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@tsrx/typescript-plugin": "0.3.120",
23
23
  "@types/node": "24.13.3",
24
24
  "typescript": "5.9.3",
25
- "vitest": "4.1.10"
25
+ "vitest": "4.1.11"
26
26
  }
27
27
  }
@@ -21,6 +21,6 @@
21
21
  "devDependencies": {
22
22
  "@tsrx/prettier-plugin": "0.3.120",
23
23
  "prettier": "3.6.2",
24
- "flowdular": "0.1.0"
24
+ "flowdular": "0.2.1"
25
25
  }
26
26
  }
@@ -1,6 +1,8 @@
1
1
  import {
2
2
  assertRouteConflicts,
3
3
  createModuleWebRoutes,
4
+ createApplicationRoutes,
5
+ validateApplicationPath,
4
6
  } from '@flowdular/sdk/server';
5
7
  import { resolve } from 'node:path';
6
8
  import { defineConfig, RenderRoute } from '@octanejs/vite-plugin';
@@ -16,6 +18,7 @@ import {
16
18
  import {
17
19
  composeModuleServer,
18
20
  moduleWebMounts,
21
+ applicationBasePath,
19
22
  } from './src/generated/modules.server.ts';
20
23
  import {
21
24
  createPlatformDatabaseProvider,
@@ -35,8 +38,12 @@ const workspaceRoot = resolve(import.meta.dirname, '..');
35
38
  const databases = createPlatformDatabaseProvider(
36
39
  databaseProviderConfigFromEnvironment(process.env, workspaceRoot),
37
40
  );
41
+ const configuredApplicationPath = validateApplicationPath(
42
+ process.env.FD_APPLICATION_PATH ?? applicationBasePath,
43
+ );
38
44
  const authRuntime = createAuthRuntime({
39
45
  ...authRuntimeOptionsFromEnvironment(process.env, workspaceRoot),
46
+ applicationPath: configuredApplicationPath,
40
47
  databases,
41
48
  });
42
49
 
@@ -83,22 +90,17 @@ export default defineConfig({
83
90
  middlewares: [authRuntime.middleware],
84
91
  router: {
85
92
  routes: checkedRoutes([
86
- new RenderRoute({ path: '/', entry: SHELL }),
87
- new RenderRoute({ path: '/auth', entry: SHELL }),
88
- new RenderRoute({ path: '/auth/login', entry: SHELL }),
89
- new RenderRoute({ path: '/auth/register', entry: SHELL }),
90
- new RenderRoute({ path: '/auth/forgot-password', entry: SHELL }),
91
- new RenderRoute({ path: '/auth/reset-password', entry: SHELL }),
92
- new RenderRoute({ path: '/auth/accept-invitation', entry: SHELL }),
93
- new RenderRoute({ path: '/auth/mfa', entry: SHELL }),
94
- new RenderRoute({ path: '/app', entry: SHELL }),
95
- new RenderRoute({ path: '/app/:workspace', entry: SHELL }),
96
- new RenderRoute({ path: '/app/:workspace/:view', entry: SHELL }),
93
+ ...createApplicationRoutes({
94
+ path: configuredApplicationPath,
95
+ entry: SHELL,
96
+ publicRoot: moduleWebMounts.some((site) => site.path === '/'),
97
+ }),
97
98
  ...createAuthRoutes(authRuntime),
98
99
  ...moduleCompositions.flatMap((composition) => composition.routes),
99
100
  ...createModuleWebRoutes({
100
101
  modules: moduleCompositions,
101
102
  mounts: moduleWebMounts,
103
+ applicationPath: configuredApplicationPath,
102
104
  resolveIdentity: (context) => {
103
105
  const principal = principalFromContext(context);
104
106
  return principal
@@ -110,8 +112,6 @@ export default defineConfig({
110
112
  : null;
111
113
  },
112
114
  }),
113
- new RenderRoute({ path: '/:workspace', entry: SHELL }),
114
- new RenderRoute({ path: '/:workspace/:view', entry: SHELL }),
115
115
  ]),
116
116
  },
117
117
  });
@@ -14,7 +14,7 @@
14
14
  "@octanejs/vite-plugin": "0.1.51",
15
15
  "octane": "0.1.51",
16
16
  "pg": "8.23.0",
17
- "@flowdular/sdk": "0.1.0"
17
+ "@flowdular/sdk": "0.2.1"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@octanejs/app-core": "0.0.47",
@@ -1,4 +1,4 @@
1
- import { configureApplicationRouting } from '@flowdular/sdk/client/routing';
1
+ import { configureApplicationFromPage } from '@flowdular/sdk/client/routing';
2
2
  import {
3
3
  ApplicationShell,
4
4
  activeLocale,
@@ -12,11 +12,12 @@ import {
12
12
  import type { AuthPrincipal } from '@flowdular/sdk/modules/auth';
13
13
  import { Head } from '@octanejs/seo';
14
14
  import type { RenderRouteProps } from '@octanejs/vite-plugin';
15
- import { createModuleClientContributions, applicationBasePath } from './generated/modules.client.ts';
15
+ import {
16
+ createModuleClientContributions,
17
+ applicationBasePath,
18
+ } from './generated/modules.client.ts';
16
19
  import './styles.css';
17
20
 
18
- configureApplicationRouting(applicationBasePath);
19
-
20
21
  interface AuthenticatedAppProps {
21
22
  initialUrl: string;
22
23
  principal: AuthPrincipal;
@@ -62,6 +63,7 @@ function AuthenticatedApp(props: AuthenticatedAppProps) @{
62
63
  }
63
64
 
64
65
  export function App(props?: RenderRouteProps) @{
66
+ configureApplicationFromPage(props, applicationBasePath);
65
67
  const initialUrl =
66
68
  props?.url ?? (typeof window === 'undefined' ? '/' : window.location.href);
67
69
  <Head>
@@ -1,5 +1,6 @@
1
1
  /* GENERATED by "flowdular module sync". Do not edit by hand; run
2
2
  "pnpm flowdular module sync --apply" after enabling or disabling modules. */
3
+ export const applicationBasePath = '/app';
3
4
  import type {
4
5
  ModuleClientContext,
5
6
  ModuleClientContribution,
@@ -4,6 +4,7 @@ import type {
4
4
  PlatformServerComposition,
5
5
  PlatformServerContext,
6
6
  } from '@flowdular/sdk/modules/auth/server';
7
+ import type { WebMount } from '@flowdular/sdk/server';
7
8
  import { createServerComposition as system_core } from '@flowdular/sdk/modules/system/platform';
8
9
  import { createServerComposition as example_core } from '@app/module-example/platform';
9
10
 
@@ -28,4 +29,5 @@ export function composeModuleServer(
28
29
  ];
29
30
  }
30
31
 
31
- export const moduleWebMounts = [] as const;
32
+ export const moduleWebMounts: readonly WebMount[] = [] as const;
33
+ export const applicationBasePath = '/app';