@lpdjs/firestore-repo-service 2.6.6 → 2.6.8
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/{create-servers-BlxW-09M.d.ts → create-servers-DA8xV-aT.d.ts} +3 -3
- package/dist/{create-servers-DoOU7VMv.d.cts → create-servers-k4vH90mn.d.cts} +3 -3
- package/dist/{index-BuxFmMV8.d.cts → index-BOYhux7q.d.cts} +1 -1
- package/dist/{index-BM1mgnpJ.d.ts → index-BRjxlxWa.d.ts} +1 -1
- package/dist/index.cjs +69 -69
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +69 -69
- package/dist/index.js.map +1 -1
- package/dist/{openapi-ChZojCEO.d.ts → openapi-BnVlzg59.d.ts} +1 -1
- package/dist/{openapi-DpMtzJGo.d.cts → openapi-Cci3oqin.d.cts} +1 -1
- package/dist/servers/admin/index.d.cts +2 -2
- package/dist/servers/admin/index.d.ts +2 -2
- package/dist/servers/crud/index.d.cts +4 -4
- package/dist/servers/crud/index.d.ts +4 -4
- package/dist/servers/hono/cli.cjs +41 -39
- package/dist/servers/hono/cli.cjs.map +1 -1
- package/dist/servers/hono/cli.js +41 -39
- package/dist/servers/hono/cli.js.map +1 -1
- package/dist/servers/index.d.cts +5 -5
- package/dist/servers/index.d.ts +5 -5
- package/dist/{types-KYdNUffK.d.cts → types-B7KFW9S9.d.cts} +54 -1
- package/dist/{types-CeyFvYXO.d.ts → types-n7q6N_Zw.d.ts} +54 -1
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import 'zod';
|
|
2
2
|
import 'firebase-functions/v2/https';
|
|
3
|
-
import '../../types-
|
|
3
|
+
import '../../types-B7KFW9S9.cjs';
|
|
4
4
|
export { h as Middleware, M as MiniRouter, R as RouteHandler } from '../../firebase-auth-BTclYg-c.cjs';
|
|
5
|
-
export { a as AdminRepoConfig, b as AdminRepoEntry, A as AdminServerOptions, B as BasicAuthConfig, c as RepoRegistry, d as createAdminServer } from '../../index-
|
|
5
|
+
export { a as AdminRepoConfig, b as AdminRepoEntry, A as AdminServerOptions, B as BasicAuthConfig, c as RepoRegistry, d as createAdminServer } from '../../index-BOYhux7q.cjs';
|
|
6
6
|
import '../../read-CTWZjxyh.cjs';
|
|
7
7
|
import 'firebase-admin/firestore';
|
|
8
8
|
import 'firebase-functions/v2/firestore';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import 'zod';
|
|
2
2
|
import 'firebase-functions/v2/https';
|
|
3
|
-
import '../../types-
|
|
3
|
+
import '../../types-n7q6N_Zw.js';
|
|
4
4
|
export { h as Middleware, M as MiniRouter, R as RouteHandler } from '../../firebase-auth-BTclYg-c.js';
|
|
5
|
-
export { a as AdminRepoConfig, b as AdminRepoEntry, A as AdminServerOptions, B as BasicAuthConfig, c as RepoRegistry, d as createAdminServer } from '../../index-
|
|
5
|
+
export { a as AdminRepoConfig, b as AdminRepoEntry, A as AdminServerOptions, B as BasicAuthConfig, c as RepoRegistry, d as createAdminServer } from '../../index-BRjxlxWa.js';
|
|
6
6
|
import '../../read-CTWZjxyh.js';
|
|
7
7
|
import 'firebase-admin/firestore';
|
|
8
8
|
import 'firebase-functions/v2/firestore';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { HttpsOptions } from 'firebase-functions/v2/https';
|
|
2
|
-
import { C as ConfiguredRepository, a as CrudServerOptions } from '../../types-
|
|
3
|
-
export { A as ApiResponse, B as BasicAuthConfig, b as CrudRepoConfig, c as CrudRepoEntry, d as CrudRepoRegistry, F as FieldRole, L as ListResponseData, M as Middleware, O as OpenAPISpecOptions, Q as QueryRequestBody, R as RepoFieldPath, e as RepoRelationKeys, U as UserFieldPath } from '../../types-
|
|
4
|
-
import { O as OpenAPIDocument } from '../../openapi-
|
|
5
|
-
export { g as generateOpenAPISpec } from '../../openapi-
|
|
2
|
+
import { C as ConfiguredRepository, a as CrudServerOptions } from '../../types-B7KFW9S9.cjs';
|
|
3
|
+
export { A as ApiResponse, B as BasicAuthConfig, b as CrudRepoConfig, c as CrudRepoEntry, d as CrudRepoRegistry, F as FieldRole, L as ListResponseData, M as Middleware, O as OpenAPISpecOptions, Q as QueryRequestBody, R as RepoFieldPath, e as RepoRelationKeys, U as UserFieldPath } from '../../types-B7KFW9S9.cjs';
|
|
4
|
+
import { O as OpenAPIDocument } from '../../openapi-Cci3oqin.cjs';
|
|
5
|
+
export { g as generateOpenAPISpec } from '../../openapi-Cci3oqin.cjs';
|
|
6
6
|
import '../../firebase-auth-BTclYg-c.cjs';
|
|
7
7
|
import 'zod';
|
|
8
8
|
import '../../read-CTWZjxyh.cjs';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { HttpsOptions } from 'firebase-functions/v2/https';
|
|
2
|
-
import { C as ConfiguredRepository, a as CrudServerOptions } from '../../types-
|
|
3
|
-
export { A as ApiResponse, B as BasicAuthConfig, b as CrudRepoConfig, c as CrudRepoEntry, d as CrudRepoRegistry, F as FieldRole, L as ListResponseData, M as Middleware, O as OpenAPISpecOptions, Q as QueryRequestBody, R as RepoFieldPath, e as RepoRelationKeys, U as UserFieldPath } from '../../types-
|
|
4
|
-
import { O as OpenAPIDocument } from '../../openapi-
|
|
5
|
-
export { g as generateOpenAPISpec } from '../../openapi-
|
|
2
|
+
import { C as ConfiguredRepository, a as CrudServerOptions } from '../../types-n7q6N_Zw.js';
|
|
3
|
+
export { A as ApiResponse, B as BasicAuthConfig, b as CrudRepoConfig, c as CrudRepoEntry, d as CrudRepoRegistry, F as FieldRole, L as ListResponseData, M as Middleware, O as OpenAPISpecOptions, Q as QueryRequestBody, R as RepoFieldPath, e as RepoRelationKeys, U as UserFieldPath } from '../../types-n7q6N_Zw.js';
|
|
4
|
+
import { O as OpenAPIDocument } from '../../openapi-BnVlzg59.js';
|
|
5
|
+
export { g as generateOpenAPISpec } from '../../openapi-BnVlzg59.js';
|
|
6
6
|
import '../../firebase-auth-BTclYg-c.js';
|
|
7
7
|
import 'zod';
|
|
8
8
|
import '../../read-CTWZjxyh.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
'use strict';var fs=require('fs'),path=require('path'),process$1=require('process'),promises=require('readline/promises');var O={skipSegments:["useCases","useCase","use-cases","use-case"],casing:"preserve"};function M(e,t=O){let s=new Set(t.skipSegments.map(o=>o.toLowerCase()));return "/"+e.split("/").filter(Boolean).filter(o=>!s.has(o.toLowerCase())).map(o=>t.casing==="kebab"?
|
|
2
|
+
'use strict';var fs=require('fs'),path=require('path'),process$1=require('process'),promises=require('readline/promises');var O={skipSegments:["useCases","useCase","use-cases","use-case"],casing:"preserve"};function M(e,t=O){let s=new Set(t.skipSegments.map(o=>o.toLowerCase()));return "/"+e.split("/").filter(Boolean).filter(o=>!s.has(o.toLowerCase())).map(o=>t.casing==="kebab"?re(o):o).join("/")}function re(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/[\s_]+/g,"-").toLowerCase()}function H(e,t,s){let r=B(e),o=B(t),n=0;for(;n<r.length&&n<o.length&&r[n]===o[n];)n++;let c=r.length-n,i=o.slice(n),d=(i[i.length-1]??"").replace(/\.[mc]?[tj]sx?$/i,""),f=s===""?d:`${d}${s}`;return i[i.length-1]=f,(c===0?"./":"../".repeat(c))+i.join("/")}function B(e){return e.replace(/\\/g,"/").replace(/\/+$/,"").split("/").filter((s,r)=>!(r===0&&s===""))}var ce="/**\n * AUTO-GENERATED by `@lpdjs/firestore-repo-service` Hono codegen.\n * Do not edit by hand \u2014 re-run `hono:gen` after adding / removing route files.\n */\n";function W(e,t){let s=path.dirname(t.outFile);fs.mkdirSync(s,{recursive:true});let r=t.banner??ce,o=(t.now??new Date).toISOString(),n=t.importExtension,c=[],i=[],a=[];e.forEach((f,u)=>{let b=H(s,f.absPath,n),v=M(f.relDir,t.derive);c.push(`import mod${u} from ${JSON.stringify(b)};`),i.push(` { __derivedPath: ${JSON.stringify(v)}, mod: mod${u} },`),a.push({source:f.relPath,url:v});});let d=`${r}// Generated at ${o} \u2014 ${e.length} route file${e.length===1?"":"s"}.
|
|
3
3
|
|
|
4
4
|
import type { AnyRouteDef, RouteModuleDefault } from "@lpdjs/firestore-repo-service/servers/hono";
|
|
5
5
|
|
|
@@ -16,8 +16,8 @@ export const routes: AnyRouteDef[] = __defs.flatMap(({ __derivedPath, mod }) =>
|
|
|
16
16
|
const list = Array.isArray(mod) ? mod : [mod];
|
|
17
17
|
return list.map((route) => ({ ...route, path: route.path ?? __derivedPath }));
|
|
18
18
|
});
|
|
19
|
-
`;return fs.writeFileSync(t.outFile,d,"utf8"),{outFile:t.outFile,routeCount:e.length,derivedPaths:a}}var I={routesFile:"routes.ts",excludeSegments:["node_modules","__generated__","tests","__tests__",".turbo","dist","build",".next"]};function J(e,t=I){let s=[];return K(e,e,t,s),s.sort((r,o)=>r.relPath.localeCompare(o.relPath)),s}function K(e,t,s,r){let o;try{o=fs.readdirSync(t);}catch{return}for(let n of o){if(s.excludeSegments.includes(n))continue;let c=path.join(t,n),i;try{i=fs.statSync(c);}catch{continue}if(i.isDirectory())K(e,c,s,r);else if(i.isFile()&&n===s.routesFile){let a=path.relative(e,c).split(path.sep).join("/"),d=a.replace(/\/?[^/]+$/,"");r.push({absPath:c,relPath:a,relDir:d});}}}var X=".frsrc.json";function T(e=process.cwd()){let t=path.resolve(e,X);if(!fs.existsSync(t))return {};try{return JSON.parse(fs.readFileSync(t,"utf8"))}catch{return {}}}function
|
|
20
|
-
`,"utf8"),s}function
|
|
19
|
+
`;return fs.writeFileSync(t.outFile,d,"utf8"),{outFile:t.outFile,routeCount:e.length,derivedPaths:a}}var I={routesFile:"routes.ts",excludeSegments:["node_modules","__generated__","tests","__tests__",".turbo","dist","build",".next"]};function J(e,t=I){let s=[];return K(e,e,t,s),s.sort((r,o)=>r.relPath.localeCompare(o.relPath)),s}function K(e,t,s,r){let o;try{o=fs.readdirSync(t);}catch{return}for(let n of o){if(s.excludeSegments.includes(n))continue;let c=path.join(t,n),i;try{i=fs.statSync(c);}catch{continue}if(i.isDirectory())K(e,c,s,r);else if(i.isFile()&&n===s.routesFile){let a=path.relative(e,c).split(path.sep).join("/"),d=a.replace(/\/?[^/]+$/,"");r.push({absPath:c,relPath:a,relDir:d});}}}var X=".frsrc.json";function T(e=process.cwd()){let t=path.resolve(e,X);if(!fs.existsSync(t))return {};try{return JSON.parse(fs.readFileSync(t,"utf8"))}catch{return {}}}function ge(e,t=process.cwd()){let s=path.resolve(t,X),o={...T(t),...e};return fs.writeFileSync(s,`${JSON.stringify(o,null,2)}
|
|
20
|
+
`,"utf8"),s}function he(e){let[t,...s]=e,r={};for(let o=0;o<s.length;o++){let n=s[o];if(!n.startsWith("--"))continue;let c=n.slice(2),i=s[o+1];i&&!i.startsWith("--")?(r[c]=i,o++):r[c]=true;}return {command:t??"help",flags:r}}function Y(){console.log(`frs \u2014 Hono file-based codegen
|
|
21
21
|
|
|
22
22
|
Usage:
|
|
23
23
|
frs init [flags]
|
|
@@ -62,8 +62,10 @@ Flags (new <name>):
|
|
|
62
62
|
--usecase-folder <name>
|
|
63
63
|
Parent folder under <domain>.
|
|
64
64
|
Default: .frsrc.json "useCaseFolder" or useCases
|
|
65
|
-
--with-usecase Also scaffold a sibling useCase.ts file
|
|
66
|
-
|
|
65
|
+
--with-usecase Also scaffold a sibling <domain>.<name>.useCase.ts file
|
|
66
|
+
(default: true)
|
|
67
|
+
--with-test Also scaffold a sibling <domain>.<name>.useCase.test.ts
|
|
68
|
+
(Vitest, default: true)
|
|
67
69
|
--apis-import <path> Import path for the registry (default: auto-detect
|
|
68
70
|
../../../../apis.js \u2014 adjust if your layout differs)
|
|
69
71
|
--force Overwrite if files already exist
|
|
@@ -81,8 +83,8 @@ Examples:
|
|
|
81
83
|
frs new createPost --domain posts --method post
|
|
82
84
|
frs new listPosts --domain posts --method get --api v1
|
|
83
85
|
frs add service postRepo
|
|
84
|
-
`);}function Z(e){if(typeof e=="string")return e.split(",").map(t=>t.trim()).filter(Boolean)}function m(e){return typeof e=="string"?e:void 0}function ee(e){if(e||!process$1.stdin.isTTY)return {ask:async(s,r)=>r??"",askChoice:async(s,r,o)=>o??"",askBool:async(s,r)=>r,close:()=>{}};let t=promises.createInterface({input:process$1.stdin,output:process$1.stdout});return {async ask(s,r){let o=r?` (${r})`:"";return (await t.question(`? ${s}${o} \u203A `)).trim()||r||""},async askChoice(s,r,o){let n=` [${r.join("/")}${o?`, default: ${o}`:""}]`;for(;;){let c=(await t.question(`? ${s}${n} \u203A `)).trim().toLowerCase();if(!c&&o)return o;if(r.includes(c))return c;console.log(` invalid choice \u2014 pick one of: ${r.join(", ")}`);}},async askBool(s,r){let o=` (${r?"Y/n":"y/N"})`,n=(await t.question(`? ${s}${o} \u203A `)).trim().toLowerCase();return n?n==="y"||n==="yes"||n==="true":r},close:()=>t.close()}}async function
|
|
85
|
-
* ${
|
|
86
|
+
`);}function Z(e){if(typeof e=="string")return e.split(",").map(t=>t.trim()).filter(Boolean)}function m(e){return typeof e=="string"?e:void 0}function ee(e){if(e||!process$1.stdin.isTTY)return {ask:async(s,r)=>r??"",askChoice:async(s,r,o)=>o??"",askBool:async(s,r)=>r,close:()=>{}};let t=promises.createInterface({input:process$1.stdin,output:process$1.stdout});return {async ask(s,r){let o=r?` (${r})`:"";return (await t.question(`? ${s}${o} \u203A `)).trim()||r||""},async askChoice(s,r,o){let n=` [${r.join("/")}${o?`, default: ${o}`:""}]`;for(;;){let c=(await t.question(`? ${s}${n} \u203A `)).trim().toLowerCase();if(!c&&o)return o;if(r.includes(c))return c;console.log(` invalid choice \u2014 pick one of: ${r.join(", ")}`);}},async askBool(s,r){let o=` (${r?"Y/n":"y/N"})`,n=(await t.question(`? ${s}${o} \u203A `)).trim().toLowerCase();return n?n==="y"||n==="yes"||n==="true":r},close:()=>t.close()}}async function ve(e){let t=T(),s=m(e.root)??t.root;s||(console.error("[frs] --root is required (or run `frs init` to write it to .frsrc.json)"),process.exit(2));let r=path.resolve(process.cwd(),s);fs.existsSync(r)||(console.error(`[frs] root not found: ${r}`),process.exit(2));let o=m(e.out)??t.out??"__generated__/routes.ts",n=Z(e.skip)??O.skipSegments,c=m(e.casing)==="kebab"?"kebab":O.casing,i={skipSegments:n,casing:c},a=m(e.ext)??".js",d=Z(e.exclude)??I.excludeSegments,f=m(e["routes-file"])??I.routesFile,b=J(r,{routesFile:f,excludeSegments:d});b.length===0&&console.warn(`[frs] no "${f}" files found under ${r} \u2014 generated an empty manifest.`);let v=W(b,{outFile:path.resolve(r,o),derive:i,importExtension:a});if(!e.silent){console.log(`[frs] wrote ${v.outFile} (${v.routeCount} route${v.routeCount===1?"":"s"})`);for(let{source:S,url:g}of v.derivedPaths)console.log(` ${g.padEnd(48)} \u2190 ${S}`);}}async function ye(e,t){let s=t.yes===true,r=ee(s),o=T();try{let n=e&&!e.startsWith("--")?e:void 0;n||(n=(await r.ask("Route name (e.g. createPost)")).trim(),n||(console.error("[frs] route name is required"),process.exit(2)));let c=m(t.domain);c||(c=(await r.ask("Domain name (e.g. posts)")).trim(),c||(console.error("[frs] --domain is required"),process.exit(2)));let i=m(t.root)??o.root??"src/domains",a=m(t.method)?.toLowerCase();a||(a=await r.askChoice("HTTP method",["get","post","put","patch","delete"],"post")),["get","post","put","patch","delete"].includes(a)||(console.error(`[frs] invalid --method: ${a}`),process.exit(2));let d=m(t.api);if(!d){let $=o.apis?.[0]??"v1";d=(await r.ask("API tag",$)).trim()||$;}let f=m(t["usecase-folder"])??o.useCaseFolder??"useCases",u=t["with-usecase"]===void 0?s?!0:await r.askBool("Scaffold useCase.ts?",!0):t["with-usecase"]!==!1,b=t["with-test"]===void 0?s||!u?u:await r.askBool("Scaffold useCase.test.ts (Vitest)?",!0):t["with-test"]!==!1,v=t.force===!0,S=path.resolve(process.cwd(),i),g=path.resolve(S,c,f,n),D=path.resolve(g,"routes.ts"),y=`${c}.${n}.useCase`,k=path.resolve(g,`${y}.ts`),F=path.resolve(g,`${y}.test.ts`);fs.mkdirSync(g,{recursive:!0});let w=`${n.charAt(0).toUpperCase()}${n.slice(1)}UseCase`,P="@lpdjs/firestore-repo-service/servers/hono",_=be(S,g),h=a==="get"?"// GET \u2192 lu depuis les query params":`// ${a.toUpperCase()} \u2192 lu depuis le body JSON`,C=`/**
|
|
87
|
+
* ${w} \u2014 pure business logic, no HTTP awareness.
|
|
86
88
|
*
|
|
87
89
|
* Owns its Zod \`input\` / \`output\` schemas (declared as \`static\` members, the
|
|
88
90
|
* single source of truth shared with \`routes.ts\`) and runs the logic in
|
|
@@ -92,10 +94,10 @@ Examples:
|
|
|
92
94
|
|
|
93
95
|
import { z } from "zod";
|
|
94
96
|
import { UseCase } from "${P}";
|
|
95
|
-
import type { Services } from "${
|
|
97
|
+
import type { Services } from "${_}";
|
|
96
98
|
|
|
97
99
|
const input = z.object({
|
|
98
|
-
${
|
|
100
|
+
${h}
|
|
99
101
|
example: z.string(),
|
|
100
102
|
});
|
|
101
103
|
|
|
@@ -103,7 +105,7 @@ const output = z.object({
|
|
|
103
105
|
id: z.string(),
|
|
104
106
|
});
|
|
105
107
|
|
|
106
|
-
export class ${
|
|
108
|
+
export class ${w} extends UseCase<typeof input, typeof output, Services> {
|
|
107
109
|
static readonly input = input;
|
|
108
110
|
static readonly output = output;
|
|
109
111
|
|
|
@@ -114,22 +116,22 @@ export class ${y} extends UseCase<typeof input, typeof output, Services> {
|
|
|
114
116
|
return { id: payload.example };
|
|
115
117
|
}
|
|
116
118
|
}
|
|
117
|
-
`,
|
|
118
|
-
source: "query",`:"",
|
|
119
|
-
`:"",
|
|
120
|
-
import { useCaseRoute } from "${
|
|
121
|
-
${
|
|
119
|
+
`,N=a==="get"?`
|
|
120
|
+
source: "query",`:"",l=u?`import { ${w} } from "./${y}.js";
|
|
121
|
+
`:"",j=m(t["apis-import"])??xe(S,g),te=u?`import { defineRoutes } from "${P}";
|
|
122
|
+
import { useCaseRoute } from "${j}";
|
|
123
|
+
${l}
|
|
122
124
|
export default defineRoutes([
|
|
123
|
-
useCaseRoute(${
|
|
125
|
+
useCaseRoute(${w}, {
|
|
124
126
|
api: "${d}",
|
|
125
|
-
method: "${a}",${
|
|
127
|
+
method: "${a}",${N}
|
|
126
128
|
summary: "TODO: ${n}",
|
|
127
129
|
tags: ["${c}"],
|
|
128
130
|
}),
|
|
129
131
|
]);
|
|
130
132
|
`:`import { z } from "zod";
|
|
131
133
|
import { defineRoutes } from "${P}";
|
|
132
|
-
import { defineRoute } from "${
|
|
134
|
+
import { defineRoute } from "${j}";
|
|
133
135
|
|
|
134
136
|
export default defineRoutes([
|
|
135
137
|
defineRoute({
|
|
@@ -137,7 +139,7 @@ export default defineRoutes([
|
|
|
137
139
|
method: "${a}",
|
|
138
140
|
|
|
139
141
|
input: z.object({
|
|
140
|
-
${
|
|
142
|
+
${h}
|
|
141
143
|
example: z.string(),
|
|
142
144
|
}),
|
|
143
145
|
|
|
@@ -154,32 +156,32 @@ export default defineRoutes([
|
|
|
154
156
|
},
|
|
155
157
|
}),
|
|
156
158
|
]);
|
|
157
|
-
`,z=[],G=[],q=($,
|
|
158
|
-
import type { Services } from "${
|
|
159
|
-
import { ${
|
|
159
|
+
`,z=[],G=[],q=($,se)=>{if(fs.existsSync($)&&!v){G.push($);return}fs.writeFileSync($,se,"utf8"),z.push($);};if(q(D,te),u&&q(k,C),u&&b){let $=`import { describe, it, expect } from "vitest";
|
|
160
|
+
import type { Services } from "${_}";
|
|
161
|
+
import { ${w} } from "./${y}.js";
|
|
160
162
|
|
|
161
|
-
describe("${
|
|
163
|
+
describe("${w}", () => {
|
|
162
164
|
it("returns a response shaped like the output schema", async () => {
|
|
163
165
|
// TODO: replace with real mocks for the services the useCase consumes.
|
|
164
166
|
const services = {} as unknown as Services;
|
|
165
167
|
|
|
166
|
-
const useCase = new ${
|
|
168
|
+
const useCase = new ${w}(services);
|
|
167
169
|
const result = await useCase.execute({ example: "hello" });
|
|
168
170
|
expect(result).toMatchObject({ id: expect.any(String) });
|
|
169
171
|
});
|
|
170
172
|
|
|
171
173
|
// TODO: add error-path tests, repository mocks, etc.
|
|
172
174
|
});
|
|
173
|
-
`;q(
|
|
174
|
-
[frs] reminder: run "frs gen --root ${i}" to refresh the manifest.`);}finally{r.close();}}async function
|
|
175
|
+
`;q(F,$);}for(let $ of z)console.log(`[frs] wrote ${$}`);for(let $ of G)console.log(`[frs] skipped ${$} (use --force to overwrite)`);console.log(`
|
|
176
|
+
[frs] reminder: run "frs gen --root ${i}" to refresh the manifest.`);}finally{r.close();}}async function $e(e){let t=e.yes===true,s=ee(t);try{let r=e.force===!0,o=m(e.root);o||(o=(await s.ask("Domain root","src/domains")).trim()||"src/domains");let n=m(e["apis-file"]);n||(n=(await s.ask("apis.ts location","src/apis.ts")).trim()||"src/apis.ts");let c=m(e["services-file"]);if(!c){let l=n.replace(/apis\.ts$/,"services.ts")||"src/services.ts";c=(await s.ask("services.ts location",l)).trim()||l;}let i=m(e.apis);i||(i=(await s.ask("API tags (comma-separated)","v1")).trim()||"v1");let a=i.split(",").map(l=>l.trim()).filter(Boolean);a.length===0&&(console.error("[frs] at least one API tag is required"),process.exit(2));let d=m(e["base-path"]),f=path.resolve(process.cwd(),o),u=path.resolve(process.cwd(),n),b=path.resolve(process.cwd(),c),v=path.resolve(f,"__generated__"),S=path.resolve(v,"routes.ts"),g=[],D=[],y=(l,j)=>{if(fs.mkdirSync(path.dirname(l),{recursive:!0}),fs.existsSync(l)&&!r){D.push(l);return}fs.writeFileSync(l,j,"utf8"),g.push(l);},k=a.map(l=>{let j=d??`/${l}`;return ` ${l}: {
|
|
175
177
|
basePath: "${j}",
|
|
176
178
|
openapi: {
|
|
177
|
-
info: { title: "${
|
|
179
|
+
info: { title: "${l.toUpperCase()} API", version: "1.0.0", description: "" },
|
|
178
180
|
},
|
|
179
181
|
verbose: process.env["NODE_ENV"] !== "production",
|
|
180
182
|
},`}).join(`
|
|
181
|
-
`),
|
|
182
|
-
import { services } from "${E(path.dirname(u),
|
|
183
|
+
`),F=`import { createApiRegistry } from "@lpdjs/firestore-repo-service/servers/hono";
|
|
184
|
+
import { services } from "${E(path.dirname(u),b)}";
|
|
183
185
|
|
|
184
186
|
/**
|
|
185
187
|
* Single source of truth for every API exposed by this project.
|
|
@@ -199,7 +201,7 @@ ${k}
|
|
|
199
201
|
/** Typed helpers used inside every route file. */
|
|
200
202
|
export const defineRoute = apis.defineRoute;
|
|
201
203
|
export const useCaseRoute = apis.useCaseRoute;
|
|
202
|
-
`;
|
|
204
|
+
`;y(u,F),y(b,`import { createServices } from "@lpdjs/firestore-repo-service/servers/hono";
|
|
203
205
|
|
|
204
206
|
/**
|
|
205
207
|
* Global DI container \u2014 declare every singleton (repositories, SDK
|
|
@@ -232,13 +234,13 @@ export const services = createServices({
|
|
|
232
234
|
|
|
233
235
|
/** Convenience type \u2014 \`function fn(svc: Services) { ... }\`. */
|
|
234
236
|
export type Services = typeof services;
|
|
235
|
-
`);let
|
|
237
|
+
`);let P=`// AUTO-GENERATED by frs \u2014 do not edit.
|
|
236
238
|
// Run \`frs gen --root ${o}\` to refresh.
|
|
237
239
|
|
|
238
240
|
import type { AnyRouteDef } from "@lpdjs/firestore-repo-service/servers/hono";
|
|
239
241
|
|
|
240
242
|
export const routes: AnyRouteDef[] = [];
|
|
241
|
-
`;
|
|
243
|
+
`;y(S,P);let _=ge({root:o,apisFile:n,servicesFile:c,apis:a});g.push(_);let h=E(path.dirname(u),u),C=E(path.dirname(u),S),N=a.length===1?`export const { ${a[0]} } = apis.toFunctions(routes, onRequest, {`:`export const { ${a.join(", ")} } = apis.toFunctions(routes, onRequest, {`;for(let l of g)console.log(`[frs] wrote ${l}`);for(let l of D)console.log(`[frs] skipped ${l} (use --force to overwrite)`);console.log(`
|
|
242
244
|
Next steps:
|
|
243
245
|
|
|
244
246
|
1. Wire the registry in your Functions entrypoint (e.g. src/index.ts):
|
|
@@ -258,10 +260,10 @@ Next steps:
|
|
|
258
260
|
3. Refresh the manifest before each build:
|
|
259
261
|
|
|
260
262
|
frs gen --root ${o}
|
|
261
|
-
`);}finally{s.close();}}function E(e,t){let s=path.relative(e,t).replace(/\\/g,"/");return s=s.replace(/\.ts$/,".js"),s.startsWith(".")||(s=`./${s}`),s}async function
|
|
263
|
+
`);}finally{s.close();}}function E(e,t){let s=path.relative(e,t).replace(/\\/g,"/");return s=s.replace(/\.ts$/,".js"),s.startsWith(".")||(s=`./${s}`),s}async function we(e,t,s){e!=="service"&&(console.error(`[frs] unknown "add" target: ${e??"(missing)"} \u2014 supported: service`),process.exit(2)),t||(console.error("[frs] service name is required: frs add service <name>"),process.exit(2));let r=s.force===true,o=T(),c=[m(s["services-file"]),o.servicesFile,"src/services.ts","services.ts"].filter(h=>typeof h=="string"&&h.length>0),i;for(let h of c){let C=path.resolve(process.cwd(),h);if(fs.existsSync(C)){i=C;break}}if(!i){let h=c.map(C=>path.resolve(process.cwd(),C)).join(`
|
|
262
264
|
`);console.error(`[frs] services file not found. Tried:
|
|
263
265
|
${h}
|
|
264
|
-
Run \`frs init\` first or pass --services-file <path>.`),process.exit(2);}let a=m(s["services-dir"])??o.servicesDir??path.resolve(path.dirname(i),"services"),d=path.resolve(process.cwd(),a);fs.mkdirSync(d,{recursive:true});let f=`${t.charAt(0).toUpperCase()}${t.slice(1)}Service`,u=path.resolve(d,`${t}.ts`),
|
|
266
|
+
Run \`frs init\` first or pass --services-file <path>.`),process.exit(2);}let a=m(s["services-dir"])??o.servicesDir??path.resolve(path.dirname(i),"services"),d=path.resolve(process.cwd(),a);fs.mkdirSync(d,{recursive:true});let f=`${t.charAt(0).toUpperCase()}${t.slice(1)}Service`,u=path.resolve(d,`${t}.ts`),b=`import type { RequestContext } from "@lpdjs/firestore-repo-service/servers/hono";
|
|
265
267
|
|
|
266
268
|
/**
|
|
267
269
|
* ${f} \u2014 generated by \`frs add service ${t}\`.
|
|
@@ -290,9 +292,9 @@ export class ${f} {
|
|
|
290
292
|
return \`hello from ${t} \u2014 user=\${this.ctx.maybeC?.get("user")?.id ?? "anonymous"}\`;
|
|
291
293
|
}
|
|
292
294
|
}
|
|
293
|
-
`;fs.existsSync(u)&&!r?console.log(`[frs] skipped ${u} (use --force to overwrite)`):(fs.writeFileSync(u,
|
|
294
|
-
`),k=-1;for(let h=0;h<
|
|
295
|
-
`),
|
|
296
|
-
`+D+
|
|
297
|
-
`),Y(),process.exit(2);}}
|
|
295
|
+
`;fs.existsSync(u)&&!r?console.log(`[frs] skipped ${u} (use --force to overwrite)`):(fs.writeFileSync(u,b,"utf8"),console.log(`[frs] wrote ${u}`));let v=fs.readFileSync(i,"utf8"),S=E(path.dirname(i),u),g=`import { ${f} } from "${S}";`,D=` ${t}: ({ ctx }) => new ${f}(ctx),`;if(v.includes(g)){console.log(`[frs] services.ts already registers "${t}" \u2014 skipping.`);return}let y=v.split(`
|
|
296
|
+
`),k=-1;for(let h=0;h<y.length;h++)/^import\s/.test(y[h])&&(k=h);k>=0?y.splice(k+1,0,g):y.unshift(g);let F=y.join(`
|
|
297
|
+
`),w=F.match(/createServices\s*\(\s*\{/);if(!w){console.error(`[frs] could not find \`createServices({\` in ${i} \u2014 register "${t}" manually.`);return}let P=w.index+w[0].length,_=F.slice(0,P)+`
|
|
298
|
+
`+D+F.slice(P);fs.writeFileSync(i,_,"utf8"),console.log(`[frs] updated ${i} (+ ${t})`);}function xe(e,t){let s=["apis.ts","apis.js","api.ts","api.js"],r=[e,path.dirname(e),path.dirname(path.dirname(e))];for(let o of r)for(let n of s){let c=path.resolve(o,n);if(fs.existsSync(c)){let i=path.relative(t,c).replace(/\\/g,"/");return i=i.replace(/\.ts$/,".js").replace(/\.js$/,".js"),i.startsWith(".")||(i=`./${i}`),i}}return "../../../../apis.js"}function be(e,t){let s=["services.ts","services.js"],r=[e,path.dirname(e),path.dirname(path.dirname(e))];for(let o of r)for(let n of s){let c=path.resolve(o,n);if(fs.existsSync(c)){let i=path.relative(t,c).replace(/\\/g,"/");return i=i.replace(/\.ts$/,".js"),i.startsWith(".")||(i=`./${i}`),i}}return "../../../../services.js"}async function Se(){let e=process.argv.slice(2),{command:t,flags:s}=he(e);switch(t){case "init":await $e(s);return;case "gen":await ve(s);return;case "new":await ye(e[1],s);return;case "add":await we(e[1],e[2],s);return;case "help":case "--help":case "-h":Y();return;default:console.error(`[frs] unknown command: ${t}
|
|
299
|
+
`),Y(),process.exit(2);}}Se().catch(e=>{console.error(e),process.exit(1);});//# sourceMappingURL=cli.cjs.map
|
|
298
300
|
//# sourceMappingURL=cli.cjs.map
|