@getstrata/starter 2.0.8 → 2.1.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/dist/cli.js CHANGED
@@ -2337,7 +2337,6 @@ function renderHomeView(projectName, layers) {
2337
2337
  <a class="button" href="/register">Create account</a>
2338
2338
  <a class="button button-secondary" href="/login">Sign in</a>
2339
2339
  </div>
2340
- <p class="muted">Seeded demo: <code>demo@example.com</code> / <code>StrataDemo!ChangeMe</code>.</p>
2341
2340
  <% } else { %>
2342
2341
  <p class="lede">You are signed in as <strong><%= it.currentUser.email %></strong>.</p>
2343
2342
  <p>Add routes in <code>src/modules</code>. This homepage is yours to restyle.</p>
@@ -3192,9 +3191,9 @@ function renderPackageJson(projectName, options = {}) {
3192
3191
  "@getstrata/cli": "workspace:*",
3193
3192
  "@getstrata/core": "workspace:*"
3194
3193
  } : {
3195
- "@getstrata/bootstrap": "^2.0.8",
3196
- "@getstrata/cli": "^2.0.8",
3197
- "@getstrata/core": "^2.0.8"
3194
+ "@getstrata/bootstrap": "^2.1.0",
3195
+ "@getstrata/cli": "^2.1.0",
3196
+ "@getstrata/core": "^2.1.0"
3198
3197
  };
3199
3198
  coreDeps.eta = "^4.6.0";
3200
3199
  if (options.layers?.database === "mysql") {
@@ -3440,7 +3439,7 @@ function renderReadme(projectName, layers, options = {}) {
3440
3439
  if (needsFrontendBuild(layers.frontend)) {
3441
3440
  next.push("bun run frontend:install", "bun run frontend:build");
3442
3441
  }
3443
- next.push("bun run db:migrate", "bun run db:seed:demo", "bun run dev");
3442
+ next.push("bun run db:migrate", "bun run dev");
3444
3443
  const extras = Object.entries(layers.extras).filter(([, on]) => on).map(([key]) => key);
3445
3444
  const dockerServices = selectedDockerServices(layers);
3446
3445
  const neededTools = neededDockerServices(layers);
@@ -3474,7 +3473,7 @@ ${next.join(`
3474
3473
  Open http://localhost:3000. Health check: \`GET /health\`. Redis worker: \`bun run queue:work\` (requires \`REDIS_URL\`).
3475
3474
 
3476
3475
  ${renderSupportingToolsReadme(layers)}${layers.auth !== "headers" ? `
3477
- Seeded login (password \`StrataDemo!ChangeMe\`):
3476
+ Optional development demo accounts: run \`bun run db:seed:demo\` explicitly after migrations. This command refuses production and staging. It creates these accounts with password \`StrataDemo!ChangeMe\`:
3478
3477
 
3479
3478
  - \`demo@example.com\` (member)
3480
3479
  - \`admin@example.test\` (admin)
@@ -4048,12 +4047,6 @@ const notesTable = defineTable<NoteRecord, "id">({
4048
4047
  defaultOrderBy: { column: "id", direction: "ASC" },
4049
4048
  });
4050
4049
 
4051
- class NoteRepository extends BaseRepository<NoteRecord, "id"> {
4052
- constructor() {
4053
- super(notesTable);
4054
- }
4055
- }
4056
-
4057
4050
  class Note extends Model<NoteRecord, "id"> {
4058
4051
  static $fillable = ${fillable} as const;
4059
4052
  // created_at uses the table default. Sending a JS Date from $timestamps
@@ -4061,7 +4054,7 @@ class Note extends Model<NoteRecord, "id"> {
4061
4054
  static $timestamps = false;
4062
4055
  }
4063
4056
 
4064
- registerModelRepository(Note, new NoteRepository());
4057
+ registerModelRepository(Note, new BaseRepository(notesTable));
4065
4058
 
4066
4059
  export type { NoteRecord };
4067
4060
  export { Note };
@@ -4121,12 +4114,6 @@ const usersTable = defineTable<UserRecord, "id">({
4121
4114
  defaultOrderBy: { column: "id", direction: "ASC" },
4122
4115
  });
4123
4116
 
4124
- class UserRepository extends BaseRepository<UserRecord, "id"> {
4125
- constructor() {
4126
- super(usersTable);
4127
- }
4128
- }
4129
-
4130
4117
  class User extends Model<UserRecord, "id"> {
4131
4118
  static $fillable = ${fillableLiteral} as const;
4132
4119
  static $hidden = ${hiddenLiteral} as const;
@@ -4135,7 +4122,7 @@ class User extends Model<UserRecord, "id"> {
4135
4122
  static $timestamps = false;
4136
4123
  }
4137
4124
 
4138
- registerModelRepository(User, new UserRepository());
4125
+ registerModelRepository(User, new BaseRepository(usersTable));
4139
4126
 
4140
4127
  export type { UserRecord };
4141
4128
  export { User };
@@ -4164,12 +4151,6 @@ const apiTokensTable = defineTable<ApiTokenRecord, "id">({
4164
4151
  defaultOrderBy: { column: "id", direction: "ASC" },
4165
4152
  });
4166
4153
 
4167
- class ApiTokenRepository extends BaseRepository<ApiTokenRecord, "id"> {
4168
- constructor() {
4169
- super(apiTokensTable);
4170
- }
4171
- }
4172
-
4173
4154
  class ApiToken extends Model<ApiTokenRecord, "id"> {
4174
4155
  static $fillable = ["user_id", "name", "token_hash", "abilities", "expires_at", "last_used_at"] as const;
4175
4156
  // created_at uses the table default. Sending a JS Date from $timestamps
@@ -4177,7 +4158,7 @@ class ApiToken extends Model<ApiTokenRecord, "id"> {
4177
4158
  static $timestamps = false;
4178
4159
  }
4179
4160
 
4180
- registerModelRepository(ApiToken, new ApiTokenRepository());
4161
+ registerModelRepository(ApiToken, new BaseRepository(apiTokensTable));
4181
4162
 
4182
4163
  export type { ApiTokenRecord };
4183
4164
  export { ApiToken };
@@ -4204,18 +4185,12 @@ const authOneTimeTokensTable = defineTable<AuthOneTimeTokenRecord, "id">({
4204
4185
  defaultOrderBy: { column: "id", direction: "ASC" },
4205
4186
  });
4206
4187
 
4207
- class AuthOneTimeTokenRepository extends BaseRepository<AuthOneTimeTokenRecord, "id"> {
4208
- constructor() {
4209
- super(authOneTimeTokensTable);
4210
- }
4211
- }
4212
-
4213
4188
  class AuthOneTimeToken extends Model<AuthOneTimeTokenRecord, "id"> {
4214
4189
  static $fillable = ["purpose", "user_id", "token_hash", "expires_at", "consumed_at"] as const;
4215
4190
  static $timestamps = false;
4216
4191
  }
4217
4192
 
4218
- registerModelRepository(AuthOneTimeToken, new AuthOneTimeTokenRepository());
4193
+ registerModelRepository(AuthOneTimeToken, new BaseRepository(authOneTimeTokensTable));
4219
4194
 
4220
4195
  export type { AuthOneTimeTokenRecord };
4221
4196
  export { AuthOneTimeToken };
@@ -4225,7 +4200,6 @@ function renderModelsRegister(layers) {
4225
4200
  const lines = [
4226
4201
  "// Side-effect imports run registerModelRepository() in each model file.",
4227
4202
  "// registerModelClass() is only for a string alias that is neither constructor.name nor $morphClass.",
4228
- 'import { registerModelClass } from "@getstrata/core/database/model";',
4229
4203
  'import "./Note.ts";'
4230
4204
  ];
4231
4205
  if (authNeedsUsers(layers.auth)) {
@@ -4236,9 +4210,9 @@ function renderModelsRegister(layers) {
4236
4210
  lines.push('import "./ApiToken.ts";');
4237
4211
  }
4238
4212
  lines.push("");
4239
- lines.push("// Example after you add a Product model with belongsTo('Category'):");
4240
- lines.push('// registerModelClass("Category", Category);');
4241
- lines.push("void registerModelClass;");
4213
+ lines.push("// Optional alias when a relation uses belongsTo('CategoryAlias'):");
4214
+ lines.push('// import { registerModelClass } from "@getstrata/core/database/model";');
4215
+ lines.push('// registerModelClass("CategoryAlias", Category);');
4242
4216
  lines.push("");
4243
4217
  return `${lines.join(`
4244
4218
  `)}
@@ -4614,10 +4588,9 @@ import "./preload.ts";
4614
4588
  import { runProviderPhase } from "@getstrata/bootstrap/context";
4615
4589
  import {
4616
4590
  type AppContext,
4617
- type AppDependencies,
4618
4591
  type AppRouteMap,
4619
4592
  assertAppDependenciesComplete,
4620
- type ConfigStore,
4593
+ ConfigStore,
4621
4594
  type MutableAppDependencies,
4622
4595
  type ProviderContext,
4623
4596
  ServiceContainer,
@@ -4650,34 +4623,9 @@ export interface BootstrappedApp {
4650
4623
  config: ReturnType<typeof loadConfig>;
4651
4624
  }
4652
4625
 
4653
- class AppConfigStore {
4654
- private readonly values = new Map<string, unknown>();
4655
-
4656
- set<T>(key: string, value: T): T {
4657
- this.values.set(key, value);
4658
- return value;
4659
- }
4660
-
4661
- get<T>(key: string): T | undefined {
4662
- return this.values.get(key) as T | undefined;
4663
- }
4664
-
4665
- require<T>(key: string): T {
4666
- const value = this.get<T>(key);
4667
- if (value === undefined) {
4668
- throw new Error(\`Missing required config value "\${key}".\`);
4669
- }
4670
- return value;
4671
- }
4672
-
4673
- has(key: string): boolean {
4674
- return this.values.has(key);
4675
- }
4676
- }
4677
-
4678
4626
  function createAppContext(): AppContext {
4679
4627
  const container = new ServiceContainer();
4680
- const config = new AppConfigStore() as unknown as ConfigStore;
4628
+ const config = new ConfigStore();
4681
4629
  const dependencies: MutableAppDependencies = { container };
4682
4630
  const context: ProviderContext = { container, config, dependencies };
4683
4631
 
@@ -4690,8 +4638,8 @@ function createAppContext(): AppContext {
4690
4638
 
4691
4639
  assertAppDependenciesComplete(dependencies);
4692
4640
 
4693
- const appContext = { container, config, dependencies: dependencies as AppDependencies };
4694
- setActiveApplicationContext(appContext as never);
4641
+ const appContext: AppContext = { container, config, dependencies };
4642
+ setActiveApplicationContext(appContext);
4695
4643
  return appContext;
4696
4644
  }
4697
4645
 
@@ -6,8 +6,8 @@ import { useAuth } from "../auth/AuthContext";
6
6
  export default function LoginPage() {
7
7
  const { login, user } = useAuth();
8
8
  const navigate = useNavigate();
9
- const [email, setEmail] = useState("admin@example.test");
10
- const [password, setPassword] = useState("StrataDemo!ChangeMe");
9
+ const [email, setEmail] = useState("");
10
+ const [password, setPassword] = useState("");
11
11
  const [error, setError] = useState<string | null>(null);
12
12
  const [submitting, setSubmitting] = useState(false);
13
13
 
@@ -33,10 +33,7 @@ export default function LoginPage() {
33
33
  return (
34
34
  <section className="card">
35
35
  <h1>Sign in</h1>
36
- <p className="hint">
37
- Seeded users are <code>demo@example.com</code> and <code>admin@example.test</code>, password
38
- <code>StrataDemo!ChangeMe</code>.
39
- </p>
36
+ <p className="hint">Enter your account email and password.</p>
40
37
 
41
38
  {error ? <p className="error">{error}</p> : null}
42
39
 
@@ -45,6 +42,8 @@ export default function LoginPage() {
45
42
  Email
46
43
  <input
47
44
  type="email"
45
+ name="email"
46
+ autoComplete="username"
48
47
  value={email}
49
48
  onChange={(event) => setEmail(event.target.value)}
50
49
  required
@@ -55,6 +54,8 @@ export default function LoginPage() {
55
54
  Password
56
55
  <input
57
56
  type="password"
57
+ name="password"
58
+ autoComplete="current-password"
58
59
  value={password}
59
60
  onChange={(event) => setPassword(event.target.value)}
60
61
  required
@@ -12,9 +12,9 @@
12
12
  "check": "tsc --noEmit"
13
13
  },
14
14
  "dependencies": {
15
- "@getstrata/bootstrap": "^2.0.8",
16
- "@getstrata/cli": "^2.0.8",
17
- "@getstrata/core": "^2.0.8",
15
+ "@getstrata/bootstrap": "^2.1.0",
16
+ "@getstrata/cli": "^2.1.0",
17
+ "@getstrata/core": "^2.1.0",
18
18
  "eta": "^4.6.0"
19
19
  },
20
20
  "devDependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getstrata/starter",
3
- "version": "2.0.8",
3
+ "version": "2.1.0",
4
4
  "description": "Interactive create-strata wizard. Choose each layer; one database engine.",
5
5
  "type": "module",
6
6
  "license": "MIT",