@xano/sdk 1.0.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.
- package/CHANGELOG.md +788 -0
- package/LICENSE +21 -0
- package/README.md +541 -0
- package/dist/.build-fingerprint +1 -0
- package/dist/agent-file-refresh-ZEMK33AX.js +38 -0
- package/dist/answer-shape-K67TAAPY.js +33 -0
- package/dist/backend-dir-2U53CIAL.js +39 -0
- package/dist/backend-slot-7QXW2QYC.js +28 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +255 -0
- package/dist/branch-NCRNWQBQ.js +61 -0
- package/dist/branch-commands-ACIRCEQJ.js +79 -0
- package/dist/bundle.d.ts +223 -0
- package/dist/bundle.js +153 -0
- package/dist/capture-WAXPD7DR.js +41 -0
- package/dist/chunk-27GWNP2I.js +23 -0
- package/dist/chunk-2CMJZDCL.js +177 -0
- package/dist/chunk-2EZ3ZJZZ.js +302 -0
- package/dist/chunk-2GNFDZA2.js +390 -0
- package/dist/chunk-2MNLRIOX.js +11 -0
- package/dist/chunk-2TFRR6JV.js +104 -0
- package/dist/chunk-2ZUEE4EK.js +408 -0
- package/dist/chunk-36JUQZVQ.js +22 -0
- package/dist/chunk-3DRXWLJ5.js +83 -0
- package/dist/chunk-3JDU4VRL.js +137 -0
- package/dist/chunk-3KZCLN4Z.js +241 -0
- package/dist/chunk-3LDULPRE.js +168 -0
- package/dist/chunk-3M4LFYNQ.js +111 -0
- package/dist/chunk-3XI5CTUE.js +22 -0
- package/dist/chunk-3YW23UFH.js +50 -0
- package/dist/chunk-45UIT5T2.js +862 -0
- package/dist/chunk-4BW2SG2N.js +46 -0
- package/dist/chunk-4KHEMC32.js +79 -0
- package/dist/chunk-4POWHT2K.js +321 -0
- package/dist/chunk-4Q2GN7NW.js +192 -0
- package/dist/chunk-5A2PLKZB.js +70 -0
- package/dist/chunk-5FBYXK5P.js +159 -0
- package/dist/chunk-5HVXPTU4.js +323 -0
- package/dist/chunk-5QU2P5CA.js +304 -0
- package/dist/chunk-5V5XU32D.js +191 -0
- package/dist/chunk-5ZSO4T2G.js +10 -0
- package/dist/chunk-622HUCZT.js +10 -0
- package/dist/chunk-65HWOMGV.js +177 -0
- package/dist/chunk-6ELFRN3P.js +365 -0
- package/dist/chunk-6HO3NCSJ.js +1055 -0
- package/dist/chunk-6IUMKYWI.js +457 -0
- package/dist/chunk-6KEB3C3U.js +65 -0
- package/dist/chunk-6MR5TI5V.js +987 -0
- package/dist/chunk-6NNTNXN7.js +157 -0
- package/dist/chunk-6PBR37LN.js +97 -0
- package/dist/chunk-6QXLMMT3.js +155 -0
- package/dist/chunk-6ZGJCBZS.js +224 -0
- package/dist/chunk-73IVBKMA.js +250 -0
- package/dist/chunk-7G3CTU7I.js +286 -0
- package/dist/chunk-A3UDOZB6.js +222 -0
- package/dist/chunk-A6E77GDW.js +85 -0
- package/dist/chunk-AHJWCYQO.js +660 -0
- package/dist/chunk-AKNCFVKZ.js +36 -0
- package/dist/chunk-AM4FKL4J.js +237 -0
- package/dist/chunk-AN6BL47T.js +26 -0
- package/dist/chunk-AOSYVMUS.js +147 -0
- package/dist/chunk-APWXY5SL.js +182 -0
- package/dist/chunk-AWEIIR2U.js +218 -0
- package/dist/chunk-AWQ7BQTQ.js +73 -0
- package/dist/chunk-BAUZOWGX.js +393 -0
- package/dist/chunk-BHACRS6R.js +940 -0
- package/dist/chunk-BWPNT55T.js +680 -0
- package/dist/chunk-C6RIMRU4.js +187 -0
- package/dist/chunk-CGVQZXYG.js +263 -0
- package/dist/chunk-CIMQZRRE.js +162 -0
- package/dist/chunk-CJHQKJU4.js +113 -0
- package/dist/chunk-CTMO46PK.js +1897 -0
- package/dist/chunk-D53J55C5.js +106 -0
- package/dist/chunk-D7VGG3WS.js +90 -0
- package/dist/chunk-DAD3ONIS.js +245 -0
- package/dist/chunk-DGWHAVRG.js +162 -0
- package/dist/chunk-DX4QR4B2.js +483 -0
- package/dist/chunk-EHP3WPEG.js +21 -0
- package/dist/chunk-ELP2HMXC.js +432 -0
- package/dist/chunk-ERVIASGL.js +21 -0
- package/dist/chunk-ET4Y4XCB.js +865 -0
- package/dist/chunk-ETO6LGLD.js +4750 -0
- package/dist/chunk-EUUUMY7J.js +24 -0
- package/dist/chunk-FQJ2TTHP.js +218 -0
- package/dist/chunk-FQOF7E2E.js +133 -0
- package/dist/chunk-FWD7AL6N.js +21 -0
- package/dist/chunk-FXFV3KU6.js +138 -0
- package/dist/chunk-FXRQOWTE.js +171 -0
- package/dist/chunk-G554NZNI.js +210 -0
- package/dist/chunk-GSGDWJB5.js +13 -0
- package/dist/chunk-H2V3N23D.js +66 -0
- package/dist/chunk-H5C7MBCR.js +159 -0
- package/dist/chunk-HHN734BU.js +371 -0
- package/dist/chunk-HRVBLCVJ.js +243 -0
- package/dist/chunk-HVRUQXGD.js +1264 -0
- package/dist/chunk-I4F5TCJH.js +130 -0
- package/dist/chunk-IDOTCMDV.js +57 -0
- package/dist/chunk-IGOLHKWF.js +427 -0
- package/dist/chunk-JGE7CAWB.js +148 -0
- package/dist/chunk-JTUKLCXS.js +92 -0
- package/dist/chunk-JZGVVJSI.js +66 -0
- package/dist/chunk-K4WX6UUU.js +923 -0
- package/dist/chunk-K5BBGTYZ.js +217 -0
- package/dist/chunk-K6RXBGUB.js +427 -0
- package/dist/chunk-KTSDSD36.js +165 -0
- package/dist/chunk-L5JYN3NM.js +1038 -0
- package/dist/chunk-LIEOKXKD.js +354 -0
- package/dist/chunk-LLNZGEFK.js +51 -0
- package/dist/chunk-LPECSJ2J.js +55 -0
- package/dist/chunk-LQCMKAJ7.js +413 -0
- package/dist/chunk-LRN4ZJCQ.js +1145 -0
- package/dist/chunk-MJ4ZVHKN.js +17 -0
- package/dist/chunk-MXHSQOC4.js +3061 -0
- package/dist/chunk-N5GKCWE5.js +367 -0
- package/dist/chunk-NA3PXMEF.js +10 -0
- package/dist/chunk-NAQDMEHV.js +76 -0
- package/dist/chunk-NWKXM5RD.js +109 -0
- package/dist/chunk-NZOWWHU5.js +196 -0
- package/dist/chunk-OHX6MIUZ.js +184 -0
- package/dist/chunk-OOXWYAA4.js +15 -0
- package/dist/chunk-OPHB5ORL.js +1990 -0
- package/dist/chunk-OXA6PSZT.js +1725 -0
- package/dist/chunk-P2HAGF6H.js +73 -0
- package/dist/chunk-PTHVMXZI.js +3036 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-Q325JKYB.js +189 -0
- package/dist/chunk-Q7DGTQ5G.js +255 -0
- package/dist/chunk-QCNYHBL7.js +601 -0
- package/dist/chunk-QO6BVGS5.js +145 -0
- package/dist/chunk-QXTKSOFI.js +76 -0
- package/dist/chunk-ROY4YAEQ.js +66 -0
- package/dist/chunk-RTJRZFFY.js +447 -0
- package/dist/chunk-SAVJUS2X.js +128 -0
- package/dist/chunk-SFLHVCKX.js +173 -0
- package/dist/chunk-STSFNCY4.js +127 -0
- package/dist/chunk-SWBF2LTK.js +170 -0
- package/dist/chunk-T5KELPAR.js +109 -0
- package/dist/chunk-TFFGOFVZ.js +1481 -0
- package/dist/chunk-TLHIFK4M.js +256 -0
- package/dist/chunk-TLQE7ZN3.js +156 -0
- package/dist/chunk-TPHWJ7UG.js +1981 -0
- package/dist/chunk-TRJCALW3.js +291 -0
- package/dist/chunk-TTEIYD5P.js +133 -0
- package/dist/chunk-U64O2MXY.js +407 -0
- package/dist/chunk-UCQ2VUTG.js +630 -0
- package/dist/chunk-UTI5G6OJ.js +44 -0
- package/dist/chunk-UVHDMMIP.js +188 -0
- package/dist/chunk-UZ6QQWJT.js +120 -0
- package/dist/chunk-VAX3UZOY.js +686 -0
- package/dist/chunk-W3HBUKFO.js +57 -0
- package/dist/chunk-WKQLGKCL.js +2823 -0
- package/dist/chunk-WQFNASK4.js +560 -0
- package/dist/chunk-WRBKLYSJ.js +224 -0
- package/dist/chunk-WTPZRR4I.js +17 -0
- package/dist/chunk-WZDJ2LLX.js +2385 -0
- package/dist/chunk-X2NL4KUO.js +14 -0
- package/dist/chunk-X4DVXBFY.js +38 -0
- package/dist/chunk-X677DMZM.js +7050 -0
- package/dist/chunk-XBKMWY7F.js +612 -0
- package/dist/chunk-XNCP4KYO.js +78 -0
- package/dist/chunk-XVBGLISP.js +35 -0
- package/dist/chunk-XW6KISBB.js +1192 -0
- package/dist/chunk-YGZHHAAB.js +8156 -0
- package/dist/chunk-YHEFQUQB.js +186 -0
- package/dist/chunk-YLDALTWZ.js +653 -0
- package/dist/chunk-YU4HSQW7.js +229 -0
- package/dist/chunk-ZDPP6RKB.js +27 -0
- package/dist/chunk-ZFDZKNGG.js +194 -0
- package/dist/chunk-ZIY7RNUT.js +49 -0
- package/dist/chunk-ZYJP6BOO.js +30 -0
- package/dist/cli.d.ts +1111 -0
- package/dist/cli.js +165 -0
- package/dist/codegen-command-VR2GWR6C.js +173 -0
- package/dist/codegen.d.ts +115 -0
- package/dist/codegen.js +19 -0
- package/dist/commands-GJMJ4XYZ.js +76 -0
- package/dist/completion-ZQLO6PB6.js +738 -0
- package/dist/config-MBYGCAFK.js +136 -0
- package/dist/deploy-command-JVZPWHMK.js +180 -0
- package/dist/deploy-source-3W45CXMP.js +81 -0
- package/dist/dev-env-sync-HN44K4D5.js +188 -0
- package/dist/diagnostics-UEAAHWVF.js +30 -0
- package/dist/display-name-hint-ABBPVQIR.js +46 -0
- package/dist/emit-CyhBDxli.d.ts +7007 -0
- package/dist/env-example-refresh-ET5HMMDW.js +126 -0
- package/dist/env-pull-command-TNMNB3CV.js +323 -0
- package/dist/env-target-O4HRKTGZ.js +40 -0
- package/dist/env-var-command-ZIRDCAZA.js +427 -0
- package/dist/ephemeral-P7F3PMAD.js +54 -0
- package/dist/ephemeral-command-CLJJKOFT.js +592 -0
- package/dist/ephemeral-state-PYCBSOGX.js +61 -0
- package/dist/file-lock-PT74GWYW.js +10 -0
- package/dist/generate-command-AYEOLA26.js +510 -0
- package/dist/gitignore-3SJ3WNRG.js +51 -0
- package/dist/guards-4EBNCZDC.js +162 -0
- package/dist/hosted-file-PSHJB3HX.js +28 -0
- package/dist/impersonate-command-5JAS3WSV.js +152 -0
- package/dist/import-EQSFU6JC.js +19 -0
- package/dist/index.d.ts +5470 -0
- package/dist/index.js +371 -0
- package/dist/init-command-X2FR4UAK.js +125 -0
- package/dist/init-modules-RY7UHAOL.js +50 -0
- package/dist/init-web-M4YZSZK6.js +42 -0
- package/dist/internal.d.ts +179 -0
- package/dist/internal.js +2634 -0
- package/dist/io-RC56QSN5.js +26 -0
- package/dist/keep-data-merge-7MPLVAVI.js +1119 -0
- package/dist/lambda-config-reconcile-OUZ4OYAB.js +116 -0
- package/dist/landed-753YLJ5H.js +40 -0
- package/dist/landing-record-SU52SKXU.js +61 -0
- package/dist/live-diff-YONW2VI3.js +65 -0
- package/dist/local-engine-choice-CH5X3W7E.js +79 -0
- package/dist/local-engine-command-Z3OL7VOD.js +766 -0
- package/dist/local-engine-config-5U3SC434.js +39 -0
- package/dist/local-engine-deploy-PCQ4SNPB.js +39 -0
- package/dist/local-engine-process-EHTE5LLU.js +63 -0
- package/dist/local-engine-state-A4FTRFAF.js +32 -0
- package/dist/local-engine-update-check-6L645VBL.js +162 -0
- package/dist/lock-MRRHW5GS.js +87 -0
- package/dist/lock-commands-2QG25HL7.js +963 -0
- package/dist/login-command-QPYRWOXZ.js +538 -0
- package/dist/logout-command-WOIQLDP6.js +56 -0
- package/dist/loop-ALIZLOSX.js +191 -0
- package/dist/marketplace-command-K5YL42NO.js +977 -0
- package/dist/marketplace-resolve-LY32JES5.js +40 -0
- package/dist/meta-client-YXGPW53C.js +244 -0
- package/dist/module-manifest-JFGHU2TC.js +38 -0
- package/dist/near-key.d.ts +13 -0
- package/dist/near-key.js +8 -0
- package/dist/node.d.ts +95 -0
- package/dist/node.js +969 -0
- package/dist/operation-outcome-TZSESNC7.js +51 -0
- package/dist/output-target-AL3I44GG.js +47 -0
- package/dist/package-manager-PRAHUSCN.js +34 -0
- package/dist/plan-disclosure-6G4MLZKD.js +114 -0
- package/dist/plugin-contributions-WRNY5ABG.js +28 -0
- package/dist/plugin-prompt-4VA3B4FF.js +20 -0
- package/dist/plugin-questions-JTSYA74Q.js +24 -0
- package/dist/plugin.d.ts +396 -0
- package/dist/plugin.js +1 -0
- package/dist/preflight-command-2T5Z36MI.js +321 -0
- package/dist/profile-command-AH3PIM4X.js +800 -0
- package/dist/profile-pointer-GRWJU3YD.js +31 -0
- package/dist/profile-select-74TRDEPD.js +23 -0
- package/dist/project-dependency-KSH63ODT.js +35 -0
- package/dist/project-sdk-REPPOIBD.js +24 -0
- package/dist/promote-command-PCWT5N6S.js +140 -0
- package/dist/prompt-II3F3LND.js +27 -0
- package/dist/publish-command-TTDUUJI5.js +414 -0
- package/dist/pull-command-VBO7C4S3.js +161 -0
- package/dist/pull-superseded-GJWLG7XO.js +20 -0
- package/dist/release-command-N4ZPKMHR.js +146 -0
- package/dist/release-ns-command-3KFDMZ6G.js +1745 -0
- package/dist/response-HlXahv4K.d.ts +925 -0
- package/dist/retry-command-AS5EVREX.js +34 -0
- package/dist/routes-manifest-SNWUVBT6.js +43 -0
- package/dist/runtime-XETHVF33.js +14 -0
- package/dist/scaffold.d.ts +1911 -0
- package/dist/scaffold.js +107 -0
- package/dist/secrets-file-LVZD6IIM.js +56 -0
- package/dist/secrets-fill-command-TTCPSVXN.js +218 -0
- package/dist/seed-VU7C3QYS.js +46 -0
- package/dist/sent-writes-N7X4OVXT.js +22 -0
- package/dist/source-resolve-S2XA3XZF.js +83 -0
- package/dist/static-host-B2Y6AG3W.js +352 -0
- package/dist/status-command-RUDXTF7I.js +554 -0
- package/dist/store-6VNCD4D7.js +20 -0
- package/dist/store-ARM6VMO5.js +98 -0
- package/dist/store-DuYfzKlW.d.ts +3144 -0
- package/dist/suggest-6FOOYKHG.js +12 -0
- package/dist/sveltekit.d.ts +154 -0
- package/dist/sveltekit.js +109 -0
- package/dist/sync-contributions-UCEROO26.js +415 -0
- package/dist/table-ENAVMITR.js +42 -0
- package/dist/tables-command-GUPXXSB5.js +156 -0
- package/dist/tenant-IIHPOHGP.js +42 -0
- package/dist/tenant-command-D5HGI2X4.js +965 -0
- package/dist/test-command-TIKZMDPZ.js +476 -0
- package/dist/tests-BGGIOK3L.js +26 -0
- package/dist/token-NICJUTMT.js +72 -0
- package/dist/toolchain-hooks-GHKLUJOH.js +96 -0
- package/dist/toolchain-modules-5EAZUONB.js +24 -0
- package/dist/tracked-backend-EIBUMDZA.js +80 -0
- package/dist/update-check-2W2NLDTC.js +136 -0
- package/dist/upgrade-command-QHNFWM7O.js +531 -0
- package/dist/verify-rollout-DRCK5TDD.js +61 -0
- package/dist/whoami-command-STGINTXH.js +51 -0
- package/dist/workspace-2CLHU2LK.js +93 -0
- package/dist/workspace-binding-56PIIPCP.js +54 -0
- package/dist/workspace-command-JEXQETJD.js +535 -0
- package/dist/workspace-env-F2RFMSC5.js +70 -0
- package/dist/workspace-export-OJSH2HIW.js +21 -0
- package/dist/writable-VA7OISSK.js +25 -0
- package/dist/xano-ICFUSPFR.js +42 -0
- package/dist/xanosdk-import-GN42TO2B.js +56 -0
- package/dist/xanosdk-project-S6DXJONQ.js +41 -0
- package/dist/xdo-CxDr2Q1C.d.ts +1371 -0
- package/guides/README.md +33 -0
- package/guides/authoring.md +921 -0
- package/guides/cli.md +401 -0
- package/guides/codegen.md +177 -0
- package/guides/codes.md +404 -0
- package/guides/coverage.md +74 -0
- package/guides/deploying.md +1525 -0
- package/guides/environment.md +400 -0
- package/guides/marketplace.md +415 -0
- package/guides/module-contract.md +558 -0
- package/guides/object-kinds.md +433 -0
- package/guides/project-structure.md +43 -0
- package/guides/scaffold.md +351 -0
- package/guides/typed-frontend.md +242 -0
- package/llms/client.md +63 -0
- package/llms/errors.md +56 -0
- package/llms/fields.md +176 -0
- package/llms/filters.md +183 -0
- package/llms/kinds-agent-mcp.md +30 -0
- package/llms/kinds-core.md +100 -0
- package/llms/kinds-knowledge.md +20 -0
- package/llms/kinds-realtime.md +76 -0
- package/llms/lambda.md +94 -0
- package/llms/legacy.md +44 -0
- package/llms/lock.md +40 -0
- package/llms/object-kinds.md +34 -0
- package/llms/statements-calls.md +62 -0
- package/llms/statements-catalog.md +320 -0
- package/llms/statements-data.md +66 -0
- package/llms/statements-runtime.md +68 -0
- package/llms/tests.md +59 -0
- package/llms/toolchain.md +16 -0
- package/llms/triggers.md +36 -0
- package/llms/values.md +29 -0
- package/llms-full.txt +2085 -0
- package/llms.txt +493 -0
- package/manifest.json +11224 -0
- package/package.json +162 -0
- package/types/lambda-globals.d.ts +129 -0
|
@@ -0,0 +1,1145 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ROUTES_MANIFEST_BASENAME
|
|
3
|
+
} from "./chunk-RTJRZFFY.js";
|
|
4
|
+
import {
|
|
5
|
+
questionOrCancel
|
|
6
|
+
} from "./chunk-65HWOMGV.js";
|
|
7
|
+
import {
|
|
8
|
+
ensureWorkspaceEnvGitignored
|
|
9
|
+
} from "./chunk-YHEFQUQB.js";
|
|
10
|
+
import {
|
|
11
|
+
readVersion
|
|
12
|
+
} from "./chunk-ETO6LGLD.js";
|
|
13
|
+
import {
|
|
14
|
+
WORKSPACE_ENV_EXAMPLE_FILE,
|
|
15
|
+
renderWorkspaceEnvExample
|
|
16
|
+
} from "./chunk-DAD3ONIS.js";
|
|
17
|
+
import {
|
|
18
|
+
parseSlot,
|
|
19
|
+
requireBackendSlot
|
|
20
|
+
} from "./chunk-STSFNCY4.js";
|
|
21
|
+
import {
|
|
22
|
+
XANO_DIR,
|
|
23
|
+
changedOnDisk,
|
|
24
|
+
decideOverwrite,
|
|
25
|
+
isNonEmptyDir,
|
|
26
|
+
plannedAgentsMd,
|
|
27
|
+
scaffoldProject
|
|
28
|
+
} from "./chunk-AHJWCYQO.js";
|
|
29
|
+
import {
|
|
30
|
+
inProject,
|
|
31
|
+
installModules,
|
|
32
|
+
parseMarketplaceFlag,
|
|
33
|
+
preflightPackages,
|
|
34
|
+
rebaseLocalSpec,
|
|
35
|
+
renderXanoIndexWithModules
|
|
36
|
+
} from "./chunk-DX4QR4B2.js";
|
|
37
|
+
import {
|
|
38
|
+
npmViewVersion
|
|
39
|
+
} from "./chunk-ZFDZKNGG.js";
|
|
40
|
+
import {
|
|
41
|
+
shellWord
|
|
42
|
+
} from "./chunk-FWD7AL6N.js";
|
|
43
|
+
import {
|
|
44
|
+
isLocalSpecifier
|
|
45
|
+
} from "./chunk-2GNFDZA2.js";
|
|
46
|
+
import {
|
|
47
|
+
readToolchainBlock
|
|
48
|
+
} from "./chunk-JTUKLCXS.js";
|
|
49
|
+
import {
|
|
50
|
+
detectInstallRoot,
|
|
51
|
+
detectPackageManager,
|
|
52
|
+
installCommandFor,
|
|
53
|
+
userAgentVersion
|
|
54
|
+
} from "./chunk-WRBKLYSJ.js";
|
|
55
|
+
import {
|
|
56
|
+
localPackageName,
|
|
57
|
+
localPathOf,
|
|
58
|
+
packageNameOf,
|
|
59
|
+
readInstalledManifestState
|
|
60
|
+
} from "./chunk-3LDULPRE.js";
|
|
61
|
+
import {
|
|
62
|
+
statusLabel
|
|
63
|
+
} from "./chunk-YLDALTWZ.js";
|
|
64
|
+
import {
|
|
65
|
+
readEnvVar
|
|
66
|
+
} from "./chunk-X2NL4KUO.js";
|
|
67
|
+
import {
|
|
68
|
+
DEFAULT_FRAMEWORK,
|
|
69
|
+
FRAMEWORKS,
|
|
70
|
+
NODE_MIN,
|
|
71
|
+
allFrontendPresets,
|
|
72
|
+
checkJobDir,
|
|
73
|
+
checkWorkflowName,
|
|
74
|
+
checkWorkflowPath,
|
|
75
|
+
findFrontendPreset,
|
|
76
|
+
initLanding,
|
|
77
|
+
renderApiTs,
|
|
78
|
+
renderCheckWorkflow,
|
|
79
|
+
renderCnUtil,
|
|
80
|
+
renderEnvExample,
|
|
81
|
+
renderGitattributes,
|
|
82
|
+
renderGitignore,
|
|
83
|
+
renderIndexCss,
|
|
84
|
+
renderIndexHtml,
|
|
85
|
+
renderLambdaTsconfig,
|
|
86
|
+
renderPackageJson,
|
|
87
|
+
renderReadme,
|
|
88
|
+
renderThemeModule,
|
|
89
|
+
renderTsconfig,
|
|
90
|
+
renderViteConfig,
|
|
91
|
+
renderXanoExampleMd,
|
|
92
|
+
renderXanoIndex,
|
|
93
|
+
resolveFrameworkFlag,
|
|
94
|
+
sdkDep
|
|
95
|
+
} from "./chunk-OPHB5ORL.js";
|
|
96
|
+
import {
|
|
97
|
+
ICON_LIBRARIES,
|
|
98
|
+
resolveIconsFlag
|
|
99
|
+
} from "./chunk-UCQ2VUTG.js";
|
|
100
|
+
import {
|
|
101
|
+
UsageError,
|
|
102
|
+
blank,
|
|
103
|
+
cliPrefixAt,
|
|
104
|
+
detail,
|
|
105
|
+
displayPath,
|
|
106
|
+
error,
|
|
107
|
+
flagName,
|
|
108
|
+
flagNames,
|
|
109
|
+
info,
|
|
110
|
+
isMachineOutput,
|
|
111
|
+
projectFileCli,
|
|
112
|
+
projectSdkDir,
|
|
113
|
+
quotedNames,
|
|
114
|
+
spellProjectCli,
|
|
115
|
+
spellProjectSdkDir,
|
|
116
|
+
step,
|
|
117
|
+
style,
|
|
118
|
+
success,
|
|
119
|
+
unknownFlag,
|
|
120
|
+
warn,
|
|
121
|
+
writeJson
|
|
122
|
+
} from "./chunk-PTHVMXZI.js";
|
|
123
|
+
import {
|
|
124
|
+
suggest
|
|
125
|
+
} from "./chunk-UTI5G6OJ.js";
|
|
126
|
+
import {
|
|
127
|
+
shellQuote
|
|
128
|
+
} from "./chunk-5ZSO4T2G.js";
|
|
129
|
+
import {
|
|
130
|
+
ACCENTS,
|
|
131
|
+
BASE_COLORS,
|
|
132
|
+
DARK_MODES,
|
|
133
|
+
DEFAULT_DARK_MODE,
|
|
134
|
+
defaultThemeChoice,
|
|
135
|
+
findFont,
|
|
136
|
+
fontIdsFor,
|
|
137
|
+
normalizeRadius,
|
|
138
|
+
resolveDarkModeFlag,
|
|
139
|
+
resolveFontFlag,
|
|
140
|
+
resolveThemeFlag,
|
|
141
|
+
themeFromRegistryItem,
|
|
142
|
+
withRadius
|
|
143
|
+
} from "./chunk-TFFGOFVZ.js";
|
|
144
|
+
|
|
145
|
+
// src/emit/init-command.ts
|
|
146
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync as readFileSync2, rmSync, writeFileSync } from "fs";
|
|
147
|
+
import { spawnSync } from "child_process";
|
|
148
|
+
import { basename, dirname, join, relative, resolve, sep } from "path";
|
|
149
|
+
|
|
150
|
+
// src/emit/frontend-resolve.ts
|
|
151
|
+
import { createInterface } from "readline/promises";
|
|
152
|
+
|
|
153
|
+
// src/emit/theme-resolve.ts
|
|
154
|
+
import { readFileSync } from "fs";
|
|
155
|
+
import { resolve as resolvePath } from "path";
|
|
156
|
+
function flagValue(raw, candidates, resolve2) {
|
|
157
|
+
try {
|
|
158
|
+
return resolve2();
|
|
159
|
+
} catch (err) {
|
|
160
|
+
if (!(err instanceof Error)) throw err;
|
|
161
|
+
const near = suggest(raw.trim().toLowerCase(), candidates);
|
|
162
|
+
throw new UsageError(err.message, near === void 0 ? {} : { suggestion: near });
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function fontFlag(raw, slot) {
|
|
166
|
+
if (findFont(raw) !== void 0) {
|
|
167
|
+
try {
|
|
168
|
+
return resolveFontFlag(raw, slot);
|
|
169
|
+
} catch (err) {
|
|
170
|
+
throw err instanceof Error ? new UsageError(err.message) : err;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return flagValue(raw, fontIdsFor(slot), () => resolveFontFlag(raw, slot));
|
|
174
|
+
}
|
|
175
|
+
function themeIds() {
|
|
176
|
+
return BASE_COLORS.flatMap((b) => [b, ...ACCENTS.map((a) => `${b}-${a}`)]);
|
|
177
|
+
}
|
|
178
|
+
function isRegistryRef(value) {
|
|
179
|
+
return /^https?:\/\//i.test(value) || value.toLowerCase().endsWith(".json");
|
|
180
|
+
}
|
|
181
|
+
async function loadRegistryTheme(ref) {
|
|
182
|
+
if (/^https?:\/\//i.test(ref)) {
|
|
183
|
+
let res;
|
|
184
|
+
try {
|
|
185
|
+
res = await fetch(ref, { headers: { accept: "application/json" } });
|
|
186
|
+
} catch (err) {
|
|
187
|
+
throw new Error(
|
|
188
|
+
`Could not fetch the theme at ${ref}: ${err instanceof Error ? err.message : String(err)}`
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
if (!res.ok) throw new Error(`Could not fetch the theme at ${ref}: ${statusLabel(res)}`);
|
|
192
|
+
const text2 = await res.text();
|
|
193
|
+
return themeFromRegistryItem(parseJson(text2, ref), ref);
|
|
194
|
+
}
|
|
195
|
+
const path = resolvePath(ref);
|
|
196
|
+
let text;
|
|
197
|
+
try {
|
|
198
|
+
text = readFileSync(path, "utf8");
|
|
199
|
+
} catch (err) {
|
|
200
|
+
throw new Error(
|
|
201
|
+
`Could not read the theme file ${path}: ${err instanceof Error ? err.message : String(err)}`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
return themeFromRegistryItem(parseJson(text, path), path);
|
|
205
|
+
}
|
|
206
|
+
function parseJson(text, source) {
|
|
207
|
+
try {
|
|
208
|
+
return JSON.parse(text);
|
|
209
|
+
} catch {
|
|
210
|
+
throw new Error(`${source} is not valid JSON \u2014 a registry theme is a JSON registry item.`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
async function themeFromFlag(raw) {
|
|
214
|
+
return isRegistryRef(raw.trim()) ? loadRegistryTheme(raw.trim()) : flagValue(raw, themeIds(), () => resolveThemeFlag(raw));
|
|
215
|
+
}
|
|
216
|
+
async function resolveThemeChoice(args) {
|
|
217
|
+
const dark = args.dark === void 0 || args.dark === "" ? DEFAULT_DARK_MODE : flagValue(args.dark, DARK_MODES, () => resolveDarkModeFlag(args.dark));
|
|
218
|
+
const fonts = {
|
|
219
|
+
...args.font !== void 0 && args.font !== "" ? { sans: fontFlag(args.font, "sans") } : {},
|
|
220
|
+
...args.fontMono !== void 0 && args.fontMono !== "" ? { mono: fontFlag(args.fontMono, "mono") } : {},
|
|
221
|
+
...args.fontHeading !== void 0 && args.fontHeading !== "" ? { heading: fontFlag(args.fontHeading, "heading") } : {}
|
|
222
|
+
};
|
|
223
|
+
const icons = args.icons === void 0 || args.icons === "" ? void 0 : flagValue(args.icons, ICON_LIBRARIES, () => resolveIconsFlag(args.icons)).id;
|
|
224
|
+
let theme = args.theme !== void 0 && args.theme !== "" ? await themeFromFlag(args.theme) : defaultThemeChoice().theme;
|
|
225
|
+
if (args.radius !== void 0 && args.radius !== "") {
|
|
226
|
+
theme = withRadius(theme, flagValue(args.radius, [], () => normalizeRadius(args.radius)));
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
theme,
|
|
230
|
+
dark,
|
|
231
|
+
...Object.keys(fonts).length === 0 ? {} : { fonts },
|
|
232
|
+
...icons === void 0 ? {} : { icons }
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// src/emit/frontend-resolve.ts
|
|
237
|
+
function defaultFrontendPreset() {
|
|
238
|
+
const preset = findFrontendPreset(DEFAULT_FRAMEWORK);
|
|
239
|
+
if (preset === void 0) {
|
|
240
|
+
throw new Error(`Default frontend preset "${DEFAULT_FRAMEWORK}" is missing from the table.`);
|
|
241
|
+
}
|
|
242
|
+
return preset;
|
|
243
|
+
}
|
|
244
|
+
async function promptFramework() {
|
|
245
|
+
const presets = allFrontendPresets();
|
|
246
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
247
|
+
try {
|
|
248
|
+
process.stderr.write(
|
|
249
|
+
`
|
|
250
|
+
Which frontend framework?
|
|
251
|
+
` + presets.map((p, i) => ` ${i + 1}) ${p.label}${p.id === DEFAULT_FRAMEWORK ? " (default)" : ""}`).join("\n") + `
|
|
252
|
+
`
|
|
253
|
+
);
|
|
254
|
+
const answer = await questionOrCancel(rl, `Enter a number or name, or leave blank for the default: `);
|
|
255
|
+
const token = answer.trim().toLowerCase();
|
|
256
|
+
if (token === "") return defaultFrontendPreset();
|
|
257
|
+
const byIndex = Number.parseInt(token, 10);
|
|
258
|
+
if (Number.isInteger(byIndex) && byIndex >= 1 && byIndex <= presets.length) {
|
|
259
|
+
return presets[byIndex - 1];
|
|
260
|
+
}
|
|
261
|
+
return findFrontendPreset(token) ?? defaultFrontendPreset();
|
|
262
|
+
} finally {
|
|
263
|
+
rl.close();
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
async function resolveFrontendPreset(flag) {
|
|
267
|
+
if (flag !== void 0 && flag !== "") return flagValue(flag, FRAMEWORKS, () => resolveFrameworkFlag(flag));
|
|
268
|
+
if (process.stdin.isTTY && process.stderr.isTTY) return promptFramework();
|
|
269
|
+
return defaultFrontendPreset();
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/emit/init-command.ts
|
|
273
|
+
function projectInstallOf(dir, env = process.env) {
|
|
274
|
+
const found = detectInstallRoot(dir, env);
|
|
275
|
+
const { manager, root } = found;
|
|
276
|
+
const member = relative(root, resolve(dir)).split(sep).join("/");
|
|
277
|
+
const needsVersion = !found.declared && (manager === "pnpm" || manager === "bun");
|
|
278
|
+
const version = needsVersion ? userAgentVersion(env.npm_config_user_agent, manager) ?? managerVersion(manager) : void 0;
|
|
279
|
+
return {
|
|
280
|
+
manager,
|
|
281
|
+
member,
|
|
282
|
+
declared: found.declared,
|
|
283
|
+
...version === void 0 ? {} : { version },
|
|
284
|
+
...found.ignoreWorkspace ? { ignoreWorkspace: true } : {},
|
|
285
|
+
...repoDirOf(root)
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
function repoDirOf(root) {
|
|
289
|
+
if (existsSync(join(root, ".git"))) return {};
|
|
290
|
+
for (let d = dirname(root); ; d = dirname(d)) {
|
|
291
|
+
if (existsSync(join(d, ".git"))) return { repoDir: relative(d, root).split(sep).join("/") };
|
|
292
|
+
if (dirname(d) === d) return {};
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
function workflowPlacementNote(install, projectDir) {
|
|
296
|
+
const jobDir = checkJobDir(install);
|
|
297
|
+
if (jobDir === "") return "";
|
|
298
|
+
const file = checkWorkflowName(install);
|
|
299
|
+
return `GitHub runs workflows only from the repository root: move ${displayPath(join(projectDir, ".github", "workflows", file))} to ${displayPath(join(workflowRootDir(projectDir, jobDir), ".github", "workflows"))}/ (its steps already run in ${jobDir}).`;
|
|
300
|
+
}
|
|
301
|
+
function workflowMoveTarget(install, projectDir) {
|
|
302
|
+
const jobDir = checkJobDir(install);
|
|
303
|
+
if (jobDir === "") return void 0;
|
|
304
|
+
const target = join(workflowRootDir(projectDir, jobDir), ".github", "workflows", checkWorkflowName(install));
|
|
305
|
+
return existsSync(target) ? displayPath(target) : void 0;
|
|
306
|
+
}
|
|
307
|
+
function reportWorkflowPlacement(written, install, projectDir) {
|
|
308
|
+
if (!written.includes(checkWorkflowPath(install))) return;
|
|
309
|
+
const placement = workflowPlacementNote(install, projectDir);
|
|
310
|
+
if (placement !== "") info(placement);
|
|
311
|
+
const taken = workflowMoveTarget(install, projectDir);
|
|
312
|
+
if (taken !== void 0) {
|
|
313
|
+
warn(`${taken} already exists \u2014 moving the new workflow there replaces it.`, "init.workflow-exists", [
|
|
314
|
+
`Compare the two first, and keep whichever this project's CI should run.`
|
|
315
|
+
]);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function workflowRootDir(projectDir, jobDir) {
|
|
319
|
+
return resolve(projectDir, ...jobDir.split("/").map(() => ".."));
|
|
320
|
+
}
|
|
321
|
+
function templateVarsFor(appName, dir, env = process.env) {
|
|
322
|
+
const install = projectInstallOf(dir, env);
|
|
323
|
+
return {
|
|
324
|
+
appName,
|
|
325
|
+
sdkVersion: readVersion(),
|
|
326
|
+
install,
|
|
327
|
+
cli: projectFileCli(dir, install.manager),
|
|
328
|
+
sdkDir: projectSdkDir(dir, install.manager)
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
function managerVersion(manager) {
|
|
332
|
+
const r = spawnSync(manager, ["--version"], { encoding: "utf8", timeout: 1e4, shell: process.platform === "win32" });
|
|
333
|
+
const v = r.status === 0 ? r.stdout.trim() : "";
|
|
334
|
+
return /^\d+\.\d+\.\d+/.test(v) ? v : void 0;
|
|
335
|
+
}
|
|
336
|
+
var TRANSLITERATED = {
|
|
337
|
+
\u0142: "l",
|
|
338
|
+
\u0141: "L",
|
|
339
|
+
\u00DF: "ss",
|
|
340
|
+
"\u1E9E": "SS",
|
|
341
|
+
\u00E6: "ae",
|
|
342
|
+
\u00C6: "AE",
|
|
343
|
+
\u00F8: "o",
|
|
344
|
+
\u00D8: "O",
|
|
345
|
+
\u0111: "d",
|
|
346
|
+
\u0110: "D",
|
|
347
|
+
\u00F0: "d",
|
|
348
|
+
\u00D0: "D",
|
|
349
|
+
\u00FE: "th",
|
|
350
|
+
\u00DE: "Th",
|
|
351
|
+
\u0153: "oe",
|
|
352
|
+
\u0152: "OE",
|
|
353
|
+
\u0127: "h",
|
|
354
|
+
\u0126: "H",
|
|
355
|
+
\u0131: "i",
|
|
356
|
+
\u0140: "l",
|
|
357
|
+
\u013F: "L",
|
|
358
|
+
\u0167: "t",
|
|
359
|
+
\u0166: "T"
|
|
360
|
+
};
|
|
361
|
+
function sanitizeAppName(raw) {
|
|
362
|
+
const name = raw.normalize("NFKD").replace(/\p{M}+/gu, "").replace(/\P{ASCII}/gu, (c) => TRANSLITERATED[c] ?? c).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
363
|
+
return name === "" ? "app" : name;
|
|
364
|
+
}
|
|
365
|
+
function withXanoSdkBlock(rendered, xanosdk, existing) {
|
|
366
|
+
const merged = { ...existing, ...xanosdk };
|
|
367
|
+
if (Object.keys(merged).length === 0) return rendered;
|
|
368
|
+
const manifest = JSON.parse(rendered);
|
|
369
|
+
manifest["xanosdk"] = merged;
|
|
370
|
+
try {
|
|
371
|
+
return `${JSON.stringify(manifest, null, 2)}
|
|
372
|
+
`;
|
|
373
|
+
} catch (error2) {
|
|
374
|
+
warn(
|
|
375
|
+
"A module's configuration could not be serialized and was left out of package.json.",
|
|
376
|
+
"init.module-config-dropped",
|
|
377
|
+
[error2 instanceof Error ? error2.message : String(error2)]
|
|
378
|
+
);
|
|
379
|
+
return rendered;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
function projectShellFiles(vars, preset, parts, choice = defaultThemeChoice(), contributions = {}, existingXanoSdk) {
|
|
383
|
+
return spelledForProject(vars, [
|
|
384
|
+
{
|
|
385
|
+
path: "package.json",
|
|
386
|
+
// The plugin config block rides in the rendered manifest rather than
|
|
387
|
+
// being written after, so the scaffold has one file to reconcile instead
|
|
388
|
+
// of a second pass patching the one it just wrote. What the project
|
|
389
|
+
// already stored is folded in HERE rather than left to the scaffold's
|
|
390
|
+
// merge, because that merge only runs on the two-pass (`--marketplace`)
|
|
391
|
+
// path — a plain `init --force` writes this file once, and the block has
|
|
392
|
+
// to survive that too.
|
|
393
|
+
content: withXanoSdkBlock(
|
|
394
|
+
renderPackageJson(vars, preset, choice),
|
|
395
|
+
contributions.xanosdk,
|
|
396
|
+
existingXanoSdk
|
|
397
|
+
)
|
|
398
|
+
},
|
|
399
|
+
{ path: "tsconfig.json", content: renderTsconfig(preset) },
|
|
400
|
+
{ path: "xano/lambdas/tsconfig.json", content: renderLambdaTsconfig() },
|
|
401
|
+
{ path: "vite.config.ts", content: renderViteConfig(preset) },
|
|
402
|
+
{ path: ".gitignore", content: renderGitignore(preset) },
|
|
403
|
+
// The line-ending rule every generated artifact depends on. An installed
|
|
404
|
+
// toolchain module adds its own display rules below it, each inside a
|
|
405
|
+
// marked block keyed by the contributing package so a later reconcile can
|
|
406
|
+
// find, replace, or remove exactly that module's lines.
|
|
407
|
+
{ path: ".gitattributes", content: renderGitattributes(contributions.gitattributes) },
|
|
408
|
+
// The job that keeps derived state honest. A module contributes no steps to
|
|
409
|
+
// it: its frozen check already rides on `npm run xano:check` through its
|
|
410
|
+
// `onBundle` hook, so there is nothing for a CI slot to add.
|
|
411
|
+
{ path: checkWorkflowPath(vars.install), content: renderCheckWorkflow(vars.install) },
|
|
412
|
+
{ path: ".env.example", content: renderEnvExample() },
|
|
413
|
+
{ path: "README.md", content: parts.readme },
|
|
414
|
+
// Skipped when the framework supplies its own entry document — see
|
|
415
|
+
// FrontendPreset.ownsHtmlEntry. A second index.html beside SvelteKit's
|
|
416
|
+
// app.html would never be served and would still read as the entry point.
|
|
417
|
+
...preset.ownsHtmlEntry === true ? [] : [{ path: "frontend/index.html", content: renderIndexHtml(vars, preset, choice) }],
|
|
418
|
+
// Shared across every framework: both UI kits resolve against the same
|
|
419
|
+
// Tailwind v4 semantic tokens and look for library code at
|
|
420
|
+
// frontend/src/lib/. Only the alias NAME pointing at that directory
|
|
421
|
+
// differs, and the preset owns that — as it does where `cn()` comes from.
|
|
422
|
+
{ path: "frontend/src/index.css", content: renderIndexCss(choice) },
|
|
423
|
+
{ path: "frontend/src/lib/api.ts", content: renderApiTs() },
|
|
424
|
+
{ path: "frontend/src/lib/utils.ts", content: preset.libUtils ?? renderCnUtil(preset.libUtilsExtra) },
|
|
425
|
+
// The mode store behind `--dark toggle`, shared by both presets' toggles —
|
|
426
|
+
// it is plain DOM and localStorage, with nothing framework-shaped in it.
|
|
427
|
+
// `system` and `off` need no state, so nothing is written for them.
|
|
428
|
+
...choice.dark === "toggle" ? [{ path: "frontend/src/lib/theme.ts", content: renderThemeModule() }] : [],
|
|
429
|
+
// The framework's own half: entry module, app component, vendored UI kit,
|
|
430
|
+
// and whatever tool config that kit's CLI reads.
|
|
431
|
+
...preset.files(vars, parts.landing, choice)
|
|
432
|
+
]);
|
|
433
|
+
}
|
|
434
|
+
function spelledForProject(vars, files) {
|
|
435
|
+
return files.map((f) => ({ ...f, content: spellProjectSdkDir(spellProjectCli(f.content, vars.cli), vars.sdkDir) }));
|
|
436
|
+
}
|
|
437
|
+
function buildFileSet(vars, preset, choice, contributions = {}, existingXanoSdk) {
|
|
438
|
+
return [
|
|
439
|
+
...projectShellFiles(
|
|
440
|
+
vars,
|
|
441
|
+
preset,
|
|
442
|
+
{ readme: renderReadme(vars, preset, choice), landing: initLanding(vars) },
|
|
443
|
+
choice,
|
|
444
|
+
contributions,
|
|
445
|
+
existingXanoSdk
|
|
446
|
+
),
|
|
447
|
+
...spelledForProject(vars, [
|
|
448
|
+
{ path: "xano/index.ts", content: renderXanoIndex(vars) },
|
|
449
|
+
{ path: "xano/EXAMPLE.md", content: renderXanoExampleMd(vars) }
|
|
450
|
+
]),
|
|
451
|
+
// The BACKEND counterpart of `.env.example`, one directory down: the same
|
|
452
|
+
// pair, for the half of the project the engine runs. `xano/.env` itself is
|
|
453
|
+
// never written by a scaffold — only by the user, or by `xanosdk env pull`.
|
|
454
|
+
//
|
|
455
|
+
// Here rather than in `projectShellFiles`, which the PULL path also uses:
|
|
456
|
+
// `placeGeneratedFiles` emits this file with the names the source declares,
|
|
457
|
+
// and two entries for one path left the right one winning on array order
|
|
458
|
+
// alone. A bare `init` has no names, so it writes the empty template.
|
|
459
|
+
{ path: WORKSPACE_ENV_EXAMPLE_FILE, content: renderWorkspaceEnvExample([]) }
|
|
460
|
+
];
|
|
461
|
+
}
|
|
462
|
+
function resolveFromSource(raw) {
|
|
463
|
+
return parseSlot(requireBackendSlot("init", void 0, "from"), raw);
|
|
464
|
+
}
|
|
465
|
+
function rejectPullOnlyFlags(args) {
|
|
466
|
+
const passed = [
|
|
467
|
+
...args.report !== void 0 ? ["--report"] : [],
|
|
468
|
+
...args.skipRoundtrip ? ["--skip-roundtrip"] : [],
|
|
469
|
+
// Tokens are found by decoding a source; a plain init decodes nothing.
|
|
470
|
+
...args.noSecrets ? ["--no-secrets"] : [],
|
|
471
|
+
// Confirms replacing a decoded `xano/` (`--from`), or the files an
|
|
472
|
+
// `init --force` over an existing project overwrites.
|
|
473
|
+
...args.yes && !args.force ? ["--yes"] : [],
|
|
474
|
+
...args.branch !== void 0 ? ["--branch"] : [],
|
|
475
|
+
// A plain init signs in to nothing, so an OAuth host has nowhere to go.
|
|
476
|
+
...args.authHost !== void 0 ? ["--origin"] : []
|
|
477
|
+
];
|
|
478
|
+
if (passed.length === 0) return;
|
|
479
|
+
if (passed.length === 1 && passed[0] === "--yes") {
|
|
480
|
+
throw new UsageError(
|
|
481
|
+
"`--yes` confirms what `--from` or `--force` replaces, so it does nothing without one of them. Add `--force` to scaffold over an existing project, or drop the flag.",
|
|
482
|
+
{ helpFor: { command: "init" } }
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
throw new UsageError(
|
|
486
|
+
`${passed.join(" and ")} ${passed.length === 1 ? "describes" : "describe"} the pull that \`--from\` performs, so ${passed.length === 1 ? "it does" : "they do"} nothing without it. Add \`--from <source>\`, or drop ${passed.length === 1 ? "the flag" : "them"}.`,
|
|
487
|
+
{ helpFor: { command: "init" } }
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
function decideScaffoldTarget(targetDir, force) {
|
|
491
|
+
const decided = decideOverwrite(targetDir, { force, regenerable: false });
|
|
492
|
+
if (decided === "refuse") {
|
|
493
|
+
throw new UsageError(
|
|
494
|
+
`Target directory ${targetDir} is not empty. ` + (process.stdin.isTTY === true ? `Re-run with --force to scaffold into it anyway.` : `Re-run with --force --yes to scaffold into it anyway (--yes confirms the overwrite, which cannot be asked without a terminal).`)
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
return decided;
|
|
498
|
+
}
|
|
499
|
+
function readLockEntryCount(targetDir) {
|
|
500
|
+
const path = join(targetDir, LOCK_REL);
|
|
501
|
+
if (!existsSync(path)) return void 0;
|
|
502
|
+
try {
|
|
503
|
+
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
504
|
+
return parsed.objects !== null && typeof parsed.objects === "object" ? Object.keys(parsed.objects).length : 0;
|
|
505
|
+
} catch {
|
|
506
|
+
return 0;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
async function confirmForcedOverwrite(targetDir, files, args, agents) {
|
|
510
|
+
const agentsMd = plannedAgentsMd(targetDir, {
|
|
511
|
+
agentsMd: !args.noAgentsMd,
|
|
512
|
+
appName: agents.appName,
|
|
513
|
+
regenerable: false,
|
|
514
|
+
sdkVersion: readVersion(),
|
|
515
|
+
frontend: agents.frontend,
|
|
516
|
+
theme: agents.theme
|
|
517
|
+
});
|
|
518
|
+
const changed = changedOnDisk(targetDir, agentsMd === void 0 ? files : [...files, agentsMd]);
|
|
519
|
+
if (changed.length === 0) return true;
|
|
520
|
+
warn(
|
|
521
|
+
`init --force overwrites ${changed.length} file${changed.length === 1 ? "" : "s"} already in ${targetDir}:`,
|
|
522
|
+
"init.overwrite",
|
|
523
|
+
[...changed.slice(0, 30), ...changed.length > 30 ? [`\u2026 and ${changed.length - 30} more`] : []]
|
|
524
|
+
);
|
|
525
|
+
if (args.yes === true) return true;
|
|
526
|
+
const { confirm } = await import("./prompt-II3F3LND.js");
|
|
527
|
+
const { yesRerun } = await import("./retry-command-AS5EVREX.js");
|
|
528
|
+
const { rerun, note } = yesRerun(args, "init");
|
|
529
|
+
const ok = await confirm(
|
|
530
|
+
`Overwrite ${changed.length === 1 ? "this file" : `these ${changed.length} files`} in ${targetDir}?`,
|
|
531
|
+
{ flag: "--yes", refusal: { details: { written: false, files: changed }, rerun, note } }
|
|
532
|
+
);
|
|
533
|
+
if (!ok) info("Cancelled. Nothing was written.");
|
|
534
|
+
return ok;
|
|
535
|
+
}
|
|
536
|
+
function renderMinimalPackageJson(appName, sdkVersion) {
|
|
537
|
+
return `${JSON.stringify(
|
|
538
|
+
{
|
|
539
|
+
name: appName,
|
|
540
|
+
// yarn 1 ignores a workspace member with no version and then fails the
|
|
541
|
+
// add; the scaffold's own manifest carries the same one.
|
|
542
|
+
version: "0.1.0",
|
|
543
|
+
private: true,
|
|
544
|
+
type: "module",
|
|
545
|
+
// `sdkDep`, not `^version`: the scaffold's range is written out as
|
|
546
|
+
// `>=<version> <next major`, the same shape a module's peer range has, so
|
|
547
|
+
// every manifest this CLI writes or restores reads alike.
|
|
548
|
+
dependencies: { "@xano/sdk": sdkDep(sdkVersion) },
|
|
549
|
+
engines: { node: `>=${NODE_MIN}` }
|
|
550
|
+
},
|
|
551
|
+
null,
|
|
552
|
+
2
|
|
553
|
+
)}
|
|
554
|
+
`;
|
|
555
|
+
}
|
|
556
|
+
var EXIT_MODULE_INSTALL_FAILED = 2;
|
|
557
|
+
var PASS_ONE_REWRITES = ["package.json", "package-lock.json"];
|
|
558
|
+
function snapshotForRollback(dir) {
|
|
559
|
+
if (!existsSync(dir)) return { dir, entries: void 0, saved: /* @__PURE__ */ new Map() };
|
|
560
|
+
const saved = /* @__PURE__ */ new Map();
|
|
561
|
+
for (const name of PASS_ONE_REWRITES) {
|
|
562
|
+
const path = join(dir, name);
|
|
563
|
+
if (existsSync(path)) saved.set(name, readFileSync2(path, "utf8"));
|
|
564
|
+
}
|
|
565
|
+
return { dir, entries: new Set(readdirSync(dir)), saved };
|
|
566
|
+
}
|
|
567
|
+
function rollBackPassOne(snap, err) {
|
|
568
|
+
let note;
|
|
569
|
+
try {
|
|
570
|
+
if (snap.entries === void 0) {
|
|
571
|
+
rmSync(snap.dir, { recursive: true, force: true });
|
|
572
|
+
note = `Nothing was left behind: ${snap.dir} was created by this run and has been removed.`;
|
|
573
|
+
} else {
|
|
574
|
+
for (const entry of readdirSync(snap.dir)) {
|
|
575
|
+
if (!snap.entries.has(entry)) rmSync(join(snap.dir, entry), { recursive: true, force: true });
|
|
576
|
+
}
|
|
577
|
+
for (const [name, text] of snap.saved) writeFileSync(join(snap.dir, name), text, "utf8");
|
|
578
|
+
note = snap.entries.has("node_modules") ? `What this run wrote into ${snap.dir} was undone, except node_modules, which already existed.` : `Nothing was left behind: what this run wrote into ${snap.dir} has been removed.`;
|
|
579
|
+
}
|
|
580
|
+
} catch (cleanup) {
|
|
581
|
+
note = `Cleaning up ${snap.dir} failed (${cleanup instanceof Error ? cleanup.message : String(cleanup)}); remove it before re-running.`;
|
|
582
|
+
}
|
|
583
|
+
if (err instanceof Error) err.message = `${err.message} ${note}`;
|
|
584
|
+
}
|
|
585
|
+
async function runInitCommand(args) {
|
|
586
|
+
if (args.from !== void 0) {
|
|
587
|
+
if (args.unknownFlags.length > 0) {
|
|
588
|
+
throw unknownFlag(args.unknownFlags, { command: "init" });
|
|
589
|
+
}
|
|
590
|
+
if (args.marketplace.length > 0) {
|
|
591
|
+
throw new UsageError(
|
|
592
|
+
"`--from` and `--marketplace` do not compose: `--from` writes a project around a backend that already exists. Scaffold it first, then add each package with `xanosdk marketplace install <package>`.",
|
|
593
|
+
{ helpFor: { command: "init" } }
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
const source = resolveFromSource(args.from);
|
|
597
|
+
if (source.kind === "file") await refuseUnknownProfileFlag(args, resolve(args.positionals[0] ?? "."));
|
|
598
|
+
const { runInitFromCommand } = await import("./codegen-command-VR2GWR6C.js");
|
|
599
|
+
return runInitFromCommand(args, source);
|
|
600
|
+
}
|
|
601
|
+
rejectPullOnlyFlags(args);
|
|
602
|
+
const targetArg = args.positionals[0] ?? ".";
|
|
603
|
+
const targetDir = resolve(targetArg);
|
|
604
|
+
await refuseUnknownProfileFlag(args, targetDir);
|
|
605
|
+
const appName = sanitizeAppName(args.name ?? basename(targetDir));
|
|
606
|
+
const existingXanoSdk = readToolchainBlock(targetDir);
|
|
607
|
+
const typedModules = parseMarketplaceFlag(args.marketplace);
|
|
608
|
+
if (args.framework !== void 0) await resolveFrontendPreset(args.framework);
|
|
609
|
+
await resolveThemeChoice(args);
|
|
610
|
+
const unclaimable = args.unknownFlags.filter((f) => {
|
|
611
|
+
const name = flagName(f);
|
|
612
|
+
if (!name.startsWith("--")) return true;
|
|
613
|
+
const bare = name.slice(2);
|
|
614
|
+
return flagNames().includes(bare) || bare.startsWith("no-") && flagNames().includes(bare.slice(3));
|
|
615
|
+
});
|
|
616
|
+
if (unclaimable.length > 0) throw unknownFlag(unclaimable, { command: "init" });
|
|
617
|
+
const { refusePlugAndPlay } = await import("./project-dependency-KSH63ODT.js");
|
|
618
|
+
const { retryCommand } = await import("./retry-command-AS5EVREX.js");
|
|
619
|
+
refusePlugAndPlay(targetDir, retryCommand(args, { command: "init" }).command);
|
|
620
|
+
const { resolveMarketplaceSpecs, withCatalogueRerun } = await import("./marketplace-resolve-LY32JES5.js");
|
|
621
|
+
const resolvedModules = typedModules.length === 0 ? [] : await resolveMarketplaceSpecs(typedModules, "xanosdk init --marketplace").catch(async (err) => {
|
|
622
|
+
throw await withCatalogueRerun(err, args, "init");
|
|
623
|
+
});
|
|
624
|
+
const requestedModules = resolvedModules.map((spec) => rebaseLocalSpec(spec, process.cwd(), targetDir));
|
|
625
|
+
if (args.noInstall) for (const spec of requestedModules) deferredDependency(spec, targetDir);
|
|
626
|
+
if (requestedModules.length > 0) preflightPackages(requestedModules, targetDir);
|
|
627
|
+
const deferredModules = args.noInstall ? requestedModules : [];
|
|
628
|
+
const modules = args.noInstall ? [] : requestedModules;
|
|
629
|
+
let overwrite;
|
|
630
|
+
let moduleOutcome;
|
|
631
|
+
const forcedOver = args.force && isNonEmptyDir(targetDir);
|
|
632
|
+
const hadLock = readLockEntryCount(targetDir);
|
|
633
|
+
let earlyPreset;
|
|
634
|
+
let passOne;
|
|
635
|
+
if (modules.length > 0) {
|
|
636
|
+
overwrite = decideScaffoldTarget(targetDir, args.force);
|
|
637
|
+
if (forcedOver) {
|
|
638
|
+
earlyPreset = await resolveFrontendPreset(args.framework);
|
|
639
|
+
const earlyTheme = await resolveThemeChoice(args);
|
|
640
|
+
const provisional = buildFileSet(
|
|
641
|
+
{ appName, sdkVersion: readVersion() },
|
|
642
|
+
earlyPreset,
|
|
643
|
+
earlyTheme,
|
|
644
|
+
{ gitattributes: [], xanosdk: {} },
|
|
645
|
+
existingXanoSdk
|
|
646
|
+
);
|
|
647
|
+
const agents = { appName, frontend: earlyPreset, theme: earlyTheme };
|
|
648
|
+
if (!await confirmForcedOverwrite(targetDir, provisional, args, agents)) return;
|
|
649
|
+
}
|
|
650
|
+
passOne = snapshotForRollback(targetDir);
|
|
651
|
+
mkdirSync(targetDir, { recursive: true });
|
|
652
|
+
writeFileSync(
|
|
653
|
+
join(targetDir, "package.json"),
|
|
654
|
+
renderMinimalPackageJson(appName, readVersion()),
|
|
655
|
+
"utf8"
|
|
656
|
+
);
|
|
657
|
+
blank();
|
|
658
|
+
moduleOutcome = await installModules(targetDir, modules);
|
|
659
|
+
}
|
|
660
|
+
let scaffolded = false;
|
|
661
|
+
try {
|
|
662
|
+
const { discoverToolchainPlugins } = await import("./toolchain-modules-5EAZUONB.js");
|
|
663
|
+
const toolchain = await discoverToolchainPlugins(targetDir, { frozen: false, configuring: true });
|
|
664
|
+
const preset = earlyPreset ?? await resolveFrontendPreset(args.framework);
|
|
665
|
+
const choice = await resolveThemeChoice(args);
|
|
666
|
+
const { pluginPrompter } = await import("./plugin-prompt-4VA3B4FF.js");
|
|
667
|
+
const { contributionOutcomes, recordedConfig, runPluginQuestionnaire } = await import("./plugin-contributions-WRNY5ABG.js");
|
|
668
|
+
const { answers: pluginAnswers } = await runPluginQuestionnaire(toolchain.loaded, {
|
|
669
|
+
host: "init",
|
|
670
|
+
unknownFlags: args.unknownFlags,
|
|
671
|
+
// `init --json` answers with one document, so a question prompted under it
|
|
672
|
+
// would interleave with a stdout a script is about to parse.
|
|
673
|
+
prompter: pluginPrompter({ json: args.json })
|
|
674
|
+
});
|
|
675
|
+
const outcomes = contributionOutcomes(toolchain.loaded, pluginAnswers, "init");
|
|
676
|
+
const gitattributes = outcomes.flatMap((o) => {
|
|
677
|
+
const lines = o.parts?.gitattributes ?? [];
|
|
678
|
+
return lines.length === 0 ? [] : [{ pkg: o.pkg, version: o.version, lines }];
|
|
679
|
+
});
|
|
680
|
+
const pluginConfig = {};
|
|
681
|
+
for (const outcome of outcomes) {
|
|
682
|
+
const record = recordedConfig(outcome, existingXanoSdk?.[outcome.pkg]);
|
|
683
|
+
if (record !== void 0) pluginConfig[outcome.pkg] = record;
|
|
684
|
+
}
|
|
685
|
+
const vars = templateVarsFor(appName, targetDir);
|
|
686
|
+
overwrite ??= decideScaffoldTarget(targetDir, args.force);
|
|
687
|
+
const fileSet = buildFileSet(vars, preset, choice, { gitattributes, xanosdk: pluginConfig }, existingXanoSdk);
|
|
688
|
+
if (forcedOver && earlyPreset === void 0 && !await confirmForcedOverwrite(targetDir, fileSet, args, { appName, frontend: preset, theme: choice }))
|
|
689
|
+
return;
|
|
690
|
+
step(
|
|
691
|
+
`Scaffolding ${style.bold(appName)} (${preset.label}, ${choice.theme.label}) in ${targetDir}`
|
|
692
|
+
);
|
|
693
|
+
const pin = await planProfilePin(args, targetDir);
|
|
694
|
+
scaffolded = true;
|
|
695
|
+
const result = await scaffoldProject({
|
|
696
|
+
targetDir,
|
|
697
|
+
files: [...fileSet, ...pin.file === null ? [] : [pin.file]],
|
|
698
|
+
agentsMd: !args.noAgentsMd,
|
|
699
|
+
appName,
|
|
700
|
+
force: args.force,
|
|
701
|
+
noInstall: args.noInstall,
|
|
702
|
+
// An `init` project's `xano/` is hand-authored, never machine-written: it is
|
|
703
|
+
// not refreshable, and `--force` must not clear it.
|
|
704
|
+
regenerable: false,
|
|
705
|
+
overwrite,
|
|
706
|
+
// Only this path writes package.json twice, so only this path merges.
|
|
707
|
+
mergePackageJson: modules.length > 0,
|
|
708
|
+
// A project install failing for the reason an add-on's already did (the
|
|
709
|
+
// manifest they share names a range npm has no version for) is that one
|
|
710
|
+
// failure, already warned — not a second warning repeating npm's text.
|
|
711
|
+
reportedNpmFailures: moduleOutcome?.reported,
|
|
712
|
+
sdkVersion: readVersion(),
|
|
713
|
+
frontend: preset,
|
|
714
|
+
theme: choice
|
|
715
|
+
});
|
|
716
|
+
ensureWorkspaceEnvGitignored(targetDir);
|
|
717
|
+
if (vars.install?.ignoreWorkspace === true) {
|
|
718
|
+
info(
|
|
719
|
+
`${targetDir} is below a pnpm workspace that does not list it, so it installs on its own: \`${installCommandFor(targetDir)}\`. To make it a member instead, add its path to that workspace's pnpm-workspace.yaml.`
|
|
720
|
+
);
|
|
721
|
+
}
|
|
722
|
+
reportWorkflowPlacement(result.written, vars.install, targetDir);
|
|
723
|
+
pin.report();
|
|
724
|
+
const pinnedProfile = pin.name;
|
|
725
|
+
info(`Theme: ${choice.theme.label} \u2014 dark mode: ${choice.dark}`);
|
|
726
|
+
if (deferredModules.length > 0) {
|
|
727
|
+
recordDeferredModules(targetDir, deferredModules);
|
|
728
|
+
info(`Added to package.json, not installed (--no-install): ${deferredModules.join(", ")}.`);
|
|
729
|
+
const listed = deferredModules.filter((m) => !isLocalSpecifier(m)).map(packageNameOf);
|
|
730
|
+
const local = deferredModules.flatMap((m) => {
|
|
731
|
+
const name = localPackageName(m, targetDir);
|
|
732
|
+
return name === void 0 ? [] : [`${name} (${localPathOf(m)})`];
|
|
733
|
+
});
|
|
734
|
+
detail(
|
|
735
|
+
`Run \`${inProject(targetDir)}${installCommandFor(targetDir)}\`, then register ${deferredModules.length === 1 ? "it" : "each"} in xano/index.ts` + (listed.length === 0 ? "" : ` \u2014 ${listed.map((m) => `\`xanosdk marketplace details ${shellQuote(m)}\``).join(", ")} print${listed.length === 1 ? "s" : ""} the wiring`) + (local.length === 0 ? "" : `${listed.length === 0 ? " \u2014" : ";"} ${local.join(", ")}: see ${local.length === 1 ? "its" : "each one's"} README`) + `.`
|
|
736
|
+
);
|
|
737
|
+
}
|
|
738
|
+
let derived = [];
|
|
739
|
+
let entryFailed = false;
|
|
740
|
+
let addonEnv = [];
|
|
741
|
+
if (moduleOutcome !== void 0) {
|
|
742
|
+
const outcome = moduleOutcome;
|
|
743
|
+
if (outcome.installed.length > 0) {
|
|
744
|
+
writeFileSync(
|
|
745
|
+
join(targetDir, "xano", "index.ts"),
|
|
746
|
+
spellProjectCli(renderXanoIndexWithModules(appName, outcome.registered, outcome.unwired), vars.cli),
|
|
747
|
+
"utf8"
|
|
748
|
+
);
|
|
749
|
+
}
|
|
750
|
+
if (outcome.toolchain.length > 0) {
|
|
751
|
+
info(
|
|
752
|
+
`Extends the CLI (nothing to register): ${outcome.toolchain.join(", ")}. Configured in this project's package.json "xanosdk" block.`
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
if (outcome.registered.length > 0) {
|
|
756
|
+
info(`Registered in xano/index.ts: ${outcome.registered.map((m) => m.pkg).join(", ")}`);
|
|
757
|
+
if (result.install === "installed" && sdkResolves(targetDir)) {
|
|
758
|
+
const derivation = await writeDerivedFiles(
|
|
759
|
+
targetDir,
|
|
760
|
+
(env) => spellProjectCli(renderXanoIndexWithModules(appName, outcome.registered, outcome.unwired, env), vars.cli)
|
|
761
|
+
);
|
|
762
|
+
derived = derivation.written;
|
|
763
|
+
entryFailed = derivation.failed === true;
|
|
764
|
+
addonEnv = derivation.env;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
for (const module of outcome.unwired) {
|
|
768
|
+
warn(
|
|
769
|
+
`${module.pkg} is installed but not registered \u2014 ${runFromHere(module.reason, targetDir)}.`,
|
|
770
|
+
"module.unregistered",
|
|
771
|
+
[`Import it in xano/index.ts and register it onto the workspace yourself.`]
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
if (outcome.failed.length > 0) {
|
|
775
|
+
process.exitCode = EXIT_MODULE_INSTALL_FAILED;
|
|
776
|
+
}
|
|
777
|
+
if (outcome.legacyPeer.length > 0) {
|
|
778
|
+
warn(
|
|
779
|
+
`Installed with --legacy-peer-deps: ${outcome.legacyPeer.join(", ")}. npm refused the tree on peer ranges, so this one is not the tree npm would build on its own.`,
|
|
780
|
+
"module.legacy-peer-deps"
|
|
781
|
+
);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
if (result.install === "installed") {
|
|
785
|
+
const { skewedProjectSdk } = await import("./project-sdk-REPPOIBD.js");
|
|
786
|
+
const installedSdk = skewedProjectSdk(targetDir, readVersion());
|
|
787
|
+
if (installedSdk !== void 0) {
|
|
788
|
+
const { reconcileWithInstalled } = await import("./upgrade-command-QHNFWM7O.js");
|
|
789
|
+
const rendered = reconcileWithInstalled(targetDir);
|
|
790
|
+
if (rendered.length > 0) {
|
|
791
|
+
info(`Rendered ${rendered.join(", ")} with the installed @xano/sdk ${installedSdk.version} (this CLI is ${readVersion()}).`);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
blank();
|
|
796
|
+
const shortBy = moduleOutcome?.failed.length ?? 0;
|
|
797
|
+
const manager = detectPackageManager(targetDir);
|
|
798
|
+
const installLine = installCommandFor(targetDir);
|
|
799
|
+
if (result.install === "failed") {
|
|
800
|
+
error(`Project scaffolded, but its dependencies are NOT installed \u2014 ${manager} install failed (its reason is above).`);
|
|
801
|
+
detail(`Fix what ${manager} reported, then run \`${installLine}\` in ${targetDir}. Nothing needs to be scaffolded again.`);
|
|
802
|
+
process.exitCode = EXIT_MODULE_INSTALL_FAILED;
|
|
803
|
+
} else if (entryFailed) {
|
|
804
|
+
error(`Project scaffolded, but it does not build yet \u2014 xano/index.ts fails to load (the reason is above).`);
|
|
805
|
+
detail(`Fix xano/index.ts, then run \`npm run xano:export\` in ${targetDir}. Nothing needs to be scaffolded again.`);
|
|
806
|
+
process.exitCode = EXIT_MODULE_INSTALL_FAILED;
|
|
807
|
+
} else {
|
|
808
|
+
success(
|
|
809
|
+
shortBy === 0 ? "Project ready." : `Project ready, without ${shortBy} add-on${shortBy === 1 ? "" : "s"}.`
|
|
810
|
+
);
|
|
811
|
+
}
|
|
812
|
+
if (moduleOutcome !== void 0 && shortBy > 0) {
|
|
813
|
+
const failed = moduleOutcome.failed;
|
|
814
|
+
detail(
|
|
815
|
+
`Not installed: ${failed.join(", ")} (${manager}'s reason is above). Add ${failed.length === 1 ? "it" : "them"} with ` + failed.map((pkg) => `\`${inProject(targetDir)}xanosdk marketplace install ${shellWord(pkg)}\``).join(", ") + ` once ${manager}'s error is fixed.`
|
|
816
|
+
);
|
|
817
|
+
}
|
|
818
|
+
const cdHint = targetDir === process.cwd() ? "" : ` cd ${shellWord(targetArg)}
|
|
819
|
+
`;
|
|
820
|
+
detail(
|
|
821
|
+
`Next steps:
|
|
822
|
+
` + cdHint + (result.install === "installed" || sdkResolves(targetDir) ? `` : ` ${installLine}
|
|
823
|
+
`) + ` npm run dev # run the frontend
|
|
824
|
+
` + loginNextStep(pin, targetDir) + // A declared name with no line in xano/.env refuses the deploy, so the
|
|
825
|
+
// step that supplies it comes first.
|
|
826
|
+
(addonEnv.length > 0 ? ` cp xano/.env.example xano/.env # then set ${addonEnv.join(", ")} \u2014 the add-ons read ${addonEnv.length === 1 ? "it" : "them"}
|
|
827
|
+
` : ``) + ` npm run xano:deploy # build the frontend, then deploy \u2192 live ephemeral URL
|
|
828
|
+
|
|
829
|
+
` + (hadLock !== void 0 ? `xano/xano.lock was kept (${hadLock} ${hadLock === 1 ? "entry" : "entries"}). An entry the new xano/index.ts
|
|
830
|
+
does not export fails \`npm run xano:check\`; once those objects are gone for good,
|
|
831
|
+
\`${projectCli(targetDir)} lock prune ./xano/index.ts --yes\` drops them.` : (derived.includes(LOCK_REL) ? `xano/xano.lock was written for the add-ons' objects \u2014 commit it. It pins each
|
|
832
|
+
` : `The first export or deploy writes xano/xano.lock \u2014 commit it. It pins each
|
|
833
|
+
`) + `object's identity, so renaming one later renames it instead of deleting and
|
|
834
|
+
recreating it. See "xano.lock \u2014 commit it" in the README.`) + (derived.includes(ROUTES_REL) ? `
|
|
835
|
+
${ROUTES_REL} was written for the add-ons' endpoints \u2014 commit it too.` : "")
|
|
836
|
+
);
|
|
837
|
+
if (isMachineOutput(args)) {
|
|
838
|
+
writeJson({
|
|
839
|
+
dir: targetDir,
|
|
840
|
+
name: appName,
|
|
841
|
+
framework: preset.id,
|
|
842
|
+
theme: choice.theme.id,
|
|
843
|
+
dark: choice.dark,
|
|
844
|
+
install: result.install,
|
|
845
|
+
pinnedProfile,
|
|
846
|
+
// `--no-install` still names what it added: recorded in package.json,
|
|
847
|
+
// not installed, not wired.
|
|
848
|
+
...moduleOutcome === void 0 && deferredModules.length > 0 ? {
|
|
849
|
+
marketplace: {
|
|
850
|
+
added: [...deferredModules],
|
|
851
|
+
installed: [],
|
|
852
|
+
failed: [],
|
|
853
|
+
registered: [],
|
|
854
|
+
unwired: [],
|
|
855
|
+
toolchain: []
|
|
856
|
+
}
|
|
857
|
+
} : {},
|
|
858
|
+
...moduleOutcome === void 0 ? {} : {
|
|
859
|
+
marketplace: {
|
|
860
|
+
installed: moduleOutcome.installed,
|
|
861
|
+
failed: moduleOutcome.failed,
|
|
862
|
+
registered: moduleOutcome.registered.map((m) => m.pkg),
|
|
863
|
+
unwired: moduleOutcome.unwired.map((m) => m.pkg),
|
|
864
|
+
toolchain: moduleOutcome.toolchain
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
} catch (err) {
|
|
870
|
+
if (passOne !== void 0 && !scaffolded) rollBackPassOne(passOne, err);
|
|
871
|
+
throw err;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
var LOCK_REL = `${XANO_DIR}/xano.lock`;
|
|
875
|
+
var ROUTES_REL = `${XANO_DIR}/${ROUTES_MANIFEST_BASENAME}`;
|
|
876
|
+
function recordDeferredModules(targetDir, specifiers) {
|
|
877
|
+
const path = join(targetDir, "package.json");
|
|
878
|
+
const pkg = JSON.parse(readFileSync2(path, "utf8"));
|
|
879
|
+
const deps = { ...pkg.dependencies ?? {} };
|
|
880
|
+
for (const specifier of specifiers) {
|
|
881
|
+
const local = deferredDependency(specifier, targetDir);
|
|
882
|
+
if (local !== void 0) {
|
|
883
|
+
deps[local.name] = local.spec;
|
|
884
|
+
continue;
|
|
885
|
+
}
|
|
886
|
+
const name = packageNameOf(specifier);
|
|
887
|
+
const pinned = specifier.length > name.length + 1 ? specifier.slice(name.length + 1) : void 0;
|
|
888
|
+
if (pinned !== void 0) {
|
|
889
|
+
deps[name] = pinned;
|
|
890
|
+
continue;
|
|
891
|
+
}
|
|
892
|
+
const view = npmViewVersion(name, targetDir);
|
|
893
|
+
deps[name] = view.ok ? `^${view.version}` : "latest";
|
|
894
|
+
}
|
|
895
|
+
pkg.dependencies = Object.fromEntries(Object.entries(deps).sort(([a], [b]) => a.localeCompare(b)));
|
|
896
|
+
writeFileSync(path, `${JSON.stringify(pkg, null, 2)}
|
|
897
|
+
`, "utf8");
|
|
898
|
+
}
|
|
899
|
+
function deferredDependency(specifier, targetDir) {
|
|
900
|
+
if (!isLocalSpecifier(specifier)) return void 0;
|
|
901
|
+
const name = localPackageName(specifier, targetDir);
|
|
902
|
+
if (name !== void 0) return { name, spec: `file:${localPathOf(specifier)}` };
|
|
903
|
+
throw new UsageError(
|
|
904
|
+
`\`--marketplace ${specifier}\` with \`--no-install\`: its package name is only known once it is installed, so it cannot be recorded in package.json. Drop --no-install, or add it once the project exists with \`${inProject(targetDir)}xanosdk marketplace install ${shellWord(specifier)}\`.`,
|
|
905
|
+
{ helpFor: { command: "init" } }
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
async function writeDerivedFiles(targetDir, renderIndexWithEnv) {
|
|
909
|
+
const written = [];
|
|
910
|
+
let declaredEnv = [];
|
|
911
|
+
const lockPath = join(targetDir, LOCK_REL);
|
|
912
|
+
const routesPath = join(targetDir, ROUTES_REL);
|
|
913
|
+
try {
|
|
914
|
+
const { loadDefault, checkStandInTokens } = await import("./cli.js");
|
|
915
|
+
const { Xano } = await import("./xano-ICFUSPFR.js");
|
|
916
|
+
const { createLockContext, lockKey, mergeObserved } = await import("./lock-MRRHW5GS.js");
|
|
917
|
+
const { resetLockOverrides, seedLockOverrides } = await import("./store-6VNCD4D7.js");
|
|
918
|
+
const { readLockFile, writeLockFile } = await import("./io-RC56QSN5.js");
|
|
919
|
+
const { setDiagnosticSink } = await import("./diagnostics-UEAAHWVF.js");
|
|
920
|
+
const { planRouteManifest, renderPlannedManifest } = await import("./routes-manifest-SNWUVBT6.js");
|
|
921
|
+
const existing = existsSync(lockPath) ? readLockFile(lockPath) : void 0;
|
|
922
|
+
resetLockOverrides();
|
|
923
|
+
if (existing !== void 0) seedLockOverrides(existing);
|
|
924
|
+
const ctx = createLockContext(existing);
|
|
925
|
+
const { envNamesRead } = await import("./guards-4EBNCZDC.js");
|
|
926
|
+
const { refreshEnvExample } = await import("./env-example-refresh-ET5HMMDW.js");
|
|
927
|
+
const def = await loadDefault(join(targetDir, XANO_DIR, "index.ts"));
|
|
928
|
+
if (!Xano.isXano(def)) return { written, env: declaredEnv };
|
|
929
|
+
const previousSink = setDiagnosticSink(() => {
|
|
930
|
+
});
|
|
931
|
+
let payload;
|
|
932
|
+
try {
|
|
933
|
+
payload = def.export({ lock: ctx, documentationTokens: checkStandInTokens(def).values }).payload;
|
|
934
|
+
} finally {
|
|
935
|
+
setDiagnosticSink(previousSink);
|
|
936
|
+
}
|
|
937
|
+
const sections = {};
|
|
938
|
+
for (const [key, value] of Object.entries(payload)) if (Array.isArray(value)) sections[key] = value;
|
|
939
|
+
const env = envNamesRead(sections);
|
|
940
|
+
if (env.length > 0) {
|
|
941
|
+
writeFileSync(join(targetDir, XANO_DIR, "index.ts"), renderIndexWithEnv(env), "utf8");
|
|
942
|
+
refreshEnvExample(join(targetDir, XANO_DIR), Object.fromEntries(env.map((name) => [name, ""])));
|
|
943
|
+
declaredEnv = env;
|
|
944
|
+
}
|
|
945
|
+
const { lock } = mergeObserved(ctx.lock, ctx.observed);
|
|
946
|
+
if (existing === void 0 && Object.keys(lock.objects).length > 0) {
|
|
947
|
+
writeLockFile(lockPath, lock);
|
|
948
|
+
written.push(LOCK_REL);
|
|
949
|
+
}
|
|
950
|
+
const manifest = renderPlannedManifest(
|
|
951
|
+
planRouteManifest(payload, (kind, name) => lock.objects[lockKey(kind, name)]?.canonical)
|
|
952
|
+
);
|
|
953
|
+
if (manifest !== void 0) {
|
|
954
|
+
writeFileSync(routesPath, manifest, "utf8");
|
|
955
|
+
written.push(ROUTES_REL);
|
|
956
|
+
}
|
|
957
|
+
} catch (err) {
|
|
958
|
+
warn(
|
|
959
|
+
`xano/index.ts does not load yet, so ${LOCK_REL} and ${ROUTES_REL} were not written: ${err instanceof Error ? err.message : String(err)}`,
|
|
960
|
+
"init.lock-derive-failed",
|
|
961
|
+
[`Fix xano/index.ts, then run \`npm run xano:export\` \u2014 it writes both.`]
|
|
962
|
+
);
|
|
963
|
+
return { written, env: declaredEnv, failed: true };
|
|
964
|
+
}
|
|
965
|
+
return { written, env: declaredEnv };
|
|
966
|
+
}
|
|
967
|
+
async function refuseUnknownProfileFlag(args, targetDir) {
|
|
968
|
+
const { ENV_PROFILE } = await import("./profile-select-74TRDEPD.js");
|
|
969
|
+
const envRaw = readEnvVar(ENV_PROFILE)?.trim();
|
|
970
|
+
const fromEnv = args.profile === void 0 && envRaw !== void 0;
|
|
971
|
+
const name = args.profile ?? (fromEnv ? envRaw : void 0);
|
|
972
|
+
if (name === void 0) return;
|
|
973
|
+
if (fromEnv && targetDir !== void 0) {
|
|
974
|
+
const { POINTER_FILE } = await import("./profile-pointer-GRWJU3YD.js");
|
|
975
|
+
if (existsSync(join(targetDir, POINTER_FILE))) return;
|
|
976
|
+
}
|
|
977
|
+
const { readCredentialFile, resolveAuthFilePath, profileNames, loginHint } = await import("./store-ARM6VMO5.js");
|
|
978
|
+
const path = resolveAuthFilePath(args, "read");
|
|
979
|
+
const file = readCredentialFile(path);
|
|
980
|
+
const stored = file === null ? [] : profileNames(file);
|
|
981
|
+
if (stored.includes(name)) return;
|
|
982
|
+
const { ProfileNotFoundError } = await import("./token-NICJUTMT.js");
|
|
983
|
+
const have = stored.length === 0 ? "Nothing is signed in on this machine." : `Stored profiles: ${quotedNames(stored)}.`;
|
|
984
|
+
throw new ProfileNotFoundError(
|
|
985
|
+
`No credential profile "${name}" in ${path} (from ${fromEnv ? `$${ENV_PROFILE}` : "--profile"}), so there is nothing to pin this project to. ${have} Run ${loginHint(name)} to add it, or name a stored one${fromEnv ? ` (or unset ${ENV_PROFILE})` : ""}.`,
|
|
986
|
+
{ name, source: fromEnv ? "env" : "flag" },
|
|
987
|
+
stored
|
|
988
|
+
);
|
|
989
|
+
}
|
|
990
|
+
async function envCredentialSet() {
|
|
991
|
+
const { envMetaCredentialVarsSet } = await import("./token-NICJUTMT.js");
|
|
992
|
+
return envMetaCredentialVarsSet().length > 0;
|
|
993
|
+
}
|
|
994
|
+
function loginNextStep(pin, projectDir) {
|
|
995
|
+
return pin.signedIn ? "" : ` ${projectCli(projectDir)} login # authenticate with Xano
|
|
996
|
+
`;
|
|
997
|
+
}
|
|
998
|
+
function projectCli(projectDir) {
|
|
999
|
+
const prefix = cliPrefixAt(projectDir);
|
|
1000
|
+
return prefix === "xanosdk" || prefix === "npx @xano/sdk" ? "npx xanosdk" : prefix;
|
|
1001
|
+
}
|
|
1002
|
+
function runFromHere(text, targetDir) {
|
|
1003
|
+
return text.replace(/`npx xanosdk /g, `\`${inProject(targetDir)}xanosdk `);
|
|
1004
|
+
}
|
|
1005
|
+
async function planProfilePin(args, targetDir, opts = {}) {
|
|
1006
|
+
const { POINTER_FILE, readPointerFile } = await import("./profile-pointer-GRWJU3YD.js");
|
|
1007
|
+
const { readCredentialFile, resolveAuthFilePath, profileNames, loginHint } = await import("./store-ARM6VMO5.js");
|
|
1008
|
+
const credentialPath = resolveAuthFilePath(args, "read");
|
|
1009
|
+
const file = readCredentialFile(credentialPath);
|
|
1010
|
+
const signedIn = file !== null && profileNames(file).length > 0 || await envCredentialSet();
|
|
1011
|
+
const pointerPath = join(targetDir, POINTER_FILE);
|
|
1012
|
+
if (existsSync(pointerPath)) {
|
|
1013
|
+
let pinned = null;
|
|
1014
|
+
try {
|
|
1015
|
+
pinned = readPointerFile(pointerPath) ?? null;
|
|
1016
|
+
} catch {
|
|
1017
|
+
}
|
|
1018
|
+
const unknownPin = pinned !== null && !(file !== null && profileNames(file).includes(pinned)) && !await envCredentialSet();
|
|
1019
|
+
return {
|
|
1020
|
+
// What the project IS pinned to — `init --force` over a pinned target
|
|
1021
|
+
// keeps the pin, so reporting null here said the opposite of the file.
|
|
1022
|
+
name: pinned,
|
|
1023
|
+
signedIn,
|
|
1024
|
+
file: null,
|
|
1025
|
+
report: () => {
|
|
1026
|
+
detail(`Already pinned: ${POINTER_FILE} is left as it is.`);
|
|
1027
|
+
if (unknownPin) {
|
|
1028
|
+
warn(
|
|
1029
|
+
`${POINTER_FILE} pins profile "${pinned}", which this machine does not have \u2014 commands here will fail until you run ${loginHint(pinned)}, or re-pin with \`${inProject(targetDir)}xanosdk profile use <name>\`.`,
|
|
1030
|
+
"profile.pin-missing"
|
|
1031
|
+
);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
if (opts.credentialRead === true) {
|
|
1037
|
+
const { environmentCredentialVars } = await import("./token-NICJUTMT.js");
|
|
1038
|
+
const env = environmentCredentialVars();
|
|
1039
|
+
if (env.complete) {
|
|
1040
|
+
return {
|
|
1041
|
+
name: null,
|
|
1042
|
+
signedIn,
|
|
1043
|
+
file: null,
|
|
1044
|
+
report: () => detail(
|
|
1045
|
+
`Not pinned: this read used the environment credential (${env.vars.join(", ")}), not a stored profile. To pin one, run \`${inProject(targetDir)}xanosdk profile use <name>\` \u2014 it writes ${POINTER_FILE}.`
|
|
1046
|
+
)
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
const { resolveActiveProfile } = await import("./profile-select-74TRDEPD.js");
|
|
1051
|
+
const selection = resolveActiveProfile({
|
|
1052
|
+
flag: args.profile,
|
|
1053
|
+
fileDefault: file?.default,
|
|
1054
|
+
// Nothing is pinned yet — that is what this function is about to decide —
|
|
1055
|
+
// so the pointer rung has nothing to contribute to its own creation.
|
|
1056
|
+
readPointer: () => void 0
|
|
1057
|
+
});
|
|
1058
|
+
const stored = file === null ? [] : profileNames(file);
|
|
1059
|
+
if (!stored.includes(selection.name)) {
|
|
1060
|
+
const env = stored.length === 0 ? (await import("./token-NICJUTMT.js")).environmentCredentialVars() : void 0;
|
|
1061
|
+
const storeEnv = env?.complete === true ? await storeEnvCredentialCommand(credentialPath, targetDir) : "";
|
|
1062
|
+
return {
|
|
1063
|
+
name: null,
|
|
1064
|
+
signedIn,
|
|
1065
|
+
file: null,
|
|
1066
|
+
report: () => detail(
|
|
1067
|
+
env?.complete === true ? `Not pinned: commands here use the environment credential (${env.vars.join(", ")}), not a stored profile. To pin it, store it as a profile and pin that: \`${storeEnv}\` \u2014 it writes ${POINTER_FILE}.` : stored.length === 0 ? `Not pinned: no signed-in profile to pin to yet. Run \`${inProject(targetDir)}xanosdk login && xanosdk profile use <name>\` to write ${POINTER_FILE}.` : `Not pinned: none of the signed-in profiles (${quotedNames(stored)}) is the default. Run \`${inProject(targetDir)}xanosdk profile use <name>\` to write ${POINTER_FILE}.`
|
|
1068
|
+
)
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
if (selection.source === "file-default" || selection.source === "implicit") {
|
|
1072
|
+
const elsewhere = await envAddressesElsewhere(file, selection.name, credentialPath);
|
|
1073
|
+
if (elsewhere !== null) {
|
|
1074
|
+
return {
|
|
1075
|
+
name: null,
|
|
1076
|
+
signedIn,
|
|
1077
|
+
file: null,
|
|
1078
|
+
report: () => detail(
|
|
1079
|
+
`Not pinned: commands here use the environment credential (${elsewhere.env}), not the default profile "${selection.name}" (${elsewhere.stored}). To pin "${selection.name}" deliberately, run \`${inProject(targetDir)}xanosdk profile use ${shellWord(selection.name)}\` \u2014 it writes ${POINTER_FILE}.`
|
|
1080
|
+
)
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
const { writePointerFile } = await import("./profile-pointer-GRWJU3YD.js");
|
|
1085
|
+
return {
|
|
1086
|
+
name: selection.name,
|
|
1087
|
+
signedIn,
|
|
1088
|
+
// The same bytes `writePointerFile` writes.
|
|
1089
|
+
file: { path: POINTER_FILE, content: `${JSON.stringify({ profile: selection.name }, null, 2)}
|
|
1090
|
+
` },
|
|
1091
|
+
report: () => {
|
|
1092
|
+
if (!existsSync(join(targetDir, POINTER_FILE))) writePointerFile(targetDir, selection.name);
|
|
1093
|
+
info(`Pinned to profile "${selection.name}" in ${POINTER_FILE} \u2014 commit it, so every clone deploys here.`);
|
|
1094
|
+
}
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
async function envAddressesElsewhere(file, name, credentialPath) {
|
|
1098
|
+
const instance = readEnvVar("XANO_INSTANCE_URL")?.trim();
|
|
1099
|
+
const workspace = readEnvVar("XANO_WORKSPACE_ID")?.trim();
|
|
1100
|
+
if (instance === void 0 || workspace === void 0 || readEnvVar("XANO_META_TOKEN") === void 0) return null;
|
|
1101
|
+
const { readProfile, sameOriginAs } = await import("./store-ARM6VMO5.js");
|
|
1102
|
+
let record;
|
|
1103
|
+
try {
|
|
1104
|
+
record = readProfile(file, name, credentialPath);
|
|
1105
|
+
} catch {
|
|
1106
|
+
return null;
|
|
1107
|
+
}
|
|
1108
|
+
if (record === null) return null;
|
|
1109
|
+
const storedInstance = record.type === "token" ? record.instance_base_url : record.instance;
|
|
1110
|
+
if (sameOriginAs(storedInstance, instance) && String(record.workspace_id) === workspace) return null;
|
|
1111
|
+
return {
|
|
1112
|
+
env: `workspace ${workspace} on ${instance}`,
|
|
1113
|
+
stored: `workspace ${record.workspace_id} on ${storedInstance}`
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
async function storeEnvCredentialCommand(credentialPath, targetDir) {
|
|
1117
|
+
const { credentialFileFlag, profileAddCommand } = await import("./store-ARM6VMO5.js");
|
|
1118
|
+
const { DEFAULT_PROFILE } = await import("./profile-select-74TRDEPD.js");
|
|
1119
|
+
const instance = readEnvVar("XANO_INSTANCE_URL");
|
|
1120
|
+
const workspaceId = readEnvVar("XANO_WORKSPACE_ID");
|
|
1121
|
+
const flag = credentialFileFlag(credentialPath);
|
|
1122
|
+
const store = instance !== void 0 && workspaceId !== void 0 && readEnvVar("XANO_META_TOKEN") !== void 0 ? `printf %s "$XANO_META_TOKEN" | ${profileAddCommand(DEFAULT_PROFILE, { path: credentialPath, instance, workspaceId: workspaceId.trim() })}` : `xanosdk login${flag}`;
|
|
1123
|
+
return `${inProject(targetDir)}${store} && xanosdk profile use ${DEFAULT_PROFILE}${flag}`;
|
|
1124
|
+
}
|
|
1125
|
+
function sdkResolves(dir) {
|
|
1126
|
+
return readInstalledManifestState(dir, "@xano/sdk").kind !== "absent";
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
export {
|
|
1130
|
+
resolveThemeChoice,
|
|
1131
|
+
resolveFrontendPreset,
|
|
1132
|
+
projectInstallOf,
|
|
1133
|
+
workflowPlacementNote,
|
|
1134
|
+
workflowMoveTarget,
|
|
1135
|
+
reportWorkflowPlacement,
|
|
1136
|
+
templateVarsFor,
|
|
1137
|
+
sanitizeAppName,
|
|
1138
|
+
projectShellFiles,
|
|
1139
|
+
resolveFromSource,
|
|
1140
|
+
runInitCommand,
|
|
1141
|
+
loginNextStep,
|
|
1142
|
+
projectCli,
|
|
1143
|
+
planProfilePin
|
|
1144
|
+
};
|
|
1145
|
+
//# sourceMappingURL=chunk-LRN4ZJCQ.js.map
|