@coffer-org/plugin-transit 1.5.0 → 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.
@@ -6,7 +6,7 @@ export default defineShelf({
6
6
  label: 'transit.bus_route.label',
7
7
  icon: 'lucide:bus',
8
8
  views: {
9
- table: ['route_number', 'from', 'to'],
9
+ list: { fields: ['route_number', 'from', 'to'] },
10
10
  },
11
11
  fields: [
12
12
  field.title({ key: 'name', label: 'core.fields.name' }),
package/dist/schema.js CHANGED
@@ -4609,6 +4609,25 @@ function internalApiToken(o) {
4609
4609
  ]
4610
4610
  });
4611
4611
  }
4612
+ /**
4613
+ * Internal "connected apps" list — the OAuth clients (claude.ai & co) the user
4614
+ * has authorized for MCP access. Same "internal" caveat and custom-renderer
4615
+ * trick as internalApiToken(): read-only rows + a revoke action, never part of
4616
+ * the parent form's save.
4617
+ */
4618
+ function internalOauthGrants(o) {
4619
+ return group({
4620
+ key: o.key,
4621
+ label: o.label ?? o.key,
4622
+ multiple: true,
4623
+ view: { kind: "internalOauthGrants" },
4624
+ fields: [
4625
+ string({ key: "clientName" }),
4626
+ string({ key: "createdAt" }),
4627
+ string({ key: "lastUsedAt" })
4628
+ ]
4629
+ });
4630
+ }
4612
4631
  var SLUG_RE = /^[a-z0-9-]+$/;
4613
4632
  function slug(raw) {
4614
4633
  const o = normalizeOpts(raw);
@@ -5038,7 +5057,8 @@ var presets = {
5038
5057
  weight,
5039
5058
  dimensions,
5040
5059
  country,
5041
- internalApiToken
5060
+ internalApiToken,
5061
+ internalOauthGrants
5042
5062
  };
5043
5063
  //#endregion
5044
5064
  //#region ../../node_modules/iso-639-1/src/data.js
@@ -5867,7 +5887,7 @@ function group(o) {
5867
5887
  required: o.required,
5868
5888
  unique: r.unique,
5869
5889
  label: o.label,
5870
- icon: v.icon,
5890
+ icon: o.icon,
5871
5891
  display: v.display ?? "wrap",
5872
5892
  kind: v.kind,
5873
5893
  fixed: r.fixed,
@@ -5878,11 +5898,9 @@ function group(o) {
5878
5898
  function row(o) {
5879
5899
  return group({
5880
5900
  label: o.label,
5901
+ icon: o.icon,
5881
5902
  fields: o.fields,
5882
- view: {
5883
- ...o.view,
5884
- display: "scroll"
5885
- }
5903
+ view: { display: "scroll" }
5886
5904
  });
5887
5905
  }
5888
5906
  /** Tabular collection (array of rows → <table>, aligned by columns). Sugar. */
@@ -5890,14 +5908,12 @@ function table(o) {
5890
5908
  return group({
5891
5909
  key: o.key,
5892
5910
  label: o.label,
5911
+ icon: o.icon,
5893
5912
  fields: o.fields,
5894
5913
  multiple: true,
5895
5914
  required: o.required,
5896
5915
  rules: o.rules,
5897
- view: {
5898
- ...o.view,
5899
- display: "table"
5900
- }
5916
+ view: { display: "table" }
5901
5917
  });
5902
5918
  }
5903
5919
  /**
@@ -5913,11 +5929,9 @@ function sheet(o) {
5913
5929
  });
5914
5930
  return group({
5915
5931
  label: o.label,
5932
+ icon: o.icon,
5916
5933
  fields: flat,
5917
- view: {
5918
- ...o.view,
5919
- display: "sheet"
5920
- }
5934
+ view: { display: "sheet" }
5921
5935
  });
5922
5936
  }
5923
5937
  /**
@@ -5949,8 +5963,8 @@ function keyed(o) {
5949
5963
  return {
5950
5964
  ...(o.container ?? group)({
5951
5965
  label: o.label,
5952
- fields: [o.by, ...o.fields],
5953
- view: o.view
5966
+ icon: o.icon,
5967
+ fields: [o.by, ...o.fields]
5954
5968
  }),
5955
5969
  key: o.key,
5956
5970
  multiple: true,
@@ -6387,7 +6401,7 @@ function relation(raw) {
6387
6401
  },
6388
6402
  relation: {
6389
6403
  library: raw.options.library,
6390
- type: raw.options.shelf
6404
+ shelf: raw.options.shelf
6391
6405
  },
6392
6406
  ...multi && { json: true },
6393
6407
  zod: optionalize(s, required)
@@ -6767,15 +6781,44 @@ function period(raw) {
6767
6781
  zod: optionalize(s, required)
6768
6782
  });
6769
6783
  }
6784
+ /** Keys a file entry may carry. Everything else is rejected — see fileEntryIssue. */
6785
+ var FILE_KEYS = /* @__PURE__ */ new Set([
6786
+ "name",
6787
+ "mime",
6788
+ "size"
6789
+ ]);
6790
+ /** Keys that mean "the author pasted a remote address" — the one mistake worth naming. */
6791
+ var FILE_URL_KEYS = [
6792
+ "url",
6793
+ "src",
6794
+ "href",
6795
+ "link"
6796
+ ];
6797
+ /**
6798
+ * A file entry points at a file already uploaded to the server: `{ name }`, where
6799
+ * name is the bare filename returned by POST /api/upload. Anything else — a remote
6800
+ * URL, an extra key, a path — is refused here, so a record can never hold a
6801
+ * reference the server cannot serve. `mime`/`size` are accepted (legacy payloads
6802
+ * and the web uploader send them) but the server overwrites them from disk.
6803
+ * Returns a vmsg code, or null when the entry is well-formed.
6804
+ */
6805
+ function fileEntryIssue(it) {
6806
+ if (typeof it !== "object" || it === null || Array.isArray(it)) return "file_structure";
6807
+ const rec = it;
6808
+ if (FILE_URL_KEYS.some((k) => k in rec)) return "file_remote_url";
6809
+ const name = rec["name"];
6810
+ if (typeof name !== "string" || name === "") return "file_structure";
6811
+ if (name.includes("://") || name.startsWith("//")) return "file_remote_url";
6812
+ if (/[\\/]/.test(name) || name.includes("..")) return "file_name";
6813
+ for (const k of Object.keys(rec)) if (!FILE_KEYS.has(k)) return "file_unknown_key";
6814
+ if (rec["mime"] !== void 0 && typeof rec["mime"] !== "string") return "file_structure";
6815
+ if (rec["size"] !== void 0 && typeof rec["size"] !== "number") return "file_structure";
6816
+ return null;
6817
+ }
6770
6818
  function makeFile(kind, raw) {
6771
6819
  const o = normalizeOpts(raw);
6772
6820
  const required = o.required ?? false;
6773
6821
  const multiple = o.multiple ?? false;
6774
- const rowSchema = object({
6775
- name: string$1().min(1),
6776
- mime: string$1().optional(),
6777
- size: number$1().optional()
6778
- });
6779
6822
  const s = unknown().superRefine((raw, ctx) => {
6780
6823
  if (typeof raw === "string") try {
6781
6824
  JSON.parse(raw);
@@ -6788,12 +6831,15 @@ function makeFile(kind, raw) {
6788
6831
  }
6789
6832
  const parsed = jsonValue(raw);
6790
6833
  const items = Array.isArray(parsed) ? parsed : [parsed];
6791
- for (const it of items) if (!rowSchema.safeParse(it).success) {
6792
- ctx.addIssue({
6793
- code: ZodIssueCode.custom,
6794
- message: vmsg("file_structure")
6795
- });
6796
- return;
6834
+ for (const it of items) {
6835
+ const code = fileEntryIssue(it);
6836
+ if (code) {
6837
+ ctx.addIssue({
6838
+ code: ZodIssueCode.custom,
6839
+ message: vmsg(code)
6840
+ });
6841
+ return;
6842
+ }
6797
6843
  }
6798
6844
  });
6799
6845
  return wrapKey(o, {
@@ -7729,7 +7775,7 @@ function defineShelf(m) {
7729
7775
  const keys = fieldEntries(m.fields).map(([k]) => k);
7730
7776
  const dup = keys.find((k, i) => keys.indexOf(k) !== i);
7731
7777
  if (dup) throw new Error(`[shelf] ${m.library}/${m.shelf}: duplicate key '${dup}'`);
7732
- if (m.standalone !== false && !m.views?.table?.length) console.warn(`[shelf] ${m.library}/${m.shelf}: standalone shelf without an explicit views.table`);
7778
+ if (m.standalone !== false && !m.views?.list?.fields?.length) console.warn(`[shelf] ${m.library}/${m.shelf}: standalone shelf without an explicit views.list`);
7733
7779
  return m;
7734
7780
  }
7735
7781
  //#endregion
@@ -7745,11 +7791,11 @@ var bus_route_default = defineShelf({
7745
7791
  library: "transit",
7746
7792
  label: "transit.bus_route.label",
7747
7793
  icon: "lucide:bus",
7748
- views: { table: [
7794
+ views: { list: { fields: [
7749
7795
  "route_number",
7750
7796
  "from",
7751
7797
  "to"
7752
- ] },
7798
+ ] } },
7753
7799
  fields: [
7754
7800
  field.title({
7755
7801
  key: "name",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coffer-org/plugin-transit",
3
- "version": "1.5.0",
3
+ "version": "2.1.0",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=24"
@@ -25,9 +25,9 @@
25
25
  "test": "node --import tsx/esm --test 'src/runtime/*.test.ts'"
26
26
  },
27
27
  "dependencies": {
28
- "@coffer-org/sdk": "^1.5.0",
29
- "@coffer-org/server": "^1.8.0",
30
- "@coffer-org/dav": "^1.5.0"
28
+ "@coffer-org/sdk": "^2.1.0",
29
+ "@coffer-org/server": "^2.2.0",
30
+ "@coffer-org/dav": "^2.1.0"
31
31
  },
32
32
  "coffer": {
33
33
  "schema": "dist/schema.js"