@getstrata/starter 1.0.8 → 1.0.9
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/dist/cli.js +77 -24
- package/dist/templates/package.json +3 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1702,11 +1702,13 @@ function renderSiteModule(_layers) {
|
|
|
1702
1702
|
import { withErrorHandling } from "@getstrata/core/http/response";
|
|
1703
1703
|
import { getSql, pingDatabase } from "../../bootstrap/database.ts";
|
|
1704
1704
|
import { plainText, renderPage } from "../../lib/view.ts";
|
|
1705
|
+
import { Note } from "../../models/Note.ts";
|
|
1705
1706
|
|
|
1706
1707
|
// Proves the database answers and the schema is migrated. Point it at a table your app owns.
|
|
1707
1708
|
async function schemaReady(): Promise<boolean> {
|
|
1708
1709
|
try {
|
|
1709
|
-
|
|
1710
|
+
getSql();
|
|
1711
|
+
await Note.query().value("id");
|
|
1710
1712
|
return true;
|
|
1711
1713
|
} catch {
|
|
1712
1714
|
return false;
|
|
@@ -2529,9 +2531,9 @@ function renderPackageJson(projectName, options = {}) {
|
|
|
2529
2531
|
"@getstrata/cli": "workspace:*",
|
|
2530
2532
|
"@getstrata/core": "workspace:*"
|
|
2531
2533
|
} : {
|
|
2532
|
-
"@getstrata/bootstrap": "^1.0.
|
|
2533
|
-
"@getstrata/cli": "^1.0.
|
|
2534
|
-
"@getstrata/core": "^1.0.
|
|
2534
|
+
"@getstrata/bootstrap": "^1.0.9",
|
|
2535
|
+
"@getstrata/cli": "^1.0.9",
|
|
2536
|
+
"@getstrata/core": "^1.0.9"
|
|
2535
2537
|
};
|
|
2536
2538
|
coreDeps.eta = "^4.6.0";
|
|
2537
2539
|
if (options.layers?.database === "mysql") {
|
|
@@ -2666,7 +2668,7 @@ Create a module under \`src/modules/\` and return a route map. Modules are disco
|
|
|
2666
2668
|
// src/modules/notes/index.ts
|
|
2667
2669
|
import type { AppModule } from "@getstrata/bootstrap/contracts";
|
|
2668
2670
|
import { jsonResponse } from "@getstrata/core/http/response";
|
|
2669
|
-
import {
|
|
2671
|
+
import { Note } from "../../models/Note.ts";
|
|
2670
2672
|
|
|
2671
2673
|
const notesModule: AppModule = {
|
|
2672
2674
|
name: "notes",
|
|
@@ -2674,10 +2676,8 @@ const notesModule: AppModule = {
|
|
|
2674
2676
|
routes({ kernel }) {
|
|
2675
2677
|
return {
|
|
2676
2678
|
"/api/v1/notes": kernel.wrap("api", async () => {
|
|
2677
|
-
const
|
|
2678
|
-
|
|
2679
|
-
);
|
|
2680
|
-
return jsonResponse({ data: rows });
|
|
2679
|
+
const bodiesById = await Note.query().orderBy({ id: "desc" }).pluck("body", "id");
|
|
2680
|
+
return jsonResponse({ data: Object.fromEntries(bodiesById) });
|
|
2681
2681
|
}),
|
|
2682
2682
|
};
|
|
2683
2683
|
},
|
|
@@ -2695,7 +2695,25 @@ Import from \`@getstrata/core/...\` subpaths rather than the package root, so si
|
|
|
2695
2695
|
- [Databases](https://github.com/EyK-26/strata/blob/main/docs/DATABASE.md)
|
|
2696
2696
|
`;
|
|
2697
2697
|
}
|
|
2698
|
-
function
|
|
2698
|
+
function renderReadmeIntro(projectName, options) {
|
|
2699
|
+
if (options.dogfood) {
|
|
2700
|
+
return `# ${projectName}
|
|
2701
|
+
|
|
2702
|
+
This in-repo app is Strata dogfood for internal end-to-end testing (migrate, seed, boot, OpenAPI, smoke). It is not a product. Start a product app with \`bunx create-strata\`.
|
|
2703
|
+
`;
|
|
2704
|
+
}
|
|
2705
|
+
if (options.inRepoExample) {
|
|
2706
|
+
return `# ${projectName}
|
|
2707
|
+
|
|
2708
|
+
This in-repo app is a generated sibling layer map. It is not a product and it is not CI dogfood. CI dogfood is \`apps/hiroapp\`. Start a product app with \`bunx create-strata\`.
|
|
2709
|
+
`;
|
|
2710
|
+
}
|
|
2711
|
+
return `# ${projectName}
|
|
2712
|
+
|
|
2713
|
+
Strata app generated by \`create-strata\`.
|
|
2714
|
+
`;
|
|
2715
|
+
}
|
|
2716
|
+
function renderReadme(projectName, layers, options = {}) {
|
|
2699
2717
|
const docker = renderDockerCompose(projectName, layers);
|
|
2700
2718
|
const next = [`cd ${projectName}`, "cp .env.example .env"];
|
|
2701
2719
|
if (docker) {
|
|
@@ -2710,10 +2728,7 @@ function renderReadme(projectName, layers) {
|
|
|
2710
2728
|
const dockerServices = selectedDockerServices(layers);
|
|
2711
2729
|
const neededTools = neededDockerServices(layers);
|
|
2712
2730
|
const dockerLabel = neededTools.length === 0 ? "not needed" : dockerServices.length > 0 ? dockerServices.join(", ") : "off (local installs)";
|
|
2713
|
-
return
|
|
2714
|
-
|
|
2715
|
-
Strata app generated by \`create-strata\`.
|
|
2716
|
-
|
|
2731
|
+
return `${renderReadmeIntro(projectName, options)}
|
|
2717
2732
|
## Layers
|
|
2718
2733
|
|
|
2719
2734
|
| Layer | Choice |
|
|
@@ -3089,7 +3104,6 @@ function renderMigrateTs(layers) {
|
|
|
3089
3104
|
const list = statements.map((sql) => ` \`${sql}\`,`).join(`
|
|
3090
3105
|
`);
|
|
3091
3106
|
const ph = layers.database === "postgres";
|
|
3092
|
-
const notePlaceholder = ph ? "$1" : "?";
|
|
3093
3107
|
const verifyOn = layers.extras.emailVerification && authNeedsUsers(layers.auth);
|
|
3094
3108
|
const userColumns = verifyOn ? "name, email, password, is_admin, email_verified_at" : "name, email, password, is_admin";
|
|
3095
3109
|
const userPlaceholders = verifyOn ? ph ? "$1, $2, $3, $4, $5), ($6, $7, $8, $9, $10" : "?, ?, ?, ?, ?), (?, ?, ?, ?, ?" : ph ? "$1, $2, $3, $4), ($5, $6, $7, $8" : "?, ?, ?, ?), (?, ?, ?, ?";
|
|
@@ -3121,21 +3135,19 @@ function renderMigrateTs(layers) {
|
|
|
3121
3135
|
const hashImport = authNeedsUsers(layers.auth) ? `import { hashPassword } from "@getstrata/core/auth/password";
|
|
3122
3136
|
` : "";
|
|
3123
3137
|
const seedBlock = `${seedTenant}${seedUsers}`;
|
|
3138
|
+
const bindSql = seedBlock.length > 0 ? ` const sql = getSql();
|
|
3139
|
+
` : ` getSql();
|
|
3140
|
+
`;
|
|
3124
3141
|
return `${hashImport}${ensureImport(layers)}import { closeDatabase, getSql } from "../bootstrap/database.ts";
|
|
3142
|
+
import { Note } from "../models/Note.ts";
|
|
3125
3143
|
|
|
3126
3144
|
const migrations = [
|
|
3127
3145
|
${list}
|
|
3128
3146
|
];
|
|
3129
3147
|
|
|
3130
3148
|
export async function seed() {
|
|
3131
|
-
${ensureCall(layers)}
|
|
3132
|
-
|
|
3133
|
-
"SELECT COUNT(*) AS count FROM notes",
|
|
3134
|
-
);
|
|
3135
|
-
if (Number(count) === 0) {
|
|
3136
|
-
await sql.unsafe("INSERT INTO notes (body) VALUES (${notePlaceholder})", [
|
|
3137
|
-
"Welcome to Strata!",
|
|
3138
|
-
]);
|
|
3149
|
+
${ensureCall(layers)}${bindSql} if ((await Note.query().value("id")) === null) {
|
|
3150
|
+
await Note.create({ body: "Welcome to Strata!" });
|
|
3139
3151
|
}${seedBlock}
|
|
3140
3152
|
}
|
|
3141
3153
|
|
|
@@ -3160,6 +3172,43 @@ if (import.meta.main) {
|
|
|
3160
3172
|
}
|
|
3161
3173
|
`;
|
|
3162
3174
|
}
|
|
3175
|
+
function renderNoteModel() {
|
|
3176
|
+
return `import { BaseRepository } from "@getstrata/core/database/baseRepository";
|
|
3177
|
+
import { Model, registerModelRepository } from "@getstrata/core/database/model";
|
|
3178
|
+
import { defineTable } from "@getstrata/core/database/table";
|
|
3179
|
+
|
|
3180
|
+
interface NoteRecord {
|
|
3181
|
+
id: number;
|
|
3182
|
+
body: string;
|
|
3183
|
+
created_at: Date | string;
|
|
3184
|
+
}
|
|
3185
|
+
|
|
3186
|
+
const notesTable = defineTable<NoteRecord, "id">({
|
|
3187
|
+
name: "notes",
|
|
3188
|
+
primaryKey: "id",
|
|
3189
|
+
columns: ["id", "body", "created_at"],
|
|
3190
|
+
defaultOrderBy: { column: "id", direction: "ASC" },
|
|
3191
|
+
});
|
|
3192
|
+
|
|
3193
|
+
class NoteRepository extends BaseRepository<NoteRecord, "id"> {
|
|
3194
|
+
constructor() {
|
|
3195
|
+
super(notesTable);
|
|
3196
|
+
}
|
|
3197
|
+
}
|
|
3198
|
+
|
|
3199
|
+
class Note extends Model<NoteRecord, "id"> {
|
|
3200
|
+
static $fillable = ["body"] as const;
|
|
3201
|
+
// created_at uses the table default. Sending a JS Date from $timestamps
|
|
3202
|
+
// is rejected by SQLite bindings.
|
|
3203
|
+
static $timestamps = false;
|
|
3204
|
+
}
|
|
3205
|
+
|
|
3206
|
+
registerModelRepository(Note, new NoteRepository());
|
|
3207
|
+
|
|
3208
|
+
export type { NoteRecord };
|
|
3209
|
+
export { Note };
|
|
3210
|
+
`;
|
|
3211
|
+
}
|
|
3163
3212
|
function dropTables(layers) {
|
|
3164
3213
|
const ordered = [];
|
|
3165
3214
|
if (authUsesToken(layers.auth)) {
|
|
@@ -4064,7 +4113,10 @@ function writeGeneratedFiles(options) {
|
|
|
4064
4113
|
writeText(join2(targetDir, ".env.example"), renderEnvExample(projectName, layers));
|
|
4065
4114
|
writeText(join2(targetDir, ".gitignore"), renderGitignore());
|
|
4066
4115
|
writeText(join2(targetDir, "package.json"), renderPackageJson(projectName, { ...options, layers }));
|
|
4067
|
-
writeText(join2(targetDir, "README.md"), renderReadme(projectName, layers
|
|
4116
|
+
writeText(join2(targetDir, "README.md"), renderReadme(projectName, layers, {
|
|
4117
|
+
inRepoExample: options.inRepoExample,
|
|
4118
|
+
dogfood: options.dogfood
|
|
4119
|
+
}));
|
|
4068
4120
|
if (layers.frontend === "api") {
|
|
4069
4121
|
writeText(join2(targetDir, "docs/API.md"), renderApiDocs(projectName, layers));
|
|
4070
4122
|
} else {
|
|
@@ -4095,6 +4147,7 @@ function writeGeneratedFiles(options) {
|
|
|
4095
4147
|
writeText(join2(src, "bootstrap/providers/queue.ts"), renderQueueProvider());
|
|
4096
4148
|
writeText(join2(src, "bootstrap/providers/index.ts"), renderProvidersIndex());
|
|
4097
4149
|
writeText(join2(src, "bootstrap/providers/auth.ts"), renderAuthProvider(layers));
|
|
4150
|
+
writeText(join2(src, "models/Note.ts"), renderNoteModel());
|
|
4098
4151
|
writeText(join2(src, "db/migrate.ts"), renderMigrateTs(layers));
|
|
4099
4152
|
writeText(join2(src, "db/fresh.ts"), renderFreshTs(layers));
|
|
4100
4153
|
writeText(join2(src, "db/seed.ts"), renderSeedTs());
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
"check": "tsc --noEmit"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@getstrata/bootstrap": "^1.0.
|
|
15
|
-
"@getstrata/cli": "^1.0.
|
|
16
|
-
"@getstrata/core": "^1.0.
|
|
14
|
+
"@getstrata/bootstrap": "^1.0.9",
|
|
15
|
+
"@getstrata/cli": "^1.0.9",
|
|
16
|
+
"@getstrata/core": "^1.0.9",
|
|
17
17
|
"eta": "^4.6.0"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|