@fougere/adapter-rest 0.17.3-alpha.0 → 0.18.0-alpha.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.
@@ -1,10 +1,4 @@
1
- import type { SchemaView } from '@fougere/schema';
2
- export interface OperationMeta {
3
- input?: SchemaView;
4
- output?: SchemaView;
5
- /** Canonical kind from core's EffectiveOperation. */
6
- kind: 'query' | 'command';
7
- /** The operation in words — see `RouteDefinition.description`. */
8
- description?: string;
9
- }
1
+ import type { EffectiveOperation } from '@fougere/core';
2
+ /** What a route reads of an effective operation — its `binding` is what the path is derived from. */
3
+ export type OperationMeta = Pick<EffectiveOperation, 'input' | 'output' | 'kind' | 'description'> & Partial<Pick<EffectiveOperation, 'binding'>>;
10
4
  //# sourceMappingURL=OperationMeta.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"OperationMeta.d.ts","sourceRoot":"","sources":["../../src/routes/OperationMeta.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,qDAAqD;IACrD,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1B,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB"}
1
+ {"version":3,"file":"OperationMeta.d.ts","sourceRoot":"","sources":["../../src/routes/OperationMeta.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD,qGAAqG;AACrG,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,kBAAkB,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,aAAa,CAAC,GAC7F,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import type { Fields } from '@fougere/schema';
2
2
  import type { HttpMethod } from '@fougere/http';
3
- import type { HandlerEntry as CoreHandlerEntry } from '@fougere/core';
3
+ import type { HandlerEntry as CoreHandlerEntry, OperationOverride } from '@fougere/core';
4
4
  import type { OperationMeta } from './OperationMeta.js';
5
5
  import type { GenerateRoutesOptions } from './GenerateRoutesOptions.js';
6
6
  export interface RouteDefinition {
@@ -32,13 +32,7 @@ interface FrondLike {
32
32
  presenters: PresenterEntry[];
33
33
  surfaces?: Record<string, string[]>;
34
34
  /** What `frond.config.ts` said per op — `rest:` is read here, `graphql:` next facade. */
35
- operationsOverrides?: Record<string, {
36
- rest?: {
37
- method?: string;
38
- path?: string;
39
- status?: number;
40
- };
41
- }>;
35
+ operationsOverrides?: Record<string, Pick<OperationOverride, 'rest'>>;
42
36
  }
43
37
  interface AppLike {
44
38
  fronds: FrondLike[];
@@ -1 +1 @@
1
- {"version":3,"file":"RouteDefinition.d.ts","sourceRoot":"","sources":["../../src/routes/RouteDefinition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAExE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,OAAO,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAC;CAItB;AAED,4DAA4D;AAC5D,KAAK,YAAY,GAAG,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC,CAAC;AAS9E,UAAU,cAAc;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACpC,yFAAyF;IACzF,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;CACtG;AAED,UAAU,OAAO;IACf,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,4EAA4E;IAC5E,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,SAAS,CAAC;IACnF,kDAAkD;IAClD,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,SAAS,CAAC;CAC1F;AA8DD,wGAAwG;AACxG,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,qBAA0B,GAAG,eAAe,EAAE,CAInG"}
1
+ {"version":3,"file":"RouteDefinition.d.ts","sourceRoot":"","sources":["../../src/routes/RouteDefinition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,IAAI,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEzF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAExE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,OAAO,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAC;CAItB;AAED,4DAA4D;AAC5D,KAAK,YAAY,GAAG,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC,CAAC;AAS9E,UAAU,cAAc;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACpC,yFAAyF;IACzF,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,CAAC;CACvE;AAED,UAAU,OAAO;IACf,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,4EAA4E;IAC5E,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,SAAS,CAAC;IACnF,kDAAkD;IAClD,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,SAAS,CAAC;CAC1F;AA6DD,wGAAwG;AACxG,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,qBAA0B,GAAG,eAAe,EAAE,CAInG"}
@@ -1,8 +1,7 @@
1
1
  import { Visibility } from '@fougere/schema';
2
2
  // ─── Naming conventions ─────────────────────────
3
- function hasById(name) {
4
- return name.includes('ById') || name === 'findById' || name === 'update' || name === 'delete';
5
- }
3
+ /** The five a Crud handler brings answer at the collection or the row, never under their own name. */
4
+ const CRUD = new Set(['list', 'findById', 'create', 'update', 'delete']);
6
5
  function pluralize(name) {
7
6
  return name.endsWith('y')
8
7
  ? name.slice(0, -1) + 'ies'
@@ -24,25 +23,21 @@ function deriveMethod(opName, resolvedKind) {
24
23
  return 'DELETE';
25
24
  return 'POST';
26
25
  }
27
- /** Derive route path from the address + operation name. */
28
- function derivePath(address, opName) {
29
- const base = `/${pluralize(address)}`;
30
- // Standard CRUD
31
- if (opName === 'list')
32
- return base;
33
- if (opName === 'findById')
34
- return `${base}/:id`;
35
- if (opName === 'create')
36
- return base;
37
- if (opName === 'update')
38
- return `${base}/:id`;
39
- if (opName === 'delete')
40
- return `${base}/:id`;
41
- // Remaining operations (convention-based)
42
- const withId = hasById(opName);
43
- const cleanName = opName.replace('ById', '');
44
- const segment = cleanName.replace(/[A-Z]/g, (c) => '-' + c.toLowerCase());
45
- return withId ? `${base}/:id/${segment}` : `${base}/${segment}`;
26
+ /**
27
+ * Read off the signature: what designates a row comes before the op, the other required values
28
+ * after it, and an optional one is left to the query string.
29
+ * `publish(id: Post['id'])` → `/posts/:id/publish`, `move(id: Post['id'], position: number)` →
30
+ * `/posts/:id/move/:position`, `byTag(tag: string)` → `/posts/by-tag/:tag`.
31
+ */
32
+ function derivePath(address, opName, binding = []) {
33
+ const required = binding.flatMap(({ source, optional }) => source.kind === 'param' && !optional ? [source] : []);
34
+ const designating = required.filter((param) => param.identifies);
35
+ const following = required.filter((param) => !param.identifies);
36
+ const named = CRUD.has(opName) ? [] : [opName.replace(/[A-Z]/g, (letter) => '-' + letter.toLowerCase())];
37
+ return ['', pluralize(address), ...designating.map(segmentOf), ...named, ...following.map(segmentOf)].join('/');
38
+ }
39
+ function segmentOf({ name }) {
40
+ return `:${name}`;
46
41
  }
47
42
  // ─── Route generation helpers ───────────────────
48
43
  // Update routes carry the SAME fields: input omissibility is a projection of the
@@ -100,7 +95,7 @@ function routeFor({ address, frond, facade, opName, meta, options }) {
100
95
  }
101
96
  return {
102
97
  method: override.method ?? deriveMethod(opName, meta.kind),
103
- path: (options.prefix ?? '') + (override.path ?? derivePath(address, opName)),
98
+ path: (options.prefix ?? '') + (override.path ?? derivePath(address, opName, meta.binding)),
104
99
  operationName: opName,
105
100
  address,
106
101
  handler: (invocation) => op(invocation),
@@ -1 +1 @@
1
- {"version":3,"file":"RouteDefinition.js","sourceRoot":"","sources":["../../src/routes/RouteDefinition.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"RouteDefinition.js","sourceRoot":"","sources":["../../src/routes/RouteDefinition.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fougere/adapter-rest",
3
- "version": "0.17.3-alpha.0",
3
+ "version": "0.18.0-alpha.0",
4
4
  "description": "Entity → REST routes.",
5
5
  "keywords": [
6
6
  "fougere",
@@ -29,9 +29,9 @@
29
29
  "src"
30
30
  ],
31
31
  "dependencies": {
32
- "@fougere/core": "0.17.3-alpha.0",
33
- "@fougere/schema": "0.17.3-alpha.0",
34
- "@fougere/http": "0.17.3-alpha.0"
32
+ "@fougere/core": "0.18.0-alpha.0",
33
+ "@fougere/schema": "0.18.0-alpha.0",
34
+ "@fougere/http": "0.18.0-alpha.0"
35
35
  },
36
36
  "publishConfig": {
37
37
  "access": "public"
@@ -1,10 +1,5 @@
1
- import type { SchemaView } from '@fougere/schema';
1
+ import type { EffectiveOperation } from '@fougere/core';
2
2
 
3
- export interface OperationMeta {
4
- input?: SchemaView;
5
- output?: SchemaView;
6
- /** Canonical kind from core's EffectiveOperation. */
7
- kind: 'query' | 'command';
8
- /** The operation in words — see `RouteDefinition.description`. */
9
- description?: string;
10
- }
3
+ /** What a route reads of an effective operation — its `binding` is what the path is derived from. */
4
+ export type OperationMeta = Pick<EffectiveOperation, 'input' | 'output' | 'kind' | 'description'>
5
+ & Partial<Pick<EffectiveOperation, 'binding'>>;
@@ -1,7 +1,8 @@
1
1
  import type { Fields } from '@fougere/schema';
2
2
  import { Visibility } from '@fougere/schema';
3
3
  import type { HttpMethod } from '@fougere/http';
4
- import type { HandlerEntry as CoreHandlerEntry } from '@fougere/core';
4
+ import type { HandlerEntry as CoreHandlerEntry, OperationOverride } from '@fougere/core';
5
+ import type { BindingPlan } from '@fougere/core/descriptor';
5
6
  import type { OperationMeta } from './OperationMeta.js';
6
7
  import type { GenerateRoutesOptions } from './GenerateRoutesOptions.js';
7
8
 
@@ -47,7 +48,7 @@ interface FrondLike {
47
48
  presenters: PresenterEntry[];
48
49
  surfaces?: Record<string, string[]>;
49
50
  /** What `frond.config.ts` said per op — `rest:` is read here, `graphql:` next facade. */
50
- operationsOverrides?: Record<string, { rest?: { method?: string; path?: string; status?: number } }>;
51
+ operationsOverrides?: Record<string, Pick<OperationOverride, 'rest'>>;
51
52
  }
52
53
 
53
54
  interface AppLike {
@@ -62,9 +63,8 @@ type HandlerFacade = Record<string, Function>;
62
63
 
63
64
  // ─── Naming conventions ─────────────────────────
64
65
 
65
- function hasById(name: string): boolean {
66
- return name.includes('ById') || name === 'findById' || name === 'update' || name === 'delete';
67
- }
66
+ /** The five a Crud handler brings answer at the collection or the row, never under their own name. */
67
+ const CRUD = new Set(['list', 'findById', 'create', 'update', 'delete']);
68
68
 
69
69
  function pluralize(name: string): string {
70
70
  return name.endsWith('y')
@@ -91,23 +91,23 @@ function deriveMethod(
91
91
  return 'POST';
92
92
  }
93
93
 
94
- /** Derive route path from the address + operation name. */
95
- function derivePath(address: string, opName: string): string {
96
- const base = `/${pluralize(address)}`;
97
-
98
- // Standard CRUD
99
- if (opName === 'list') return base;
100
- if (opName === 'findById') return `${base}/:id`;
101
- if (opName === 'create') return base;
102
- if (opName === 'update') return `${base}/:id`;
103
- if (opName === 'delete') return `${base}/:id`;
104
-
105
- // Remaining operations (convention-based)
106
- const withId = hasById(opName);
107
- const cleanName = opName.replace('ById', '');
108
- const segment = cleanName.replace(/[A-Z]/g, (c) => '-' + c.toLowerCase());
94
+ /**
95
+ * Read off the signature: what designates a row comes before the op, the other required values
96
+ * after it, and an optional one is left to the query string.
97
+ * `publish(id: Post['id'])` → `/posts/:id/publish`, `move(id: Post['id'], position: number)` →
98
+ * `/posts/:id/move/:position`, `byTag(tag: string)` → `/posts/by-tag/:tag`.
99
+ */
100
+ function derivePath(address: string, opName: string, binding: BindingPlan = []): string {
101
+ const required = binding.flatMap(({ source, optional }) => source.kind === 'param' && !optional ? [source] : []);
102
+ const designating = required.filter((param) => param.identifies);
103
+ const following = required.filter((param) => !param.identifies);
104
+ const named = CRUD.has(opName) ? [] : [opName.replace(/[A-Z]/g, (letter) => '-' + letter.toLowerCase())];
105
+
106
+ return ['', pluralize(address), ...designating.map(segmentOf), ...named, ...following.map(segmentOf)].join('/');
107
+ }
109
108
 
110
- return withId ? `${base}/:id/${segment}` : `${base}/${segment}`;
109
+ function segmentOf({ name }: { name: string }): string {
110
+ return `:${name}`;
111
111
  }
112
112
 
113
113
  // ─── Route generation helpers ───────────────────
@@ -194,7 +194,7 @@ function routeFor({ address, frond, facade, opName, meta, options }: Projecting)
194
194
 
195
195
  return {
196
196
  method: override.method ?? deriveMethod(opName, meta.kind),
197
- path: (options.prefix ?? '') + (override.path ?? derivePath(address, opName)),
197
+ path: (options.prefix ?? '') + (override.path ?? derivePath(address, opName, meta.binding)),
198
198
  operationName: opName,
199
199
  address,
200
200
  handler: (invocation) => op(invocation),