create-inox-app 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/dist/cli.js +81 -10
- package/dist/templates/ci/.gitlab-ci.yml.hbs +2 -6
- package/dist/templates/docker/docker-compose.yml.hbs +3 -3
- package/dist/templates/kustomize/overlays/{{env}}/configs/app.config.env.hbs +1 -1
- package/dist/templates/kustomize/overlays/{{env}}/configs/paradedb.config.env.hbs +1 -1
- package/dist/templates/kustomize/overlays/{{env}}/kustomization.yaml.hbs +1 -1
- package/dist/templates/presets/ai-chat-app/apps/web/lib/db/seed.ts +17 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,7 +45,10 @@ npx create-inox-app@latest my-app \
|
|
|
45
45
|
--auth better-auth \
|
|
46
46
|
--observability langfuse \
|
|
47
47
|
--environments dev,staging,production \
|
|
48
|
-
--gitlab-group
|
|
48
|
+
--gitlab-group my-group \
|
|
49
|
+
--gitlab-url https://gitlab.example.com \
|
|
50
|
+
--registry-host registry.example.com \
|
|
51
|
+
--domain-suffix apps.example.com \
|
|
49
52
|
--git \
|
|
50
53
|
--install
|
|
51
54
|
```
|
|
@@ -60,6 +63,9 @@ npx create-inox-app@latest my-app \
|
|
|
60
63
|
| `--observability <o>` | `langfuse` \| `none` |
|
|
61
64
|
| `--environments <e>` | Comma-separated: `dev,staging,production` |
|
|
62
65
|
| `--gitlab-group <g>` | GitLab group name |
|
|
66
|
+
| `--gitlab-url <url>` | GitLab instance URL |
|
|
67
|
+
| `--registry-host <host>` | Docker registry host |
|
|
68
|
+
| `--domain-suffix <suffix>` | Domain suffix for environment URLs |
|
|
63
69
|
| `--git` / `--no-git` | Initialize git repository |
|
|
64
70
|
| `--install` / `--no-install` | Install dependencies |
|
|
65
71
|
| `-y, --yes` | Accept all defaults |
|
package/dist/cli.js
CHANGED
|
@@ -6724,6 +6724,18 @@ const parseFlags = (argv$2) => {
|
|
|
6724
6724
|
flags.gitlabGroup = next;
|
|
6725
6725
|
i$2++;
|
|
6726
6726
|
break;
|
|
6727
|
+
case "--gitlab-url":
|
|
6728
|
+
flags.gitlabUrl = next;
|
|
6729
|
+
i$2++;
|
|
6730
|
+
break;
|
|
6731
|
+
case "--registry-host":
|
|
6732
|
+
flags.registryHost = next;
|
|
6733
|
+
i$2++;
|
|
6734
|
+
break;
|
|
6735
|
+
case "--domain-suffix":
|
|
6736
|
+
flags.domainSuffix = next;
|
|
6737
|
+
i$2++;
|
|
6738
|
+
break;
|
|
6727
6739
|
case "--template":
|
|
6728
6740
|
flags.template = templateEnum.parse(next);
|
|
6729
6741
|
i$2++;
|
|
@@ -6781,11 +6793,15 @@ const validateProjectName = (name) => {
|
|
|
6781
6793
|
|
|
6782
6794
|
//#endregion
|
|
6783
6795
|
//#region src/constants.ts
|
|
6784
|
-
const
|
|
6785
|
-
const
|
|
6796
|
+
const DEFAULT_REGISTRY_HOST = "registry.example.com";
|
|
6797
|
+
const DEFAULT_DOMAIN_SUFFIX = "apps.example.com";
|
|
6798
|
+
const DEFAULT_GITLAB_URL = "https://gitlab.example.com";
|
|
6786
6799
|
const DEFAULT_CONFIG = {
|
|
6787
6800
|
projectName: "my-inox-app",
|
|
6788
|
-
gitlabGroup: "
|
|
6801
|
+
gitlabGroup: "my-group",
|
|
6802
|
+
gitlabUrl: DEFAULT_GITLAB_URL,
|
|
6803
|
+
registryHost: DEFAULT_REGISTRY_HOST,
|
|
6804
|
+
domainSuffix: DEFAULT_DOMAIN_SUFFIX,
|
|
6789
6805
|
template: "ai-chat-app",
|
|
6790
6806
|
database: "postgresql-paradedb",
|
|
6791
6807
|
cache: "redis",
|
|
@@ -6805,8 +6821,8 @@ const DEFAULT_CONFIG = {
|
|
|
6805
6821
|
git: true,
|
|
6806
6822
|
install: true
|
|
6807
6823
|
};
|
|
6808
|
-
const buildRegistryImage = (group, project, appName) => `${
|
|
6809
|
-
const buildDomain = (appName, env$3) => `${appName}.${env$3}.${
|
|
6824
|
+
const buildRegistryImage = (registryHost, group, project, appName) => `${registryHost}/${group}/${project}/${appName}-web`;
|
|
6825
|
+
const buildDomain = (appName, env$3, domainSuffix) => `${appName}.${env$3}.${domainSuffix}`;
|
|
6810
6826
|
|
|
6811
6827
|
//#endregion
|
|
6812
6828
|
//#region src/utils/navigation.ts
|
|
@@ -6925,8 +6941,41 @@ const promptProjectName = (isFirst) => {
|
|
|
6925
6941
|
const promptGitlabGroup = () => {
|
|
6926
6942
|
return navigableText({
|
|
6927
6943
|
message: "What is the GitLab group?",
|
|
6928
|
-
placeholder: "
|
|
6929
|
-
defaultValue: "
|
|
6944
|
+
placeholder: "my-group",
|
|
6945
|
+
defaultValue: "my-group",
|
|
6946
|
+
isFirstPrompt: false
|
|
6947
|
+
});
|
|
6948
|
+
};
|
|
6949
|
+
|
|
6950
|
+
//#endregion
|
|
6951
|
+
//#region src/prompts/gitlab-url.ts
|
|
6952
|
+
const promptGitlabUrl = () => {
|
|
6953
|
+
return navigableText({
|
|
6954
|
+
message: "GitLab instance URL?",
|
|
6955
|
+
placeholder: "https://gitlab.example.com",
|
|
6956
|
+
defaultValue: "https://gitlab.example.com",
|
|
6957
|
+
isFirstPrompt: false
|
|
6958
|
+
});
|
|
6959
|
+
};
|
|
6960
|
+
|
|
6961
|
+
//#endregion
|
|
6962
|
+
//#region src/prompts/registry-host.ts
|
|
6963
|
+
const promptRegistryHost = () => {
|
|
6964
|
+
return navigableText({
|
|
6965
|
+
message: "Docker registry host?",
|
|
6966
|
+
placeholder: "registry.example.com",
|
|
6967
|
+
defaultValue: "registry.example.com",
|
|
6968
|
+
isFirstPrompt: false
|
|
6969
|
+
});
|
|
6970
|
+
};
|
|
6971
|
+
|
|
6972
|
+
//#endregion
|
|
6973
|
+
//#region src/prompts/domain-suffix.ts
|
|
6974
|
+
const promptDomainSuffix = () => {
|
|
6975
|
+
return navigableText({
|
|
6976
|
+
message: "Domain suffix for environments?",
|
|
6977
|
+
placeholder: "apps.example.com",
|
|
6978
|
+
defaultValue: "apps.example.com",
|
|
6930
6979
|
isFirstPrompt: false
|
|
6931
6980
|
});
|
|
6932
6981
|
};
|
|
@@ -7141,6 +7190,9 @@ const gatherConfig = async (flags) => {
|
|
|
7141
7190
|
...DEFAULT_CONFIG,
|
|
7142
7191
|
projectName: name,
|
|
7143
7192
|
gitlabGroup: flags.gitlabGroup ?? DEFAULT_CONFIG.gitlabGroup,
|
|
7193
|
+
gitlabUrl: flags.gitlabUrl ?? DEFAULT_CONFIG.gitlabUrl,
|
|
7194
|
+
registryHost: flags.registryHost ?? DEFAULT_CONFIG.registryHost,
|
|
7195
|
+
domainSuffix: flags.domainSuffix ?? DEFAULT_CONFIG.domainSuffix,
|
|
7144
7196
|
template: flags.template ?? DEFAULT_CONFIG.template,
|
|
7145
7197
|
database: flags.database ?? DEFAULT_CONFIG.database,
|
|
7146
7198
|
cache: flags.cache ?? DEFAULT_CONFIG.cache,
|
|
@@ -7161,6 +7213,18 @@ const gatherConfig = async (flags) => {
|
|
|
7161
7213
|
key: "gitlabGroup",
|
|
7162
7214
|
fn: () => flags.gitlabGroup ?? promptGitlabGroup()
|
|
7163
7215
|
},
|
|
7216
|
+
{
|
|
7217
|
+
key: "gitlabUrl",
|
|
7218
|
+
fn: () => flags.gitlabUrl ?? promptGitlabUrl()
|
|
7219
|
+
},
|
|
7220
|
+
{
|
|
7221
|
+
key: "registryHost",
|
|
7222
|
+
fn: () => flags.registryHost ?? promptRegistryHost()
|
|
7223
|
+
},
|
|
7224
|
+
{
|
|
7225
|
+
key: "domainSuffix",
|
|
7226
|
+
fn: () => flags.domainSuffix ?? promptDomainSuffix()
|
|
7227
|
+
},
|
|
7164
7228
|
{
|
|
7165
7229
|
key: "template",
|
|
7166
7230
|
fn: () => flags.template ?? promptTemplate()
|
|
@@ -7214,6 +7278,9 @@ const gatherConfig = async (flags) => {
|
|
|
7214
7278
|
return {
|
|
7215
7279
|
projectName,
|
|
7216
7280
|
gitlabGroup: results.gitlabGroup ?? DEFAULT_CONFIG.gitlabGroup,
|
|
7281
|
+
gitlabUrl: results.gitlabUrl ?? DEFAULT_CONFIG.gitlabUrl,
|
|
7282
|
+
registryHost: results.registryHost ?? DEFAULT_CONFIG.registryHost,
|
|
7283
|
+
domainSuffix: results.domainSuffix ?? DEFAULT_CONFIG.domainSuffix,
|
|
7217
7284
|
template: results.template ?? DEFAULT_CONFIG.template,
|
|
7218
7285
|
database: results.database ?? DEFAULT_CONFIG.database,
|
|
7219
7286
|
cache: results.cache ?? DEFAULT_CONFIG.cache,
|
|
@@ -7232,7 +7299,7 @@ const gatherConfig = async (flags) => {
|
|
|
7232
7299
|
const buildTemplateContext = (config) => {
|
|
7233
7300
|
const environments = config.environments.map((env$3, i$2) => ({
|
|
7234
7301
|
name: env$3,
|
|
7235
|
-
domain: buildDomain(config.projectName, env$3),
|
|
7302
|
+
domain: buildDomain(config.projectName, env$3, config.domainSuffix),
|
|
7236
7303
|
isFirst: i$2 === 0,
|
|
7237
7304
|
isLast: i$2 === config.environments.length - 1
|
|
7238
7305
|
}));
|
|
@@ -7240,11 +7307,12 @@ const buildTemplateContext = (config) => {
|
|
|
7240
7307
|
projectName: config.projectName,
|
|
7241
7308
|
appName: config.projectName,
|
|
7242
7309
|
gitlabGroup: config.gitlabGroup,
|
|
7243
|
-
|
|
7310
|
+
gitlabUrl: config.gitlabUrl,
|
|
7311
|
+
registryImage: buildRegistryImage(config.registryHost, config.gitlabGroup, config.projectName, config.projectName),
|
|
7244
7312
|
hasDatabase: config.database !== "none",
|
|
7245
7313
|
isParadedb: config.database === "postgresql-paradedb",
|
|
7246
7314
|
hasRedis: config.cache === "redis",
|
|
7247
|
-
hasAuth: config.auth
|
|
7315
|
+
hasAuth: config.auth !== "none",
|
|
7248
7316
|
hasLangfuse: config.observability === "langfuse",
|
|
7249
7317
|
hasIngress: config.addons.includes("ingress"),
|
|
7250
7318
|
hasTls: config.addons.includes("tls"),
|
|
@@ -22140,6 +22208,9 @@ const buildReproducibleCmd = (config) => {
|
|
|
22140
22208
|
const parts = ["bunx create-inox-app"];
|
|
22141
22209
|
parts.push(`--name ${config.projectName}`);
|
|
22142
22210
|
if (config.gitlabGroup !== DEFAULT_CONFIG.gitlabGroup) parts.push(`--gitlab-group ${config.gitlabGroup}`);
|
|
22211
|
+
if (config.gitlabUrl !== DEFAULT_CONFIG.gitlabUrl) parts.push(`--gitlab-url ${config.gitlabUrl}`);
|
|
22212
|
+
if (config.registryHost !== DEFAULT_CONFIG.registryHost) parts.push(`--registry-host ${config.registryHost}`);
|
|
22213
|
+
if (config.domainSuffix !== DEFAULT_CONFIG.domainSuffix) parts.push(`--domain-suffix ${config.domainSuffix}`);
|
|
22143
22214
|
parts.push(`--template ${config.template}`);
|
|
22144
22215
|
if (config.database !== "none") parts.push(`--database ${config.database}`);
|
|
22145
22216
|
else parts.push("--database none");
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
include:
|
|
2
|
-
- project: "gitlab-ci/gitlab-ci-templates"
|
|
3
|
-
ref: main
|
|
4
|
-
file: "/deploy-v2/.gitlab-ci.yml"
|
|
5
|
-
|
|
6
1
|
stages:
|
|
7
2
|
- validate
|
|
8
3
|
- build
|
|
@@ -66,5 +61,6 @@ deploy:{{this.name}}:
|
|
|
66
61
|
PATCH_IMAGE_TAG: build-$CI_COMMIT_SHORT_SHA
|
|
67
62
|
environment:
|
|
68
63
|
name: {{this.name}}
|
|
69
|
-
|
|
64
|
+
script:
|
|
65
|
+
- echo "Deploy to {{this.name}} — configure your deployment pipeline here"
|
|
70
66
|
{{/each}}
|
|
@@ -31,9 +31,9 @@ services:
|
|
|
31
31
|
profiles: [dev, prod]
|
|
32
32
|
image: paradedb/paradedb:latest
|
|
33
33
|
environment:
|
|
34
|
-
POSTGRES_USER:
|
|
35
|
-
POSTGRES_PASSWORD:
|
|
36
|
-
POSTGRES_DB:
|
|
34
|
+
POSTGRES_USER: postgres
|
|
35
|
+
POSTGRES_PASSWORD: changeme
|
|
36
|
+
POSTGRES_DB: {{appName}}
|
|
37
37
|
ports:
|
|
38
38
|
- "5432:5432"
|
|
39
39
|
volumes:
|
|
@@ -2,7 +2,7 @@ NODE_ENV=production
|
|
|
2
2
|
APP_URL=https://{{currentEnv.domain}}
|
|
3
3
|
SOURCE_VERSION=dev
|
|
4
4
|
{{#if hasDatabase}}
|
|
5
|
-
DATABASE_URL=postgresql://postgres:
|
|
5
|
+
DATABASE_URL=postgresql://postgres:CHANGE_ME@paradedb:5432/{{appName}}
|
|
6
6
|
{{/if}}
|
|
7
7
|
{{#if hasRedis}}
|
|
8
8
|
REDIS_URL=redis://redis:6379
|
|
@@ -2,7 +2,7 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
|
|
2
2
|
kind: Kustomization
|
|
3
3
|
|
|
4
4
|
resources:
|
|
5
|
-
-
|
|
5
|
+
- {{gitlabUrl}}/{{gitlabGroup}}/{{projectName}}/kustomize/base//?ref=main
|
|
6
6
|
{{#if isParadedb}}
|
|
7
7
|
- storage/paradedb-pvc.yaml
|
|
8
8
|
- deployments/paradedb.yaml
|
|
@@ -7,32 +7,24 @@ import * as schema from "./schema";
|
|
|
7
7
|
|
|
8
8
|
const DATABASE_URL = process.env.DATABASE_URL;
|
|
9
9
|
const SEED_EMAILS = process.env.SEED_EMAILS;
|
|
10
|
-
const SEED_PASSWORD =
|
|
10
|
+
const SEED_PASSWORD = process.env.SEED_PASSWORD;
|
|
11
|
+
const BETTER_AUTH_SECRET = process.env.BETTER_AUTH_SECRET;
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
process.stderr.write(
|
|
14
|
-
JSON.stringify({
|
|
15
|
-
timestamp: new Date().toISOString(),
|
|
16
|
-
level: "error",
|
|
17
|
-
event: "db:seed",
|
|
18
|
-
outcome: "failure",
|
|
19
|
-
error: "DATABASE_URL is not set",
|
|
20
|
-
}) + "\n",
|
|
21
|
-
);
|
|
22
|
-
process.exit(1);
|
|
23
|
-
}
|
|
13
|
+
const requiredEnvVars = { DATABASE_URL, SEED_EMAILS, SEED_PASSWORD, BETTER_AUTH_SECRET };
|
|
24
14
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
15
|
+
for (const [name, value] of Object.entries(requiredEnvVars)) {
|
|
16
|
+
if (!value) {
|
|
17
|
+
process.stderr.write(
|
|
18
|
+
JSON.stringify({
|
|
19
|
+
timestamp: new Date().toISOString(),
|
|
20
|
+
level: "error",
|
|
21
|
+
event: "db:seed",
|
|
22
|
+
outcome: "failure",
|
|
23
|
+
error: `${name} is not set`,
|
|
24
|
+
}) + "\n",
|
|
25
|
+
);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
36
28
|
}
|
|
37
29
|
|
|
38
30
|
function deriveName(email: string): string {
|
|
@@ -51,7 +43,7 @@ try {
|
|
|
51
43
|
|
|
52
44
|
const auth = betterAuth({
|
|
53
45
|
database: drizzleAdapter(db, { provider: "pg", schema }),
|
|
54
|
-
secret:
|
|
46
|
+
secret: BETTER_AUTH_SECRET!,
|
|
55
47
|
baseURL: process.env.BETTER_AUTH_URL ?? "http://localhost:3000",
|
|
56
48
|
emailAndPassword: { enabled: true },
|
|
57
49
|
});
|