create-inox-app 0.2.3 → 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 +90 -22
- 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
|
@@ -3087,13 +3087,10 @@ const TITLE_TEXT = `
|
|
|
3087
3087
|
╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝
|
|
3088
3088
|
`;
|
|
3089
3089
|
const INOX_THEME = {
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
lime: "#84CC16",
|
|
3095
|
-
yellow: "#EAB308",
|
|
3096
|
-
orange: "#F97316"
|
|
3090
|
+
red: "#D20000",
|
|
3091
|
+
warmRed: "#E83600",
|
|
3092
|
+
orange: "#F06800",
|
|
3093
|
+
amber: "#F59E0B"
|
|
3097
3094
|
};
|
|
3098
3095
|
const renderTitle = () => {
|
|
3099
3096
|
const cols = process.stdout.columns ?? 80;
|
|
@@ -6727,6 +6724,18 @@ const parseFlags = (argv$2) => {
|
|
|
6727
6724
|
flags.gitlabGroup = next;
|
|
6728
6725
|
i$2++;
|
|
6729
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;
|
|
6730
6739
|
case "--template":
|
|
6731
6740
|
flags.template = templateEnum.parse(next);
|
|
6732
6741
|
i$2++;
|
|
@@ -6784,11 +6793,15 @@ const validateProjectName = (name) => {
|
|
|
6784
6793
|
|
|
6785
6794
|
//#endregion
|
|
6786
6795
|
//#region src/constants.ts
|
|
6787
|
-
const
|
|
6788
|
-
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";
|
|
6789
6799
|
const DEFAULT_CONFIG = {
|
|
6790
6800
|
projectName: "my-inox-app",
|
|
6791
|
-
gitlabGroup: "
|
|
6801
|
+
gitlabGroup: "my-group",
|
|
6802
|
+
gitlabUrl: DEFAULT_GITLAB_URL,
|
|
6803
|
+
registryHost: DEFAULT_REGISTRY_HOST,
|
|
6804
|
+
domainSuffix: DEFAULT_DOMAIN_SUFFIX,
|
|
6792
6805
|
template: "ai-chat-app",
|
|
6793
6806
|
database: "postgresql-paradedb",
|
|
6794
6807
|
cache: "redis",
|
|
@@ -6808,8 +6821,8 @@ const DEFAULT_CONFIG = {
|
|
|
6808
6821
|
git: true,
|
|
6809
6822
|
install: true
|
|
6810
6823
|
};
|
|
6811
|
-
const buildRegistryImage = (group, project, appName) => `${
|
|
6812
|
-
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}`;
|
|
6813
6826
|
|
|
6814
6827
|
//#endregion
|
|
6815
6828
|
//#region src/utils/navigation.ts
|
|
@@ -6844,7 +6857,7 @@ const navigableGroup = async (steps) => {
|
|
|
6844
6857
|
const prevIndex = shownSteps.pop();
|
|
6845
6858
|
delete results[steps[prevIndex].key];
|
|
6846
6859
|
i$2 = prevIndex;
|
|
6847
|
-
}
|
|
6860
|
+
} else throw new UserCancelledError();
|
|
6848
6861
|
continue;
|
|
6849
6862
|
}
|
|
6850
6863
|
if (isCancel(result)) throw new UserCancelledError();
|
|
@@ -6928,8 +6941,41 @@ const promptProjectName = (isFirst) => {
|
|
|
6928
6941
|
const promptGitlabGroup = () => {
|
|
6929
6942
|
return navigableText({
|
|
6930
6943
|
message: "What is the GitLab group?",
|
|
6931
|
-
placeholder: "
|
|
6932
|
-
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",
|
|
6933
6979
|
isFirstPrompt: false
|
|
6934
6980
|
});
|
|
6935
6981
|
};
|
|
@@ -7144,6 +7190,9 @@ const gatherConfig = async (flags) => {
|
|
|
7144
7190
|
...DEFAULT_CONFIG,
|
|
7145
7191
|
projectName: name,
|
|
7146
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,
|
|
7147
7196
|
template: flags.template ?? DEFAULT_CONFIG.template,
|
|
7148
7197
|
database: flags.database ?? DEFAULT_CONFIG.database,
|
|
7149
7198
|
cache: flags.cache ?? DEFAULT_CONFIG.cache,
|
|
@@ -7164,6 +7213,18 @@ const gatherConfig = async (flags) => {
|
|
|
7164
7213
|
key: "gitlabGroup",
|
|
7165
7214
|
fn: () => flags.gitlabGroup ?? promptGitlabGroup()
|
|
7166
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
|
+
},
|
|
7167
7228
|
{
|
|
7168
7229
|
key: "template",
|
|
7169
7230
|
fn: () => flags.template ?? promptTemplate()
|
|
@@ -7217,6 +7278,9 @@ const gatherConfig = async (flags) => {
|
|
|
7217
7278
|
return {
|
|
7218
7279
|
projectName,
|
|
7219
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,
|
|
7220
7284
|
template: results.template ?? DEFAULT_CONFIG.template,
|
|
7221
7285
|
database: results.database ?? DEFAULT_CONFIG.database,
|
|
7222
7286
|
cache: results.cache ?? DEFAULT_CONFIG.cache,
|
|
@@ -7235,7 +7299,7 @@ const gatherConfig = async (flags) => {
|
|
|
7235
7299
|
const buildTemplateContext = (config) => {
|
|
7236
7300
|
const environments = config.environments.map((env$3, i$2) => ({
|
|
7237
7301
|
name: env$3,
|
|
7238
|
-
domain: buildDomain(config.projectName, env$3),
|
|
7302
|
+
domain: buildDomain(config.projectName, env$3, config.domainSuffix),
|
|
7239
7303
|
isFirst: i$2 === 0,
|
|
7240
7304
|
isLast: i$2 === config.environments.length - 1
|
|
7241
7305
|
}));
|
|
@@ -7243,11 +7307,12 @@ const buildTemplateContext = (config) => {
|
|
|
7243
7307
|
projectName: config.projectName,
|
|
7244
7308
|
appName: config.projectName,
|
|
7245
7309
|
gitlabGroup: config.gitlabGroup,
|
|
7246
|
-
|
|
7310
|
+
gitlabUrl: config.gitlabUrl,
|
|
7311
|
+
registryImage: buildRegistryImage(config.registryHost, config.gitlabGroup, config.projectName, config.projectName),
|
|
7247
7312
|
hasDatabase: config.database !== "none",
|
|
7248
7313
|
isParadedb: config.database === "postgresql-paradedb",
|
|
7249
7314
|
hasRedis: config.cache === "redis",
|
|
7250
|
-
hasAuth: config.auth
|
|
7315
|
+
hasAuth: config.auth !== "none",
|
|
7251
7316
|
hasLangfuse: config.observability === "langfuse",
|
|
7252
7317
|
hasIngress: config.addons.includes("ingress"),
|
|
7253
7318
|
hasTls: config.addons.includes("tls"),
|
|
@@ -22131,9 +22196,9 @@ const printPostInstall = (config) => {
|
|
|
22131
22196
|
} else if (config.cache === "redis") steps.push("docker compose --profile dev up -d redis");
|
|
22132
22197
|
steps.push("bun run dev");
|
|
22133
22198
|
consola.box({
|
|
22134
|
-
title: import_picocolors$1.default.bold(import_picocolors$1.default.
|
|
22199
|
+
title: import_picocolors$1.default.bold(import_picocolors$1.default.red("Next steps")),
|
|
22135
22200
|
message: steps.map((s$1) => import_picocolors$1.default.cyan(s$1)).join("\n"),
|
|
22136
|
-
style: { borderColor: "
|
|
22201
|
+
style: { borderColor: "red" }
|
|
22137
22202
|
});
|
|
22138
22203
|
};
|
|
22139
22204
|
|
|
@@ -22143,6 +22208,9 @@ const buildReproducibleCmd = (config) => {
|
|
|
22143
22208
|
const parts = ["bunx create-inox-app"];
|
|
22144
22209
|
parts.push(`--name ${config.projectName}`);
|
|
22145
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}`);
|
|
22146
22214
|
parts.push(`--template ${config.template}`);
|
|
22147
22215
|
if (config.database !== "none") parts.push(`--database ${config.database}`);
|
|
22148
22216
|
else parts.push("--database none");
|
|
@@ -22168,7 +22236,7 @@ const createInoxCli = async () => {
|
|
|
22168
22236
|
return;
|
|
22169
22237
|
}
|
|
22170
22238
|
renderTitle();
|
|
22171
|
-
Ie(import_picocolors.default.
|
|
22239
|
+
Ie(import_picocolors.default.red("Create a new Inox project"));
|
|
22172
22240
|
try {
|
|
22173
22241
|
const config = await gatherConfig(flags);
|
|
22174
22242
|
M.info([
|
|
@@ -22186,7 +22254,7 @@ const createInoxCli = async () => {
|
|
|
22186
22254
|
].join("\n"));
|
|
22187
22255
|
await scaffold(config);
|
|
22188
22256
|
M.info(import_picocolors.default.dim(buildReproducibleCmd(config)));
|
|
22189
|
-
Se(import_picocolors.default.
|
|
22257
|
+
Se(import_picocolors.default.red("Happy building!"));
|
|
22190
22258
|
printPostInstall(config);
|
|
22191
22259
|
} catch (err) {
|
|
22192
22260
|
if (err instanceof UserCancelledError) {
|
|
@@ -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
|
});
|