@primate/core 0.9.5 → 0.9.6

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.
@@ -34,6 +34,7 @@ declare function sort_invalid_value(field: string, value: unknown): import("@rco
34
34
  declare function select_empty(): import("@rcompat/error").TemplateError;
35
35
  declare function select_invalid(): import("@rcompat/error").TemplateError;
36
36
  declare function limit_invalid(): import("@rcompat/error").TemplateError;
37
+ declare function first_limit_invalid(): import("@rcompat/error").TemplateError;
37
38
  declare function select_invalid_value(index: number, x: unknown): import("@rcompat/error").TemplateError;
38
39
  declare function where_required(): import("@rcompat/error").TemplateError;
39
40
  declare function where_invalid(): import("@rcompat/error").TemplateError;
@@ -94,6 +95,7 @@ declare const errors: {
94
95
  where_invalid_value: typeof where_invalid_value;
95
96
  set_empty: typeof set_empty;
96
97
  limit_invalid: typeof limit_invalid;
98
+ first_limit_invalid: typeof first_limit_invalid;
97
99
  offset_invalid: typeof offset_invalid;
98
100
  offset_requires_limit: typeof offset_requires_limit;
99
101
  relation_unknown: typeof relation_unknown;
@@ -150,6 +152,7 @@ export declare const Code: {
150
152
  where_invalid_value: "where_invalid_value";
151
153
  set_empty: "set_empty";
152
154
  limit_invalid: "limit_invalid";
155
+ first_limit_invalid: "first_limit_invalid";
153
156
  offset_invalid: "offset_invalid";
154
157
  offset_requires_limit: "offset_requires_limit";
155
158
  relation_unknown: "relation_unknown";
@@ -152,6 +152,9 @@ function select_invalid() {
152
152
  function limit_invalid() {
153
153
  return t `invalid limit`;
154
154
  }
155
+ function first_limit_invalid() {
156
+ return t `${"first"} does not accept ${"limit"}`;
157
+ }
155
158
  function select_invalid_value(index, x) {
156
159
  return t `select[${index}]: must be string, received ${kind_of(x)}`;
157
160
  }
@@ -185,6 +188,7 @@ const QUERY = error.coded({
185
188
  where_invalid_value,
186
189
  set_empty,
187
190
  limit_invalid,
191
+ first_limit_invalid,
188
192
  offset_invalid,
189
193
  offset_requires_limit,
190
194
  });
@@ -1498,6 +1498,24 @@ export default (db) => {
1498
1498
  assert(yes.length).equals(1);
1499
1499
  assert(yes[0].name).equals("MiXeDCase");
1500
1500
  });
1501
+ $user("first: returns first matching record", async (assert) => {
1502
+ await User.insert({ name: "FirstLow", age: 1 });
1503
+ await User.insert({ name: "FirstHigh", age: 2 });
1504
+ const user = await User.first({
1505
+ where: { name: { $like: "First%" } },
1506
+ sort: { age: "desc" },
1507
+ });
1508
+ assert(user?.name).equals("FirstHigh");
1509
+ });
1510
+ $user("first: returns undefined when no record matches", async (assert) => {
1511
+ const user = await User.first({ where: { name: "MissingFirst" } });
1512
+ assert(user).undefined();
1513
+ });
1514
+ $user$("first: rejects limit", async (assert) => {
1515
+ await throws(assert, Code.first_limit_invalid, () => {
1516
+ return User.first({ limit: 10 });
1517
+ });
1518
+ });
1501
1519
  $user("find: $ilike is case-insensitive", async (assert) => {
1502
1520
  await User.insert({ name: "MiXeDCase2" });
1503
1521
  const rows = await User.find({ where: { name: { $ilike: "mixed%" } } });
@@ -18,8 +18,9 @@ export default function frontend_module(init) {
18
18
  const conditions = init.conditions ?? [];
19
19
  const schema = base_schema.extend(init.schema ?? {});
20
20
  async function normalize(path) {
21
- const file = fs.ref(path);
22
- const basename = path.slice(0, -file.fullExtension.length);
21
+ const extension = init.extensions.find(extension => path.endsWith(extension))
22
+ ?? fs.ref(path).fullExtension;
23
+ const basename = path.slice(0, -extension.length);
23
24
  return `p_${await hash(`${basename}.${module_name}`)}`;
24
25
  }
25
26
  return (input) => {
@@ -206,11 +207,11 @@ export default function frontend_module(init) {
206
207
  build.onLoad({ filter: views_filter }, async () => {
207
208
  const views = await views_base.files({
208
209
  recursive: true,
209
- filter: c => extensions.includes(c.fullExtension),
210
+ filter: c => extensions.some(ext => c.path.endsWith(ext)),
210
211
  });
211
212
  const pages = await pages_base.files({
212
213
  recursive: true,
213
- filter: c => extensions.includes(c.fullExtension),
214
+ filter: c => extensions.some(ext => c.path.endsWith(ext)),
214
215
  });
215
216
  let contents = "";
216
217
  for (const view of views) {
@@ -5,5 +5,5 @@ import type ResponseFunction from "#response/ResponseFunction";
5
5
  * @param options response options
6
6
  * @return Response rendering function
7
7
  */
8
- export default function json<const T>(body: T, init?: ResponseInit): ResponseFunction<never, T>;
8
+ export default function json<T>(body: T, init?: ResponseInit): ResponseFunction<never, T>;
9
9
  //# sourceMappingURL=json.d.ts.map
@@ -179,6 +179,17 @@ export default class Store<T extends StoreInput, N extends string = string> impl
179
179
  offset?: number;
180
180
  with?: W;
181
181
  }): Promise<WithRelations<Projected<Schema<T>, S>, ExtractRelations<T>, W>[]>;
182
+ /**
183
+ * Find the first matching record.
184
+ */
185
+ first<const S extends Select<Schema<T>> | undefined = undefined, const W extends WithInput<ExtractRelations<T>> | undefined = undefined>(options?: {
186
+ where?: Where<T>;
187
+ select?: S;
188
+ sort?: Sort<Schema<T>>;
189
+ offset?: number;
190
+ with?: W;
191
+ limit?: never;
192
+ }): Promise<WithRelations<Projected<Schema<T>, S>, ExtractRelations<T>, W> | undefined>;
182
193
  toJSON(): {
183
194
  type: "object";
184
195
  properties: Dict<import("pema").Serialized>;
@@ -590,6 +590,16 @@ export default class Store {
590
590
  });
591
591
  return result;
592
592
  }
593
+ /**
594
+ * Find the first matching record.
595
+ */
596
+ async first(options) {
597
+ guard_options(options, ["where", "select", "sort", "offset", "with", "limit"]);
598
+ if (is.defined(options?.limit))
599
+ throw E.first_limit_invalid();
600
+ const [first] = await this.find({ ...options, limit: 1 });
601
+ return first;
602
+ }
593
603
  toJSON() {
594
604
  return this.#schema.toJSON();
595
605
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primate/core",
3
- "version": "0.9.5",
3
+ "version": "0.9.6",
4
4
  "description": "The universal web framework",
5
5
  "homepage": "https://primate.run",
6
6
  "bugs": "https://github.com/primate-run/primate/issues",