@percepta/create 4.1.6 → 4.1.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/{git-ops-BD7JNnal.js → git-ops-BNpQnEc1.js} +1 -1
- package/dist/{git-ops-BD7JNnal.js.map → git-ops-BNpQnEc1.js.map} +1 -1
- package/dist/{github-D3YOEl91.js → github-BOp8VQCY.js} +1 -1
- package/dist/{github-D3YOEl91.js.map → github-BOp8VQCY.js.map} +1 -1
- package/dist/index.js +107 -15
- package/dist/index.js.map +1 -1
- package/dist/{init-BD3EyyLO.js → init-CsuO_mu2.js} +2 -4
- package/dist/{init-BD3EyyLO.js.map → init-CsuO_mu2.js.map} +1 -1
- package/dist/{register-app-DZg-Pmtd.js → register-app-mNc1oYVK.js} +3 -5
- package/dist/{register-app-DZg-Pmtd.js.map → register-app-mNc1oYVK.js.map} +1 -1
- package/dist/{register-os-blueprint-Cgq1rXzQ.js → register-os-blueprint-Gdyn0pN1.js} +3 -4
- package/dist/{register-os-blueprint-Cgq1rXzQ.js.map → register-os-blueprint-Gdyn0pN1.js.map} +1 -1
- package/dist/{status-K6raTwwu.js → status-BrK9v1yb.js} +3 -3
- package/dist/{status-K6raTwwu.js.map → status-BrK9v1yb.js.map} +1 -1
- package/dist/{sync-Bi958-2W.js → sync-DC5DhIBT.js} +3 -3
- package/dist/{sync-Bi958-2W.js.map → sync-DC5DhIBT.js.map} +1 -1
- package/dist/{upstream-CAraZeSS.js → upstream-PNL6DGtl.js} +3 -3
- package/dist/{upstream-CAraZeSS.js.map → upstream-PNL6DGtl.js.map} +1 -1
- package/package.json +3 -3
- package/template-versions.json +2 -2
- package/templates/monorepo/auth/src/drizzle/migrations/meta/0000_snapshot.json +547 -0
- package/templates/monorepo/package.json.template +6 -6
- package/templates/monorepo/pnpm-workspace.yaml +1 -1
- package/templates/webapp/AGENTS.md +38 -16
- package/templates/webapp/README.md +56 -58
- package/templates/webapp/agent-skills/access-control.md +10 -9
- package/templates/webapp/agent-skills/database.md +10 -4
- package/templates/webapp/agent-skills/inngest.md +10 -8
- package/templates/webapp/agent-skills/langfuse.md +7 -5
- package/templates/webapp/agent-skills/oneshot.md +15 -13
- package/templates/webapp/package.json.template +5 -5
- package/templates/webapp/playwright.config.ts +1 -2
- package/templates/webapp/src/app/(app)/page.tsx +5 -3
- package/templates/webapp/src/app/(auth)/layout.tsx +2 -2
- package/templates/webapp/src/app/(settings)/settings/page.tsx +20 -21
- package/templates/webapp/src/components/FaroProvider.tsx +1 -2
- package/templates/webapp/src/components/Header.tsx +2 -8
- package/templates/webapp/src/components/form/FormItem.tsx +1 -1
- package/templates/webapp/src/drizzle/db.ts +3 -1
- package/templates/webapp/src/drizzle/schema/utils/jsonbFromZod.ts +1 -1
- package/templates/webapp/src/instrumentation.ts +3 -6
- package/templates/webapp/src/lib/auth-client.ts +3 -2
- package/templates/webapp/src/lib/trpc.ts +1 -1
- package/templates/webapp/src/server/trpc.ts +1 -1
- package/templates/webapp/src/services/DatabaseService.ts +1 -1
- package/templates/webapp/src/services/access/AppAccessControl.ts +1 -3
- package/templates/webapp/src/services/inngest/AppWorkflowService.ts +1 -1
- package/templates/webapp/src/styles/globals.css +13 -2
- package/dist/manifest-By1SgOjC.js +0 -59
- package/dist/manifest-By1SgOjC.js.map +0 -1
- package/dist/template-versions-CEIP9vhl.js +0 -35
- package/dist/template-versions-CEIP9vhl.js.map +0 -1
- package/dist/validate-dssldJAj.js +0 -14
- package/dist/validate-dssldJAj.js.map +0 -1
|
@@ -48,4 +48,4 @@ function getFileAtTag(repoPath, tag, filePath) {
|
|
|
48
48
|
//#endregion
|
|
49
49
|
export { getTemplateVersionFromTag as i, getLatestTemplateTag as n, getTemplateDiff as r, getFileAtTag as t };
|
|
50
50
|
|
|
51
|
-
//# sourceMappingURL=git-ops-
|
|
51
|
+
//# sourceMappingURL=git-ops-BNpQnEc1.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-ops-
|
|
1
|
+
{"version":3,"file":"git-ops-BNpQnEc1.js","names":[],"sources":["../src/utils/git-ops.ts"],"sourcesContent":["import { execFileSync } from \"node:child_process\";\n\n// Git requires forward slashes for in-repo paths regardless of OS\nfunction toGitPath(p: string): string {\n return p.replace(/\\\\/g, \"/\");\n}\n\nexport function getLatestTemplateTag(\n type: string,\n repoPath: string,\n): string | null {\n try {\n const tags = execFileSync(\n \"git\",\n [\"tag\", \"-l\", `template/${type}/*`, \"--sort=-v:refname\"],\n { cwd: repoPath, encoding: \"utf-8\" },\n ).trim();\n if (!tags) return null;\n return tags.split(\"\\n\")[0] ?? null;\n } catch {\n return null;\n }\n}\n\nexport function getTemplateVersionFromTag(tag: string): string {\n const parts = tag.split(\"/\");\n return parts[parts.length - 1] ?? \"\";\n}\n\nexport function getTemplateDiff(\n repoPath: string,\n templatePath: string,\n fromTag: string,\n toTag: string,\n): string {\n return execFileSync(\n \"git\",\n [\"diff\", `${fromTag}..${toTag}`, \"--\", toGitPath(templatePath)],\n {\n cwd: repoPath,\n encoding: \"utf-8\",\n },\n );\n}\n\nexport function getFileAtTag(\n repoPath: string,\n tag: string,\n filePath: string,\n): string | null {\n try {\n return execFileSync(\"git\", [\"show\", `${tag}:${toGitPath(filePath)}`], {\n cwd: repoPath,\n encoding: \"utf-8\",\n });\n } catch {\n return null;\n }\n}\n"],"mappings":";;AAGA,SAAS,UAAU,GAAmB;CACpC,OAAO,EAAE,QAAQ,OAAO,GAAG;AAC7B;AAEA,SAAgB,qBACd,MACA,UACe;CACf,IAAI;EACF,MAAM,OAAO,aACX,OACA;GAAC;GAAO;GAAM,YAAY,KAAK;GAAK;EAAmB,GACvD;GAAE,KAAK;GAAU,UAAU;EAAQ,CACrC,EAAE,KAAK;EACP,IAAI,CAAC,MAAM,OAAO;EAClB,OAAO,KAAK,MAAM,IAAI,EAAE,MAAM;CAChC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,0BAA0B,KAAqB;CAC7D,MAAM,QAAQ,IAAI,MAAM,GAAG;CAC3B,OAAO,MAAM,MAAM,SAAS,MAAM;AACpC;AAEA,SAAgB,gBACd,UACA,cACA,SACA,OACQ;CACR,OAAO,aACL,OACA;EAAC;EAAQ,GAAG,QAAQ,IAAI;EAAS;EAAM,UAAU,YAAY;CAAC,GAC9D;EACE,KAAK;EACL,UAAU;CACZ,CACF;AACF;AAEA,SAAgB,aACd,UACA,KACA,UACe;CACf,IAAI;EACF,OAAO,aAAa,OAAO,CAAC,QAAQ,GAAG,IAAI,GAAG,UAAU,QAAQ,GAAG,GAAG;GACpE,KAAK;GACL,UAAU;EACZ,CAAC;CACH,QAAQ;EACN,OAAO;CACT;AACF"}
|
|
@@ -144,4 +144,4 @@ function encodePathSegments(filePath) {
|
|
|
144
144
|
//#endregion
|
|
145
145
|
export { createOrUpdateInfraPullRequestFiles as a, createOrUpdateInfraPullRequest as i, INFRA_REPOSITORY as n, resolveGitHubToken as o, createInfraGitHubApi as r, INFRA_BASE_BRANCH as t };
|
|
146
146
|
|
|
147
|
-
//# sourceMappingURL=github-
|
|
147
|
+
//# sourceMappingURL=github-BOp8VQCY.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-D3YOEl91.js","names":[],"sources":["../src/commands/infra/github.ts"],"sourcesContent":["import { execFileSync } from \"node:child_process\";\n\nconst GITHUB_API_BASE_URL = \"https://api.github.com\";\n\nexport const INFRA_REPOSITORY = \"Percepta-Core/infra\";\nexport const INFRA_REPOSITORY_OWNER = \"Percepta-Core\";\nexport const INFRA_BASE_BRANCH = \"main\";\n\nexport interface GitHubFile {\n sha: string;\n content: string;\n}\n\nexport interface GitHubPullRequest {\n number: number;\n url: string;\n}\n\nexport interface InfraGitHubApi {\n getFile(path: string, ref: string): Promise<GitHubFile | null>;\n getBranchSha(branch: string): Promise<string | null>;\n createBranch(branch: string, sha: string): Promise<void>;\n putFile(args: {\n path: string;\n branch: string;\n content: string;\n message: string;\n sha?: string;\n }): Promise<void>;\n findOpenPullRequest(branch: string): Promise<GitHubPullRequest | null>;\n createPullRequest(args: {\n branch: string;\n title: string;\n body: string;\n }): Promise<GitHubPullRequest>;\n}\n\nexport interface InfraPullRequestResult {\n pullRequestUrl: string;\n status: \"created_pr\" | \"updated_pr\";\n}\n\nexport interface InfraPullRequestFile {\n baseFileSha?: string;\n content: string;\n message: string;\n path: string;\n}\n\nexport async function createOrUpdateInfraPullRequest(args: {\n baseFileSha?: string;\n body: string;\n branchName: string;\n content: string;\n github: InfraGitHubApi;\n message: string;\n targetPath: string;\n title: string;\n}): Promise<InfraPullRequestResult> {\n return createOrUpdateInfraPullRequestFiles({\n body: args.body,\n branchName: args.branchName,\n files: [\n {\n baseFileSha: args.baseFileSha,\n content: args.content,\n message: args.message,\n path: args.targetPath,\n },\n ],\n github: args.github,\n title: args.title,\n });\n}\n\nexport async function createOrUpdateInfraPullRequestFiles(args: {\n body: string;\n branchName: string;\n files: InfraPullRequestFile[];\n github: InfraGitHubApi;\n title: string;\n}): Promise<InfraPullRequestResult> {\n const mainSha = await args.github.getBranchSha(INFRA_BASE_BRANCH);\n if (!mainSha) {\n throw new Error(`Could not find ${INFRA_REPOSITORY}@${INFRA_BASE_BRANCH}.`);\n }\n\n if (!(await args.github.getBranchSha(args.branchName))) {\n await args.github.createBranch(args.branchName, mainSha);\n }\n\n const existingPullRequest = await args.github.findOpenPullRequest(\n args.branchName,\n );\n\n for (const file of args.files) {\n const branchFile = await args.github.getFile(file.path, args.branchName);\n if (branchFile?.content !== file.content) {\n await args.github.putFile({\n path: file.path,\n branch: args.branchName,\n content: file.content,\n message: file.message,\n sha: branchFile?.sha ?? file.baseFileSha,\n });\n }\n }\n\n const pullRequest =\n existingPullRequest ??\n (await args.github.createPullRequest({\n branch: args.branchName,\n title: args.title,\n body: args.body,\n }));\n\n return {\n pullRequestUrl: pullRequest.url,\n status: existingPullRequest ? \"updated_pr\" : \"created_pr\",\n };\n}\n\nexport function createInfraGitHubApi(token: string): InfraGitHubApi {\n return {\n async getFile(filePath, ref) {\n const encodedPath = encodePathSegments(filePath);\n const response = await requestGitHub<{\n content?: unknown;\n sha?: unknown;\n type?: unknown;\n }>(\n token,\n \"GET\",\n `/repos/${INFRA_REPOSITORY}/contents/${encodedPath}?ref=${encodeURIComponent(ref)}`,\n );\n if (response == null) return null;\n if (\n typeof response.sha !== \"string\" ||\n typeof response.content !== \"string\" ||\n response.type !== \"file\"\n ) {\n throw new Error(\n `Unexpected GitHub content response for ${filePath} in ${INFRA_REPOSITORY}.`,\n );\n }\n\n return {\n sha: response.sha,\n content: Buffer.from(\n response.content.replace(/\\s/g, \"\"),\n \"base64\",\n ).toString(\"utf-8\"),\n };\n },\n\n async getBranchSha(branch) {\n const response = await requestGitHub<{\n object?: { sha?: unknown };\n }>(token, \"GET\", `/repos/${INFRA_REPOSITORY}/git/ref/heads/${branch}`);\n if (response == null) return null;\n const sha = response.object?.sha;\n if (typeof sha !== \"string\") {\n throw new Error(`Unexpected GitHub ref response for ${branch}.`);\n }\n return sha;\n },\n\n async createBranch(branch, sha) {\n await requestGitHub(\n token,\n \"POST\",\n `/repos/${INFRA_REPOSITORY}/git/refs`,\n {\n ref: `refs/heads/${branch}`,\n sha,\n },\n );\n },\n\n async putFile({ path: filePath, branch, content, message, sha }) {\n const encodedPath = encodePathSegments(filePath);\n await requestGitHub(\n token,\n \"PUT\",\n `/repos/${INFRA_REPOSITORY}/contents/${encodedPath}`,\n {\n branch,\n content: Buffer.from(content, \"utf-8\").toString(\"base64\"),\n message,\n sha,\n },\n );\n },\n\n async findOpenPullRequest(branch) {\n const params = new URLSearchParams({\n base: INFRA_BASE_BRANCH,\n head: `${INFRA_REPOSITORY_OWNER}:${branch}`,\n state: \"open\",\n });\n const response = await requestGitHub<\n Array<{ html_url?: unknown; number?: unknown }>\n >(token, \"GET\", `/repos/${INFRA_REPOSITORY}/pulls?${params}`);\n const pullRequest = response?.[0];\n if (!pullRequest) return null;\n if (\n typeof pullRequest.html_url !== \"string\" ||\n typeof pullRequest.number !== \"number\"\n ) {\n throw new Error(`Unexpected GitHub pull request response.`);\n }\n return {\n number: pullRequest.number,\n url: pullRequest.html_url,\n };\n },\n\n async createPullRequest({ branch, title, body }) {\n const response = await requestGitHub<{\n html_url?: unknown;\n number?: unknown;\n }>(token, \"POST\", `/repos/${INFRA_REPOSITORY}/pulls`, {\n base: INFRA_BASE_BRANCH,\n body,\n head: branch,\n maintainer_can_modify: true,\n title,\n });\n if (\n !response ||\n typeof response.html_url !== \"string\" ||\n typeof response.number !== \"number\"\n ) {\n throw new Error(`Unexpected GitHub pull request response.`);\n }\n return {\n number: response.number,\n url: response.html_url,\n };\n },\n };\n}\n\nexport function resolveGitHubToken(): string {\n const envToken = process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN;\n if (envToken) return envToken;\n\n try {\n const token = execFileSync(\"gh\", [\"auth\", \"token\"], {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim();\n if (token) return token;\n } catch {\n // Fall through to the actionable error below.\n }\n\n throw new Error(\n \"GitHub auth is required. Set GITHUB_TOKEN or GH_TOKEN, or run `gh auth login`.\",\n );\n}\n\nasync function requestGitHub<T>(\n token: string,\n method: string,\n path: string,\n body?: unknown,\n): Promise<T | null> {\n const response = await fetch(`${GITHUB_API_BASE_URL}${path}`, {\n method,\n headers: {\n Accept: \"application/vnd.github+json\",\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n });\n\n if (response.status === 404) return null;\n\n if (!response.ok) {\n const responseText = await response.text();\n throw new Error(\n `GitHub ${method} ${path} failed with ${response.status}: ${responseText}`,\n );\n }\n\n if (response.status === 204) return null;\n return (await response.json()) as T;\n}\n\nfunction encodePathSegments(filePath: string): string {\n return filePath.split(\"/\").map(encodeURIComponent).join(\"/\");\n}\n"],"mappings":";;AAEA,MAAM,sBAAsB;AAE5B,MAAa,mBAAmB;AAChC,MAAa,yBAAyB;AACtC,MAAa,oBAAoB;AA2CjC,eAAsB,+BAA+B,MASjB;AAClC,QAAO,oCAAoC;EACzC,MAAM,KAAK;EACX,YAAY,KAAK;EACjB,OAAO,CACL;GACE,aAAa,KAAK;GAClB,SAAS,KAAK;GACd,SAAS,KAAK;GACd,MAAM,KAAK;GACZ,CACF;EACD,QAAQ,KAAK;EACb,OAAO,KAAK;EACb,CAAC;;AAGJ,eAAsB,oCAAoC,MAMtB;CAClC,MAAM,UAAU,MAAM,KAAK,OAAO,aAAa,kBAAkB;AACjE,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,kBAAkB,iBAAiB,GAAG,kBAAkB,GAAG;AAG7E,KAAI,CAAE,MAAM,KAAK,OAAO,aAAa,KAAK,WAAW,CACnD,OAAM,KAAK,OAAO,aAAa,KAAK,YAAY,QAAQ;CAG1D,MAAM,sBAAsB,MAAM,KAAK,OAAO,oBAC5C,KAAK,WACN;AAED,MAAK,MAAM,QAAQ,KAAK,OAAO;EAC7B,MAAM,aAAa,MAAM,KAAK,OAAO,QAAQ,KAAK,MAAM,KAAK,WAAW;AACxE,MAAI,YAAY,YAAY,KAAK,QAC/B,OAAM,KAAK,OAAO,QAAQ;GACxB,MAAM,KAAK;GACX,QAAQ,KAAK;GACb,SAAS,KAAK;GACd,SAAS,KAAK;GACd,KAAK,YAAY,OAAO,KAAK;GAC9B,CAAC;;AAYN,QAAO;EACL,iBARA,uBACC,MAAM,KAAK,OAAO,kBAAkB;GACnC,QAAQ,KAAK;GACb,OAAO,KAAK;GACZ,MAAM,KAAK;GACZ,CAAC,EAG0B;EAC5B,QAAQ,sBAAsB,eAAe;EAC9C;;AAGH,SAAgB,qBAAqB,OAA+B;AAClE,QAAO;EACL,MAAM,QAAQ,UAAU,KAAK;GAE3B,MAAM,WAAW,MAAM,cAKrB,OACA,OACA,UAAU,iBAAiB,YART,mBAAmB,SAQa,CAAC,OAAO,mBAAmB,IAAI,GAClF;AACD,OAAI,YAAY,KAAM,QAAO;AAC7B,OACE,OAAO,SAAS,QAAQ,YACxB,OAAO,SAAS,YAAY,YAC5B,SAAS,SAAS,OAElB,OAAM,IAAI,MACR,0CAA0C,SAAS,MAAM,iBAAiB,GAC3E;AAGH,UAAO;IACL,KAAK,SAAS;IACd,SAAS,OAAO,KACd,SAAS,QAAQ,QAAQ,OAAO,GAAG,EACnC,SACD,CAAC,SAAS,QAAQ;IACpB;;EAGH,MAAM,aAAa,QAAQ;GACzB,MAAM,WAAW,MAAM,cAEpB,OAAO,OAAO,UAAU,iBAAiB,iBAAiB,SAAS;AACtE,OAAI,YAAY,KAAM,QAAO;GAC7B,MAAM,MAAM,SAAS,QAAQ;AAC7B,OAAI,OAAO,QAAQ,SACjB,OAAM,IAAI,MAAM,sCAAsC,OAAO,GAAG;AAElE,UAAO;;EAGT,MAAM,aAAa,QAAQ,KAAK;AAC9B,SAAM,cACJ,OACA,QACA,UAAU,iBAAiB,YAC3B;IACE,KAAK,cAAc;IACnB;IACD,CACF;;EAGH,MAAM,QAAQ,EAAE,MAAM,UAAU,QAAQ,SAAS,SAAS,OAAO;AAE/D,SAAM,cACJ,OACA,OACA,UAAU,iBAAiB,YAJT,mBAAmB,SAIa,IAClD;IACE;IACA,SAAS,OAAO,KAAK,SAAS,QAAQ,CAAC,SAAS,SAAS;IACzD;IACA;IACD,CACF;;EAGH,MAAM,oBAAoB,QAAQ;GAShC,MAAM,eAAc,MAHG,cAErB,OAAO,OAAO,UAAU,iBAAiB,SAAS,IAPjC,gBAAgB;IACjC,MAAM;IACN,MAAM,GAAG,uBAAuB,GAAG;IACnC,OAAO;IACR,CAGyD,GAAG,IAC9B;AAC/B,OAAI,CAAC,YAAa,QAAO;AACzB,OACE,OAAO,YAAY,aAAa,YAChC,OAAO,YAAY,WAAW,SAE9B,OAAM,IAAI,MAAM,2CAA2C;AAE7D,UAAO;IACL,QAAQ,YAAY;IACpB,KAAK,YAAY;IAClB;;EAGH,MAAM,kBAAkB,EAAE,QAAQ,OAAO,QAAQ;GAC/C,MAAM,WAAW,MAAM,cAGpB,OAAO,QAAQ,UAAU,iBAAiB,SAAS;IACpD,MAAM;IACN;IACA,MAAM;IACN,uBAAuB;IACvB;IACD,CAAC;AACF,OACE,CAAC,YACD,OAAO,SAAS,aAAa,YAC7B,OAAO,SAAS,WAAW,SAE3B,OAAM,IAAI,MAAM,2CAA2C;AAE7D,UAAO;IACL,QAAQ,SAAS;IACjB,KAAK,SAAS;IACf;;EAEJ;;AAGH,SAAgB,qBAA6B;CAC3C,MAAM,WAAW,QAAQ,IAAI,gBAAgB,QAAQ,IAAI;AACzD,KAAI,SAAU,QAAO;AAErB,KAAI;EACF,MAAM,QAAQ,aAAa,MAAM,CAAC,QAAQ,QAAQ,EAAE;GAClD,UAAU;GACV,OAAO;IAAC;IAAU;IAAQ;IAAS;GACpC,CAAC,CAAC,MAAM;AACT,MAAI,MAAO,QAAO;SACZ;AAIR,OAAM,IAAI,MACR,iFACD;;AAGH,eAAe,cACb,OACA,QACA,MACA,MACmB;CACnB,MAAM,WAAW,MAAM,MAAM,GAAG,sBAAsB,QAAQ;EAC5D;EACA,SAAS;GACP,QAAQ;GACR,eAAe,UAAU;GACzB,gBAAgB;GAChB,wBAAwB;GACzB;EACD,MAAM,SAAS,KAAA,IAAY,KAAA,IAAY,KAAK,UAAU,KAAK;EAC5D,CAAC;AAEF,KAAI,SAAS,WAAW,IAAK,QAAO;AAEpC,KAAI,CAAC,SAAS,IAAI;EAChB,MAAM,eAAe,MAAM,SAAS,MAAM;AAC1C,QAAM,IAAI,MACR,UAAU,OAAO,GAAG,KAAK,eAAe,SAAS,OAAO,IAAI,eAC7D;;AAGH,KAAI,SAAS,WAAW,IAAK,QAAO;AACpC,QAAQ,MAAM,SAAS,MAAM;;AAG/B,SAAS,mBAAmB,UAA0B;AACpD,QAAO,SAAS,MAAM,IAAI,CAAC,IAAI,mBAAmB,CAAC,KAAK,IAAI"}
|
|
1
|
+
{"version":3,"file":"github-BOp8VQCY.js","names":[],"sources":["../src/commands/infra/github.ts"],"sourcesContent":["import { execFileSync } from \"node:child_process\";\n\nconst GITHUB_API_BASE_URL = \"https://api.github.com\";\n\nexport const INFRA_REPOSITORY = \"Percepta-Core/infra\";\nexport const INFRA_REPOSITORY_OWNER = \"Percepta-Core\";\nexport const INFRA_BASE_BRANCH = \"main\";\n\nexport interface GitHubFile {\n sha: string;\n content: string;\n}\n\nexport interface GitHubPullRequest {\n number: number;\n url: string;\n}\n\nexport interface InfraGitHubApi {\n getFile(path: string, ref: string): Promise<GitHubFile | null>;\n getBranchSha(branch: string): Promise<string | null>;\n createBranch(branch: string, sha: string): Promise<void>;\n putFile(args: {\n path: string;\n branch: string;\n content: string;\n message: string;\n sha?: string;\n }): Promise<void>;\n findOpenPullRequest(branch: string): Promise<GitHubPullRequest | null>;\n createPullRequest(args: {\n branch: string;\n title: string;\n body: string;\n }): Promise<GitHubPullRequest>;\n}\n\nexport interface InfraPullRequestResult {\n pullRequestUrl: string;\n status: \"created_pr\" | \"updated_pr\";\n}\n\nexport interface InfraPullRequestFile {\n baseFileSha?: string;\n content: string;\n message: string;\n path: string;\n}\n\nexport async function createOrUpdateInfraPullRequest(args: {\n baseFileSha?: string;\n body: string;\n branchName: string;\n content: string;\n github: InfraGitHubApi;\n message: string;\n targetPath: string;\n title: string;\n}): Promise<InfraPullRequestResult> {\n return createOrUpdateInfraPullRequestFiles({\n body: args.body,\n branchName: args.branchName,\n files: [\n {\n baseFileSha: args.baseFileSha,\n content: args.content,\n message: args.message,\n path: args.targetPath,\n },\n ],\n github: args.github,\n title: args.title,\n });\n}\n\nexport async function createOrUpdateInfraPullRequestFiles(args: {\n body: string;\n branchName: string;\n files: InfraPullRequestFile[];\n github: InfraGitHubApi;\n title: string;\n}): Promise<InfraPullRequestResult> {\n const mainSha = await args.github.getBranchSha(INFRA_BASE_BRANCH);\n if (!mainSha) {\n throw new Error(`Could not find ${INFRA_REPOSITORY}@${INFRA_BASE_BRANCH}.`);\n }\n\n if (!(await args.github.getBranchSha(args.branchName))) {\n await args.github.createBranch(args.branchName, mainSha);\n }\n\n const existingPullRequest = await args.github.findOpenPullRequest(\n args.branchName,\n );\n\n for (const file of args.files) {\n const branchFile = await args.github.getFile(file.path, args.branchName);\n if (branchFile?.content !== file.content) {\n await args.github.putFile({\n path: file.path,\n branch: args.branchName,\n content: file.content,\n message: file.message,\n sha: branchFile?.sha ?? file.baseFileSha,\n });\n }\n }\n\n const pullRequest =\n existingPullRequest ??\n (await args.github.createPullRequest({\n branch: args.branchName,\n title: args.title,\n body: args.body,\n }));\n\n return {\n pullRequestUrl: pullRequest.url,\n status: existingPullRequest ? \"updated_pr\" : \"created_pr\",\n };\n}\n\nexport function createInfraGitHubApi(token: string): InfraGitHubApi {\n return {\n async getFile(filePath, ref) {\n const encodedPath = encodePathSegments(filePath);\n const response = await requestGitHub<{\n content?: unknown;\n sha?: unknown;\n type?: unknown;\n }>(\n token,\n \"GET\",\n `/repos/${INFRA_REPOSITORY}/contents/${encodedPath}?ref=${encodeURIComponent(ref)}`,\n );\n if (response == null) return null;\n if (\n typeof response.sha !== \"string\" ||\n typeof response.content !== \"string\" ||\n response.type !== \"file\"\n ) {\n throw new Error(\n `Unexpected GitHub content response for ${filePath} in ${INFRA_REPOSITORY}.`,\n );\n }\n\n return {\n sha: response.sha,\n content: Buffer.from(\n response.content.replace(/\\s/g, \"\"),\n \"base64\",\n ).toString(\"utf-8\"),\n };\n },\n\n async getBranchSha(branch) {\n const response = await requestGitHub<{\n object?: { sha?: unknown };\n }>(token, \"GET\", `/repos/${INFRA_REPOSITORY}/git/ref/heads/${branch}`);\n if (response == null) return null;\n const sha = response.object?.sha;\n if (typeof sha !== \"string\") {\n throw new Error(`Unexpected GitHub ref response for ${branch}.`);\n }\n return sha;\n },\n\n async createBranch(branch, sha) {\n await requestGitHub(\n token,\n \"POST\",\n `/repos/${INFRA_REPOSITORY}/git/refs`,\n {\n ref: `refs/heads/${branch}`,\n sha,\n },\n );\n },\n\n async putFile({ path: filePath, branch, content, message, sha }) {\n const encodedPath = encodePathSegments(filePath);\n await requestGitHub(\n token,\n \"PUT\",\n `/repos/${INFRA_REPOSITORY}/contents/${encodedPath}`,\n {\n branch,\n content: Buffer.from(content, \"utf-8\").toString(\"base64\"),\n message,\n sha,\n },\n );\n },\n\n async findOpenPullRequest(branch) {\n const params = new URLSearchParams({\n base: INFRA_BASE_BRANCH,\n head: `${INFRA_REPOSITORY_OWNER}:${branch}`,\n state: \"open\",\n });\n const response = await requestGitHub<\n Array<{ html_url?: unknown; number?: unknown }>\n >(token, \"GET\", `/repos/${INFRA_REPOSITORY}/pulls?${params}`);\n const pullRequest = response?.[0];\n if (!pullRequest) return null;\n if (\n typeof pullRequest.html_url !== \"string\" ||\n typeof pullRequest.number !== \"number\"\n ) {\n throw new Error(`Unexpected GitHub pull request response.`);\n }\n return {\n number: pullRequest.number,\n url: pullRequest.html_url,\n };\n },\n\n async createPullRequest({ branch, title, body }) {\n const response = await requestGitHub<{\n html_url?: unknown;\n number?: unknown;\n }>(token, \"POST\", `/repos/${INFRA_REPOSITORY}/pulls`, {\n base: INFRA_BASE_BRANCH,\n body,\n head: branch,\n maintainer_can_modify: true,\n title,\n });\n if (\n !response ||\n typeof response.html_url !== \"string\" ||\n typeof response.number !== \"number\"\n ) {\n throw new Error(`Unexpected GitHub pull request response.`);\n }\n return {\n number: response.number,\n url: response.html_url,\n };\n },\n };\n}\n\nexport function resolveGitHubToken(): string {\n const envToken = process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN;\n if (envToken) return envToken;\n\n try {\n const token = execFileSync(\"gh\", [\"auth\", \"token\"], {\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim();\n if (token) return token;\n } catch {\n // Fall through to the actionable error below.\n }\n\n throw new Error(\n \"GitHub auth is required. Set GITHUB_TOKEN or GH_TOKEN, or run `gh auth login`.\",\n );\n}\n\nasync function requestGitHub<T>(\n token: string,\n method: string,\n path: string,\n body?: unknown,\n): Promise<T | null> {\n const response = await fetch(`${GITHUB_API_BASE_URL}${path}`, {\n method,\n headers: {\n Accept: \"application/vnd.github+json\",\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n });\n\n if (response.status === 404) return null;\n\n if (!response.ok) {\n const responseText = await response.text();\n throw new Error(\n `GitHub ${method} ${path} failed with ${response.status}: ${responseText}`,\n );\n }\n\n if (response.status === 204) return null;\n return (await response.json()) as T;\n}\n\nfunction encodePathSegments(filePath: string): string {\n return filePath.split(\"/\").map(encodeURIComponent).join(\"/\");\n}\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { i as toTitleCase, n as toKebabCase, r as toSnakeCase, t as getTemplateVersion } from "./template-versions-CEIP9vhl.js";
|
|
3
|
-
import { a as writeManifest, c as isValidMosaicDesignTheme, o as DEFAULT_MOSAIC_DESIGN_THEME, s as VALID_MOSAIC_DESIGN_THEMES, t as derivePlaceholders } from "./manifest-By1SgOjC.js";
|
|
4
|
-
import { t as validateProjectName } from "./validate-dssldJAj.js";
|
|
5
2
|
import { program } from "commander";
|
|
6
3
|
import { execSync, spawn } from "node:child_process";
|
|
7
4
|
import path from "node:path";
|
|
@@ -12,6 +9,21 @@ import { fileURLToPath } from "node:url";
|
|
|
12
9
|
import { parse } from "yaml";
|
|
13
10
|
import { randomBytes } from "node:crypto";
|
|
14
11
|
import inquirer from "inquirer";
|
|
12
|
+
import validateNpmPackageName from "validate-npm-package-name";
|
|
13
|
+
//#region src/utils/case-converters.ts
|
|
14
|
+
/** Lowercase, hyphenated, npm-package-name-safe form: "My Cool App" → "my-cool-app". */
|
|
15
|
+
function toKebabCase(str) {
|
|
16
|
+
return str.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
17
|
+
}
|
|
18
|
+
/** Display form derived from a kebab-case name: "my-cool-app" → "My Cool App". */
|
|
19
|
+
function toTitleCase(str) {
|
|
20
|
+
return str.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
21
|
+
}
|
|
22
|
+
/** Identifier form for env vars and DB names: "my-cool-app" → "my_cool_app". */
|
|
23
|
+
function toSnakeCase(str) {
|
|
24
|
+
return str.replace(/-/g, "_");
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
15
27
|
//#region src/utils/copy-template.ts
|
|
16
28
|
const __filename = fileURLToPath(import.meta.url);
|
|
17
29
|
const __dirname = path.dirname(__filename);
|
|
@@ -45,7 +57,8 @@ function shouldSkip(src) {
|
|
|
45
57
|
return false;
|
|
46
58
|
}
|
|
47
59
|
function getTemplateDir(templateType) {
|
|
48
|
-
|
|
60
|
+
const candidates = [path.resolve(__dirname, "../templates", templateType), path.resolve(__dirname, "../../templates", templateType)];
|
|
61
|
+
return candidates.find((candidate) => fs.existsSync(candidate)) ?? candidates[0];
|
|
49
62
|
}
|
|
50
63
|
async function copyTemplate(targetDir, templateType) {
|
|
51
64
|
const templateDir = getTemplateDir(templateType);
|
|
@@ -67,6 +80,17 @@ async function copyTemplate(targetDir, templateType) {
|
|
|
67
80
|
}
|
|
68
81
|
}
|
|
69
82
|
//#endregion
|
|
83
|
+
//#region src/utils/design-theme.ts
|
|
84
|
+
const VALID_MOSAIC_DESIGN_THEMES = [
|
|
85
|
+
"paper",
|
|
86
|
+
"modern",
|
|
87
|
+
"dense"
|
|
88
|
+
];
|
|
89
|
+
const DEFAULT_MOSAIC_DESIGN_THEME = "modern";
|
|
90
|
+
function isValidMosaicDesignTheme(value) {
|
|
91
|
+
return typeof value === "string" && VALID_MOSAIC_DESIGN_THEMES.includes(value);
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
70
94
|
//#region src/utils/detect-monorepo.ts
|
|
71
95
|
const NOT_FOUND = {
|
|
72
96
|
found: false,
|
|
@@ -125,6 +149,49 @@ async function generateEnvLocal(packageDir) {
|
|
|
125
149
|
}
|
|
126
150
|
}
|
|
127
151
|
//#endregion
|
|
152
|
+
//#region src/utils/manifest.ts
|
|
153
|
+
const MANIFEST_FILENAME = ".mosaic-template.json";
|
|
154
|
+
function getManifestPath(dir) {
|
|
155
|
+
return path.join(dir, MANIFEST_FILENAME);
|
|
156
|
+
}
|
|
157
|
+
async function readManifest(dir) {
|
|
158
|
+
const manifestPath = getManifestPath(dir);
|
|
159
|
+
if (!await fs.pathExists(manifestPath)) throw new Error(`No ${MANIFEST_FILENAME} found in ${dir}. Run 'create init' to create one.`);
|
|
160
|
+
const content = await fs.readFile(manifestPath, "utf-8");
|
|
161
|
+
try {
|
|
162
|
+
return JSON.parse(content);
|
|
163
|
+
} catch (error) {
|
|
164
|
+
throw new Error(`Invalid JSON in ${MANIFEST_FILENAME}: ${error.message}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
async function writeManifest(dir, manifest) {
|
|
168
|
+
const manifestPath = getManifestPath(dir);
|
|
169
|
+
await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
|
|
170
|
+
}
|
|
171
|
+
async function manifestExists(dir) {
|
|
172
|
+
return fs.pathExists(getManifestPath(dir));
|
|
173
|
+
}
|
|
174
|
+
function derivePlaceholders(appName, appTitle, repoName = appName, customerSlug = repoName, designTheme = DEFAULT_MOSAIC_DESIGN_THEME) {
|
|
175
|
+
const nameSnake = appName.replace(/-/g, "_");
|
|
176
|
+
const repoNameSnake = repoName.replace(/-/g, "_");
|
|
177
|
+
return {
|
|
178
|
+
__APP_NAME__: appName,
|
|
179
|
+
__APP_TITLE__: appTitle,
|
|
180
|
+
__DB_NAME__: nameSnake + "_db",
|
|
181
|
+
__APP_NAME_UPPER__: appName.toUpperCase(),
|
|
182
|
+
__APP_NAME_SNAKE__: nameSnake,
|
|
183
|
+
__REPO_NAME__: repoName,
|
|
184
|
+
__REPO_NAME_SNAKE__: repoNameSnake,
|
|
185
|
+
__CUSTOMER_SLUG__: customerSlug,
|
|
186
|
+
__MOSAIC_DESIGN_THEME__: designTheme
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function resolveMosaicTemplatePath(options) {
|
|
190
|
+
if (options.mosaicTemplatePath) return path.resolve(options.mosaicTemplatePath);
|
|
191
|
+
if (process.env.MOSAIC_TEMPLATE_PATH) return path.resolve(process.env.MOSAIC_TEMPLATE_PATH);
|
|
192
|
+
throw new Error("Mosaic repo path required. Use --mosaic-template-path or set MOSAIC_TEMPLATE_PATH.");
|
|
193
|
+
}
|
|
194
|
+
//#endregion
|
|
128
195
|
//#region src/utils/package-metadata.ts
|
|
129
196
|
const FALLBACK_METADATA = {
|
|
130
197
|
name: "@percepta/create",
|
|
@@ -143,6 +210,16 @@ function readCreatePackageMetadata() {
|
|
|
143
210
|
return FALLBACK_METADATA;
|
|
144
211
|
}
|
|
145
212
|
//#endregion
|
|
213
|
+
//#region src/utils/validate.ts
|
|
214
|
+
function validateProjectName(name) {
|
|
215
|
+
const result = validateNpmPackageName(name);
|
|
216
|
+
if (!result.validForNewPackages) return {
|
|
217
|
+
valid: false,
|
|
218
|
+
error: [...result.errors || [], ...result.warnings || []][0] || "Invalid package name"
|
|
219
|
+
};
|
|
220
|
+
return { valid: true };
|
|
221
|
+
}
|
|
222
|
+
//#endregion
|
|
146
223
|
//#region src/utils/prompts.ts
|
|
147
224
|
const VALID_PROJECT_TYPES = [
|
|
148
225
|
"monorepo",
|
|
@@ -441,6 +518,21 @@ async function replacePlaceholders(targetDir, config) {
|
|
|
441
518
|
return stats;
|
|
442
519
|
}
|
|
443
520
|
//#endregion
|
|
521
|
+
//#region src/utils/template-versions.ts
|
|
522
|
+
const FALLBACK_TEMPLATE_VERSION = "1.0.0";
|
|
523
|
+
function readTemplateVersions() {
|
|
524
|
+
const currentDir = path.dirname(fileURLToPath(import.meta.url));
|
|
525
|
+
const candidates = [path.resolve(currentDir, "../template-versions.json"), path.resolve(currentDir, "../../template-versions.json")];
|
|
526
|
+
for (const versionsPath of candidates) try {
|
|
527
|
+
const content = fs.readFileSync(versionsPath, "utf-8");
|
|
528
|
+
return JSON.parse(content);
|
|
529
|
+
} catch {}
|
|
530
|
+
return {};
|
|
531
|
+
}
|
|
532
|
+
function getTemplateVersion(templateType) {
|
|
533
|
+
return readTemplateVersions()[templateType] ?? FALLBACK_TEMPLATE_VERSION;
|
|
534
|
+
}
|
|
535
|
+
//#endregion
|
|
444
536
|
//#region src/utils/workspace-manifest.ts
|
|
445
537
|
const WORKSPACE_MANIFEST_FILENAME = ".mosaic-workspace.json";
|
|
446
538
|
function getWorkspaceManifestPath(rootDir) {
|
|
@@ -473,8 +565,7 @@ async function readWorkspaceManifest(rootDir) {
|
|
|
473
565
|
}
|
|
474
566
|
async function writeWorkspaceManifest(rootDir, manifest) {
|
|
475
567
|
const manifestPath = getWorkspaceManifestPath(rootDir);
|
|
476
|
-
await fs.
|
|
477
|
-
await fs.appendFile(manifestPath, "\n");
|
|
568
|
+
await fs.writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
|
|
478
569
|
}
|
|
479
570
|
function getCompatibleTemplateVersion(manifest, templateType) {
|
|
480
571
|
return manifest?.compatibleTemplates[templateType] ?? getTemplateVersion(templateType);
|
|
@@ -485,6 +576,7 @@ const PACKAGE_MANAGER = "pnpm";
|
|
|
485
576
|
const MAX_INSTALL_OUTPUT_CHARS = 64e3;
|
|
486
577
|
const MAX_INSTALL_OUTPUT_LINES = 80;
|
|
487
578
|
var PackageManagerCommandError = class extends Error {
|
|
579
|
+
output;
|
|
488
580
|
constructor(message, output) {
|
|
489
581
|
super(message);
|
|
490
582
|
this.output = output;
|
|
@@ -501,7 +593,7 @@ function runPackageManagerInstall(packageManager, cwd, args = ["install"]) {
|
|
|
501
593
|
let output = "";
|
|
502
594
|
const appendOutput = (chunk) => {
|
|
503
595
|
output += chunk.toString();
|
|
504
|
-
if (output.length > MAX_INSTALL_OUTPUT_CHARS) output = output.slice(-
|
|
596
|
+
if (output.length > MAX_INSTALL_OUTPUT_CHARS) output = output.slice(-64e3);
|
|
505
597
|
};
|
|
506
598
|
const child = spawn(packageManager, args, {
|
|
507
599
|
cwd,
|
|
@@ -528,7 +620,7 @@ function printInstallFailureOutput(error) {
|
|
|
528
620
|
if (!output) return;
|
|
529
621
|
const lines = output.split(/\r?\n/);
|
|
530
622
|
const omitted = Math.max(0, lines.length - MAX_INSTALL_OUTPUT_LINES);
|
|
531
|
-
const visibleLines = lines.slice(-
|
|
623
|
+
const visibleLines = lines.slice(-80);
|
|
532
624
|
console.log();
|
|
533
625
|
console.log(chalk.bold(`Last ${visibleLines.length} lines from pnpm install:`));
|
|
534
626
|
if (omitted > 0) console.log(chalk.dim(`... omitted ${omitted} earlier lines ...`));
|
|
@@ -1207,31 +1299,31 @@ program.command("add").description("Add a Mosaic package to the current monorepo
|
|
|
1207
1299
|
});
|
|
1208
1300
|
const infra = program.command("infra").description("Manage Mosaic infra glue");
|
|
1209
1301
|
infra.command("register-os-blueprint").description("Register this customer monorepo's OS blueprint in infra").action(async () => {
|
|
1210
|
-
const { registerOsBlueprintCommand } = await import("./register-os-blueprint-
|
|
1302
|
+
const { registerOsBlueprintCommand } = await import("./register-os-blueprint-Gdyn0pN1.js");
|
|
1211
1303
|
await registerOsBlueprintCommand();
|
|
1212
1304
|
});
|
|
1213
1305
|
infra.command("register-app").description("Register a webapp database in this customer OS blueprint").argument("<app>", "Webapp package name").action(async (appName) => {
|
|
1214
|
-
const { registerAppCommand } = await import("./register-app-
|
|
1306
|
+
const { registerAppCommand } = await import("./register-app-mNc1oYVK.js");
|
|
1215
1307
|
await registerAppCommand(appName);
|
|
1216
1308
|
});
|
|
1217
1309
|
program.command("status").description("Show template sync status for current app").option("--mosaic-template-path <path>", "Path to local mosaic repo checkout").action(async (options) => {
|
|
1218
|
-
const { statusCommand } = await import("./status-
|
|
1310
|
+
const { statusCommand } = await import("./status-BrK9v1yb.js");
|
|
1219
1311
|
await statusCommand(options);
|
|
1220
1312
|
});
|
|
1221
1313
|
program.command("sync").description("Generate downstream sync context (template → app)").option("--mosaic-template-path <path>", "Path to local mosaic repo checkout").option("--to <version>", "Target template version (default: latest)").action(async (options) => {
|
|
1222
|
-
const { syncCommand } = await import("./sync-
|
|
1314
|
+
const { syncCommand } = await import("./sync-DC5DhIBT.js");
|
|
1223
1315
|
await syncCommand(options);
|
|
1224
1316
|
});
|
|
1225
1317
|
program.command("upstream").description("Generate upstream context (app → template)").option("--mosaic-template-path <path>", "Path to local mosaic repo checkout").option("--files <patterns...>", "Specific files to propose upstream").action(async (options) => {
|
|
1226
|
-
const { upstreamCommand } = await import("./upstream-
|
|
1318
|
+
const { upstreamCommand } = await import("./upstream-PNL6DGtl.js");
|
|
1227
1319
|
await upstreamCommand(options);
|
|
1228
1320
|
});
|
|
1229
1321
|
program.command("init").description("Add .mosaic-template.json to an existing app").option("-t, --type <type>", "Template type (e.g., webapp, library)").option("--template-version <version>", "Template version to set").action(async (options) => {
|
|
1230
|
-
const { initCommand } = await import("./init-
|
|
1322
|
+
const { initCommand } = await import("./init-CsuO_mu2.js");
|
|
1231
1323
|
await initCommand(options);
|
|
1232
1324
|
});
|
|
1233
1325
|
program.parse();
|
|
1234
1326
|
//#endregion
|
|
1235
|
-
export { detectMonorepo as i,
|
|
1327
|
+
export { validateProjectName as a, readManifest as c, detectMonorepo as d, toKebabCase as f, isValidProjectType as i, resolveMosaicTemplatePath as l, toTitleCase as m, getTemplateVersion as n, derivePlaceholders as o, toSnakeCase as p, VALID_PROJECT_TYPES as r, manifestExists as s, readWorkspaceManifest as t, writeManifest as u };
|
|
1236
1328
|
|
|
1237
1329
|
//# sourceMappingURL=index.js.map
|