@platforma-sdk/bootstrap 3.0.0 → 3.0.1

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/README.md ADDED
@@ -0,0 +1,61 @@
1
+ # The CLI multitool for Platforma Block developers.
2
+
3
+ ## Installation
4
+ ```bash
5
+ npm install --global @platforma-sdk/bootstrap@latest
6
+ # or
7
+ pnpm install --global @platforma-sdk/bootstrap@latest
8
+ ```
9
+ or use it without installation with
10
+ ```bash
11
+ npx @platforma-sdk/bootstrap@latest '<args>'
12
+ # or
13
+ pnpx @platforma-sdk/bootstrap@latest '<args>'
14
+ ```
15
+
16
+ ## Key features:
17
+ - empty block skeleton generation
18
+ - local Platforma Backend service control
19
+
20
+ ## Usage:
21
+
22
+ ```
23
+ pl-dev '<command>'
24
+ # or without installation
25
+ npx @platforma-sdk/bootstrap@latest '<command>'
26
+ ```
27
+
28
+ The tool has 'tree' command structure, like `aws-cli`, `docker`, `git` and many other CLI software:
29
+ commands about specific type of operations are grouped under common prefix, i.e. all operations for
30
+ platforma backend service instances are under `svc` group:
31
+ ```bash
32
+ pl-dev svc create --help
33
+ ```
34
+
35
+ All commands have `--help` flag that make the command to report its usage information:
36
+ ```bash
37
+ pl-dev --help
38
+ ```
39
+
40
+ ## Local Platforma Backend service control
41
+
42
+ To create, change, start, stop and delete Platforma Backend on your local computer, use commands in `svc` group:
43
+ - `pl-dev svc create docker NAME` creates instance of Platforma Backend inside docker container on your local computer. You can start/stop this instance with `svc up NAME` and `svc down NAME` commands, and connect to it via `localhost:6345` address.
44
+ - `pl-dev svc list` lists available service instances you created earlier.
45
+
46
+ Here are few examples on how to prepare your first instance of Platforma Backend started right on your laptop without any containerisation:
47
+
48
+ ```bash
49
+ pl-dev svc create local MyLocalPl
50
+ pl-dev svc up MyLocalPl
51
+ ```
52
+
53
+ The tool will download Platforma Backend archive for your OS and architecture, generate configuration file and all necessary directories.
54
+ `up` command will make the service instance start.
55
+
56
+ ## Block skeleton generation
57
+
58
+ To create new block skeleton, run
59
+ ```bash
60
+ pl-dev create-block
61
+ ```
package/dist/index.js CHANGED
@@ -93,11 +93,11 @@ controllers:
93
93
  Save to: ${i}`);const c=Lr.get(s);return new Promise((o,m)=>{c.on("response",f=>{if(!f.statusCode){const b=new Error("failed to download archive: no HTTP status code in response from server");c.destroy(),m(b);return}if(f.statusCode!==200){const b=new Error(`failed to download archive: ${f.statusCode} ${f.statusMessage}`);c.destroy(),m(b);return}const y=parseInt(f.headers["content-length"]||"0",10);let w=0;const v=u.createWriteStream(i);f.pipe(v),f.on("data",b=>{w+=b.length;const P=w/y*100;r&&process.stdout.write(` downloading: ${P.toFixed(2)}%\r`)}),f.on("error",b=>{u.unlinkSync(i),a.error(`Failed to download Platforma Binary: ${b.message}`),c.destroy(),m(b)}),v.on("finish",()=>{v.close(),a.info(" ... download done."),c.destroy(),o(i)})})})}function tt(a,e){a.debug("extracting archive...");const t=(e==null?void 0:e.version)??ue.getDefaultPlVersion();a.debug(` version: '${t}'`);const r=`${wr({version:t})}.tgz`,n=(e==null?void 0:e.archivePath)??g.binaries(r);a.debug(` archive path: '${n}'`);const s=(e==null?void 0:e.extractTo)??nt(n);if(a.debug(` target dir: '${s}'`),u.existsSync(s))return a.info(`Platforma Backend binaries unpack skipped: '${s}' exists`),s;if(!u.existsSync(n)){const i=`Platforma Backend binary archive not found at '${n}'`;throw a.error(i),new Error(i)}return u.existsSync(s)||(a.debug(` creating target dir '${s}'`),u.mkdirSync(s,{recursive:!0})),a.info(`Unpacking Platforma Backend archive:
94
94
  Archive: ${n}
95
95
  Target dir: ${s}`),Or.x({file:n,cwd:s,gzip:!0,sync:!0}),a.info(" ... unpack done."),s}function je(a,e){return rt(a,e).then(t=>tt(a,{archivePath:t}))}function wr(a){return`pl-${(a==null?void 0:a.version)??ue.getDefaultPlVersion()}-${pr()}`}function at(a,...e){return g.binaries(wr({version:a}),...e)}function nt(a){const e=a.lastIndexOf(".");return e===-1?a:a.slice(0,e)}class I{constructor(e){this.logger=e}startLast(){const e=g.currentInstance;if(!e)throw this.logger.error("failed to bring back Platforma Backend in the last started configuration: no last configuration found"),new Error("no previous run info found");return this.startInstance(e)}startInstance(e){if(e.runInfo){const r=this.renderRunInfo(e.runInfo);this.logger.info(`Starting platforma backend instance '${e.name}':
96
- ${r}`)}const t=pe(this.logger,e.upCommands);return de(t.executed),t.spawned.length>0&&e.type==="process"&&(e.pid=t.spawned[t.spawned.length-1].pid,g.setInstanceInfo(e.name,e),this.logger.info(`instance '${e.name}' started`)),g.currentInstanceName=e.name,t.spawned}stopInstance(e){if(!g.isInstanceActive(e)){this.logger.info(`instance '${e.name}' is not running`);return}this.logger.info(`stopping platforma backend instance '${e.name}'...`);const t=pe(this.logger,e.downCommands);switch(de(t.executed),e.type){case"docker":return;case"process":{e.pid&&g.isValidPID(e.pid)&&process.kill(e.pid);return}default:_()}}switchInstance(e){for(const t of g.instanceList)if(t!==e.name){const r=g.getInstanceInfo(t);g.isInstanceActive(r)&&this.stopInstance(r)}return this.startInstance(e)}createLocal(e,t){var o,m,f,y,w,v,b,P,S,k;const r=(t==null?void 0:t.binaryPath)??at(t==null?void 0:t.version,"binaries","platforma");let n=t==null?void 0:t.configPath;const s=(t==null?void 0:t.workdir)??(n?process.cwd():g.instanceDir(e));t!=null&&t.primaryURL&&(t.configOptions={...t.configOptions,storages:{...(o=t.configOptions)==null?void 0:o.storages,primary:V(t.primaryURL,s,(f=(m=t.configOptions)==null?void 0:m.storages)==null?void 0:f.primary)}}),t!=null&&t.libraryURL&&(t.configOptions={...t.configOptions,storages:{...(y=t.configOptions)==null?void 0:y.storages,library:V(t.libraryURL,s,(v=(w=t.configOptions)==null?void 0:w.storages)==null?void 0:v.library)}});const i=Kr(this.getLastJwt(),t==null?void 0:t.configOptions);this.logger.debug(" checking license..."),this.checkLicense((P=(b=t==null?void 0:t.configOptions)==null?void 0:b.license)==null?void 0:P.value,(k=(S=t==null?void 0:t.configOptions)==null?void 0:S.license)==null?void 0:k.file);const c=[`${i.localRoot}/packages`,`${i.localRoot}/packages-local`,`${i.localRoot}/blocks-local`];i.storages.primary.type==="FS"&&c.push(i.storages.primary.rootPath),i.storages.library.type==="FS"&&(c.push(i.storages.library.rootPath),i.hacks.libraryDownloadable=!1),i.storages.work.type==="FS"&&c.push(i.storages.work.rootPath),this.logger.debug(" creating pl state directories...");for(const p of c)u.existsSync(p)||(this.logger.debug(` '${p}'`),u.mkdirSync(p,{recursive:!0}));for(const p of i.core.auth.drivers)p.driver==="htpasswd"&&(u.existsSync(p.path)||(this.logger.debug(` installing default 'users.htpasswd' to ${p.path}...`),u.copyFileSync(Y("users.htpasswd"),p.path)));return n||(n=h.join(i.localRoot,"config.yaml"),this.logger.debug(` rendering configuration '${n}'...`),u.writeFileSync(n,Qr(i))),g.setInstanceInfo(e,{type:"process",upCommands:[{async:!0,cmd:r,args:["-config",n],workdir:s,runOpts:{stdio:"inherit"}}],downCommands:[],cleanupCommands:[],runInfo:{configPath:n,dbPath:i.core.db.path,apiAddr:i.grpc.listen,logPath:i.log.path,primary:i.storages.primary,work:i.storages.work,library:i.storages.library}}),g.getInstanceInfo(e)}createLocalS3(e,t){var c;this.logger.debug("creating platforma instance in 'local s3' mode...");const r=(t==null?void 0:t.minioPort)??9e3,n=this.createLocal(e,{...t,primaryURL:(t==null?void 0:t.primaryURL)??`s3e://testuser:testpassword@localhost:${r}/main-bucket/?region=no-region`,libraryURL:(t==null?void 0:t.libraryURL)??`s3e://testuser:testpassword@localhost:${r}/library-bucket/?region=no-region`}),s=(c=t==null?void 0:t.configOptions)==null?void 0:c.localRoot,i=this.createMinio(e,{minioPort:r,minioConsolePort:t==null?void 0:t.minioConsolePort,storage:s?h.join(s,"minio"):void 0});return n.upCommands=[i.start,...n.upCommands],n.downCommands=[i.stop,...n.downCommands],n.cleanupCommands=[i.cleanup,...n.cleanupCommands],g.setInstanceInfo(e,n),n}createMinio(e,t){this.logger.debug(" creating docker compose for minio service...");const r=Y("compose-backend.yaml"),n=g.instanceDir(e,"compose-minio.yaml");we(r,n,`pl-${e}-minio`,new Map([["minio",{}]]),{dropVolumes:!0});const s=t!=null&&t.version?`:${t.version}`:"";this.logger.debug(` minio version: ${s}`);const i=(t==null?void 0:t.image)??`quay.io/minio/minio${s}`;this.logger.debug(` minio image: ${i}`);const c=(t==null?void 0:t.storage)??g.instanceDir(e,"minio");ye(c,{mode:"0775"});const o=(t==null?void 0:t.minioPort)??9e3,m=(t==null?void 0:t.minioConsolePort)??9001,f={MINIO_IMAGE:i,MINIO_STORAGE:h.resolve(c),MINIO_PORT:o.toString(),MINIO_CONSOLE_PORT:m.toString()};return{start:{cmd:"docker",args:["compose",`--file=${n}`,"up","--detach","--remove-orphans","--pull=missing"],envs:f,workdir:g.instanceDir(e),runOpts:{stdio:"inherit"}},stop:{cmd:"docker",args:["compose",`--file=${n}`,"down"],envs:f,workdir:g.instanceDir(e),runOpts:{stdio:"inherit"}},cleanup:{cmd:"docker",args:["compose",`--file=${n}`,"down","--volumes","--remove-orphans"],envs:f,workdir:g.instanceDir(e),runOpts:{stdio:"inherit"}}}}buildPlatforma(e){const t=h.resolve(e.repoRoot,"cmd","platforma"),r=e.binPath??h.join(T.tmpdir(),"platforma-local-build");this.logger.info("Building Platforma Backend binary from sources"),this.logger.info(` sources path: ${e.repoRoot}`),this.logger.info(` binary path: ${r}`);const n=ae.spawnSync("go",["build","-o",r,"."],{cwd:t,stdio:"inherit"});return de([n],"failed to build platforma binary from sources using 'go build' command"),r}createDockerS3(e,t,r){this.logger.debug("creating platforma instance in 'docker s3' mode...");const n=Y("compose-backend.yaml"),s=(r==null?void 0:r.image)??or(r==null?void 0:r.version);this.checkLicense(r==null?void 0:r.license,r==null?void 0:r.licenseFile);const i=(...p)=>h.join(t,...p),c=p=>{const $=i(p);return ye($,{mode:"0775"}),$},o=i("logs","platforma.log");u.existsSync(o)||(u.mkdirSync(h.dirname(o),{recursive:!0}),u.writeFileSync(o,""));const m=(r==null?void 0:r.presignHost)??"localhost",f=V("s3e://testuser:testpassword@minio:9000/main-bucket");if(f.type!=="S3")throw new Error("primary storage must have 'S3' type in 'docker s3' configuration");f.presignEndpoint=`http://${m}:9000`;const y=V("s3e://testuser:testpassword@minio:9000/library-bucket");if(y.type!=="S3")throw new Error(`${y.type} storage type is not supported for library storage`);y.presignEndpoint=`http://${m}:9000`;const w=c("db"),v=c("work"),b=i("users.htpasswd");u.existsSync(b)||u.copyFileSync(Y("users.htpasswd"),b);const P=i("compose.yaml");u.existsSync(P)&&this.logger.info(`replacing docker compose file ${P}`);const S=[];for(const p of(r==null?void 0:r.customMounts)??[])S.push({hostPath:p.hostPath,containerPath:p.containerPath??p.hostPath});we(n,P,`pl-${e}`,new Map([["minio",{}],["backend",{platform:r==null?void 0:r.platformOverride,mounts:S}]]));const k={MINIO_IMAGE:"quay.io/minio/minio",MINIO_STORAGE:c("minio"),PL_IMAGE:s,PL_AUTH_HTPASSWD_PATH:b,PL_LICENSE:r==null?void 0:r.license,PL_LICENSE_FILE:r==null?void 0:r.licenseFile,PL_LOG_LEVEL:(r==null?void 0:r.logLevel)??"info",PL_LOG_DIR:h.dirname(o),PL_LOG_ROTATION_ENABLED:"true",PL_DATA_DB_ROOT:w,PL_DATA_PRIMARY_ROOT:c("primary"),PL_DATA_LIBRARY_ROOT:c("library"),PL_DATA_WORKDIR_ROOT:v,...this.configureDockerStorage("primary",f),...this.configureDockerStorage("library",y)};if(r!=null&&r.grpcAddr&&(k.PL_GRPC_ADDR=r.grpcAddr),r!=null&&r.grpcPort&&(k.PL_GRPC_PORT=r.grpcPort.toString()),r!=null&&r.monitoringAddr&&(k.PL_MONITORING_ADDR=r.monitoringAddr),r!=null&&r.monitoringPort&&(k.PL_MONITORING_PORT=r.monitoringPort.toString()),r!=null&&r.debugAddr&&(k.PL_DEBUG_ADDR=r.debugAddr),r!=null&&r.debugPort&&(k.PL_DEBUG_PORT=r.debugPort.toString()),r!=null&&r.auth&&(r.auth.enabled&&(k.PL_AUTH_ENABLED="true"),r.auth.drivers)){for(const p of r.auth.drivers)p.driver==="htpasswd"&&(k.PL_AUTH_HTPASSWD_PATH=h.resolve(p.path),p.path="/etc/platforma/users.htpasswd");k.PL_AUTH_DRIVERS=JSON.stringify(r.auth.drivers)}return g.setInstanceInfo(e,{type:"docker",upCommands:[{cmd:"docker",args:["compose",`--file=${P}`,"up","--detach","--remove-orphans","--pull=missing"],envs:k,runOpts:{stdio:"inherit"}}],downCommands:[{cmd:"docker",args:["compose",`--file=${P}`,"down"],envs:k,runOpts:{stdio:"inherit"}}],cleanupCommands:[{cmd:"docker",args:["compose",`--file=${P}`,"down","--volumes","--remove-orphans"],envs:k,runOpts:{stdio:"inherit"}}],runInfo:{apiPort:r==null?void 0:r.grpcPort,apiAddr:r==null?void 0:r.grpcAddr,logPath:o,primary:f,work:{type:"FS",rootPath:v},library:y,dbPath:w}}),g.getInstanceInfo(e)}createDocker(e,t,r){this.logger.debug("creating platforma instance in 'docker' mode...");const n=Y("compose-backend.yaml"),s=(r==null?void 0:r.image)??or(r==null?void 0:r.version);this.checkLicense(r==null?void 0:r.license,r==null?void 0:r.licenseFile);const i=(...$)=>h.join(t,...$),c=$=>{const ne=i($);return ye(ne,{mode:"0775"}),ne},o=i("logs","platforma.log");u.existsSync(o)||(u.mkdirSync(h.dirname(o),{recursive:!0}),u.writeFileSync(o,""));const m=c("db"),f=c("primary"),y=c("library"),w=c("work"),v=i("users.htpasswd");u.existsSync(v)||u.copyFileSync(Y("users.htpasswd"),v);const b=i("compose.yaml");u.existsSync(b)&&this.logger.info(`replacing docker compose file ${b}`);const P=[];for(const $ of(r==null?void 0:r.customMounts)??[])P.push({hostPath:$.hostPath,containerPath:$.containerPath??$.hostPath});this.logger.debug(`Rendering docker compose file '${b}' using '${n}' as base template`),we(n,b,`pl-${e}`,new Map([["backend",{platform:r==null?void 0:r.platformOverride,mounts:P}]]));const S=V((r==null?void 0:r.primaryStorageURL)??`file:${f}`,"."),k=V((r==null?void 0:r.libraryStorageURL)??`file:${y}`,"."),p={MINIO_IMAGE:"quay.io/minio/minio",MINIO_STORAGE:c("minio"),PL_IMAGE:s,PL_AUTH_HTPASSWD_PATH:v,PL_LICENSE:r==null?void 0:r.license,PL_LICENSE_FILE:r==null?void 0:r.licenseFile,PL_LOG_LEVEL:"info",PL_LOG_DIR:h.dirname(o),PL_LOG_ROTATION_ENABLED:"true",PL_DATA_DB_ROOT:m,PL_DATA_PRIMARY_ROOT:f,PL_DATA_LIBRARY_ROOT:y,PL_DATA_WORKDIR_ROOT:w,PL_DATA_PACKAGE_ROOT:c("packages"),...this.configureDockerStorage("primary",S),...this.configureDockerStorage("library",k)};if(r!=null&&r.grpcAddr&&(p.PL_GRPC_ADDR=r.grpcAddr),r!=null&&r.grpcPort&&(p.PL_GRPC_PORT=r.grpcPort.toString()),r!=null&&r.monitoringAddr&&(p.PL_MONITORING_ADDR=r.monitoringAddr),r!=null&&r.monitoringPort&&(p.PL_MONITORING_PORT=r.monitoringPort.toString()),r!=null&&r.debugAddr&&(p.PL_DEBUG_ADDR=r.debugAddr),r!=null&&r.debugPort&&(p.PL_DEBUG_PORT=r.debugPort.toString()),r!=null&&r.auth&&(r.auth.enabled&&(p.PL_AUTH_ENABLED="true"),r.auth.drivers)){for(const $ of r.auth.drivers)$.driver==="htpasswd"&&(p.PL_AUTH_HTPASSWD_PATH=h.resolve($.path),$.path="/etc/platforma/users.htpasswd");p.PL_AUTH_DRIVERS=JSON.stringify(r.auth.drivers)}return g.setInstanceInfo(e,{type:"docker",upCommands:[{cmd:"docker",args:["compose",`--file=${b}`,"up","--detach","--remove-orphans","--pull=missing"],envs:p,runOpts:{stdio:"inherit"}}],downCommands:[{cmd:"docker",args:["compose",`--file=${b}`,"down"],envs:p,runOpts:{stdio:"inherit"}}],cleanupCommands:[{cmd:"docker",args:["compose",`--file=${b}`,"down","--volumes","--remove-orphans"],envs:p,runOpts:{stdio:"inherit"}}],runInfo:{apiPort:r==null?void 0:r.grpcPort,apiAddr:r==null?void 0:r.grpcAddr,logPath:o,primary:S,work:{type:"FS",rootPath:w},library:k,dbPath:m}}),g.getInstanceInfo(e)}cleanupInstance(e){const t=[],r=new Map;let n="";if(e){const s=g.getInstanceInfo(e);switch(r.set(e,s),s.type){case"docker":{t.push(`docker service 'pl-${e}', including all its volumes and data in '${g.instanceDir(e)}' will be destroyed`);break}case"process":{t.push(`directory '${g.instanceDir(e)}' would be deleted`),s.downCommands&&t.push("associated docker service, including all volumes and data will be destroyed");break}default:_()}e===g.currentInstanceName&&t.push("last command run cache ('pl-service start' shorthand will stop working until next full start command call)"),n=`
96
+ ${r}`)}const t=pe(this.logger,e.upCommands);return de(t.executed),t.spawned.length>0&&e.type==="process"&&(e.pid=t.spawned[t.spawned.length-1].pid,g.setInstanceInfo(e.name,e),this.logger.info(`instance '${e.name}' started`)),g.currentInstanceName=e.name,t.spawned}stopInstance(e){if(!g.isInstanceActive(e)){this.logger.info(`instance '${e.name}' is not running`);return}this.logger.info(`stopping platforma backend instance '${e.name}'...`);const t=pe(this.logger,e.downCommands);switch(de(t.executed),e.type){case"docker":return;case"process":{e.pid&&g.isValidPID(e.pid)&&process.kill(e.pid);return}default:_()}}switchInstance(e){for(const t of g.instanceList)if(t!==e.name){const r=g.getInstanceInfo(t);g.isInstanceActive(r)&&this.stopInstance(r)}return this.startInstance(e)}createLocal(e,t){var o,m,f,y,w,v,b,P,S,k;const r=(t==null?void 0:t.binaryPath)??at(t==null?void 0:t.version,"binaries","platforma");let n=t==null?void 0:t.configPath;const s=(t==null?void 0:t.workdir)??(n?process.cwd():g.instanceDir(e));t!=null&&t.primaryURL&&(t.configOptions={...t.configOptions,storages:{...(o=t.configOptions)==null?void 0:o.storages,primary:V(t.primaryURL,s,(f=(m=t.configOptions)==null?void 0:m.storages)==null?void 0:f.primary)}}),t!=null&&t.libraryURL&&(t.configOptions={...t.configOptions,storages:{...(y=t.configOptions)==null?void 0:y.storages,library:V(t.libraryURL,s,(v=(w=t.configOptions)==null?void 0:w.storages)==null?void 0:v.library)}});const i=Kr(this.getLastJwt(),t==null?void 0:t.configOptions);this.logger.debug(" checking license..."),this.checkLicense((P=(b=t==null?void 0:t.configOptions)==null?void 0:b.license)==null?void 0:P.value,(k=(S=t==null?void 0:t.configOptions)==null?void 0:S.license)==null?void 0:k.file);const c=[`${i.localRoot}/packages`,`${i.localRoot}/packages-local`,`${i.localRoot}/blocks-local`];i.storages.primary.type==="FS"&&c.push(i.storages.primary.rootPath),i.storages.library.type==="FS"&&(c.push(i.storages.library.rootPath),i.hacks.libraryDownloadable=!1),i.storages.work.type==="FS"&&c.push(i.storages.work.rootPath),this.logger.debug(" creating pl state directories...");for(const p of c)u.existsSync(p)||(this.logger.debug(` '${p}'`),u.mkdirSync(p,{recursive:!0}));for(const p of i.core.auth.drivers)p.driver==="htpasswd"&&(u.existsSync(p.path)||(this.logger.debug(` installing default 'users.htpasswd' to ${p.path}...`),u.copyFileSync(Y("users.htpasswd"),p.path)));return n||(n=h.join(i.localRoot,"config.yaml"),this.logger.debug(` rendering configuration '${n}'...`),u.writeFileSync(n,Qr(i))),g.setInstanceInfo(e,{type:"process",upCommands:[{async:!0,cmd:r,args:["-config",n],workdir:s,runOpts:{stdio:"inherit"}}],downCommands:[],cleanupCommands:[],runInfo:{configPath:n,dbPath:i.core.db.path,apiAddr:i.grpc.listen,logPath:i.log.path,primary:i.storages.primary,work:i.storages.work,library:i.storages.library}}),g.getInstanceInfo(e)}createLocalS3(e,t){var c;this.logger.debug("creating platforma instance in 'local s3' mode...");const r=(t==null?void 0:t.minioPort)??9e3,n=this.createLocal(e,{...t,primaryURL:(t==null?void 0:t.primaryURL)??`s3e://testuser:testpassword@localhost:${r}/main-bucket/?region=no-region`,libraryURL:(t==null?void 0:t.libraryURL)??`s3e://testuser:testpassword@localhost:${r}/library-bucket/?region=no-region`}),s=(c=t==null?void 0:t.configOptions)==null?void 0:c.localRoot,i=this.createMinio(e,{minioPort:r,minioConsolePort:t==null?void 0:t.minioConsolePort,storage:s?h.join(s,"minio"):void 0});return n.upCommands=[i.start,...n.upCommands],n.downCommands=[i.stop,...n.downCommands],n.cleanupCommands=[i.cleanup,...n.cleanupCommands],g.setInstanceInfo(e,n),n}createMinio(e,t){this.logger.debug(" creating docker compose for minio service...");const r=Y("compose-backend.yaml"),n=g.instanceDir(e,"compose-minio.yaml");we(r,n,`pl-${e}-minio`,new Map([["minio",{}]]),{dropVolumes:!0});const s=t!=null&&t.version?`:${t.version}`:"";this.logger.debug(` minio version: ${s}`);const i=(t==null?void 0:t.image)??`quay.io/minio/minio${s}`;this.logger.debug(` minio image: ${i}`);const c=(t==null?void 0:t.storage)??g.instanceDir(e,"minio");ye(c,{mode:"0775"});const o=(t==null?void 0:t.minioPort)??9e3,m=(t==null?void 0:t.minioConsolePort)??9001,f={MINIO_IMAGE:i,MINIO_STORAGE:h.resolve(c),MINIO_PORT:o.toString(),MINIO_CONSOLE_PORT:m.toString()};return{start:{cmd:"docker",args:["compose",`--file=${n}`,"up","--detach","--remove-orphans","--pull=missing"],envs:f,workdir:g.instanceDir(e),runOpts:{stdio:"inherit"}},stop:{cmd:"docker",args:["compose",`--file=${n}`,"down"],envs:f,workdir:g.instanceDir(e),runOpts:{stdio:"inherit"}},cleanup:{cmd:"docker",args:["compose",`--file=${n}`,"down","--volumes","--remove-orphans"],envs:f,workdir:g.instanceDir(e),runOpts:{stdio:"inherit"}}}}buildPlatforma(e){const t=h.resolve(e.repoRoot,"cmd","platforma"),r=e.binPath??h.join(T.tmpdir(),"platforma-local-build");this.logger.info("Building Platforma Backend binary from sources"),this.logger.info(` sources path: ${e.repoRoot}`),this.logger.info(` binary path: ${r}`);const n=ae.spawnSync("go",["build","-o",r,"."],{cwd:t,stdio:"inherit"});return de([n],"failed to build platforma binary from sources using 'go build' command"),r}createDockerS3(e,t,r){this.logger.debug("creating platforma instance in 'docker s3' mode...");const n=Y("compose-backend.yaml"),s=(r==null?void 0:r.image)??or(r==null?void 0:r.version);this.checkLicense(r==null?void 0:r.license,r==null?void 0:r.licenseFile);const i=(...p)=>h.join(t,...p),c=p=>{const $=i(p);return ye($,{mode:"0775"}),$},o=i("logs","platforma.log");u.existsSync(o)||(u.mkdirSync(h.dirname(o),{recursive:!0}),u.writeFileSync(o,""));const m=(r==null?void 0:r.presignHost)??"localhost",f=V("s3e://testuser:testpassword@minio:9000/main-bucket");if(f.type!=="S3")throw new Error("primary storage must have 'S3' type in 'docker s3' configuration");f.presignEndpoint=`http://${m}:9000`;const y=V("s3e://testuser:testpassword@minio:9000/library-bucket");if(y.type!=="S3")throw new Error(`${y.type} storage type is not supported for library storage`);y.presignEndpoint=`http://${m}:9000`;const w=c("db"),v=c("work"),b=i("users.htpasswd");u.existsSync(b)||u.copyFileSync(Y("users.htpasswd"),b);const P=i("compose.yaml");u.existsSync(P)&&this.logger.info(`replacing docker compose file ${P}`);const S=[];for(const p of(r==null?void 0:r.customMounts)??[])S.push({hostPath:p.hostPath,containerPath:p.containerPath??p.hostPath});we(n,P,`pl-${e}`,new Map([["minio",{}],["backend",{platform:r==null?void 0:r.platformOverride,mounts:S}]]));const k={MINIO_IMAGE:"quay.io/minio/minio",MINIO_STORAGE:c("minio"),PL_IMAGE:s,PL_AUTH_HTPASSWD_PATH:b,PL_LICENSE:r==null?void 0:r.license,PL_LICENSE_FILE:r==null?void 0:r.licenseFile,PL_LOG_LEVEL:(r==null?void 0:r.logLevel)??"info",PL_LOG_DIR:h.dirname(o),PL_LOG_ROTATION_ENABLED:"true",PL_DATA_DB_ROOT:w,PL_DATA_PRIMARY_ROOT:c("primary"),PL_DATA_LIBRARY_ROOT:c("library"),PL_DATA_WORKDIR_ROOT:v,...this.configureDockerStorage("primary",f),...this.configureDockerStorage("library",y)};if(r!=null&&r.grpcAddr&&(k.PL_GRPC_ADDR=r.grpcAddr),r!=null&&r.grpcPort&&(k.PL_GRPC_PORT=r.grpcPort.toString()),r!=null&&r.monitoringAddr&&(k.PL_MONITORING_ADDR=r.monitoringAddr),r!=null&&r.monitoringPort&&(k.PL_MONITORING_PORT=r.monitoringPort.toString()),r!=null&&r.debugAddr&&(k.PL_DEBUG_ADDR=r.debugAddr),r!=null&&r.debugPort&&(k.PL_DEBUG_PORT=r.debugPort.toString()),r!=null&&r.auth&&(r.auth.enabled&&(k.PL_AUTH_ENABLED="true"),r.auth.drivers)){for(const p of r.auth.drivers)p.driver==="htpasswd"&&(k.PL_AUTH_HTPASSWD_PATH=h.resolve(p.path),p.path="/etc/platforma/users.htpasswd");k.PL_AUTH_DRIVERS=JSON.stringify(r.auth.drivers)}return g.setInstanceInfo(e,{type:"docker",upCommands:[{cmd:"docker",args:["compose",`--file=${P}`,"up","--detach","--remove-orphans","--pull=missing"],envs:k,runOpts:{stdio:"inherit"}}],downCommands:[{cmd:"docker",args:["compose",`--file=${P}`,"down"],envs:k,runOpts:{stdio:"inherit"}}],cleanupCommands:[{cmd:"docker",args:["compose",`--file=${P}`,"down","--volumes","--remove-orphans"],envs:k,runOpts:{stdio:"inherit"}}],runInfo:{apiPort:r==null?void 0:r.grpcPort,apiAddr:r==null?void 0:r.grpcAddr,logPath:o,primary:f,work:{type:"FS",rootPath:v},library:y,dbPath:w}}),g.getInstanceInfo(e)}createDocker(e,t,r){this.logger.debug("creating platforma instance in 'docker' mode...");const n=Y("compose-backend.yaml"),s=(r==null?void 0:r.image)??or(r==null?void 0:r.version);this.checkLicense(r==null?void 0:r.license,r==null?void 0:r.licenseFile);const i=(...$)=>h.join(t,...$),c=$=>{const ne=i($);return ye(ne,{mode:"0775"}),ne},o=i("logs","platforma.log");u.existsSync(o)||(u.mkdirSync(h.dirname(o),{recursive:!0}),u.writeFileSync(o,""));const m=c("db"),f=c("primary"),y=c("library"),w=c("work"),v=i("users.htpasswd");u.existsSync(v)||u.copyFileSync(Y("users.htpasswd"),v);const b=i("compose.yaml");u.existsSync(b)&&this.logger.info(`replacing docker compose file ${b}`);const P=[];for(const $ of(r==null?void 0:r.customMounts)??[])P.push({hostPath:$.hostPath,containerPath:$.containerPath??$.hostPath});this.logger.debug(`Rendering docker compose file '${b}' using '${n}' as base template`),we(n,b,`pl-${e}`,new Map([["backend",{platform:r==null?void 0:r.platformOverride,mounts:P}]]));const S=V((r==null?void 0:r.primaryStorageURL)??`file:${f}`,"."),k=V((r==null?void 0:r.libraryStorageURL)??`file:${y}`,"."),p={MINIO_IMAGE:"quay.io/minio/minio",MINIO_STORAGE:c("minio"),PL_IMAGE:s,PL_AUTH_HTPASSWD_PATH:v,PL_LICENSE:r==null?void 0:r.license,PL_LICENSE_FILE:r==null?void 0:r.licenseFile,PL_LOG_LEVEL:"info",PL_LOG_DIR:h.dirname(o),PL_LOG_ROTATION_ENABLED:"true",PL_DATA_DB_ROOT:m,PL_DATA_PRIMARY_ROOT:f,PL_DATA_LIBRARY_ROOT:y,PL_DATA_WORKDIR_ROOT:w,PL_DATA_PACKAGE_ROOT:c("packages"),...this.configureDockerStorage("primary",S),...this.configureDockerStorage("library",k)};if(r!=null&&r.grpcAddr&&(p.PL_GRPC_ADDR=r.grpcAddr),r!=null&&r.grpcPort&&(p.PL_GRPC_PORT=r.grpcPort.toString()),r!=null&&r.monitoringAddr&&(p.PL_MONITORING_ADDR=r.monitoringAddr),r!=null&&r.monitoringPort&&(p.PL_MONITORING_PORT=r.monitoringPort.toString()),r!=null&&r.debugAddr&&(p.PL_DEBUG_ADDR=r.debugAddr),r!=null&&r.debugPort&&(p.PL_DEBUG_PORT=r.debugPort.toString()),r!=null&&r.auth&&(r.auth.enabled&&(p.PL_AUTH_ENABLED="true"),r.auth.drivers)){for(const $ of r.auth.drivers)$.driver==="htpasswd"&&(p.PL_AUTH_HTPASSWD_PATH=h.resolve($.path),$.path="/etc/platforma/users.htpasswd");p.PL_AUTH_DRIVERS=JSON.stringify(r.auth.drivers)}return g.setInstanceInfo(e,{type:"docker",upCommands:[{cmd:"docker",args:["compose",`--file=${b}`,"up","--detach","--remove-orphans","--pull=missing"],envs:p,runOpts:{stdio:"inherit"}}],downCommands:[{cmd:"docker",args:["compose",`--file=${b}`,"down"],envs:p,runOpts:{stdio:"inherit"}}],cleanupCommands:[{cmd:"docker",args:["compose",`--file=${b}`,"down","--volumes","--remove-orphans"],envs:p,runOpts:{stdio:"inherit"}}],runInfo:{apiPort:r==null?void 0:r.grpcPort,apiAddr:r==null?void 0:r.grpcAddr,logPath:o,primary:S,work:{type:"FS",rootPath:w},library:k,dbPath:m}}),g.getInstanceInfo(e)}cleanupInstance(e){const t=[],r=new Map;let n="";if(e){const s=g.getInstanceInfo(e);switch(r.set(e,s),s.type){case"docker":{t.push(`docker service 'pl-${e}', including all its volumes and data in '${g.instanceDir(e)}' will be destroyed`);break}case"process":{t.push(`directory '${g.instanceDir(e)}' would be deleted`),s.downCommands&&t.push("associated docker service, including all volumes and data will be destroyed");break}default:_()}e===g.currentInstanceName&&t.push("last command run cache ('pl-dev start' shorthand will stop working until next full start command call)"),n=`
97
97
  You are going to reset the state of platforma service '${e}':
98
98
  - ${t.join(`
99
99
  - `)}
100
- `}else{for(const s of g.instanceList)r.set(s,g.getInstanceInfo(s));t.push("last command run cache ('pl-service start' shorthand will stop working until next full start command call)",`all service configurations stored in: ${g.instanceDir()} (including all associated docker containers and volumes)`),n=`
100
+ `}else{for(const s of g.instanceList)r.set(s,g.getInstanceInfo(s));t.push("last command run cache ('pl-dev start' shorthand will stop working until next full start command call)",`all service configurations stored in: ${g.instanceDir()} (including all associated docker containers and volumes)`),n=`
101
101
  You are going to reset the state of all platforma services configured with pl-bootstrap package.
102
102
  - ${t.join(`
103
103
  - `)}